diff --git a/mcp-worker/package.json b/mcp-worker/package.json index d94fdcdd7..5a232a80b 100644 --- a/mcp-worker/package.json +++ b/mcp-worker/package.json @@ -24,7 +24,7 @@ "devDependencies": { "@types/node": "^24.3.0", "vitest": "^3.2.4", - "wrangler": "^4.31.0" + "wrangler": "^4.36.0" }, "packageManager": "yarn@4.9.2" } diff --git a/mcp-worker/tsconfig.json b/mcp-worker/tsconfig.json index 0c5a72718..dab3805c9 100644 --- a/mcp-worker/tsconfig.json +++ b/mcp-worker/tsconfig.json @@ -16,7 +16,7 @@ "esModuleInterop": true, "skipLibCheck": true, "strict": true, - "declaration": true, + "declaration": false, "declarationMap": false, "sourceMap": true }, diff --git a/oclif.manifest.json b/oclif.manifest.json index 8c9c8bfbc..c983df213 100644 --- a/oclif.manifest.json +++ b/oclif.manifest.json @@ -1,5 +1,5 @@ { - "version": "6.0.1", + "version": "6.0.2", "commands": { "authCommand": { "id": "authCommand", diff --git a/scripts/generate-zodios-client.sh b/scripts/generate-zodios-client.sh index 51f5d370a..d97f94e24 100755 --- a/scripts/generate-zodios-client.sh +++ b/scripts/generate-zodios-client.sh @@ -2,5 +2,5 @@ url="https://api.devcycle.com/swagger.json" temp_file=$(mktemp) curl -s "$url" -o "$temp_file" -yarn openapi-zod-client "$temp_file" --with-alias --export-schemas --prettier "prettier.config.js" -o "src/api/zodClient.ts" +yarn openapi-zod-client "$temp_file" --with-alias --export-schemas --prettier "prettier.config.js" -o "src/api/zodClientV2.ts" rm "$temp_file" \ No newline at end of file diff --git a/src/api/schemas.ts b/src/api/schemas.ts index fcc69b337..54f792340 100644 --- a/src/api/schemas.ts +++ b/src/api/schemas.ts @@ -1,41 +1,73 @@ import { z } from 'zod' -import { schemas } from './zodClient' - -export type Project = z.infer -export type Environment = z.infer -export type SDKKeys = z.infer -export type Variable = z.infer -export type Variation = z.infer -export type Feature = z.infer -export type FeatureConfig = z.infer -export type Audience = z.infer -export type Target = z.infer -export type Override = z.infer -export type CustomProperty = z.infer -export type GetProjectsParams = z.infer -export const GetProjectsParams = schemas.GetProjectsParams - -export type CreateProjectParams = z.infer -export const CreateProjectDto = schemas.CreateProjectDto - -export type UpdateProjectParams = z.infer -export const UpdateProjectDto = schemas.UpdateProjectDto - -export type CreateEnvironmentParams = z.infer< - typeof schemas.CreateEnvironmentDto -> -export const CreateEnvironmentDto = schemas.CreateEnvironmentDto - -export type UpdateEnvironmentParams = z.infer< - typeof schemas.UpdateEnvironmentDto -> -export const UpdateEnvironmentDto = schemas.UpdateEnvironmentDto - -export type CreateFeatureParams = z.infer -export const CreateFeatureDto = schemas.CreateFeatureDto - -export type UpdateFeatureParams = z.infer -export const UpdateFeatureDto = schemas.UpdateFeatureDto +import { + Project, + Environment, + SDKKeys, + Variable, + Variation, + Feature, + FeatureConfig, + Audience, + Target, + Override, + CustomProperty, + GetProjectsParams, + CreateProjectDto, + UpdateProjectDto, + CreateEnvironmentDto, + UpdateEnvironmentDto, + CreateFeatureDto, + UpdateFeatureDto, + CreateVariableDto, + UpdateVariableDto, + CreateVariationDto, + UpdateFeatureConfigDto, + UpdateTargetDto, + AudienceOperatorWithAudienceMatchFilter, + AllFilter, + OptInFilter, + UserFilter, + UserCountryFilter, + UserAppVersionFilter, + UserPlatformVersionFilter, + UserCustomFilter, + AudienceMatchFilter, + UpdateUserOverrideDto, + UserOverride, + FeatureOverride, +} from './zodClient' + +export type Project = z.infer +export type Environment = z.infer +export type SDKKeys = z.infer +export type Variable = z.infer +export type Variation = z.infer +export type Feature = z.infer +export type FeatureConfig = z.infer +export type Audience = z.infer +export type Target = z.infer +export type Override = z.infer +export type CustomProperty = z.infer +export type GetProjectsParams = z.infer +export { GetProjectsParams } + +export type CreateProjectParams = z.infer +export { CreateProjectDto } + +export type UpdateProjectParams = z.infer +export { UpdateProjectDto } + +export type CreateEnvironmentParams = z.infer +export { CreateEnvironmentDto } + +export type UpdateEnvironmentParams = z.infer +export { UpdateEnvironmentDto } + +export type CreateFeatureParams = z.infer +export { CreateFeatureDto } + +export type UpdateFeatureParams = z.infer +export { UpdateFeatureDto } export const UpdateFeatureStatusDto = z.object({ status: z.enum(['active', 'complete', 'archived']), @@ -44,60 +76,58 @@ export const UpdateFeatureStatusDto = z.object({ export type UpdateFeatureStatusParams = z.infer -export type CreateVariableParams = z.infer -export const CreateVariableDto = schemas.CreateVariableDto +export type CreateVariableParams = z.infer +export { CreateVariableDto } -export type UpdateVariableParams = z.infer -export const UpdateVariableDto = schemas.UpdateVariableDto +export type UpdateVariableParams = z.infer +export { UpdateVariableDto } -export type CreateVariationParams = z.infer -export const CreateVariationDto = schemas.CreateVariationDto +export type CreateVariationParams = z.infer +export { CreateVariationDto } export type UpdateVariationParams = Partial -export type UpdateFeatureConfigDto = z.infer< - typeof schemas.UpdateFeatureConfigDto -> -export const UpdateFeatureConfigDto = schemas.UpdateFeatureConfigDto +export type UpdateFeatureConfigDto = z.infer +export { UpdateFeatureConfigDto } -export type UpdateTargetParams = z.infer -export const UpdateTargetDto = schemas.UpdateTargetDto +export type UpdateTargetParams = z.infer +export { UpdateTargetDto } export type AudienceOperatorWithAudienceMatchFilter = z.infer< - typeof schemas.AudienceOperatorWithAudienceMatchFilter + typeof AudienceOperatorWithAudienceMatchFilter > export type Filters = z.infer< - typeof schemas.AudienceOperatorWithAudienceMatchFilter.shape.filters + typeof AudienceOperatorWithAudienceMatchFilter.shape.filters > -export type AllFilter = z.infer -export const AllFilterSchema = schemas.AllFilter +export type AllFilter = z.infer +export const AllFilterSchema = AllFilter -export type OptInFilter = z.infer -export const OptInFilterSchema = schemas.OptInFilter +export type OptInFilter = z.infer +export const OptInFilterSchema = OptInFilter -export type UserFilter = z.infer -export const UserFilterSchema = schemas.UserFilter +export type UserFilter = z.infer +export const UserFilterSchema = UserFilter -export type UserCountryFilter = z.infer -export const UserCountryFilterSchema = schemas.UserCountryFilter +export type UserCountryFilter = z.infer +export const UserCountryFilterSchema = UserCountryFilter -export type UserAppVersionFilter = z.infer -export const UserAppVersionFilterSchema = schemas.UserAppVersionFilter +export type UserAppVersionFilter = z.infer +export const UserAppVersionFilterSchema = UserAppVersionFilter export type UserPlatformVersionFilter = z.infer< - typeof schemas.UserPlatformVersionFilter + typeof UserPlatformVersionFilter > -export const UserPlatformVersionFilterSchema = schemas.UserPlatformVersionFilter +export const UserPlatformVersionFilterSchema = UserPlatformVersionFilter -export type UserCustomFilter = z.infer -export const UserCustomFilterSchema = schemas.UserCustomFilter +export type UserCustomFilter = z.infer +export const UserCustomFilterSchema = UserCustomFilter -export type AudienceMatchFilter = z.infer -export const AudienceMatchFilterSchema = schemas.AudienceMatchFilter +export type AudienceMatchFilter = z.infer +export const AudienceMatchFilterSchema = AudienceMatchFilter -export type UpdateOverrideParams = z.infer -export const UpdateOverrideDto = schemas.UpdateUserOverrideDto +export type UpdateOverrideParams = z.infer +export const UpdateOverrideDto = UpdateUserOverrideDto export type Filter = | AllFilter @@ -109,4 +139,5 @@ export type Filter = | UserCustomFilter | AudienceMatchFilter -export type UserOverride = z.infer +export type UserOverride = z.infer +export type FeatureOverride = z.infer diff --git a/src/api/zodClient.ts b/src/api/zodClient.ts index cc1018464..7d7208575 100644 --- a/src/api/zodClient.ts +++ b/src/api/zodClient.ts @@ -1,5 +1,11 @@ import { makeApi, Zodios, type ZodiosOptions } from '@zodios/core' import { z } from 'zod' +import { + CreateFeatureDto as CreateFeatureDtoV2, + UpdateFeatureDto as UpdateFeatureDtoV2, + Feature as FeatureV2, + Variable as VariableV2, +} from './zodClientV2' /** * IMPORTANT: MCP Schema Compatibility @@ -390,36 +396,40 @@ const CreateVariableDto = z.object({ defaultValue: z.any().optional(), validationSchema: VariableValidationEntity.optional(), }) -const Variable = z.object({ - name: z.string().max(100).optional(), - description: z.string().max(1000).optional(), - key: z - .string() - .max(100) - .regex(/^[a-z0-9-_.]+$/), - _id: z.string(), - _project: z.string(), - _feature: z.string().optional(), - type: z.enum(['String', 'Boolean', 'Number', 'JSON']), - status: z.enum(['active', 'archived']), - defaultValue: z.any().optional(), - source: z.enum([ - 'api', - 'dashboard', - 'importer', - 'github.code_usages', - 'github.pr_insights', - 'bitbucket.code_usages', - 'bitbucket.pr_insights', - 'terraform', - 'cli', - ]), - _createdBy: z.string().optional(), - createdAt: z.string().datetime(), - updatedAt: z.string().datetime(), - validationSchema: VariableValidationEntity.optional(), - persistent: z.boolean().optional(), -}) +// const Variable = z.object({ +// name: z.string().max(100).optional(), +// description: z.string().max(1000).optional(), +// key: z +// .string() +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// _id: z.string(), +// _project: z.string(), +// _feature: z.string().optional(), +// type: z.enum(['String', 'Boolean', 'Number', 'JSON']), +// status: z.enum(['active', 'archived']), +// defaultValue: z.any().optional(), +// source: z.enum([ +// 'api', +// 'dashboard', +// 'importer', +// 'github.code_usages', +// 'github.pr_insights', +// 'gitlab.code_usages', +// 'gitlab.pr_insights', +// 'bitbucket.code_usages', +// 'bitbucket.pr_insights', +// 'terraform', +// 'cli', +// 'slack', +// 'mcp', +// ]), +// _createdBy: z.string().optional(), +// createdAt: z.string().datetime(), +// updatedAt: z.string().datetime(), +// validationSchema: VariableValidationEntity.optional(), +// persistent: z.boolean().optional(), +// }) const UpdateVariableDto = z .object({ name: z.string().max(100), @@ -470,32 +480,32 @@ const FeatureSDKVisibilityDto = z.object({ client: z.boolean(), server: z.boolean(), }) -const CreateFeatureDto = z.object({ - name: z.string().max(100), - key: z - .string() - .max(100) - .regex(/^[a-z0-9-_.]+$/), - description: z.string().max(1000).optional(), - variables: z - .array(z.union([CreateVariableDto, ReassociateVariableDto])) - .optional(), - configurations: z - .record( - z.string(), - z.object({ - targets: z.array(z.unknown()).optional(), - status: z.string().optional(), - }), - ) - .optional(), - variations: z.array(FeatureVariationDto.partial()).optional(), - controlVariation: z.string().optional(), - settings: FeatureSettingsDto.optional(), - sdkVisibility: FeatureSDKVisibilityDto.optional(), - type: z.enum(['release', 'experiment', 'permission', 'ops']).optional(), - tags: z.array(z.string()).optional(), -}) +// const CreateFeatureDto = z.object({ +// name: z.string().max(100), +// key: z +// .string() +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// description: z.string().max(1000).optional(), +// variables: z +// .array(z.union([CreateVariableDto, ReassociateVariableDto])) +// .optional(), +// configurations: z +// .record( +// z.string(), +// z.object({ +// targets: z.array(z.unknown()).optional(), +// status: z.string().optional(), +// }), +// ) +// .optional(), +// variations: z.array(FeatureVariationDto.partial()).optional(), +// controlVariation: z.string().optional(), +// settings: FeatureSettingsDto.optional(), +// sdkVisibility: FeatureSDKVisibilityDto.optional(), +// type: z.enum(['release', 'experiment', 'permission', 'ops']).optional(), +// tags: z.array(z.string()).optional(), +// }) const Variation = z.object({ key: z .string() @@ -538,25 +548,25 @@ const PreconditionFailedErrorResponse = z.object({ message: z.object({}).partial(), error: z.string(), }) -const UpdateFeatureDto = z - .object({ - name: z.string().max(100), - key: z - .string() - .max(100) - .regex(/^[a-z0-9-_.]+$/), - description: z.string().max(1000), - variables: z.array( - z.union([CreateVariableDto, ReassociateVariableDto]), - ), - variations: z.array(FeatureVariationDto), - settings: FeatureSettingsDto, - sdkVisibility: FeatureSDKVisibilityDto, - type: z.enum(['release', 'experiment', 'permission', 'ops']), - tags: z.array(z.string()), - controlVariation: z.string(), - }) - .partial() +// const UpdateFeatureDto = z +// .object({ +// name: z.string().max(100), +// key: z +// .string() +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// description: z.string().max(1000), +// variables: z.array( +// z.union([CreateVariableDto, ReassociateVariableDto]), +// ), +// variations: z.array(FeatureVariationDto), +// settings: FeatureSettingsDto, +// sdkVisibility: FeatureSDKVisibilityDto, +// type: z.enum(['release', 'experiment', 'permission', 'ops']), +// tags: z.array(z.string()), +// controlVariation: z.string(), +// }) +// .partial() const LinkJiraIssueDto = z.object({ issueId: z.string() }) const JiraIssueLink = z.object({ issueId: z.string() }) const UpdateFeatureVariationDto = z @@ -665,51 +675,51 @@ const ResultSummaryDto = z.object({ cached: z.boolean(), updatedAt: z.string().datetime(), }) -const Feature = z.object({ - name: z.string().max(100), - key: z - .string() - .max(100) - .regex(/^[a-z0-9-_.]+$/), - description: z.string().max(1000).optional(), - _id: z.string(), - _project: z.string(), - source: z.enum([ - 'api', - 'dashboard', - 'importer', - 'github.code_usages', - 'github.pr_insights', - 'bitbucket.code_usages', - 'bitbucket.pr_insights', - 'terraform', - 'cli', - ]), - type: z.enum(['release', 'experiment', 'permission', 'ops']).optional(), - status: z.enum(['active', 'complete', 'archived']).optional(), - configurations: z.array(FeatureConfig.partial()).optional(), - _createdBy: z.string().optional(), - createdAt: z.string().datetime(), - updatedAt: z.string().datetime(), - variations: z.array(Variation), - controlVariation: z.string(), - variables: z.array(Variable), - tags: z.array(z.string()).optional(), - ldLink: z.string().optional(), - readonly: z.boolean(), - settings: FeatureSettings.partial().optional(), - sdkVisibility: FeatureSDKVisibility.optional(), - staleness: z - .object({ - stale: z.boolean(), - updatedAt: z.string().datetime().optional(), - disabled: z.boolean().optional(), - snoozedUntil: z.string().datetime().optional(), - reason: z.string().optional(), - metaData: z.record(z.string(), z.unknown()).optional(), - }) - .optional(), -}) +// const Feature = z.object({ +// name: z.string().max(100), +// key: z +// .string() +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// description: z.string().max(1000).optional(), +// _id: z.string(), +// _project: z.string(), +// source: z.enum([ +// 'api', +// 'dashboard', +// 'importer', +// 'github.code_usages', +// 'github.pr_insights', +// 'bitbucket.code_usages', +// 'bitbucket.pr_insights', +// 'terraform', +// 'cli', +// ]), +// type: z.enum(['release', 'experiment', 'permission', 'ops']).optional(), +// status: z.enum(['active', 'complete', 'archived']).optional(), +// configurations: z.array(FeatureConfig.partial()).optional(), +// _createdBy: z.string().optional(), +// createdAt: z.string().datetime(), +// updatedAt: z.string().datetime(), +// variations: z.array(Variation), +// controlVariation: z.string(), +// variables: z.array(Variable), +// tags: z.array(z.string()).optional(), +// ldLink: z.string().optional(), +// readonly: z.boolean(), +// settings: FeatureSettings.partial().optional(), +// sdkVisibility: FeatureSDKVisibility.optional(), +// staleness: z +// .object({ +// stale: z.boolean(), +// updatedAt: z.string().datetime().optional(), +// disabled: z.boolean().optional(), +// snoozedUntil: z.string().datetime().optional(), +// reason: z.string().optional(), +// metaData: z.record(z.string(), z.unknown()).optional(), +// }) +// .optional(), +// }) const FeatureDataPoint = z.object({ values: z.object({}).partial(), date: z.string().datetime(), @@ -881,7 +891,7 @@ const MetricResult = z.object({ }) const MetricAssociation = z.object({ _project: z.string(), - feature: Feature, + feature: FeatureV2, metric: Metric, createdAt: z.string().datetime(), }) @@ -936,7 +946,7 @@ const UserOverride = z.object({ }) const UserOverrides = z.array(UserOverride) -export const schemas = { +export { EdgeDBSettings, ColorSettings, OptInSettings, @@ -970,21 +980,21 @@ export const schemas = { UpdateAudienceDto, VariableValidationEntity, CreateVariableDto, - Variable, + VariableV2 as Variable, UpdateVariableDto, UpdateVariableStatusDto, ReassociateVariableDto, FeatureVariationDto, FeatureSettingsDto, FeatureSDKVisibilityDto, - CreateFeatureDto, + CreateFeatureDtoV2 as CreateFeatureDto, Variation, CreateVariationDto, FeatureSettings, FeatureSDKVisibility, - Feature, + FeatureV2 as Feature, PreconditionFailedErrorResponse, - UpdateFeatureDto, + UpdateFeatureDtoV2 as UpdateFeatureDto, LinkJiraIssueDto, JiraIssueLink, UpdateFeatureVariationDto, @@ -1021,6 +1031,7 @@ export const schemas = { UpdateUserOverrideDto, Override, Overrides, + FeatureOverride, FeatureOverrideResponse, UserOverride, UserOverrides, @@ -1861,7 +1872,7 @@ const endpoints = makeApi([ { name: 'body', type: 'Body', - schema: CreateFeatureDto, + schema: CreateFeatureDtoV2, }, { name: 'project', @@ -1869,7 +1880,7 @@ const endpoints = makeApi([ schema: z.string(), }, ], - response: Feature, + response: FeatureV2, errors: [ { status: 400, @@ -1943,7 +1954,7 @@ const endpoints = makeApi([ schema: z.string(), }, ], - response: z.array(Feature), + response: z.array(FeatureV2), errors: [ { status: 400, @@ -2270,7 +2281,7 @@ const endpoints = makeApi([ schema: z.string(), }, ], - response: Feature, + response: FeatureV2, errors: [ { status: 400, @@ -2372,7 +2383,7 @@ const endpoints = makeApi([ schema: z.string(), }, ], - response: Feature, + response: FeatureV2, errors: [ { status: 400, @@ -2410,7 +2421,7 @@ const endpoints = makeApi([ schema: z.string(), }, ], - response: Feature, + response: FeatureV2, errors: [ { status: 401, @@ -2432,7 +2443,7 @@ const endpoints = makeApi([ { name: 'body', type: 'Body', - schema: UpdateFeatureDto, + schema: UpdateFeatureDtoV2, }, { name: 'key', @@ -2445,7 +2456,7 @@ const endpoints = makeApi([ schema: z.string(), }, ], - response: Feature, + response: FeatureV2, errors: [ { status: 400, @@ -2635,7 +2646,7 @@ const endpoints = makeApi([ schema: z.string(), }, ], - response: z.array(Feature), + response: z.array(FeatureV2), errors: [ { status: 400, @@ -3220,7 +3231,7 @@ const endpoints = makeApi([ schema: z.string(), }, ], - response: Variable, + response: VariableV2, errors: [ { status: 400, @@ -3294,7 +3305,7 @@ const endpoints = makeApi([ schema: z.string(), }, ], - response: z.array(Variable), + response: z.array(VariableV2), errors: [ { status: 400, @@ -3327,7 +3338,7 @@ const endpoints = makeApi([ schema: z.string(), }, ], - response: Variable, + response: VariableV2, errors: [ { status: 401, @@ -3361,7 +3372,7 @@ const endpoints = makeApi([ schema: z.string(), }, ], - response: Variable, + response: VariableV2, errors: [ { status: 400, @@ -3432,7 +3443,7 @@ const endpoints = makeApi([ schema: z.string(), }, ], - response: Variable, + response: VariableV2, errors: [ { status: 400, @@ -3692,7 +3703,7 @@ const v2Endpoints = makeApi([ { name: 'body', type: 'Body', - schema: CreateFeatureDto, + schema: CreateFeatureDtoV2, }, { name: 'project', @@ -3700,7 +3711,7 @@ const v2Endpoints = makeApi([ schema: z.string(), }, ], - response: Feature, + response: FeatureV2, errors: [ { status: 400, @@ -3799,7 +3810,7 @@ const v2Endpoints = makeApi([ schema: z.string(), }, ], - response: z.array(Feature), + response: z.array(FeatureV2), errors: [ { status: 400, @@ -3825,7 +3836,7 @@ const v2Endpoints = makeApi([ { name: 'body', type: 'Body', - schema: UpdateFeatureDto, + schema: UpdateFeatureDtoV2, }, { name: 'feature', @@ -3838,7 +3849,7 @@ const v2Endpoints = makeApi([ schema: z.string(), }, ], - response: Feature, + response: FeatureV2, errors: [ { status: 400, @@ -3884,7 +3895,7 @@ const v2Endpoints = makeApi([ schema: z.string(), }, ], - response: Feature, + response: FeatureV2, errors: [ { status: 401, @@ -3898,13 +3909,42 @@ const v2Endpoints = makeApi([ }, ]) -export const api = new Zodios(endpoints) -export const v2Api = new Zodios(v2Endpoints) +/** + * TypeScript workaround for large Zodios endpoint definitions. + * + * Our ~80+ endpoints exceed TypeScript's inference limits, causing "type exceeds + * maximum length" errors. This pattern breaks the inference chain while maintaining + * full type safety through ReturnType<> extraction. + */ +const _createApiClient: (baseUrl?: string, options?: ZodiosOptions) => any = ( + baseUrl?: string, + options?: ZodiosOptions, +) => (baseUrl ? new Zodios(baseUrl, endpoints, options) : new Zodios(endpoints)) +const _createV2ApiClient: (baseUrl?: string, options?: ZodiosOptions) => any = ( + baseUrl?: string, + options?: ZodiosOptions, +) => + baseUrl + ? new Zodios(baseUrl, v2Endpoints, options) + : new Zodios(v2Endpoints) + +type ApiClientType = ReturnType +type V2ApiClientType = ReturnType + +// Create the actual instances with explicit type annotation +export const api: ApiClientType = _createApiClient() +export const v2Api: V2ApiClientType = _createV2ApiClient() -export function createApiClient(baseUrl: string, options?: ZodiosOptions) { - return new Zodios(baseUrl, endpoints, options) +export function createApiClient( + baseUrl: string, + options?: ZodiosOptions, +): ApiClientType { + return _createApiClient(baseUrl, options) } -export function createV2ApiClient(baseUrl: string, options?: ZodiosOptions) { - return new Zodios(baseUrl, v2Endpoints, options) +export function createV2ApiClient( + baseUrl: string, + options?: ZodiosOptions, +): V2ApiClientType { + return _createV2ApiClient(baseUrl, options) } diff --git a/src/api/zodClientV2.ts b/src/api/zodClientV2.ts new file mode 100644 index 000000000..a20901b92 --- /dev/null +++ b/src/api/zodClientV2.ts @@ -0,0 +1,6222 @@ +/** + * NOTE: this file is a new export from generate-zodios-client.sh + * Using it to selectivly switch over to the new zod schemas, + * as there are a bunch of conflicts with the old schemas that are still mostly working. + */ + +// import { makeApi, Zodios, type ZodiosOptions } from '@zodios/core' +import { z } from 'zod' + +// const EdgeDBSettingsDTO = z.object({ enabled: z.boolean() }).passthrough() +// const ColorSettingsDTO = z +// .object({ +// primary: z +// .string() +// .max(9) +// .regex( +// /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/, +// ), +// secondary: z +// .string() +// .max(9) +// .regex( +// /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/, +// ), +// }) +// .passthrough() +// const OptInSettingsDTO = z +// .object({ +// title: z.string().min(1).max(100), +// description: z.string().max(1000), +// enabled: z.boolean(), +// imageURL: z.string(), +// colors: ColorSettingsDTO, +// poweredByAlignment: z.enum(['center', 'left', 'right', 'hidden']), +// }) +// .passthrough() +// const SDKTypeVisibilitySettingsDTO = z +// .object({ enabledInFeatureSettings: z.boolean() }) +// .passthrough() +// const LifeCycleSettingsDTO = z +// .object({ disableCodeRefChecks: z.boolean() }) +// .passthrough() +// const ObfuscationSettingsDTO = z +// .object({ enabled: z.boolean(), required: z.boolean() }) +// .passthrough() +// const DynatraceProjectSettingsDTO = z +// .object({ +// enabled: z.boolean(), +// environmentMap: z.object({}).partial().passthrough(), +// }) +// .partial() +// .passthrough() +// const ProjectSettingsDTO = z +// .object({ +// edgeDB: EdgeDBSettingsDTO, +// optIn: OptInSettingsDTO, +// sdkTypeVisibility: SDKTypeVisibilitySettingsDTO, +// lifeCycle: LifeCycleSettingsDTO, +// obfuscation: ObfuscationSettingsDTO, +// disablePassthroughRollouts: z.boolean(), +// dynatrace: DynatraceProjectSettingsDTO, +// }) +// .passthrough() +// const CreateProjectDto = z +// .object({ +// name: z.string().min(1).max(100), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// description: z.string().max(1000).optional(), +// color: z +// .string() +// .max(9) +// .regex( +// /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/, +// ) +// .optional(), +// settings: ProjectSettingsDTO.optional(), +// }) +// .passthrough() +// const EdgeDBSettings = z.object({ enabled: z.boolean() }).passthrough() +// const ColorSettings = z +// .object({ primary: z.string(), secondary: z.string() }) +// .passthrough() +// const OptInSettings = z +// .object({ +// enabled: z.boolean(), +// title: z.string(), +// description: z.string(), +// imageURL: z.string(), +// colors: ColorSettings, +// poweredByAlignment: z.object({}).partial().passthrough(), +// }) +// .passthrough() +// const SDKTypeVisibilitySettings = z +// .object({ enabledInFeatureSettings: z.boolean() }) +// .passthrough() +// const LifeCycleSettings = z +// .object({ disableCodeRefChecks: z.boolean() }) +// .passthrough() +// const ObfuscationSettings = z +// .object({ enabled: z.boolean(), required: z.boolean() }) +// .passthrough() +// const FeatureApprovalWorkflowSettings = z +// .object({ +// enabled: z.boolean(), +// allowPublisherBypass: z.boolean(), +// defaultReviewers: z.array(z.string()), +// }) +// .passthrough() +// const ReleasedStalenessSettings = z +// .object({ enabled: z.boolean() }) +// .passthrough() +// const UnmodifiedLongStalenessSettings = z +// .object({ enabled: z.boolean() }) +// .passthrough() +// const UnmodifiedShortStalenessSettings = z +// .object({ enabled: z.boolean() }) +// .passthrough() +// const UnusedStalenessSettings = z.object({ enabled: z.boolean() }).passthrough() +// const StalenessEmailSettings = z +// .object({ +// enabled: z.boolean(), +// frequency: z.enum(['weekly', 'biweekly', 'monthly']), +// users: z.array(z.string()), +// lastNotification: z.string().datetime({ offset: true }), +// }) +// .passthrough() +// const StalenessSettings = z +// .object({ +// enabled: z.boolean(), +// released: ReleasedStalenessSettings, +// unmodifiedLong: UnmodifiedLongStalenessSettings, +// unmodifiedShort: UnmodifiedShortStalenessSettings, +// unused: UnusedStalenessSettings, +// email: StalenessEmailSettings, +// }) +// .passthrough() +// const DynatraceProjectSettings = z +// .object({ +// enabled: z.boolean(), +// environmentMap: z.object({}).partial().passthrough(), +// }) +// .passthrough() +// const ProjectSettings = z +// .object({ +// edgeDB: EdgeDBSettings, +// optIn: OptInSettings, +// sdkTypeVisibility: SDKTypeVisibilitySettings, +// lifeCycle: LifeCycleSettings, +// obfuscation: ObfuscationSettings, +// featureApprovalWorkflow: FeatureApprovalWorkflowSettings, +// disablePassthroughRollouts: z.boolean(), +// staleness: StalenessSettings, +// dynatrace: DynatraceProjectSettings, +// }) +// .passthrough() +// const VercelEdgeConfigConnection = z +// .object({ edgeConfigName: z.string(), configurationId: z.string() }) +// .passthrough() +// const Project = z +// .object({ +// _id: z.string(), +// _organization: z.string(), +// _createdBy: z.string(), +// name: z.string(), +// key: z.string(), +// description: z.string().optional(), +// color: z.string().optional(), +// settings: ProjectSettings, +// createdAt: z.string().datetime({ offset: true }), +// updatedAt: z.string().datetime({ offset: true }), +// hasJiraIntegration: z.boolean(), +// hasReceivedCodeUsages: z.boolean(), +// hasUserConfigFetch: z.boolean(), +// jiraBaseUrl: z.string(), +// readonly: z.boolean(), +// vercelEdgeConfigConnections: z +// .array(VercelEdgeConfigConnection) +// .optional(), +// }) +// .passthrough() +// const BadRequestErrorResponse = z +// .object({ +// statusCode: z.number(), +// message: z.object({}).partial().passthrough(), +// error: z.string(), +// }) +// .passthrough() +// const ConflictErrorResponse = z +// .object({ +// statusCode: z.number(), +// message: z.object({}).partial().passthrough(), +// error: z.string(), +// errorType: z.string(), +// }) +// .passthrough() +// const NotFoundErrorResponse = z +// .object({ +// statusCode: z.number(), +// message: z.object({}).partial().passthrough(), +// error: z.string(), +// }) +// .passthrough() +// const UpdateProjectDto = z +// .object({ +// name: z.string().min(1).max(100), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// description: z.string().max(1000), +// color: z +// .string() +// .max(9) +// .regex( +// /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/, +// ), +// settings: ProjectSettingsDTO, +// }) +// .partial() +// .passthrough() +// const CannotDeleteLastItemErrorResponse = z +// .object({ +// statusCode: z.number(), +// message: z.object({}).partial().passthrough(), +// error: z.string(), +// }) +// .passthrough() +// const UpdateProjectSettingsDto = z +// .object({ settings: ProjectSettings }) +// .passthrough() +// const FeatureApprovalWorkflowDTO = z +// .object({ +// enabled: z.boolean(), +// allowPublisherBypass: z.boolean(), +// defaultReviewers: z.array(z.string()), +// }) +// .passthrough() +// const ReleasedStalenessDTO = z.object({ enabled: z.boolean() }).passthrough() +// const UnmodifiedLongStalenessDTO = z +// .object({ enabled: z.boolean() }) +// .passthrough() +// const UnmodifiedShortStalenessDTO = z +// .object({ enabled: z.boolean() }) +// .passthrough() +// const UnusedStalenessDTO = z.object({ enabled: z.boolean() }).passthrough() +// const EmailSettingsDTO = z +// .object({ +// enabled: z.boolean(), +// users: z.array(z.string()), +// frequency: z.enum(['weekly', 'biweekly', 'monthly']), +// }) +// .passthrough() +// const StalenessSettingsDTO = z +// .object({ +// enabled: z.boolean(), +// released: ReleasedStalenessDTO, +// unmodifiedLong: UnmodifiedLongStalenessDTO, +// unmodifiedShort: UnmodifiedShortStalenessDTO, +// unused: UnusedStalenessDTO, +// email: EmailSettingsDTO, +// }) +// .passthrough() +// const ProtectedProjectSettingsDto = z +// .object({ +// featureApprovalWorkflow: FeatureApprovalWorkflowDTO, +// staleness: StalenessSettingsDTO, +// }) +// .passthrough() +// const UpdateProtectedProjectSettingsDto = z +// .object({ settings: ProtectedProjectSettingsDto }) +// .passthrough() +const FeatureStalenessEntity = z + .object({ + stale: z.boolean(), + updatedAt: z.string().datetime({ offset: true }).optional(), + disabled: z.boolean(), + snoozedUntil: z.string().datetime({ offset: true }).optional(), + reason: z + .enum(['released', 'unused', 'unmodifiedShort', 'unmodifiedLong']) + .optional(), + metaData: z.object({}).partial().passthrough().optional(), + }) + .passthrough() +// const EnvironmentSettings = z +// .object({ appIconURI: z.string().max(2048) }) +// .partial() +// .passthrough() +// const CreateEnvironmentDto = z +// .object({ +// name: z.string().min(1).max(100), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// description: z.string().max(1000).optional(), +// color: z +// .string() +// .max(9) +// .regex( +// /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/, +// ) +// .optional(), +// type: z.enum([ +// 'development', +// 'staging', +// 'production', +// 'disaster_recovery', +// ]), +// settings: EnvironmentSettings.optional(), +// }) +// .passthrough() +// const APIKey = z.object({}).partial().passthrough() +// const SDKKeys = z +// .object({ +// mobile: z.array(APIKey), +// client: z.array(APIKey), +// server: z.array(APIKey), +// }) +// .passthrough() +// const Environment = z +// .object({ +// name: z.string().min(1).max(100), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// description: z.string().max(1000).optional(), +// color: z +// .string() +// .max(9) +// .regex( +// /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/, +// ) +// .optional(), +// _id: z.string(), +// _project: z.string(), +// type: z.enum([ +// 'development', +// 'staging', +// 'production', +// 'disaster_recovery', +// ]), +// _createdBy: z.string(), +// createdAt: z.string().datetime({ offset: true }), +// updatedAt: z.string().datetime({ offset: true }), +// sdkKeys: SDKKeys.optional(), +// settings: EnvironmentSettings.optional(), +// readonly: z.boolean(), +// }) +// .passthrough() +// const UpdateEnvironmentDto = z +// .object({ +// name: z.string().min(1).max(100), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// description: z.string().max(1000), +// color: z +// .string() +// .max(9) +// .regex( +// /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/, +// ), +// type: z.enum([ +// 'development', +// 'staging', +// 'production', +// 'disaster_recovery', +// ]), +// settings: EnvironmentSettings, +// }) +// .partial() +// .passthrough() +// const GenerateSdkTokensDto = z +// .object({ client: z.boolean(), server: z.boolean(), mobile: z.boolean() }) +// .partial() +// .passthrough() +const AllFilter = z.object({ type: z.literal('all').default('all') }) +const OptInFilter = z.object({ + type: z.literal('optIn').default('optIn'), + _audiences: z.array(z.string()).optional(), + values: z.array(z.string()).optional(), +}) +const UserFilter = z.object({ + subType: z.enum(['user_id', 'email', 'platform', 'deviceModel']), + comparator: z.enum([ + '=', + '!=', + 'exist', + '!exist', + 'contain', + '!contain', + 'startWith', + '!startWith', + 'endWith', + '!endWith', + ]), + values: z.array(z.string()).optional(), + type: z.literal('user').default('user'), +}) +const UserCountryFilter = z + .object({ + subType: z.literal('country').default('country'), + comparator: z.enum([ + '=', + '!=', + 'exist', + '!exist', + 'contain', + '!contain', + 'startWith', + '!startWith', + 'endWith', + '!endWith', + ]), + values: z.array(z.string()).optional(), + type: z.literal('user').default('user'), + }) + .describe('values must be valid ISO31661 Alpha2 country codes') +const UserAppVersionFilter = z + .object({ + comparator: z.enum([ + '=', + '!=', + '>', + '>=', + '<', + '<=', + 'exist', + '!exist', + ]), + values: z.array(z.string()).optional(), + type: z.literal('user').default('user'), + subType: z.literal('appVersion').default('appVersion'), + }) + .describe('values must be valid semver versions') +const UserPlatformVersionFilter = z.object({ + comparator: z.enum(['=', '!=', '>', '>=', '<', '<=', 'exist', '!exist']), + values: z.array(z.string()).optional(), + type: z.literal('user').default('user'), + subType: z.literal('appVersion').default('appVersion'), +}) +const UserCustomFilter = z + .object({ + comparator: z.enum([ + '=', + '!=', + '>', + '>=', + '<', + '<=', + 'exist', + '!exist', + 'contain', + '!contain', + 'startWith', + '!startWith', + 'endWith', + '!endWith', + ]), + dataKey: z.string().min(1), + dataKeyType: z.enum(['String', 'Boolean', 'Number']), + values: z + .array(z.union([z.boolean(), z.string(), z.number()])) + .optional(), + type: z.literal('user').default('user'), + subType: z.literal('customData').default('customData'), + }) + .describe( + 'Filters users by comparing customData[dataKey] (coerced to dataKeyType) to values using the specified comparator', + ) + .passthrough() +// const AudienceOperator = z +// .object({ +// filters: z.array( +// z.union([ +// AllFilter, +// UserFilter, +// UserCountryFilter, +// UserAppVersionFilter, +// UserPlatformVersionFilter, +// UserCustomFilter, +// ]), +// ), +// operator: z.enum(['and', 'or']), +// }) +// .passthrough() +// const CreateAudienceDto = z +// .object({ +// name: z.string().min(1).max(100).optional(), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/) +// .optional(), +// description: z.string().max(1000).optional(), +// filters: AudienceOperator, +// tags: z.array(z.string()).optional(), +// }) +// .passthrough() +// const Audience = z +// .object({ +// name: z.string().min(1).max(100).optional(), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/) +// .optional(), +// description: z.string().max(1000).optional(), +// _id: z.string(), +// _project: z.string(), +// filters: AudienceOperator, +// source: z +// .enum([ +// 'api', +// 'dashboard', +// 'importer', +// 'github.code_usages', +// 'github.pr_insights', +// 'gitlab.code_usages', +// 'gitlab.pr_insights', +// 'bitbucket.code_usages', +// 'bitbucket.pr_insights', +// 'terraform', +// 'cli', +// 'slack', +// 'mcp', +// ]) +// .optional(), +// _createdBy: z.string().optional(), +// createdAt: z.string().datetime({ offset: true }), +// updatedAt: z.string().datetime({ offset: true }), +// tags: z.array(z.string()).optional(), +// readonly: z.boolean(), +// hasUsage: z.boolean().optional(), +// }) +// .passthrough() +// const UpdateAudienceDto = z +// .object({ +// name: z.string().min(1).max(100), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// description: z.string().max(1000), +// filters: AudienceOperator, +// tags: z.array(z.string()), +// }) +// .partial() +// .passthrough() +// const AudienceEnvironments = z.object({}).partial().passthrough() +// const AudienceFeature = z +// .object({ +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// name: z.string().min(1).max(100), +// id: z.string(), +// environments: AudienceEnvironments, +// }) +// .passthrough() +// const AudienceUsage = z +// .object({ features: z.array(AudienceFeature) }) +// .passthrough() +const VariableValidationEntity = z.object({ + schemaType: z.enum(['enum', 'regex', 'jsonSchema']), + enumValues: z.union([z.array(z.string()), z.array(z.number())]).optional(), + regexPattern: z.string().optional(), + jsonSchema: z.string().optional(), + description: z.string(), + exampleValue: z.any(), +}) +const CreateVariableDto = z.object({ + name: z.string().min(1).max(100).optional(), + description: z.string().max(1000).optional(), + key: z + .string() + .min(1) + .max(100) + .regex(/^[a-z0-9-_.]+$/), + _feature: z.string().optional(), + type: z.enum(['String', 'Boolean', 'Number', 'JSON']), + defaultValue: z.any().optional(), + validationSchema: VariableValidationEntity.optional(), + tags: z.array(z.string()).optional(), +}) +// Remove defaultValue from CreateVariableDto for Features V2 endpoints +export const FeatureVariableDto = CreateVariableDto.omit({ defaultValue: true }) +export const Variable = z + .object({ + name: z.string().min(1).max(100).optional(), + description: z.string().max(1000).optional(), + key: z + .string() + .min(1) + .max(100) + .regex(/^[a-z0-9-_.]+$/), + _id: z.string(), + _project: z.string(), + _feature: z.string().optional(), + type: z.enum(['String', 'Boolean', 'Number', 'JSON']), + status: z.enum(['active', 'archived']), + defaultValue: z.any().optional(), + source: z.enum([ + 'api', + 'dashboard', + 'importer', + 'github.code_usages', + 'github.pr_insights', + 'gitlab.code_usages', + 'gitlab.pr_insights', + 'bitbucket.code_usages', + 'bitbucket.pr_insights', + 'terraform', + 'cli', + 'slack', + 'mcp', + ]), + _createdBy: z.string().optional(), + createdAt: z.string().datetime({ offset: true }), + updatedAt: z.string().datetime({ offset: true }), + validationSchema: VariableValidationEntity.optional(), + persistent: z.boolean().optional(), + tags: z.array(z.string()).optional(), + }) + .passthrough() +// const UpdateVariableDto = z +// .object({ +// name: z.string().min(1).max(100), +// description: z.string().max(1000), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// type: z.enum(['String', 'Boolean', 'Number', 'JSON']), +// validationSchema: VariableValidationEntity, +// persistent: z.boolean(), +// tags: z.array(z.string()), +// }) +// .partial() +// .passthrough() +// const PreconditionFailedErrorResponse = z +// .object({ +// statusCode: z.number(), +// message: z.object({}).partial().passthrough(), +// error: z.string(), +// }) +// .passthrough() +// const UpdateVariableStatusDto = z +// .object({ status: z.enum(['active', 'archived']) }) +// .passthrough() +const RolloutStage = z.object({ + percentage: z.number().gte(0).lte(1), + type: z.enum(['linear', 'discrete']), + date: z.string().datetime({ offset: true }), +}) +const Rollout = z.object({ + startPercentage: z.number().gte(0).lte(1).optional(), + type: z.enum(['schedule', 'gradual', 'stepped']), + startDate: z.string().datetime({ offset: true }), + stages: z.array(RolloutStage).optional(), +}) +const TargetDistribution = z.object({ + percentage: z.number().gte(0).lte(1), + _variation: z.string(), +}) +const AudienceMatchFilter = z.object({ + type: z.literal('audienceMatch').default('audienceMatch'), + comparator: z.enum(['=', '!=']).optional(), + _audiences: z.array(z.string()).optional(), +}) +const AudienceOperatorWithAudienceMatchFilter = z.object({ + filters: z.array( + z.union([ + AllFilter.passthrough(), + OptInFilter.passthrough(), + UserFilter.passthrough(), + UserCountryFilter.passthrough(), + UserAppVersionFilter.passthrough(), + UserPlatformVersionFilter.passthrough(), + UserCustomFilter.passthrough(), + AudienceMatchFilter.passthrough(), + ]), + ), + operator: z.enum(['and', 'or']), +}) +const TargetAudience = z.object({ + name: z.string().min(1).max(100).optional(), + filters: AudienceOperatorWithAudienceMatchFilter, +}) +const UpdateTargetDto = z + .object({ + _id: z.string().optional(), + name: z.string().optional(), + rollout: Rollout.optional(), + distribution: z.array(TargetDistribution), + audience: TargetAudience, + }) + .passthrough() +const UpdateFeatureConfigDto = z + .object({ + status: z.enum(['active', 'inactive']).default('inactive'), + targets: z + .array(UpdateTargetDto) + .optional() + .describe( + 'Setting an empty array will remove all targets for this configuration', + ), + }) + .partial() + .passthrough() +const CreateVariationDto = z + .object({ + key: z + .string() + .min(1) + .max(100) + .regex(/^[a-z0-9-_.]+$/), + name: z.string().min(1).max(100), + variables: z + .record( + z.union([ + z.string(), + z.number(), + z.boolean(), + z.array(z.any()), + z.object({}).partial().passthrough(), + ]), + ) + .optional(), + }) + .passthrough() +const FeatureSettingsDto = z + .object({ + publicName: z.string().max(100), + publicDescription: z.string().max(1000), + optInEnabled: z.boolean(), + }) + .passthrough() +const FeatureSDKVisibilityDto = z + .object({ mobile: z.boolean(), client: z.boolean(), server: z.boolean() }) + .passthrough() + +export const CreateFeatureDto = z.object({ + key: z + .string() + .min(1) + .max(100) + .regex(/^[a-z0-9-_.]+$/), + name: z.string().min(1).max(100), + description: z.string().max(1000).optional(), + configurations: z.record(UpdateFeatureConfigDto).optional(), + type: z.enum(['release', 'experiment', 'permission', 'ops']).optional(), + tags: z.array(z.string()).optional(), + variations: z.array(CreateVariationDto).optional(), + controlVariation: z.string().optional(), + variables: z.array(FeatureVariableDto).optional(), + settings: FeatureSettingsDto.optional(), + sdkVisibility: FeatureSDKVisibilityDto.optional(), +}) + +const Variation = z + .object({ + key: z + .string() + .min(1) + .max(100) + .regex(/^[a-z0-9-_.]+$/), + name: z.string().min(1).max(100), + variables: z + .record( + z.union([ + z.string(), + z.number(), + z.boolean(), + z.array(z.any()), + z.object({}).partial().passthrough(), + ]), + ) + .optional(), + _id: z.string(), + }) + .passthrough() +const FeatureSettings = z + .object({ + publicName: z.string().max(100), + publicDescription: z.string().max(1000), + optInEnabled: z.boolean(), + }) + .passthrough() +const FeatureSDKVisibility = z + .object({ mobile: z.boolean(), client: z.boolean(), server: z.boolean() }) + .passthrough() +const Target = z + .object({ + _id: z.string(), + name: z.string().optional(), + audience: TargetAudience, + rollout: Rollout.optional(), + distribution: z.array(TargetDistribution), + bucketingKey: z.string().optional(), + }) + .passthrough() +const FeatureConfig = z + .object({ + _feature: z.string(), + _environment: z.string(), + _createdBy: z.string().optional(), + status: z.enum(['active', 'inactive']), + startedAt: z.string().datetime({ offset: true }).optional(), + updatedAt: z.string().datetime({ offset: true }), + targets: z.array(Target), + readonly: z.boolean(), + hasStaticConfig: z.boolean(), + }) + .passthrough() +const AuditLogEntity = z + .object({ + date: z.string().datetime({ offset: true }), + a0_user: z.string(), + changes: z.array(z.object({}).partial().passthrough()), + }) + .passthrough() +// const FeatureStaleness = z.object({}).partial().passthrough() +const Link = z.object({ url: z.string(), title: z.string() }).passthrough() +const FeatureSummary = z + .object({ + maintainers: z.array(z.string()), + links: z.array(Link), + markdown: z.string(), + }) + .passthrough() +export const Feature = z + .object({ + _id: z.string(), + _project: z.string(), + source: z.enum([ + 'api', + 'dashboard', + 'importer', + 'github.code_usages', + 'github.pr_insights', + 'gitlab.code_usages', + 'gitlab.pr_insights', + 'bitbucket.code_usages', + 'bitbucket.pr_insights', + 'terraform', + 'cli', + 'slack', + 'mcp', + ]), + status: z.enum(['active', 'complete', 'archived']).optional(), + type: z.enum(['release', 'experiment', 'permission', 'ops']).optional(), + name: z.string(), + key: z.string(), + description: z.string().optional(), + _createdBy: z.string().optional(), + createdAt: z.string().datetime({ offset: true }), + updatedAt: z.string().datetime({ offset: true }), + prodTargetingUpdatedAt: z + .string() + .datetime({ offset: true }) + .optional(), + variations: z.array(Variation).optional(), + controlVariation: z.string(), + staticVariation: z.string().optional(), + variables: z.array(Variable).optional(), + tags: z.array(z.string()), + ldLink: z.string().optional(), + readonly: z.boolean(), + settings: FeatureSettings.partial().optional(), + sdkVisibility: FeatureSDKVisibility.optional(), + configurations: z.array(FeatureConfig.partial()).optional(), + latestUpdate: AuditLogEntity.optional(), + changeRequests: z + .array(z.object({}).partial().passthrough()) + .optional(), + staleness: FeatureStalenessEntity.optional(), + summary: FeatureSummary.partial().optional(), + }) + .passthrough() +const UpdateVariationDto = z + .object({ + key: z + .string() + .min(1) + .max(100) + .regex(/^[a-z0-9-_.]+$/), + name: z.string().min(1).max(100), + variables: z + .record( + z.union([ + z.string(), + z.number(), + z.boolean(), + z.array(z.any()), + z.object({}).partial().passthrough(), + ]), + ) + .optional(), + _id: z.string().optional(), + }) + .passthrough() +const UpdateFeatureSummaryDto = z + .object({ + maintainers: z.array(z.string()), + links: z.array(Link), + markdown: z.string(), + }) + .partial() + .passthrough() +export const UpdateFeatureDto = z + .object({ + key: z + .string() + .min(1) + .max(100) + .regex(/^[a-z0-9-_.]+$/), + name: z.string().min(1).max(100), + description: z.string().max(1000), + configurations: z.record(UpdateFeatureConfigDto), + variations: z.array(UpdateVariationDto), + staleness: z.object({}).partial().passthrough(), + summary: UpdateFeatureSummaryDto, + variables: z.array(FeatureVariableDto), + type: z.enum(['release', 'experiment', 'permission', 'ops']), + tags: z.array(z.string()), + controlVariation: z.string(), + settings: FeatureSettingsDto, + sdkVisibility: FeatureSDKVisibilityDto, + }) + .partial() + .passthrough() +// const UpdateFeatureStatusDto = z +// .object({ +// status: z.enum(['active', 'complete', 'archived']), +// staticVariation: z.string().optional(), +// }) +// .passthrough() +// const StaticConfiguration = z +// .object({ +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/) +// .optional(), +// name: z.string().min(1).max(100).optional(), +// description: z.string().max(1000).optional(), +// variables: z.object({}).partial().passthrough(), +// environments: z.object({}).partial().passthrough(), +// readonly: z.boolean(), +// type: z.enum(['release', 'experiment', 'permission', 'ops']).optional(), +// tags: z.array(z.string()).optional(), +// controlVariation: z.string().optional(), +// settings: FeatureSettingsDto.optional(), +// sdkVisibility: FeatureSDKVisibilityDto.optional(), +// staleness: z.object({}).partial().passthrough().optional(), +// summary: UpdateFeatureSummaryDto.optional(), +// }) +// .passthrough() +// const UpdateStaticConfigurationDto = z +// .object({ +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// name: z.string().min(1).max(100), +// description: z.string().max(1000), +// type: z.enum(['release', 'experiment', 'permission', 'ops']), +// tags: z.array(z.string()), +// controlVariation: z.string(), +// settings: FeatureSettingsDto, +// sdkVisibility: FeatureSDKVisibilityDto, +// staleness: z.object({}).partial().passthrough(), +// summary: UpdateFeatureSummaryDto, +// variables: z.object({}).partial().passthrough(), +// environments: z.object({}).partial().passthrough(), +// }) +// .partial() +// .passthrough() +// const LinkJiraIssueDto = z.object({ issueId: z.string() }).passthrough() +// const JiraIssueLink = z.object({ issueId: z.string() }).passthrough() +// const FeatureVariationDto = z +// .object({ +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// name: z.string().min(1).max(100), +// variables: z +// .record( +// z.union([ +// z.string(), +// z.number(), +// z.boolean(), +// z.array(z.any()), +// z.object({}).partial().passthrough(), +// ]), +// ) +// .optional(), +// }) +// .passthrough() +// const UpdateFeatureVariationDto = z +// .object({ +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// name: z.string().min(1).max(100), +// variables: z.record( +// z.union([ +// z.string(), +// z.number(), +// z.boolean(), +// z.array(z.any()), +// z.object({}).partial().passthrough(), +// ]), +// ), +// _id: z.string(), +// }) +// .partial() +// .passthrough() +// const FeatureDataPoint = z +// .object({ +// values: z.object({}).partial().passthrough(), +// date: z.string().datetime({ offset: true }), +// }) +// .passthrough() +// const ResultWithFeatureData = z +// .object({ evaluations: z.array(FeatureDataPoint) }) +// .passthrough() +// const ResultEvaluationsByHourDto = z +// .object({ +// result: ResultWithFeatureData, +// cached: z.boolean(), +// updatedAt: z.string().datetime({ offset: true }), +// }) +// .passthrough() +// const ProjectDataPoint = z +// .object({ date: z.string().datetime({ offset: true }), value: z.number() }) +// .passthrough() +// const ResultsWithProjectData = z +// .object({ evaluations: z.array(ProjectDataPoint) }) +// .passthrough() +// const ResultProjectEvaluationsByHourDto = z +// .object({ +// result: ResultsWithProjectData, +// cached: z.boolean(), +// updatedAt: z.string().datetime({ offset: true }), +// }) +// .passthrough() +// const ProjectUserProfile = z +// .object({ +// _id: z.string(), +// _project: z.string(), +// a0_user: z.string(), +// dvcUserId: z.string().nullish(), +// createdAt: z.string().datetime({ offset: true }), +// updatedAt: z.string().datetime({ offset: true }), +// }) +// .passthrough() +// const UpdateUserProfileDto = z +// .object({ dvcUserId: z.string().nullable() }) +// .partial() +// .passthrough() +// const AllowedValue = z +// .object({ label: z.string(), value: z.object({}).partial().passthrough() }) +// .passthrough() +// const EnumSchema = z +// .object({ +// allowedValues: z.array(AllowedValue), +// allowAdditionalValues: z.boolean(), +// }) +// .passthrough() +// const PropertySchema = z +// .object({ +// schemaType: z.enum(['enum', null]), +// required: z.boolean(), +// enumSchema: EnumSchema, +// }) +// .partial() +// .passthrough() +// const CreateCustomPropertyDto = z +// .object({ +// name: z.string().min(1).max(100), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// type: z.enum(['String', 'Boolean', 'Number']), +// propertyKey: z.string(), +// schema: PropertySchema.optional(), +// }) +// .passthrough() +// const CustomProperty = z +// .object({ +// name: z.string().min(1).max(100), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// _id: z.string(), +// _project: z.string(), +// _createdBy: z.string(), +// propertyKey: z.string(), +// type: z.enum(['String', 'Boolean', 'Number']), +// createdAt: z.string().datetime({ offset: true }), +// updatedAt: z.string().datetime({ offset: true }), +// schema: PropertySchema.optional(), +// hasUsage: z.boolean().optional(), +// }) +// .passthrough() +// const UpdateCustomPropertyDto = z +// .object({ +// name: z.string().min(1).max(100), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// propertyKey: z.string(), +// type: z.enum(['String', 'Boolean', 'Number']), +// schema: PropertySchema, +// }) +// .partial() +// .passthrough() +// const CreateMetricDto = z +// .object({ +// name: z.string().min(1).max(100), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// description: z.string().max(1000).optional(), +// event: z.string(), +// dimension: z.enum([ +// 'COUNT_PER_UNIQUE_USER', +// 'COUNT_PER_VARIABLE_EVALUATION', +// 'SUM_PER_UNIQUE_USER', +// 'AVERAGE_PER_UNIQUE_USER', +// 'TOTAL_AVERAGE', +// 'TOTAL_SUM', +// ]), +// optimize: z.enum(['increase', 'decrease']), +// }) +// .passthrough() +// const Metric = z +// .object({ +// name: z.string().min(1).max(100), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// description: z.string().max(1000).optional(), +// _id: z.string(), +// _project: z.string(), +// source: z +// .enum([ +// 'api', +// 'dashboard', +// 'importer', +// 'github.code_usages', +// 'github.pr_insights', +// 'gitlab.code_usages', +// 'gitlab.pr_insights', +// 'bitbucket.code_usages', +// 'bitbucket.pr_insights', +// 'terraform', +// 'cli', +// 'slack', +// 'mcp', +// ]) +// .optional(), +// event: z.string(), +// dimension: z.enum([ +// 'COUNT_PER_UNIQUE_USER', +// 'COUNT_PER_VARIABLE_EVALUATION', +// 'SUM_PER_UNIQUE_USER', +// 'AVERAGE_PER_UNIQUE_USER', +// 'TOTAL_AVERAGE', +// 'TOTAL_SUM', +// ]), +// optimize: z.enum(['increase', 'decrease']), +// createdAt: z.string().datetime({ offset: true }), +// updatedAt: z.string().datetime({ offset: true }), +// }) +// .passthrough() +// const UpdateMetricDto = z +// .object({ +// name: z.string().min(1).max(100), +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// description: z.string().max(1000), +// event: z.string(), +// dimension: z.enum([ +// 'COUNT_PER_UNIQUE_USER', +// 'COUNT_PER_VARIABLE_EVALUATION', +// 'SUM_PER_UNIQUE_USER', +// 'AVERAGE_PER_UNIQUE_USER', +// 'TOTAL_AVERAGE', +// 'TOTAL_SUM', +// ]), +// optimize: z.enum(['increase', 'decrease']), +// }) +// .partial() +// .passthrough() +// const VariationValues = z.object({}).partial().passthrough() +// const DataPoint = z +// .object({ +// date: z.string().datetime({ offset: true }), +// values: VariationValues, +// }) +// .passthrough() +// const VariationResult = z +// .object({ +// key: z.string(), +// name: z.string(), +// numerator: z.number(), +// denominator: z.number(), +// rate: z.number(), +// avgValue: z.number().optional(), +// totalValue: z.number().optional(), +// stdev: z.number().optional(), +// percentDifference: z.number().nullable(), +// chanceToBeatControl: z.number().nullable(), +// }) +// .passthrough() +// const Result = z +// .object({ +// dataSeries: z.array(DataPoint), +// variations: z.array(VariationResult), +// }) +// .passthrough() +// const MetricResult = z +// .object({ +// result: Result, +// cached: z.boolean(), +// updatedAt: z.string().datetime({ offset: true }), +// }) +// .passthrough() +// const MetricAssociation = z +// .object({ +// _project: z.string(), +// feature: Feature, +// metric: Metric, +// createdAt: z.string().datetime({ offset: true }), +// }) +// .passthrough() +// const CreateMetricAssociationDto = z +// .object({ metric: z.string(), feature: z.string() }) +// .passthrough() +// const UpdateOverrideDto = z +// .object({ environment: z.string(), variation: z.string() }) +// .passthrough() +// const Override = z +// .object({ +// _project: z.string(), +// _environment: z.string(), +// _feature: z.string(), +// _variation: z.string(), +// dvcUserId: z.string(), +// createdAt: z.number(), +// updatedAt: z.number(), +// a0_user: z.string().optional(), +// }) +// .passthrough() +// const FeatureOverride = z +// .object({ _environment: z.string(), _variation: z.string() }) +// .passthrough() +// const OverrideResponse = z +// .object({ overrides: z.array(FeatureOverride) }) +// .passthrough() +// const FeatureOverrides = z +// .object({ +// overrides: z.record(z.array(Override)), +// uniqueTeamMembers: z.number(), +// }) +// .passthrough() +// const UserOverride = z +// .object({ +// _feature: z.string(), +// featureName: z.string(), +// _environment: z.string(), +// environmentName: z.string(), +// _variation: z.string(), +// variationName: z.string(), +// }) +// .passthrough() +// const AudiencePatchAction = z +// .object({ +// values: z.object({}).partial().passthrough(), +// filterIndex: z.string(), +// }) +// .passthrough() +// const AudiencePatchInstructionsDto = z +// .object({ +// op: z.enum(['addFilterValues', 'removeFilterValues']), +// action: AudiencePatchAction, +// }) +// .passthrough() +// const AudiencePatchDto = z +// .object({ instructions: z.array(AudiencePatchInstructionsDto) }) +// .passthrough() +// const UpdateStalenessDto = z +// .object({ +// snoozedUntil: z.string(), +// disabled: z.boolean(), +// metaData: z.object({}).partial().passthrough(), +// }) +// .partial() +// .passthrough() +// const Reviewers = z.object({}).partial().passthrough() +// const ReviewReason = z.object({}).partial().passthrough() +// const FeatureDetails = z +// .object({ +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// name: z.string().min(1).max(100), +// id: z.string(), +// }) +// .passthrough() +// const FeatureChangeRequestSummary = z +// .object({ +// _id: z.string(), +// _project: z.string(), +// _feature: z.string(), +// status: z.enum([ +// 'draft', +// 'pending', +// 'approved', +// 'applied', +// 'rejected', +// 'cancelled', +// ]), +// operation: z.enum([ +// 'featureUpdate', +// 'featureStatusUpdate', +// 'featureStaticConfigurationUpdate', +// ]), +// description: z.string().optional(), +// reviewers: Reviewers, +// reviews: z.array(ReviewReason), +// _createdBy: z.string(), +// _updatedBy: z.string().optional(), +// createdAt: z.string().datetime({ offset: true }).optional(), +// updatedAt: z.string().datetime({ offset: true }).optional(), +// feature: FeatureDetails, +// }) +// .passthrough() +// const CreateFeatureChangeRequestDto = z +// .object({ +// path: z.string(), +// method: z.literal('PATCH'), +// body: z.object({}).partial().passthrough(), +// }) +// .passthrough() +// const FeatureChangeRequest = z +// .object({ +// _id: z.string(), +// _project: z.string(), +// _baseFeatureSnapshot: z.string(), +// _feature: z.string(), +// status: z.enum([ +// 'draft', +// 'pending', +// 'approved', +// 'applied', +// 'rejected', +// 'cancelled', +// ]), +// changes: z.array(z.object({}).partial().passthrough()).optional(), +// operation: z.enum([ +// 'featureUpdate', +// 'featureStatusUpdate', +// 'featureStaticConfigurationUpdate', +// ]), +// description: z.string().optional(), +// reviewers: Reviewers, +// reviews: z.array(ReviewReason), +// _createdBy: z.string(), +// _updatedBy: z.string().optional(), +// createdAt: z.string().datetime({ offset: true }).optional(), +// updatedAt: z.string().datetime({ offset: true }).optional(), +// }) +// .passthrough() +// const SubmitFeatureChangeRequestDto = z +// .object({ +// description: z.string().max(1000), +// reviewers: z.array(z.string()), +// }) +// .passthrough() +// const ReviewFeatureChangeRequestDto = z +// .object({ action: z.enum(['approved', 'rejected']), comment: z.string() }) +// .passthrough() +// const ApplyFeatureChangeRequestDto = z +// .object({ description: z.string().max(1000), action: z.literal('applied') }) +// .passthrough() +// const CreateWebhookDto = z +// .object({ +// name: z.string().min(1).max(100), +// description: z.string().max(1000).optional(), +// outputFormat: z.object({}).partial().passthrough().optional(), +// _feature: z.string().optional(), +// _environments: z.array(z.string()).optional(), +// events: z.array(z.string()), +// url: z.string(), +// }) +// .passthrough() +// const Webhook = z +// .object({ +// name: z.string().min(1).max(100), +// description: z.string().max(1000).optional(), +// _id: z.string(), +// _project: z.string(), +// _feature: z.string().optional(), +// _environments: z.array(z.string()), +// url: z.string(), +// events: z.array(z.string()), +// source: z +// .enum([ +// 'api', +// 'dashboard', +// 'importer', +// 'github.code_usages', +// 'github.pr_insights', +// 'gitlab.code_usages', +// 'gitlab.pr_insights', +// 'bitbucket.code_usages', +// 'bitbucket.pr_insights', +// 'terraform', +// 'cli', +// 'slack', +// 'mcp', +// ]) +// .optional(), +// createdBy: z.string().optional(), +// createdAt: z.string().datetime({ offset: true }), +// updatedAt: z.string().datetime({ offset: true }), +// outputFormat: z.object({}).partial().passthrough().optional(), +// _slackIntegration: z.string().optional(), +// }) +// .passthrough() +// const UpdateWebhookDto = z +// .object({ +// name: z.string().min(1).max(100).optional(), +// description: z.string().max(1000).optional(), +// _feature: z.string(), +// _environments: z.array(z.string()), +// events: z.array(z.string()).optional(), +// url: z.string().optional(), +// outputFormat: z.object({}).partial().passthrough().optional(), +// }) +// .passthrough() +// const CreateDynatraceIntegrationDto = z +// .object({ +// dynatraceEnvironmentId: z.string(), +// accessToken: z.string(), +// environmentUrl: z.string(), +// }) +// .passthrough() +// const DynatraceEnvironment = z +// .object({ +// dynatraceEnvironmentId: z.string(), +// accessToken: z.string(), +// environmentUrl: z.string(), +// projects: z.array(Project), +// }) +// .passthrough() +// const DynatraceIntegration = z +// .object({ environments: z.array(DynatraceEnvironment) }) +// .passthrough() +// const ReassociateVariableDto = z +// .object({ +// key: z +// .string() +// .min(1) +// .max(100) +// .regex(/^[a-z0-9-_.]+$/), +// }) +// .passthrough() + +// export const schemas = { +// EdgeDBSettingsDTO, +// ColorSettingsDTO, +// OptInSettingsDTO, +// SDKTypeVisibilitySettingsDTO, +// LifeCycleSettingsDTO, +// ObfuscationSettingsDTO, +// DynatraceProjectSettingsDTO, +// ProjectSettingsDTO, +// CreateProjectDto, +// EdgeDBSettings, +// ColorSettings, +// OptInSettings, +// SDKTypeVisibilitySettings, +// LifeCycleSettings, +// ObfuscationSettings, +// FeatureApprovalWorkflowSettings, +// ReleasedStalenessSettings, +// UnmodifiedLongStalenessSettings, +// UnmodifiedShortStalenessSettings, +// UnusedStalenessSettings, +// StalenessEmailSettings, +// StalenessSettings, +// DynatraceProjectSettings, +// ProjectSettings, +// VercelEdgeConfigConnection, +// Project, +// BadRequestErrorResponse, +// ConflictErrorResponse, +// NotFoundErrorResponse, +// UpdateProjectDto, +// CannotDeleteLastItemErrorResponse, +// UpdateProjectSettingsDto, +// FeatureApprovalWorkflowDTO, +// ReleasedStalenessDTO, +// UnmodifiedLongStalenessDTO, +// UnmodifiedShortStalenessDTO, +// UnusedStalenessDTO, +// EmailSettingsDTO, +// StalenessSettingsDTO, +// ProtectedProjectSettingsDto, +// UpdateProtectedProjectSettingsDto, +// FeatureStalenessEntity, +// EnvironmentSettings, +// CreateEnvironmentDto, +// APIKey, +// SDKKeys, +// Environment, +// UpdateEnvironmentDto, +// GenerateSdkTokensDto, +// AllFilter, +// OptInFilter, +// UserFilter, +// UserCountryFilter, +// UserAppVersionFilter, +// UserPlatformVersionFilter, +// UserCustomFilter, +// AudienceOperator, +// CreateAudienceDto, +// Audience, +// UpdateAudienceDto, +// AudienceEnvironments, +// AudienceFeature, +// AudienceUsage, +// VariableValidationEntity, +// CreateVariableDto, +// Variable, +// UpdateVariableDto, +// PreconditionFailedErrorResponse, +// UpdateVariableStatusDto, +// RolloutStage, +// Rollout, +// TargetDistribution, +// AudienceMatchFilter, +// AudienceOperatorWithAudienceMatchFilter, +// TargetAudience, +// UpdateTargetDto, +// UpdateFeatureConfigDto, +// CreateVariationDto, +// FeatureSettingsDto, +// FeatureSDKVisibilityDto, +// CreateFeatureDto, +// Variation, +// FeatureSettings, +// FeatureSDKVisibility, +// Target, +// FeatureConfig, +// AuditLogEntity, +// FeatureStaleness, +// Link, +// FeatureSummary, +// Feature, +// UpdateVariationDto, +// UpdateFeatureSummaryDto, +// UpdateFeatureDto, +// UpdateFeatureStatusDto, +// StaticConfiguration, +// UpdateStaticConfigurationDto, +// LinkJiraIssueDto, +// JiraIssueLink, +// FeatureVariationDto, +// UpdateFeatureVariationDto, +// FeatureDataPoint, +// ResultWithFeatureData, +// ResultEvaluationsByHourDto, +// ProjectDataPoint, +// ResultsWithProjectData, +// ResultProjectEvaluationsByHourDto, +// ProjectUserProfile, +// UpdateUserProfileDto, +// AllowedValue, +// EnumSchema, +// PropertySchema, +// CreateCustomPropertyDto, +// CustomProperty, +// UpdateCustomPropertyDto, +// CreateMetricDto, +// Metric, +// UpdateMetricDto, +// VariationValues, +// DataPoint, +// VariationResult, +// Result, +// MetricResult, +// MetricAssociation, +// CreateMetricAssociationDto, +// UpdateOverrideDto, +// Override, +// FeatureOverride, +// OverrideResponse, +// FeatureOverrides, +// UserOverride, +// AudiencePatchAction, +// AudiencePatchInstructionsDto, +// AudiencePatchDto, +// UpdateStalenessDto, +// Reviewers, +// ReviewReason, +// FeatureDetails, +// FeatureChangeRequestSummary, +// CreateFeatureChangeRequestDto, +// FeatureChangeRequest, +// SubmitFeatureChangeRequestDto, +// ReviewFeatureChangeRequestDto, +// ApplyFeatureChangeRequestDto, +// CreateWebhookDto, +// Webhook, +// UpdateWebhookDto, +// CreateDynatraceIntegrationDto, +// DynatraceEnvironment, +// DynatraceIntegration, +// ReassociateVariableDto, +// } + +// const endpoints = makeApi([ +// { +// method: 'post', +// path: '/v1/integrations/dynatrace', +// alias: 'DynatraceIntegrationController_createIntegration', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: CreateDynatraceIntegrationDto, +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 400, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/integrations/dynatrace', +// alias: 'DynatraceIntegrationController_getIntegrations', +// requestFormat: 'json', +// response: DynatraceIntegration, +// errors: [ +// { +// status: 400, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/integrations/dynatrace/:dynatraceEnvironmentId', +// alias: 'DynatraceIntegrationController_deleteEnvironment', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'dynatraceEnvironmentId', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 400, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/integrations/jira/:token', +// alias: 'JiraIntegrationController_remove', +// description: `DEPRECATED - Not recommended to be used. Use /integrations/jira/organization/:token or /integrations/jira/project/:token instead.`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'token', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// }, +// { +// method: 'delete', +// path: '/v1/integrations/jira/organization/:token', +// alias: 'JiraIntegrationController_removeOrganizationConnection', +// description: `Remove the Jira integration configuration for an organization. This will remove the integration for an organization wide connection, but not project connections.`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'token', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 403, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/integrations/jira/project/:token', +// alias: 'JiraIntegrationController_removeProjectConnection', +// description: `Remove a specific project`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'token', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 403, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v1/projects', +// alias: 'ProjectsController_create', +// description: `Creates a new project within the authed organization. +// The project key must be unique within the organization. +// If this is called in an Organization that has permissions controlled via an external IdP (https://docs.devcycle.com/platform/security-and-guardrails/permissions#full-role-based-access-control-project-level-roles--enterprise-only) - then no users will have permission to access this project.`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: CreateProjectDto, +// }, +// ], +// response: Project, +// errors: [ +// { +// status: 400, +// description: `Invalid request - missing or invalid properties`, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 409, +// description: `Project key already exists`, +// schema: ConflictErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects', +// alias: 'ProjectsController_findAll', +// description: `Lists all projects that the current API Token has permission to view.`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'page', +// type: 'Query', +// schema: z.number().gte(1).optional().default(1), +// }, +// { +// name: 'perPage', +// type: 'Query', +// schema: z.number().gte(1).lte(1000).optional().default(100), +// }, +// { +// name: 'sortBy', +// type: 'Query', +// schema: z +// .enum([ +// 'createdAt', +// 'updatedAt', +// 'name', +// 'key', +// 'createdBy', +// 'propertyKey', +// ]) +// .optional() +// .default('createdAt'), +// }, +// { +// name: 'sortOrder', +// type: 'Query', +// schema: z.enum(['asc', 'desc']).optional().default('desc'), +// }, +// { +// name: 'search', +// type: 'Query', +// schema: z.string().min(3).optional(), +// }, +// { +// name: 'createdBy', +// type: 'Query', +// schema: z.string().optional(), +// }, +// ], +// response: z.array(Project), +// errors: [ +// { +// status: 400, +// description: `Invalid request - missing or invalid properties`, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:key', +// alias: 'ProjectsController_findOne', +// description: `Get a Project by ID or key.`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Project, +// errors: [ +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// description: `Project does not exist by key or ID. Keys are able to be changed so try switching to ID to have a consistent value that cannot be changed.This can also be returned if the current token does not have permission to view the project.`, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:key', +// alias: 'ProjectsController_update', +// description: `Update a Project by ID or key. Certain facets of the project settings require additional permissions to update.`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateProjectDto, +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Project, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/projects/:key', +// alias: 'ProjectsController_remove', +// description: `Delete a Project by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// description: `Project not found.This can also be returned if the current token does not have permission to view the project.`, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 405, +// description: `Cannot delete the last project in an organization. Please contact support to delete the organization.`, +// schema: CannotDeleteLastItemErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:key/settings', +// alias: 'ProjectsController_updateSettings', +// description: `Update a subset of settings for a Project that only requires publisher permissions`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateProjectSettingsDto, +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Project, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:key/settings/protected', +// alias: 'ProjectsController_updateProtectedSettings', +// description: `Update the Protect Settings for a Project by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateProtectedProjectSettingsDto, +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Project, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:key/staleness', +// alias: 'ProjectsController_getStaleness', +// description: `Get all stale Features for a Project`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'page', +// type: 'Query', +// schema: z.number().gte(1).optional().default(1), +// }, +// { +// name: 'perPage', +// type: 'Query', +// schema: z.number().gte(1).lte(1000).optional().default(100), +// }, +// { +// name: 'sortBy', +// type: 'Query', +// schema: z +// .enum([ +// 'createdAt', +// 'updatedAt', +// 'name', +// 'key', +// 'createdBy', +// 'propertyKey', +// ]) +// .optional() +// .default('createdAt'), +// }, +// { +// name: 'sortOrder', +// type: 'Query', +// schema: z.enum(['asc', 'desc']).optional().default('desc'), +// }, +// { +// name: 'search', +// type: 'Query', +// schema: z.string().min(3).optional(), +// }, +// { +// name: 'createdBy', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'includeSilenced', +// type: 'Query', +// schema: z.boolean().optional().default(false), +// }, +// ], +// response: z.array(FeatureStalenessEntity), +// errors: [ +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// description: `Project not found. This can also be returned if the current token does not have permission to view the project.`, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v1/projects/:project/audiences', +// alias: 'AudiencesController_create', +// description: `Create a new Audience`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: CreateAudienceDto, +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Audience, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/audiences', +// alias: 'AudiencesController_findAll', +// description: `List Audiences`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'page', +// type: 'Query', +// schema: z.number().gte(1).optional().default(1), +// }, +// { +// name: 'perPage', +// type: 'Query', +// schema: z.number().gte(1).lte(1000).optional().default(100), +// }, +// { +// name: 'sortBy', +// type: 'Query', +// schema: z +// .enum([ +// 'createdAt', +// 'updatedAt', +// 'name', +// 'key', +// 'createdBy', +// 'propertyKey', +// ]) +// .optional() +// .default('createdAt'), +// }, +// { +// name: 'sortOrder', +// type: 'Query', +// schema: z.enum(['asc', 'desc']).optional().default('desc'), +// }, +// { +// name: 'search', +// type: 'Query', +// schema: z.string().min(3).optional(), +// }, +// { +// name: 'createdBy', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'includeUsage', +// type: 'Query', +// schema: z.boolean().optional(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(Audience), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/audiences/:key', +// alias: 'AudiencesController_findOne', +// description: `Get an Audience by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Audience, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:project/audiences/:key', +// alias: 'AudiencesController_update', +// description: `Update an Audience by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateAudienceDto, +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Audience, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/projects/:project/audiences/:key', +// alias: 'AudiencesController_remove', +// description: `Delete an Audience by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 412, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/audiences/:key/usage', +// alias: 'AudiencesController_findUsages', +// description: `Get the direct usages of an Audiences Usage by Features OR other Audiences by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: AudienceUsage, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v1/projects/:project/customProperties', +// alias: 'CustomPropertiesController_create', +// description: `Create a new Custom Property`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: CreateCustomPropertyDto, +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: CustomProperty, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/customProperties', +// alias: 'CustomPropertiesController_findAll', +// description: `List Custom Properties`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'page', +// type: 'Query', +// schema: z.number().gte(1).optional().default(1), +// }, +// { +// name: 'perPage', +// type: 'Query', +// schema: z.number().gte(1).lte(1000).optional().default(100), +// }, +// { +// name: 'sortBy', +// type: 'Query', +// schema: z +// .enum([ +// 'createdAt', +// 'updatedAt', +// 'name', +// 'key', +// 'createdBy', +// 'propertyKey', +// ]) +// .optional() +// .default('createdAt'), +// }, +// { +// name: 'sortOrder', +// type: 'Query', +// schema: z.enum(['asc', 'desc']).optional().default('desc'), +// }, +// { +// name: 'search', +// type: 'Query', +// schema: z.string().min(3).optional(), +// }, +// { +// name: 'type', +// type: 'Query', +// schema: z.enum(['String', 'Boolean', 'Number']).optional(), +// }, +// { +// name: 'includeUsage', +// type: 'Query', +// schema: z.boolean().optional(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(CustomProperty), +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/customProperties/:key', +// alias: 'CustomPropertiesController_findOne', +// description: `Get a Custom Property by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: CustomProperty, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:project/customProperties/:key', +// alias: 'CustomPropertiesController_update', +// description: `Update an Custom Property by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateCustomPropertyDto, +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: CustomProperty, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/projects/:project/customProperties/:key', +// alias: 'CustomPropertiesController_remove', +// description: `Delete an Custom Property by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v1/projects/:project/environments', +// alias: 'EnvironmentsController_create', +// description: `Create a new environment for a project. The environment key must be unique within the project. Multiple environments can share a type. +// Creating an environment will auto-generate a set of SDK Keys for the various types of SDKs. +// When permissions are enabled for the organization, the token must have Publisher permissions for the environment to be created.`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: CreateEnvironmentDto, +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Environment, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/environments', +// alias: 'EnvironmentsController_findAll', +// description: `List all environments for a project. If a token does not have permission to view protected environments the environments will be filtered to only show non-protected environments SDK Keys for security.`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'page', +// type: 'Query', +// schema: z.number().gte(1).optional().default(1), +// }, +// { +// name: 'perPage', +// type: 'Query', +// schema: z.number().gte(1).lte(1000).optional().default(100), +// }, +// { +// name: 'sortBy', +// type: 'Query', +// schema: z +// .enum([ +// 'createdAt', +// 'updatedAt', +// 'name', +// 'key', +// 'createdBy', +// 'propertyKey', +// ]) +// .optional() +// .default('createdAt'), +// }, +// { +// name: 'sortOrder', +// type: 'Query', +// schema: z.enum(['asc', 'desc']).optional().default('desc'), +// }, +// { +// name: 'search', +// type: 'Query', +// schema: z.string().min(3).optional(), +// }, +// { +// name: 'createdBy', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(Environment), +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v1/projects/:project/environments/:environment/sdk-keys', +// alias: 'SdkKeysController_generate', +// description: `Generate new SDK keys for an environment, for any or all of the SDK types. This is the expected and recommended way to rotate SDK keys. Adding a new SDK key will not invalidate existing SDK keys. +// Generating new keys is restricted for protected environments to those with Publisher permissions`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: GenerateSdkTokensDto, +// }, +// { +// name: 'environment', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Environment, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/projects/:project/environments/:environment/sdk-keys/:key', +// alias: 'SdkKeysController_invalidate', +// description: `This will invalidate all configs associated with a given key. This is an instantaneous change and all SDKs using this key will stop working immediately. This is the expected and recommended way to rotate SDK keys.`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'environment', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 405, +// schema: CannotDeleteLastItemErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/environments/:key', +// alias: 'EnvironmentsController_findOne', +// description: `Returns the environment; if the token does not have permission to view protected environments, the environment will be filtered to only show non-protected SDK Keys for security.`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Environment, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:project/environments/:key', +// alias: 'EnvironmentsController_update', +// description: `Update an environment by ID or key. The environment key (if edited) must be unique within the project. If permissions are enabled, changing a protected environment type requires Publisher permissions`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateEnvironmentDto, +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Environment, +// errors: [ +// { +// status: 400, +// description: `Invalid request body`, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// description: `Environment not found`, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 409, +// description: `Environment key already exists, cannot rename an environment to an existing one.`, +// schema: ConflictErrorResponse, +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/projects/:project/environments/:key', +// alias: 'EnvironmentsController_remove', +// description: `Delete an Environment by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 405, +// schema: CannotDeleteLastItemErrorResponse, +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v1/projects/:project/features', +// alias: 'FeaturesController_create', +// description: `Create a new Feature`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: CreateFeatureDto, +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Feature, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/features', +// alias: 'FeaturesController_findAll', +// description: `List Features`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'page', +// type: 'Query', +// schema: z.number().gte(1).optional().default(1), +// }, +// { +// name: 'perPage', +// type: 'Query', +// schema: z.number().gte(1).lte(1000).optional().default(100), +// }, +// { +// name: 'sortBy', +// type: 'Query', +// schema: z +// .enum([ +// 'createdAt', +// 'updatedAt', +// 'name', +// 'key', +// 'createdBy', +// 'propertyKey', +// ]) +// .optional() +// .default('createdAt'), +// }, +// { +// name: 'sortOrder', +// type: 'Query', +// schema: z.enum(['asc', 'desc']).optional().default('desc'), +// }, +// { +// name: 'search', +// type: 'Query', +// schema: z.string().min(3).optional(), +// }, +// { +// name: 'createdBy', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'type', +// type: 'Query', +// schema: z +// .enum(['release', 'experiment', 'permission', 'ops']) +// .optional(), +// }, +// { +// name: 'status', +// type: 'Query', +// schema: z.enum(['active', 'complete', 'archived']).optional(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(Feature), +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/features/:feature', +// alias: 'FeaturesController_findOne', +// description: `Get a Feature by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Feature, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:project/features/:feature', +// alias: 'FeaturesController_update', +// description: `Update a Feature by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateFeatureDto, +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Feature, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/projects/:project/features/:feature', +// alias: 'FeaturesController_remove', +// description: `Delete a Feature by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'deleteVariables', +// type: 'Query', +// schema: z.boolean().optional(), +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/features/:feature/audit', +// alias: 'AuditLogController_findAll', +// description: `Get Audit Log For Feature`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'page', +// type: 'Query', +// schema: z.number().gte(1).optional().default(1), +// }, +// { +// name: 'perPage', +// type: 'Query', +// schema: z.number().gte(1).lte(1000).optional().default(100), +// }, +// { +// name: 'sortBy', +// type: 'Query', +// schema: z +// .enum([ +// 'createdAt', +// 'updatedAt', +// 'name', +// 'key', +// 'createdBy', +// 'propertyKey', +// ]) +// .optional() +// .default('createdAt'), +// }, +// { +// name: 'sortOrder', +// type: 'Query', +// schema: z.enum(['asc', 'desc']).optional().default('desc'), +// }, +// { +// name: 'environment', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'a0_user', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'startDate', +// type: 'Query', +// schema: z.string().datetime({ offset: true }).optional(), +// }, +// { +// name: 'endDate', +// type: 'Query', +// schema: z.string().datetime({ offset: true }).optional(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(AuditLogEntity), +// errors: [ +// { +// status: 400, +// schema: z.void(), +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/features/:feature/configurations', +// alias: 'FeatureConfigsController_findAll', +// description: `List Feature configurations for all environments or by environment key or ID`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'environment', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(FeatureConfig), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:project/features/:feature/configurations', +// alias: 'FeatureConfigsController_update', +// description: `Update a Feature configuration by environment key or ID`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateFeatureConfigDto, +// }, +// { +// name: 'environment', +// type: 'Query', +// schema: z.string(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: FeatureConfig, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v1/projects/:project/features/:feature/integrations/jira/issues', +// alias: 'FeaturesController_linkIssue', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: z.object({ issueId: z.string() }).passthrough(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.object({ issueId: z.string() }).passthrough(), +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/features/:feature/integrations/jira/issues', +// alias: 'FeaturesController_findAllLinkedIssues', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(JiraIssueLink), +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/projects/:project/features/:feature/integrations/jira/issues/:issue_id', +// alias: 'FeaturesController_removeLinkedIssue', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'issue_id', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/features/:feature/overrides', +// alias: 'OverridesController_findOverridesForFeature', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'addMetadata', +// type: 'Query', +// schema: z.boolean().optional(), +// }, +// { +// name: 'environment', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: FeatureOverrides, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'put', +// path: '/v1/projects/:project/features/:feature/overrides/current', +// alias: 'OverridesController_updateFeatureOverride', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateOverrideDto, +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Override, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/features/:feature/overrides/current', +// alias: 'OverridesController_findOne', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: OverrideResponse, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/projects/:project/features/:feature/overrides/current', +// alias: 'OverridesController_deleteOverridesForFeature', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'environment', +// type: 'Query', +// schema: z.string(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/features/:feature/results/total-evaluations', +// alias: 'ResultsController_getTotalEvaluationsPerHourByFeature', +// description: `Fetch total variable evaluations per hour for a feature`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'startDate', +// type: 'Query', +// schema: z.number().optional(), +// }, +// { +// name: 'endDate', +// type: 'Query', +// schema: z.number().optional(), +// }, +// { +// name: 'platform', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'variable', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'environment', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'period', +// type: 'Query', +// schema: z.enum(['day', 'hour', 'month']).optional(), +// }, +// { +// name: 'sdkType', +// type: 'Query', +// schema: z +// .enum(['client', 'server', 'mobile', 'api']) +// .optional(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: ResultEvaluationsByHourDto, +// errors: [ +// { +// status: 400, +// schema: z.void(), +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/features/:feature/static-configuration', +// alias: 'FeaturesController_findStaticConfiguration', +// description: `Get a completed Feature's static configuration`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: StaticConfiguration, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:project/features/:feature/static-configuration', +// alias: 'FeaturesController_updateStaticConfiguration', +// description: `Update a completed Feature's static configuration`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateStaticConfigurationDto, +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: StaticConfiguration, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:project/features/:feature/status', +// alias: 'FeaturesController_updateStatus', +// description: `Update a Feature's status by key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateFeatureStatusDto, +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Feature, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v1/projects/:project/features/:feature/variations', +// alias: 'VariationsController_create', +// description: `Create a new variation within a Feature`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: FeatureVariationDto, +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Feature, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/features/:feature/variations', +// alias: 'VariationsController_findAll', +// description: `Get a list of variations for a feature`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(Variation), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/features/:feature/variations/:key', +// alias: 'VariationsController_findOne', +// description: `Get a variation by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Variation, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:project/features/:feature/variations/:key', +// alias: 'VariationsController_update', +// description: `Update a variation by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateFeatureVariationDto, +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Feature, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v1/projects/:project/features/multiple', +// alias: 'FeaturesController_createMultiple', +// description: `Create multiple new Features`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: z.array(z.string()), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(Feature), +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/metric-associations', +// alias: 'MetricAssociationsController_findAll', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'metric', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'feature', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(MetricAssociation), +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v1/projects/:project/metric-associations', +// alias: 'MetricAssociationsController_create', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: CreateMetricAssociationDto, +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: MetricAssociation, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/projects/:project/metric-associations', +// alias: 'MetricAssociationsController_remove', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'metric', +// type: 'Query', +// schema: z.string(), +// }, +// { +// name: 'feature', +// type: 'Query', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v1/projects/:project/metrics', +// alias: 'MetricsController_create', +// description: `Create a new Metric`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: CreateMetricDto, +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Metric, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/metrics', +// alias: 'MetricsController_findAll', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'page', +// type: 'Query', +// schema: z.number().gte(1).optional().default(1), +// }, +// { +// name: 'perPage', +// type: 'Query', +// schema: z.number().gte(1).lte(1000).optional().default(100), +// }, +// { +// name: 'sortBy', +// type: 'Query', +// schema: z +// .enum([ +// 'createdAt', +// 'updatedAt', +// 'name', +// 'key', +// 'createdBy', +// 'propertyKey', +// ]) +// .optional() +// .default('createdAt'), +// }, +// { +// name: 'sortOrder', +// type: 'Query', +// schema: z.enum(['asc', 'desc']).optional().default('desc'), +// }, +// { +// name: 'search', +// type: 'Query', +// schema: z.string().min(3).optional(), +// }, +// { +// name: 'dimension', +// type: 'Query', +// schema: z +// .enum([ +// 'COUNT_PER_UNIQUE_USER', +// 'COUNT_PER_VARIABLE_EVALUATION', +// 'SUM_PER_UNIQUE_USER', +// 'AVERAGE_PER_UNIQUE_USER', +// 'TOTAL_AVERAGE', +// 'TOTAL_SUM', +// ]) +// .optional(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(Metric), +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/metrics/:key', +// alias: 'MetricsController_findOne', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Metric, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:project/metrics/:key', +// alias: 'MetricsController_update', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateMetricDto, +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Metric, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/projects/:project/metrics/:key', +// alias: 'MetricsController_remove', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/metrics/:key/results', +// alias: 'MetricsController_fetchResults', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'feature', +// type: 'Query', +// schema: z.string(), +// }, +// { +// name: 'environment', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'startDate', +// type: 'Query', +// schema: z.string().datetime({ offset: true }), +// }, +// { +// name: 'endDate', +// type: 'Query', +// schema: z.string().datetime({ offset: true }), +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: MetricResult, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/overrides/current', +// alias: 'OverridesController_findOverridesForProject', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(UserOverride), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/projects/:project/overrides/current', +// alias: 'OverridesController_deleteOverridesForProject', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/results/evaluations', +// alias: 'ResultsController_getEvaluationsPerHourByProject', +// description: `Fetch unique user variable evaluations per hour for a project`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'startDate', +// type: 'Query', +// schema: z.number().optional(), +// }, +// { +// name: 'endDate', +// type: 'Query', +// schema: z.number().optional(), +// }, +// { +// name: 'environment', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'period', +// type: 'Query', +// schema: z.enum(['day', 'hour', 'month']).optional(), +// }, +// { +// name: 'sdkType', +// type: 'Query', +// schema: z +// .enum(['client', 'server', 'mobile', 'api']) +// .optional(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: ResultProjectEvaluationsByHourDto, +// errors: [ +// { +// status: 400, +// schema: z.void(), +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/results/total-evaluations', +// alias: 'ResultsController_getTotalEvaluationsPerHourByProject', +// description: `Fetch total variable evaluations per hour for a project`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'startDate', +// type: 'Query', +// schema: z.number().optional(), +// }, +// { +// name: 'endDate', +// type: 'Query', +// schema: z.number().optional(), +// }, +// { +// name: 'environment', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'period', +// type: 'Query', +// schema: z.enum(['day', 'hour', 'month']).optional(), +// }, +// { +// name: 'sdkType', +// type: 'Query', +// schema: z +// .enum(['client', 'server', 'mobile', 'api']) +// .optional(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: ResultProjectEvaluationsByHourDto, +// errors: [ +// { +// status: 400, +// schema: z.void(), +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/test-metric-results', +// alias: 'TestMetricResultsController_fetch', +// description: `Fetch metric results with the given parameters`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'feature', +// type: 'Query', +// schema: z.string(), +// }, +// { +// name: 'control', +// type: 'Query', +// schema: z.string(), +// }, +// { +// name: 'optimize', +// type: 'Query', +// schema: z.enum(['increase', 'decrease']), +// }, +// { +// name: 'environment', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'event', +// type: 'Query', +// schema: z.string(), +// }, +// { +// name: 'dimension', +// type: 'Query', +// schema: z.enum([ +// 'COUNT_PER_UNIQUE_USER', +// 'COUNT_PER_VARIABLE_EVALUATION', +// 'SUM_PER_UNIQUE_USER', +// 'AVERAGE_PER_UNIQUE_USER', +// 'TOTAL_AVERAGE', +// 'TOTAL_SUM', +// ]), +// }, +// { +// name: 'startDate', +// type: 'Query', +// schema: z.string().datetime({ offset: true }), +// }, +// { +// name: 'endDate', +// type: 'Query', +// schema: z.string().datetime({ offset: true }), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: MetricResult, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/userProfile/current', +// alias: 'UserProfilesController_findAll', +// description: `Get User Profile for the authenticated User in the specified Project`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: ProjectUserProfile, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:project/userProfile/current', +// alias: 'UserProfilesController_createOrUpdate', +// description: `Create or Update a User Profile for Overrides`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: z +// .object({ dvcUserId: z.string().nullable() }) +// .partial() +// .passthrough(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: ProjectUserProfile, +// errors: [ +// { +// status: 400, +// schema: z.void(), +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 409, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v1/projects/:project/variables', +// alias: 'VariablesController_create', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: CreateVariableDto, +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Variable, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/variables', +// alias: 'VariablesController_findAll', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'page', +// type: 'Query', +// schema: z.number().gte(1).optional().default(1), +// }, +// { +// name: 'perPage', +// type: 'Query', +// schema: z.number().gte(1).lte(1000).optional().default(100), +// }, +// { +// name: 'sortBy', +// type: 'Query', +// schema: z +// .enum([ +// 'createdAt', +// 'updatedAt', +// 'name', +// 'key', +// 'createdBy', +// 'propertyKey', +// ]) +// .optional() +// .default('createdAt'), +// }, +// { +// name: 'sortOrder', +// type: 'Query', +// schema: z.enum(['asc', 'desc']).optional().default('desc'), +// }, +// { +// name: 'search', +// type: 'Query', +// schema: z.string().min(3).optional(), +// }, +// { +// name: 'feature', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'type', +// type: 'Query', +// schema: z +// .enum(['String', 'Boolean', 'Number', 'JSON']) +// .optional(), +// }, +// { +// name: 'status', +// type: 'Query', +// schema: z.enum(['active', 'archived']).optional(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(Variable), +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/variables/:key', +// alias: 'VariablesController_findOne', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Variable, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:project/variables/:key', +// alias: 'VariablesController_update', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateVariableDto, +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Variable, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/projects/:project/variables/:key', +// alias: 'VariablesController_remove', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:project/variables/:key/status', +// alias: 'VariablesController_updateStatus', +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateVariableStatusDto, +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Variable, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v1/projects/:project/webhooks', +// alias: 'WebhooksController_create', +// description: `Create a new Webhook`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: CreateWebhookDto, +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Webhook, +// errors: [ +// { +// status: 400, +// schema: z.void(), +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 409, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/webhooks', +// alias: 'WebhooksController_findAll', +// description: `List Webhooks`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'page', +// type: 'Query', +// schema: z.number().gte(1).optional().default(1), +// }, +// { +// name: 'perPage', +// type: 'Query', +// schema: z.number().gte(1).lte(1000).optional().default(100), +// }, +// { +// name: 'sortBy', +// type: 'Query', +// schema: z +// .enum([ +// 'createdAt', +// 'updatedAt', +// 'name', +// 'key', +// 'createdBy', +// 'propertyKey', +// ]) +// .optional() +// .default('createdAt'), +// }, +// { +// name: 'sortOrder', +// type: 'Query', +// schema: z.enum(['asc', 'desc']).optional().default('desc'), +// }, +// { +// name: 'search', +// type: 'Query', +// schema: z.string().min(3).optional(), +// }, +// { +// name: 'createdBy', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(Webhook), +// errors: [ +// { +// status: 400, +// schema: z.void(), +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/projects/:project/webhooks/:id', +// alias: 'WebhooksController_update', +// description: `Update a Webhook`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateWebhookDto, +// }, +// { +// name: 'id', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Webhook, +// errors: [ +// { +// status: 400, +// schema: z.void(), +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v1/projects/:project/webhooks/:id', +// alias: 'WebhooksController_findOne', +// description: `Get a webhook by ID`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'id', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Webhook, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'delete', +// path: '/v1/projects/:project/webhooks/:id', +// alias: 'WebhooksController_remove', +// description: `Delete a webhook by ID`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'id', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Webhook, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v1/semantic/projects/:project/audiences/:key', +// alias: 'SemanticPatchController_semanticUpdate', +// description: `Semantic Patch Update an Audience by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: AudiencePatchDto, +// }, +// { +// name: 'key', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v2/projects/:project/change-requests', +// alias: 'ProjectChangeRequestsController_getFeatureChangeRequests', +// description: `Get a list of Feature Change Requests for a Project`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'page', +// type: 'Query', +// schema: z.number().gte(1).optional().default(1), +// }, +// { +// name: 'perPage', +// type: 'Query', +// schema: z.number().gte(1).lte(1000).optional().default(100), +// }, +// { +// name: 'sortBy', +// type: 'Query', +// schema: z +// .enum([ +// 'createdAt', +// 'updatedAt', +// 'name', +// 'key', +// 'createdBy', +// 'propertyKey', +// ]) +// .optional() +// .default('createdAt'), +// }, +// { +// name: 'sortOrder', +// type: 'Query', +// schema: z.enum(['asc', 'desc']).optional().default('desc'), +// }, +// { +// name: 'search', +// type: 'Query', +// schema: z.string().min(3).optional(), +// }, +// { +// name: 'createdBy', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'status', +// type: 'Query', +// schema: z +// .enum([ +// 'draft', +// 'pending', +// 'approved', +// 'applied', +// 'rejected', +// 'cancelled', +// ]) +// .optional(), +// }, +// { +// name: 'reviewer', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(FeatureChangeRequestSummary), +// errors: [ +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 405, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v2/projects/:project/features', +// alias: 'FeaturesController_create', +// description: `Create a new Feature`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: CreateFeatureDto, +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Feature, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v2/projects/:project/features', +// alias: 'FeaturesController_findAll', +// description: `List Features`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'page', +// type: 'Query', +// schema: z.number().gte(1).optional().default(1), +// }, +// { +// name: 'perPage', +// type: 'Query', +// schema: z.number().gte(1).lte(1000).optional().default(100), +// }, +// { +// name: 'sortBy', +// type: 'Query', +// schema: z +// .enum([ +// 'createdAt', +// 'updatedAt', +// 'name', +// 'key', +// 'createdBy', +// 'propertyKey', +// ]) +// .optional() +// .default('createdAt'), +// }, +// { +// name: 'sortOrder', +// type: 'Query', +// schema: z.enum(['asc', 'desc']).optional().default('desc'), +// }, +// { +// name: 'search', +// type: 'Query', +// schema: z.string().min(3).optional(), +// }, +// { +// name: 'createdBy', +// type: 'Query', +// schema: z.string().optional(), +// }, +// { +// name: 'type', +// type: 'Query', +// schema: z +// .enum(['release', 'experiment', 'permission', 'ops']) +// .optional(), +// }, +// { +// name: 'status', +// type: 'Query', +// schema: z.enum(['active', 'complete', 'archived']).optional(), +// }, +// { +// name: 'keys', +// type: 'Query', +// schema: z.array(z.string()).optional(), +// }, +// { +// name: 'includeLatestUpdate', +// type: 'Query', +// schema: z.boolean().optional(), +// }, +// { +// name: 'staleness', +// type: 'Query', +// schema: z +// .enum([ +// 'all', +// 'unused', +// 'released', +// 'unmodified', +// 'notStale', +// ]) +// .optional(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(Feature), +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v2/projects/:project/features/:feature', +// alias: 'FeaturesController_update', +// description: `Update a Feature by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateFeatureDto, +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Feature, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v2/projects/:project/features/:feature', +// alias: 'FeaturesController_findOne', +// description: `Get a Feature by ID or key`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Feature, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'post', +// path: '/v2/projects/:project/features/:feature/change-requests', +// alias: 'FeatureChangeRequestsController_createChangeRequest', +// description: `Create a new Feature Change Request`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: CreateFeatureChangeRequestDto, +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: FeatureChangeRequest, +// errors: [ +// { +// status: 400, +// schema: z.void(), +// }, +// { +// status: 409, +// schema: z.void(), +// }, +// { +// status: 412, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v2/projects/:project/features/:feature/change-requests', +// alias: 'FeatureChangeRequestsController_getPendingFeatureChangeRequests', +// description: `Get all pending Feature Change Requests for a Feature`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.array(FeatureChangeRequest), +// errors: [ +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 405, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v2/projects/:project/features/:feature/change-requests/:id', +// alias: 'FeatureChangeRequestsController_getFeatureChangeRequest', +// description: `Get a Feature Change Request by ID`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'id', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: FeatureChangeRequest, +// errors: [ +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 405, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v2/projects/:project/features/:feature/change-requests/:id/apply', +// alias: 'FeatureChangeRequestsController_applyFeatureChangeRequest', +// description: `Update a Feature Change Request by ID`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: ApplyFeatureChangeRequestDto, +// }, +// { +// name: 'id', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 405, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v2/projects/:project/features/:feature/change-requests/:id/cancel', +// alias: 'FeatureChangeRequestsController_cancelFeatureChangeRequest', +// description: `Cancel a Feature Change Request by ID`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'id', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 405, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v2/projects/:project/features/:feature/change-requests/:id/review', +// alias: 'FeatureChangeRequestsController_reviewFeatureChangeRequest', +// description: `Update a Feature Change Request by ID`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: ReviewFeatureChangeRequestDto, +// }, +// { +// name: 'id', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'apply', +// type: 'Query', +// schema: z.boolean().optional(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: z.void(), +// errors: [ +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 405, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v2/projects/:project/features/:feature/change-requests/:id/submit', +// alias: 'FeatureChangeRequestsController_submitChangeRequestForReview', +// description: `Submit a Feature Change Request for Review`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: SubmitFeatureChangeRequestDto, +// }, +// { +// name: 'id', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: FeatureChangeRequest, +// errors: [ +// { +// status: 400, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 405, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v2/projects/:project/features/:feature/change-requests/latest', +// alias: 'FeatureChangeRequestsController_getLatestFeatureChangeRequest', +// description: `Get the latest Feature Change Request for a Feature that is NOT in the 'draft' state`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: FeatureChangeRequest, +// errors: [ +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 405, +// schema: z.void(), +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v2/projects/:project/features/:feature/staleness', +// alias: 'FeaturesController_getStaleness', +// description: `Get a Feature's Staleness`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Feature, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v2/projects/:project/features/:feature/staleness', +// alias: 'FeaturesController_updateStaleness', +// description: `Update a Feature's Staleness`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateStalenessDto, +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: FeatureStalenessEntity, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'get', +// path: '/v2/projects/:project/features/:feature/static-configuration', +// alias: 'FeaturesController_findStaticConfiguration', +// description: `Get a completed Feature's static configuration`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: StaticConfiguration, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v2/projects/:project/features/:feature/static-configuration', +// alias: 'FeaturesController_updateStaticConfiguration', +// description: `Update a completed Feature's static configuration`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateStaticConfigurationDto, +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: StaticConfiguration, +// errors: [ +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: z.void(), +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v2/projects/:project/features/:feature/status', +// alias: 'FeaturesController_updateStatus', +// description: `Update a Feature's status`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateFeatureStatusDto, +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: Feature, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 409, +// schema: ConflictErrorResponse, +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// { +// method: 'patch', +// path: '/v2/projects/:project/features/:feature/summary', +// alias: 'FeaturesController_updateSummary', +// description: `Update a Feature's summary`, +// requestFormat: 'json', +// parameters: [ +// { +// name: 'body', +// type: 'Body', +// schema: UpdateFeatureSummaryDto, +// }, +// { +// name: 'feature', +// type: 'Path', +// schema: z.string(), +// }, +// { +// name: 'project', +// type: 'Path', +// schema: z.string(), +// }, +// ], +// response: FeatureSummary, +// errors: [ +// { +// status: 400, +// schema: BadRequestErrorResponse, +// }, +// { +// status: 401, +// schema: z.void(), +// }, +// { +// status: 403, +// schema: z.void(), +// }, +// { +// status: 404, +// schema: NotFoundErrorResponse, +// }, +// { +// status: 412, +// schema: PreconditionFailedErrorResponse, +// }, +// ], +// }, +// ]) + +// export const api = new Zodios(endpoints) + +// export function createApiClient(baseUrl: string, options?: ZodiosOptions) { +// return new Zodios(baseUrl, endpoints, options) +// } diff --git a/src/commands/authCommand.ts b/src/commands/authCommand.ts index b6769a070..ece8f3934 100644 --- a/src/commands/authCommand.ts +++ b/src/commands/authCommand.ts @@ -33,7 +33,7 @@ export default abstract class AuthCommand extends Base { const projects = await fetchProjects(this.authToken) if (flags.headless && !flags.project) { return this.writer.showResults( - projects.map((project) => project.key), + projects.map((project: Project) => project.key), ) } const selectedProject = await this.retrieveProject(projects) diff --git a/src/commands/base.ts b/src/commands/base.ts index 2ce7b9c84..1fa49b48f 100644 --- a/src/commands/base.ts +++ b/src/commands/base.ts @@ -15,6 +15,7 @@ import { import { ConfigManager } from '../utils/configManager' import { ApiAuth } from '../auth/ApiAuth' import { fetchProjects } from '../api/projects' +import type { Project } from '../api/schemas' import { promptForProject } from '../ui/promptForProject' import inquirer from 'inquirer' import Writer from '../ui/writer' @@ -25,7 +26,6 @@ import z, { ZodObject, ZodTypeAny, ZodError } from 'zod' import { getTokenExpiry } from '../auth/utils' import SSOAuth from '../auth/SSOAuth' import TableOutput from '../ui/tableOutput' -import { Project } from '../api/schemas' export default abstract class Base extends Command { static hidden = true @@ -237,7 +237,7 @@ export default abstract class Base extends Command { const projects = await fetchProjects(this.authToken) const findProjectByKey = (key: string) => { - const project = projects.find((proj) => proj.key === key) + const project = projects.find((proj: Project) => proj.key === key) if (!project) { throw new Error( `Project details could not be retrieved for configured project: ${key}`, diff --git a/src/commands/environments/list.ts b/src/commands/environments/list.ts index b6f2cff06..7d8fe1d3b 100644 --- a/src/commands/environments/list.ts +++ b/src/commands/environments/list.ts @@ -1,4 +1,5 @@ import { fetchEnvironments } from '../../api/environments' +import type { Environment } from '../../api/schemas' import Base from '../base' export default class ListEnvironments extends Base { @@ -15,7 +16,7 @@ export default class ListEnvironments extends Base { this.projectKey, ) const environmentKeys = environments.map( - (environment) => environment.key, + (environment: Environment) => environment.key, ) this.writer.showResults(environmentKeys) } diff --git a/src/commands/features/__snapshots__/update.test.ts.snap b/src/commands/features/__snapshots__/update.test.ts.snap index 0b607794a..5dbeae8b6 100644 --- a/src/commands/features/__snapshots__/update.test.ts.snap +++ b/src/commands/features/__snapshots__/update.test.ts.snap @@ -5,11 +5,11 @@ exports[`features update accepts flags and prompts for missing fields 1`] = ` 🤖 Current values: 🤖 { - \\"name\\": \\"Feature Name\\", - \\"key\\": \\"feature-key\\", \\"_id\\": \\"id\\", \\"_project\\": \\"string\\", \\"source\\": \\"api\\", + \\"name\\": \\"Feature Name\\", + \\"key\\": \\"feature-key\\", \\"_createdBy\\": \\"string\\", \\"createdAt\\": \\"2019-08-24T14:15:22Z\\", \\"updatedAt\\": \\"2019-08-24T14:15:22Z\\", @@ -29,11 +29,11 @@ exports[`features update accepts flags and prompts for missing fields 1`] = ` { - \\"name\\": \\"Feature Name\\", - \\"key\\": \\"feature-key\\", \\"_id\\": \\"id\\", \\"_project\\": \\"string\\", \\"source\\": \\"api\\", + \\"name\\": \\"Feature Name\\", + \\"key\\": \\"feature-key\\", \\"_createdBy\\": \\"string\\", \\"createdAt\\": \\"2019-08-24T14:15:22Z\\", \\"updatedAt\\": \\"2019-08-24T14:15:22Z\\", @@ -58,11 +58,11 @@ exports[`features update updates a feature after prompting for all fields 1`] = 🤖 Current values: 🤖 { - \\"name\\": \\"Feature Name\\", - \\"key\\": \\"feature-key\\", \\"_id\\": \\"id\\", \\"_project\\": \\"string\\", \\"source\\": \\"api\\", + \\"name\\": \\"Feature Name\\", + \\"key\\": \\"feature-key\\", \\"_createdBy\\": \\"string\\", \\"createdAt\\": \\"2019-08-24T14:15:22Z\\", \\"updatedAt\\": \\"2019-08-24T14:15:22Z\\", @@ -85,11 +85,11 @@ exports[`features update updates a feature after prompting for all fields 1`] = 🤖 No existing Variations. ---------------------------------------- { - \\"name\\": \\"Feature Name\\", - \\"key\\": \\"feature-key\\", \\"_id\\": \\"id\\", \\"_project\\": \\"string\\", \\"source\\": \\"api\\", + \\"name\\": \\"Feature Name\\", + \\"key\\": \\"feature-key\\", \\"_createdBy\\": \\"string\\", \\"createdAt\\": \\"2019-08-24T14:15:22Z\\", \\"updatedAt\\": \\"2019-08-24T14:15:22Z\\", @@ -110,6 +110,6 @@ exports[`features update updates a feature after prompting for all fields 1`] = `; exports[`features update updates a feature in headless mode 1`] = ` -"{\\"name\\":\\"Feature Name\\",\\"key\\":\\"feature-key\\",\\"_id\\":\\"id\\",\\"_project\\":\\"string\\",\\"source\\":\\"api\\",\\"_createdBy\\":\\"string\\",\\"createdAt\\":\\"2019-08-24T14:15:22Z\\",\\"updatedAt\\":\\"2019-08-24T14:15:22Z\\",\\"variations\\":[],\\"controlVariation\\":\\"variation_id\\",\\"variables\\":[],\\"tags\\":[],\\"ldLink\\":\\"string\\",\\"readonly\\":true,\\"settings\\":{},\\"sdkVisibility\\":{\\"mobile\\":true,\\"client\\":true,\\"server\\":true}} +"{\\"_id\\":\\"id\\",\\"_project\\":\\"string\\",\\"source\\":\\"api\\",\\"name\\":\\"Feature Name\\",\\"key\\":\\"feature-key\\",\\"_createdBy\\":\\"string\\",\\"createdAt\\":\\"2019-08-24T14:15:22Z\\",\\"updatedAt\\":\\"2019-08-24T14:15:22Z\\",\\"variations\\":[],\\"controlVariation\\":\\"variation_id\\",\\"variables\\":[],\\"tags\\":[],\\"ldLink\\":\\"string\\",\\"readonly\\":true,\\"settings\\":{},\\"sdkVisibility\\":{\\"mobile\\":true,\\"client\\":true,\\"server\\":true}} " `; diff --git a/src/commands/features/update.test.ts b/src/commands/features/update.test.ts index 01aa18150..ef6344635 100644 --- a/src/commands/features/update.test.ts +++ b/src/commands/features/update.test.ts @@ -81,7 +81,10 @@ describe('features update', () => { api .patch( `/v2/projects/${projectKey}/features/${mockFeature.key}`, - requestBodyWithVariables, + { + ...requestBodyWithVariables, + headless: true, + }, ) .reply(200, mockFeature), ) @@ -151,7 +154,11 @@ describe('features update', () => { api .patch( `/v2/projects/${projectKey}/features/${mockFeature.key}`, - requestBodyWithVariations, + { + ...requestBodyWithVariations, + whichFields: Object.keys(requestBodyWithVariations), + listPromptOption: 'continue', + }, ) .reply(200, mockFeature), ) @@ -184,7 +191,11 @@ describe('features update', () => { api .patch( `/v2/projects/${projectKey}/features/${mockFeature.key}`, - requestBody, + { + ...requestBody, + whichFields: ['key', 'description', 'sdkVisibility'], + listPromptOption: 'continue', + }, ) .reply(200, mockFeature), ) diff --git a/src/commands/overrides/get.ts b/src/commands/overrides/get.ts index 6e998d6f1..f9f253b88 100644 --- a/src/commands/overrides/get.ts +++ b/src/commands/overrides/get.ts @@ -10,7 +10,7 @@ import Base from '../base' import { fetchFeatureOverridesForUser } from '../../api/overrides' import { fetchEnvironmentByKey } from '../../api/environments' import { fetchVariationByKey } from '../../api/variations' -import { UserOverride } from '../../api/schemas' +import { UserOverride, FeatureOverride } from '../../api/schemas' import { fetchUserProfile } from '../../api/userProfile' export default class DetailedOverrides extends Base { @@ -93,7 +93,8 @@ export default class DetailedOverrides extends Base { environmentKey, ) const override = overrides.overrides.find( - (override) => override._environment === environment._id, + (override: FeatureOverride) => + override._environment === environment._id, ) if (!override) { diff --git a/src/commands/projects/get.ts b/src/commands/projects/get.ts index eada77472..826b8cd6f 100644 --- a/src/commands/projects/get.ts +++ b/src/commands/projects/get.ts @@ -1,5 +1,6 @@ import { fetchProjects } from '../../api/projects' -import { schemas } from '../../api/zodClient' +import { GetProjectsParams } from '../../api/zodClient' +import type { Project } from '../../api/schemas' import GetCommand from '../getCommand' export default class DetailedProjects extends GetCommand { @@ -15,7 +16,7 @@ export default class DetailedProjects extends GetCommand { const { flags } = await this.parse(DetailedProjects) const { sortBy, sortOrder } = flags - const params = schemas.GetProjectsParams.parse({ sortBy, sortOrder }) + const params = GetProjectsParams.parse({ sortBy, sortOrder }) const projects = await fetchProjects(this.authToken, params) return this.writer.showResults( @@ -28,7 +29,7 @@ export default class DetailedProjects extends GetCommand { description, updatedAt, createdAt, - }) => ({ + }: Project) => ({ _id, _organization, key, diff --git a/src/commands/projects/list.ts b/src/commands/projects/list.ts index 5551c9115..50fd6fa97 100644 --- a/src/commands/projects/list.ts +++ b/src/commands/projects/list.ts @@ -1,5 +1,6 @@ import chalk from 'chalk' import { fetchProjects } from '../../api/projects' +import type { Project } from '../../api/schemas' import Base from '../base' export default class ListProjects extends Base { @@ -11,7 +12,7 @@ export default class ListProjects extends Base { public async run(): Promise { const projects = await fetchProjects(this.authToken) - const projectsKeys = projects.map((project) => { + const projectsKeys = projects.map((project: Project) => { if (project.key === this.projectKey) { return chalk.green(` "${project.key}"`) } diff --git a/src/commands/projects/select.ts b/src/commands/projects/select.ts index 8bcbfd5d9..8602ce9dc 100644 --- a/src/commands/projects/select.ts +++ b/src/commands/projects/select.ts @@ -1,5 +1,5 @@ import { fetchProjects } from '../../api/projects' -import { Project } from '../../api/schemas' +import type { Project } from '../../api/schemas' import { promptForProject } from '../../ui/promptForProject' import AuthCommand from '../authCommand' export default class SelectProject extends AuthCommand { @@ -19,7 +19,7 @@ export default class SelectProject extends AuthCommand { const projects = await fetchProjects(this.authToken) if (flags.headless && !flags.project) { return this.writer.showResults( - projects.map((project) => project.key), + projects.map((project: Project) => project.key), ) } const selectedProject = await this.getSelectedProject(projects) diff --git a/src/commands/variables/create.test.ts b/src/commands/variables/create.test.ts index 9bd642d4d..09613785a 100644 --- a/src/commands/variables/create.test.ts +++ b/src/commands/variables/create.test.ts @@ -74,6 +74,7 @@ describe('variables create', () => { server: true, }, settings: {}, + tags: [], } // Headless mode dvcTest() diff --git a/src/commands/variables/create.ts b/src/commands/variables/create.ts index 31baa08d7..d9daafb47 100644 --- a/src/commands/variables/create.ts +++ b/src/commands/variables/create.ts @@ -119,15 +119,17 @@ export default class CreateVariable extends CreateCommand { ) return } + const parsedVariations = JSON.parse(variations as string) - const featureVariables = feature.variables - const featureVariations = feature.variations + const featureVariables = feature.variables || [] + const featureVariations = feature.variations || [] featureVariables.push(params as Variable) for (const featVar of featureVariations) { featVar.variables = featVar.variables || {} featVar.variables[params.key] = parsedVariations[featVar.key] } + await updateFeature( this.authToken, this.projectKey, diff --git a/src/commands/variables/list.ts b/src/commands/variables/list.ts index eb4fc2d67..c08883396 100644 --- a/src/commands/variables/list.ts +++ b/src/commands/variables/list.ts @@ -1,5 +1,6 @@ import { Flags } from '@oclif/core' import { fetchVariables } from '../../api/variables' +import type { Variable } from '../../api/schemas' import Base from '../base' export default class ListVariables extends Base { @@ -34,7 +35,7 @@ export default class ListVariables extends Base { this.projectKey, query, ) - const variableKeys = variables.map((variable) => variable.key) + const variableKeys = variables.map((variable: Variable) => variable.key) this.writer.showResults(variableKeys) } } diff --git a/src/commands/variations/__snapshots__/create.test.ts.snap b/src/commands/variations/__snapshots__/create.test.ts.snap index a8cc68cbc..0e4acf352 100644 --- a/src/commands/variations/__snapshots__/create.test.ts.snap +++ b/src/commands/variations/__snapshots__/create.test.ts.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`variations create creates a variation and returns the full feature in headless mode 1`] = ` -"{\\"_id\\":\\"63b5eea3e6e91987bae47f3a\\",\\"_project\\":\\"63b5ee5de6e91987bae47f01\\",\\"source\\":\\"dashboard\\",\\"type\\":\\"experiment\\",\\"name\\":\\"First Feature\\",\\"description\\":\\"\\",\\"key\\":\\"first-feature\\",\\"_createdBy\\":\\"google-oauth2|111559006563333334214\\",\\"createdAt\\":\\"2023-01-04T21:24:51.870Z\\",\\"updatedAt\\":\\"2023-06-16T19:27:14.862Z\\",\\"variations\\":[{\\"_id\\":\\"63b5eea3e6e91987bae47f40\\",\\"key\\":\\"yo\\",\\"name\\":\\"Yo\\",\\"variables\\":{\\"new-variable\\":false,\\"first-feature\\":true}},{\\"_id\\":\\"63b5eea3e6e91987bae47f41\\",\\"key\\":\\"variation-a\\",\\"name\\":\\"Variation A\\",\\"variables\\":{}},{\\"_id\\":\\"63b5eea3e6e91987bae47f42\\",\\"key\\":\\"variation-b\\",\\"name\\":\\"Variation B\\",\\"variables\\":{}}],\\"controlVariation\\":\\"control\\",\\"variables\\":[{\\"_id\\":\\"63b5eea3e6e91987bae47f3c\\",\\"_project\\":\\"63b5ee5de6e91987bae47f01\\",\\"_feature\\":\\"63b5eea3e6e91987bae47f3a\\",\\"name\\":\\"first-feature\\",\\"key\\":\\"first-feature\\",\\"type\\":\\"Boolean\\",\\"status\\":\\"active\\",\\"defaultValue\\":false,\\"source\\":\\"dashboard\\",\\"_createdBy\\":\\"google-oauth2|111559006563333334214\\",\\"createdAt\\":\\"2023-01-04T21:24:51.877Z\\",\\"updatedAt\\":\\"2023-01-04T21:24:51.877Z\\"}],\\"tags\\":[],\\"readonly\\":false,\\"settings\\":{\\"optInEnabled\\":false,\\"publicName\\":\\"\\",\\"publicDescription\\":\\"\\"},\\"sdkVisibility\\":{\\"client\\":false,\\"mobile\\":false,\\"server\\":true}} +"{\\"_id\\":\\"63b5eea3e6e91987bae47f3a\\",\\"_project\\":\\"63b5ee5de6e91987bae47f01\\",\\"source\\":\\"dashboard\\",\\"type\\":\\"experiment\\",\\"name\\":\\"First Feature\\",\\"description\\":\\"\\",\\"key\\":\\"first-feature\\",\\"_createdBy\\":\\"google-oauth2|111559006563333334214\\",\\"createdAt\\":\\"2023-01-04T21:24:51.870Z\\",\\"updatedAt\\":\\"2023-06-16T19:27:14.862Z\\",\\"variations\\":[{\\"_id\\":\\"63b5eea3e6e91987bae47f40\\",\\"key\\":\\"yo\\",\\"name\\":\\"Yo\\",\\"variables\\":{\\"new-variable\\":false,\\"first-feature\\":true}},{\\"_id\\":\\"63b5eea3e6e91987bae47f41\\",\\"key\\":\\"variation-a\\",\\"name\\":\\"Variation A\\",\\"variables\\":{}},{\\"_id\\":\\"63b5eea3e6e91987bae47f42\\",\\"key\\":\\"variation-b\\",\\"name\\":\\"Variation B\\",\\"variables\\":{}}],\\"controlVariation\\":\\"control\\",\\"variables\\":[{\\"_id\\":\\"63b5eea3e6e91987bae47f3c\\",\\"_project\\":\\"63b5ee5de6e91987bae47f01\\",\\"_feature\\":\\"63b5eea3e6e91987bae47f3a\\",\\"name\\":\\"first-feature\\",\\"key\\":\\"first-feature\\",\\"type\\":\\"Boolean\\",\\"status\\":\\"active\\",\\"defaultValue\\":false,\\"source\\":\\"dashboard\\",\\"_createdBy\\":\\"google-oauth2|111559006563333334214\\",\\"createdAt\\":\\"2023-01-04T21:24:51.877Z\\",\\"updatedAt\\":\\"2023-01-04T21:24:51.877Z\\"}],\\"tags\\":[],\\"readonly\\":false,\\"settings\\":{\\"optInEnabled\\":false,\\"publicName\\":\\"Public Feature Name\\",\\"publicDescription\\":\\"Public Feature Description\\"},\\"sdkVisibility\\":{\\"client\\":false,\\"mobile\\":false,\\"server\\":true}} " `; @@ -61,8 +61,8 @@ exports[`variations create creates a variation and returns the full feature in i \\"readonly\\": false, \\"settings\\": { \\"optInEnabled\\": false, - \\"publicName\\": \\"\\", - \\"publicDescription\\": \\"\\" + \\"publicName\\": \\"Public Feature Name\\", + \\"publicDescription\\": \\"Public Feature Description\\" }, \\"sdkVisibility\\": { \\"client\\": false, @@ -135,8 +135,8 @@ exports[`variations create prompts for missing fields in interactive mode 1`] = \\"readonly\\": false, \\"settings\\": { \\"optInEnabled\\": false, - \\"publicName\\": \\"\\", - \\"publicDescription\\": \\"\\" + \\"publicName\\": \\"Public Feature Name\\", + \\"publicDescription\\": \\"Public Feature Description\\" }, \\"sdkVisibility\\": { \\"client\\": false, diff --git a/src/commands/variations/__snapshots__/update.test.ts.snap b/src/commands/variations/__snapshots__/update.test.ts.snap index d114db7da..91fdc6e56 100644 --- a/src/commands/variations/__snapshots__/update.test.ts.snap +++ b/src/commands/variations/__snapshots__/update.test.ts.snap @@ -70,8 +70,8 @@ exports[`variations update prompts for variables when missing in interactive mod \\"readonly\\": false, \\"settings\\": { \\"optInEnabled\\": false, - \\"publicName\\": \\"\\", - \\"publicDescription\\": \\"\\" + \\"publicName\\": \\"Public Feature Name\\", + \\"publicDescription\\": \\"Public Feature Description\\" }, \\"sdkVisibility\\": { \\"client\\": false, @@ -83,7 +83,7 @@ exports[`variations update prompts for variables when missing in interactive mod `; exports[`variations update updates a variation and returns the full feature in headless mode 1`] = ` -"{\\"_id\\":\\"63b5eea3e6e91987bae47f3a\\",\\"_project\\":\\"63b5ee5de6e91987bae47f01\\",\\"source\\":\\"dashboard\\",\\"type\\":\\"experiment\\",\\"name\\":\\"First Feature\\",\\"key\\":\\"first-feature\\",\\"description\\":\\"\\",\\"_createdBy\\":\\"google-oauth2|111559006563333334214\\",\\"createdAt\\":\\"2023-01-04T21:24:51.870Z\\",\\"updatedAt\\":\\"2023-06-16T19:27:14.862Z\\",\\"variations\\":[{\\"_id\\":\\"63b5eea3e6e91987bae47f40\\",\\"key\\":\\"yo\\",\\"name\\":\\"Yo\\",\\"variables\\":{\\"new-variable\\":false,\\"first-feature\\":true}},{\\"_id\\":\\"63b5eea3e6e91987bae47f41\\",\\"key\\":\\"variation-a\\",\\"name\\":\\"Variation A\\",\\"variables\\":{}},{\\"_id\\":\\"63b5eea3e6e91987bae47f42\\",\\"key\\":\\"variation-b\\",\\"name\\":\\"Variation B\\",\\"variables\\":{}}],\\"controlVariation\\":\\"control\\",\\"variables\\":[{\\"_id\\":\\"63b5eea3e6e91987bae47f3c\\",\\"_project\\":\\"63b5ee5de6e91987bae47f01\\",\\"_feature\\":\\"63b5eea3e6e91987bae47f3a\\",\\"name\\":\\"first-feature\\",\\"key\\":\\"first-feature\\",\\"type\\":\\"Boolean\\",\\"status\\":\\"active\\",\\"defaultValue\\":false,\\"source\\":\\"dashboard\\",\\"_createdBy\\":\\"google-oauth2|111559006563333334214\\",\\"createdAt\\":\\"2023-01-04T21:24:51.877Z\\",\\"updatedAt\\":\\"2023-01-04T21:24:51.877Z\\"}],\\"tags\\":[],\\"readonly\\":false,\\"settings\\":{\\"optInEnabled\\":false,\\"publicName\\":\\"\\",\\"publicDescription\\":\\"\\"},\\"sdkVisibility\\":{\\"client\\":false,\\"mobile\\":false,\\"server\\":true}} +"{\\"_id\\":\\"63b5eea3e6e91987bae47f3a\\",\\"_project\\":\\"63b5ee5de6e91987bae47f01\\",\\"source\\":\\"dashboard\\",\\"type\\":\\"experiment\\",\\"name\\":\\"First Feature\\",\\"key\\":\\"first-feature\\",\\"description\\":\\"\\",\\"_createdBy\\":\\"google-oauth2|111559006563333334214\\",\\"createdAt\\":\\"2023-01-04T21:24:51.870Z\\",\\"updatedAt\\":\\"2023-06-16T19:27:14.862Z\\",\\"variations\\":[{\\"_id\\":\\"63b5eea3e6e91987bae47f40\\",\\"key\\":\\"yo\\",\\"name\\":\\"Yo\\",\\"variables\\":{\\"new-variable\\":false,\\"first-feature\\":true}},{\\"_id\\":\\"63b5eea3e6e91987bae47f41\\",\\"key\\":\\"variation-a\\",\\"name\\":\\"Variation A\\",\\"variables\\":{}},{\\"_id\\":\\"63b5eea3e6e91987bae47f42\\",\\"key\\":\\"variation-b\\",\\"name\\":\\"Variation B\\",\\"variables\\":{}}],\\"controlVariation\\":\\"control\\",\\"variables\\":[{\\"_id\\":\\"63b5eea3e6e91987bae47f3c\\",\\"_project\\":\\"63b5ee5de6e91987bae47f01\\",\\"_feature\\":\\"63b5eea3e6e91987bae47f3a\\",\\"name\\":\\"first-feature\\",\\"key\\":\\"first-feature\\",\\"type\\":\\"Boolean\\",\\"status\\":\\"active\\",\\"defaultValue\\":false,\\"source\\":\\"dashboard\\",\\"_createdBy\\":\\"google-oauth2|111559006563333334214\\",\\"createdAt\\":\\"2023-01-04T21:24:51.877Z\\",\\"updatedAt\\":\\"2023-01-04T21:24:51.877Z\\"}],\\"tags\\":[],\\"readonly\\":false,\\"settings\\":{\\"optInEnabled\\":false,\\"publicName\\":\\"Public Feature Name\\",\\"publicDescription\\":\\"Public Feature Description\\"},\\"sdkVisibility\\":{\\"client\\":false,\\"mobile\\":false,\\"server\\":true}} " `; @@ -157,8 +157,8 @@ exports[`variations update updates a variation and returns the full feature in i \\"readonly\\": false, \\"settings\\": { \\"optInEnabled\\": false, - \\"publicName\\": \\"\\", - \\"publicDescription\\": \\"\\" + \\"publicName\\": \\"Public Feature Name\\", + \\"publicDescription\\": \\"Public Feature Description\\" }, \\"sdkVisibility\\": { \\"client\\": false, diff --git a/src/commands/variations/create.test.ts b/src/commands/variations/create.test.ts index 4689dbf62..345a49dfc 100644 --- a/src/commands/variations/create.test.ts +++ b/src/commands/variations/create.test.ts @@ -110,8 +110,8 @@ describe('variations create', () => { readonly: false, settings: { optInEnabled: false, - publicName: '', - publicDescription: '', + publicName: 'Public Feature Name', + publicDescription: 'Public Feature Description', }, sdkVisibility: { client: false, diff --git a/src/commands/variations/update.test.ts b/src/commands/variations/update.test.ts index dbbf6b802..f03ebdfba 100644 --- a/src/commands/variations/update.test.ts +++ b/src/commands/variations/update.test.ts @@ -119,8 +119,8 @@ describe('variations update', () => { readonly: false, settings: { optInEnabled: false, - publicName: '', - publicDescription: '', + publicName: 'Public Feature Name', + publicDescription: 'Public Feature Description', }, sdkVisibility: { client: false, diff --git a/src/mcp/server.test.ts b/src/mcp/server.test.ts index e1974350b..f80e018c6 100644 --- a/src/mcp/server.test.ts +++ b/src/mcp/server.test.ts @@ -98,9 +98,9 @@ describe('DevCycleMCPServer', () => { await mcpServer.initialize() - // Should register many tools (37 total across all modules) + // Should register many tools (21 currently active tools across all modules) const registerToolStub = server.registerTool as sinon.SinonStub - expect(registerToolStub.callCount).to.be.greaterThan(25) + expect(registerToolStub.callCount).to.be.greaterThan(15) }) }) diff --git a/src/mcp/tools/featureTools.ts b/src/mcp/tools/featureTools.ts index d94b92619..1266bb084 100644 --- a/src/mcp/tools/featureTools.ts +++ b/src/mcp/tools/featureTools.ts @@ -455,13 +455,19 @@ export function registerFeatureTools( }, ) + const featureDescription = [ + 'Features are the main logical container for variables and targeting rules, defining what values variables will be served to users across environments.', + 'Features can contain multiple variables, and many variations, defined by the targeting rules to determine how variable values are distributed to users.', + 'Feature configurations determine the targeting rules applied for a user per environment. Configurations that are "active" (on) will serve the feature to configured users.', + 'When turning on/off configurations for a feature, keep existing targeting rules.', + ] + serverInstance.registerToolWithErrorHandling( 'create_feature', { description: [ 'Create a new DevCycle feature. Include dashboard link in the response.', - 'Features are the main logical container for variables and targeting rules, defining what values variables will be served to users across environments.', - 'Features can contin multiple variables, and many variations, defined by the targeting rules to determine how variable values are distributed to users.', + ...featureDescription, 'If a user is creating a feature, you should follow these steps and ask users for input on these steps:', '1. create a variable and associate it with this feature. (default to creating a "boolean" variable with the same key as the feature)', '2. create variations for the feature. (default to creating an "on" and "off" variation)', @@ -483,8 +489,10 @@ export function registerFeatureTools( { description: [ 'Update an existing feature flag.', - '⚠️ IMPORTANT: Changes to feature flags may affect production environments.', - 'Always confirm with the user before making changes to features that are active in production.', + 'Consider this a PATCH request to the feature, to update feature configuration, variables, variations, and targeting rules. Be careful to not overwrite existing data with the PATCH request.', + ...featureDescription, + '⚠️ IMPORTANT: Changes to feature flags may affect production environments if production environment configurations are "active".', + 'Always confirm with the user before making changes to features that have production environment configurations that are "active".', 'Include dashboard link in the response.', ].join('\n'), annotations: { @@ -541,121 +549,121 @@ export function registerFeatureTools( }, ) - serverInstance.registerToolWithErrorHandling( - 'fetch_feature_variations', - { - description: [ - 'Get a list of variations for a feature.', - 'Include dashboard link in the response.', - ].join('\n'), - annotations: { - title: 'Get Feature Variations', - readOnlyHint: true, - }, - inputSchema: ListVariationsArgsSchema.shape, - }, - async (args: any) => { - const validatedArgs = ListVariationsArgsSchema.parse(args) - return await fetchFeatureVariationsHandler(validatedArgs, apiClient) - }, - ) - - serverInstance.registerToolWithErrorHandling( - 'create_feature_variation', - { - description: [ - 'Create a new variation within a feature.', - 'Include dashboard link in the response.', - ].join('\n'), - annotations: { - title: 'Create Feature Variation', - }, - inputSchema: CreateVariationArgsSchema.shape, - }, - async (args: any) => { - const validatedArgs = CreateVariationArgsSchema.parse(args) - return await createFeatureVariationHandler(validatedArgs, apiClient) - }, - ) - - serverInstance.registerToolWithErrorHandling( - 'update_feature_variation', - { - description: [ - 'Update an existing variation by key.', - '⚠️ WARNING: Updating a feature variation may affect production environments.', - 'Include dashboard link in the response.', - ].join('\n'), - annotations: { - title: 'Update Feature Variation', - destructiveHint: true, - }, - inputSchema: UpdateVariationArgsSchema.shape, - }, - async (args: any) => { - const validatedArgs = UpdateVariationArgsSchema.parse(args) - return await updateFeatureVariationHandler(validatedArgs, apiClient) - }, - ) - - serverInstance.registerToolWithErrorHandling( - 'set_feature_targeting', - { - description: [ - 'Set targeting status for a feature in an environment.', - '⚠️ IMPORTANT: Always confirm with the user before making changes to production environments (environments where type = "production").', - 'Include dashboard link in the response.', - ].join('\n'), - annotations: { - title: 'Set Feature Targeting', - destructiveHint: true, - }, - inputSchema: SetFeatureTargetingArgsSchema.shape, - }, - async (args: any) => { - const validatedArgs = SetFeatureTargetingArgsSchema.parse(args) - return await setFeatureTargetingHandler(validatedArgs, apiClient) - }, - ) - - serverInstance.registerToolWithErrorHandling( - 'list_feature_targeting', - { - description: [ - 'List feature configurations (targeting rules) for a feature.', - 'Include dashboard link in the response.', - ].join('\n'), - annotations: { - title: 'List Feature Targeting Rules', - readOnlyHint: true, - }, - inputSchema: ListFeatureTargetingArgsSchema.shape, - }, - async (args: any) => { - const validatedArgs = ListFeatureTargetingArgsSchema.parse(args) - return await listFeatureTargetingHandler(validatedArgs, apiClient) - }, - ) - - serverInstance.registerToolWithErrorHandling( - 'update_feature_targeting', - { - description: [ - 'Update feature configuration (targeting rules) for a feature in an environment.', - '⚠️ IMPORTANT: Always confirm with the user before making changes to production environments (environments where type = "production").', - 'Include dashboard link in the response.', - ].join('\n'), - annotations: { - title: 'Update Feature Targeting Rules', - destructiveHint: true, - }, - inputSchema: UpdateFeatureTargetingArgsSchema.shape, - }, - async (args: any) => { - const validatedArgs = UpdateFeatureTargetingArgsSchema.parse(args) - return await updateFeatureTargetingHandler(validatedArgs, apiClient) - }, - ) + // serverInstance.registerToolWithErrorHandling( + // 'fetch_feature_variations', + // { + // description: [ + // 'Get a list of variations for a feature.', + // 'Include dashboard link in the response.', + // ].join('\n'), + // annotations: { + // title: 'Get Feature Variations', + // readOnlyHint: true, + // }, + // inputSchema: ListVariationsArgsSchema.shape, + // }, + // async (args: any) => { + // const validatedArgs = ListVariationsArgsSchema.parse(args) + // return await fetchFeatureVariationsHandler(validatedArgs, apiClient) + // }, + // ) + + // serverInstance.registerToolWithErrorHandling( + // 'create_feature_variation', + // { + // description: [ + // 'Create a new variation within a feature.', + // 'Include dashboard link in the response.', + // ].join('\n'), + // annotations: { + // title: 'Create Feature Variation', + // }, + // inputSchema: CreateVariationArgsSchema.shape, + // }, + // async (args: any) => { + // const validatedArgs = CreateVariationArgsSchema.parse(args) + // return await createFeatureVariationHandler(validatedArgs, apiClient) + // }, + // ) + + // serverInstance.registerToolWithErrorHandling( + // 'update_feature_variation', + // { + // description: [ + // 'Update an existing variation by key.', + // '⚠️ WARNING: Updating a feature variation may affect production environments.', + // 'Include dashboard link in the response.', + // ].join('\n'), + // annotations: { + // title: 'Update Feature Variation', + // destructiveHint: true, + // }, + // inputSchema: UpdateVariationArgsSchema.shape, + // }, + // async (args: any) => { + // const validatedArgs = UpdateVariationArgsSchema.parse(args) + // return await updateFeatureVariationHandler(validatedArgs, apiClient) + // }, + // ) + + // serverInstance.registerToolWithErrorHandling( + // 'set_feature_targeting', + // { + // description: [ + // 'Set targeting status for a feature in an environment.', + // '⚠️ IMPORTANT: Always confirm with the user before making changes to production environments (environments where type = "production").', + // 'Include dashboard link in the response.', + // ].join('\n'), + // annotations: { + // title: 'Set Feature Targeting', + // destructiveHint: true, + // }, + // inputSchema: SetFeatureTargetingArgsSchema.shape, + // }, + // async (args: any) => { + // const validatedArgs = SetFeatureTargetingArgsSchema.parse(args) + // return await setFeatureTargetingHandler(validatedArgs, apiClient) + // }, + // ) + + // serverInstance.registerToolWithErrorHandling( + // 'list_feature_targeting', + // { + // description: [ + // 'List feature configurations (targeting rules) for a feature.', + // 'Include dashboard link in the response.', + // ].join('\n'), + // annotations: { + // title: 'List Feature Targeting Rules', + // readOnlyHint: true, + // }, + // inputSchema: ListFeatureTargetingArgsSchema.shape, + // }, + // async (args: any) => { + // const validatedArgs = ListFeatureTargetingArgsSchema.parse(args) + // return await listFeatureTargetingHandler(validatedArgs, apiClient) + // }, + // ) + + // serverInstance.registerToolWithErrorHandling( + // 'update_feature_targeting', + // { + // description: [ + // 'Update feature configuration (targeting rules) for a feature in an environment.', + // '⚠️ IMPORTANT: Always confirm with the user before making changes to production environments (environments where type = "production").', + // 'Include dashboard link in the response.', + // ].join('\n'), + // annotations: { + // title: 'Update Feature Targeting Rules', + // destructiveHint: true, + // }, + // inputSchema: UpdateFeatureTargetingArgsSchema.shape, + // }, + // async (args: any) => { + // const validatedArgs = UpdateFeatureTargetingArgsSchema.parse(args) + // return await updateFeatureTargetingHandler(validatedArgs, apiClient) + // }, + // ) serverInstance.registerToolWithErrorHandling( 'get_feature_audit_log_history', diff --git a/src/mcp/types.ts b/src/mcp/types.ts index 6e61079b4..f6693d919 100644 --- a/src/mcp/types.ts +++ b/src/mcp/types.ts @@ -1,5 +1,20 @@ import { z } from 'zod' -import { schemas } from '../api/zodClient' +import { + CreateVariableDto, + UpdateVariableDto, + GetProjectsParams, + CreateProjectDto, + UpdateProjectDto, + CreateEnvironmentDto, + UpdateEnvironmentDto, + CreateFeatureDto, + UpdateFeatureDto, + CreateVariationDto, + UpdateFeatureVariationDto, + UpdateFeatureConfigDto, + CreateCustomPropertyDto, + UpdateCustomPropertyDto, +} from '../api/zodClient' import { UpdateFeatureStatusDto } from '../api/schemas' // Zod schemas for MCP tool arguments @@ -121,16 +136,16 @@ export const ListVariablesArgsSchema = z.object({ }) export const CreateVariableArgsSchema = z.object({ - key: schemas.CreateVariableDto.shape.key.describe('Unique variable key'), - name: schemas.CreateVariableDto.shape.name, - description: schemas.CreateVariableDto.shape.description.optional(), - type: schemas.CreateVariableDto.shape.type, - defaultValue: schemas.CreateVariableDto.shape.defaultValue + key: CreateVariableDto.shape.key.describe('Unique variable key'), + name: CreateVariableDto.shape.name, + description: CreateVariableDto.shape.description.optional(), + type: CreateVariableDto.shape.type, + defaultValue: CreateVariableDto.shape.defaultValue .optional() .describe( 'Default value for the variable, the data type of the defaultValue must match the variable.type', ), - _feature: schemas.CreateVariableDto.shape._feature + _feature: CreateVariableDto.shape._feature .optional() .describe( 'Feature key or ID to associate with this variable, only set if variable is associated with a feature', @@ -146,9 +161,9 @@ export const UpdateVariableArgsSchema = z.object({ .max(100) .regex(/^[a-z0-9-_.]+$/) .describe('key to identify variable'), - name: schemas.UpdateVariableDto.shape.name.optional(), - description: schemas.UpdateVariableDto.shape.description.optional(), - type: schemas.UpdateVariableDto.shape.type.optional(), + name: UpdateVariableDto.shape.name.optional(), + description: UpdateVariableDto.shape.description.optional(), + type: UpdateVariableDto.shape.type.optional(), validationSchema: VariableValidationSchema.optional().describe( 'Validation schema for variable values', ), @@ -163,32 +178,30 @@ export const DeleteFeatureArgsSchema = z.object({ }) export const ListProjectsArgsSchema = z.object({ - page: schemas.GetProjectsParams.shape.page.describe( - 'Page number for pagination', - ), - perPage: schemas.GetProjectsParams.shape.perPage.describe( + page: GetProjectsParams.shape.page.describe('Page number for pagination'), + perPage: GetProjectsParams.shape.perPage.describe( 'Number of items per page', ), - sortBy: schemas.GetProjectsParams.shape.sortBy, - sortOrder: schemas.GetProjectsParams.shape.sortOrder, - search: schemas.GetProjectsParams.shape.search.describe( + sortBy: GetProjectsParams.shape.sortBy, + sortOrder: GetProjectsParams.shape.sortOrder, + search: GetProjectsParams.shape.search.describe( 'Search term to filter projects by "name" or "key"', ), - createdBy: schemas.GetProjectsParams.shape.createdBy.describe( + createdBy: GetProjectsParams.shape.createdBy.describe( 'Filter projects by creator user ID', ), }) export const CreateProjectArgsSchema = z.object({ - name: schemas.CreateProjectDto.shape.name, - key: schemas.CreateProjectDto.shape.key.describe( + name: CreateProjectDto.shape.name, + key: CreateProjectDto.shape.key.describe( 'Unique project key (lowercase letters, numbers, dots, dashes, underscores only)', ), - description: schemas.CreateProjectDto.shape.description, - color: schemas.CreateProjectDto.shape.color.describe( + description: CreateProjectDto.shape.description, + color: CreateProjectDto.shape.color.describe( 'Project color in hex format (e.g., #FF0000)', ), - settings: schemas.CreateProjectDto.shape.settings, + settings: CreateProjectDto.shape.settings, }) export const UpdateProjectArgsSchema = z.object({ @@ -197,12 +210,12 @@ export const UpdateProjectArgsSchema = z.object({ .max(100) .regex(/^[a-z0-9-_.]+$/) .describe('key to identify project to update'), - name: schemas.UpdateProjectDto.shape.name, - description: schemas.UpdateProjectDto.shape.description, - color: schemas.UpdateProjectDto.shape.color.describe( + name: UpdateProjectDto.shape.name, + description: UpdateProjectDto.shape.description, + color: UpdateProjectDto.shape.color.describe( 'Updated project color in hex format (e.g., #FF0000)', ), - settings: schemas.UpdateProjectDto.shape.settings, + settings: UpdateProjectDto.shape.settings, }) export const ListEnvironmentsArgsSchema = z.object({ @@ -242,27 +255,27 @@ export const GetSdkKeysArgsSchema = z.object({ }) export const CreateEnvironmentArgsSchema = z.object({ - name: schemas.CreateEnvironmentDto.shape.name, - key: schemas.CreateEnvironmentDto.shape.key.describe( + name: CreateEnvironmentDto.shape.name, + key: CreateEnvironmentDto.shape.key.describe( 'Unique environment key (lowercase letters, numbers, dots, dashes, underscores only)', ), - description: schemas.CreateEnvironmentDto.shape.description, - color: schemas.CreateEnvironmentDto.shape.color.describe( + description: CreateEnvironmentDto.shape.description, + color: CreateEnvironmentDto.shape.color.describe( 'Environment color in hex format (e.g., #FF0000)', ), - type: schemas.CreateEnvironmentDto.shape.type, - settings: schemas.CreateEnvironmentDto.shape.settings, + type: CreateEnvironmentDto.shape.type, + settings: CreateEnvironmentDto.shape.settings, }) export const UpdateEnvironmentArgsSchema = z.object({ key: z.string().describe('key to identify environment to update'), - name: schemas.UpdateEnvironmentDto.shape.name, - description: schemas.UpdateEnvironmentDto.shape.description, - color: schemas.UpdateEnvironmentDto.shape.color.describe( + name: UpdateEnvironmentDto.shape.name, + description: UpdateEnvironmentDto.shape.description, + color: UpdateEnvironmentDto.shape.color.describe( 'color in hex format (e.g., #FF0000)', ), - type: schemas.UpdateEnvironmentDto.shape.type, - settings: schemas.UpdateEnvironmentDto.shape.settings, + type: UpdateEnvironmentDto.shape.type, + settings: UpdateEnvironmentDto.shape.settings, }) export const SetFeatureTargetingArgsSchema = z.object({ @@ -274,33 +287,31 @@ export const SetFeatureTargetingArgsSchema = z.object({ }) export const CreateFeatureArgsSchema = z.object({ - name: schemas.CreateFeatureDto.shape.name, - key: schemas.CreateFeatureDto.shape.key.describe( + name: CreateFeatureDto.shape.name, + key: CreateFeatureDto.shape.key.describe( 'Unique feature key (lowercase letters, numbers, dots, dashes, underscores only)', ), - description: schemas.CreateFeatureDto.shape.description, - variables: schemas.CreateFeatureDto.shape.variables.describe( + description: CreateFeatureDto.shape.description, + variables: CreateFeatureDto.shape.variables.describe( 'Array of variables to create or reassociate with this feature', ), - configurations: schemas.CreateFeatureDto.shape.configurations.describe( + configurations: CreateFeatureDto.shape.configurations.describe( 'Environment-specific configurations (key-value map of environment keys to config)', ), - variations: schemas.CreateFeatureDto.shape.variations.describe( + variations: CreateFeatureDto.shape.variations.describe( 'Array of variations for this feature', ), - controlVariation: schemas.CreateFeatureDto.shape.controlVariation.describe( + controlVariation: CreateFeatureDto.shape.controlVariation.describe( 'The key of the variation that is used as the control variation for Metrics', ), - settings: schemas.CreateFeatureDto.shape.settings.describe( + settings: CreateFeatureDto.shape.settings.describe( 'Feature-level settings configuration', ), - sdkVisibility: schemas.CreateFeatureDto.shape.sdkVisibility.describe( + sdkVisibility: CreateFeatureDto.shape.sdkVisibility.describe( 'SDK Type Visibility Settings for mobile, client, and server SDKs', ), - type: schemas.CreateFeatureDto.shape.type, - tags: schemas.CreateFeatureDto.shape.tags.describe( - 'Tags to organize features', - ), + type: CreateFeatureDto.shape.type, + tags: CreateFeatureDto.shape.tags.describe('Tags to organize features'), }) export const UpdateFeatureArgsSchema = z.object({ @@ -309,27 +320,36 @@ export const UpdateFeatureArgsSchema = z.object({ .max(100) .regex(/^[a-z0-9-_.]+$/) .describe('key to identify feature to update'), - name: schemas.UpdateFeatureDto.shape.name, - description: schemas.UpdateFeatureDto.shape.description, - variables: schemas.UpdateFeatureDto.shape.variables.describe( + name: UpdateFeatureDto.shape.name, + description: UpdateFeatureDto.shape.description, + type: UpdateFeatureDto.shape.type, + tags: UpdateFeatureDto.shape.tags.describe( + 'Updated tags to organize features', + ), + configurations: UpdateFeatureDto.shape.configurations.describe( + 'Updated environment-specific targeting configurations (key-value map of environment keys to config)', + ), + variables: UpdateFeatureDto.shape.variables.describe( 'Updated array of variables for this feature', ), - variations: schemas.UpdateFeatureDto.shape.variations.describe( + variations: UpdateFeatureDto.shape.variations.describe( 'Updated array of variations for this feature', ), - settings: schemas.UpdateFeatureDto.shape.settings.describe( + settings: UpdateFeatureDto.shape.settings.describe( 'Updated feature-level settings configuration', ), - sdkVisibility: schemas.UpdateFeatureDto.shape.sdkVisibility.describe( + sdkVisibility: UpdateFeatureDto.shape.sdkVisibility.describe( 'Updated SDK Type Visibility Settings for mobile, client, and server SDKs', ), - type: schemas.UpdateFeatureDto.shape.type, - tags: schemas.UpdateFeatureDto.shape.tags.describe( - 'Updated tags to organize features', - ), - controlVariation: schemas.UpdateFeatureDto.shape.controlVariation.describe( + controlVariation: UpdateFeatureDto.shape.controlVariation.describe( 'Updated control variation key for Metrics', ), + // summary: UpdateFeatureDto.shape.summary.describe( + // 'Updated feature summary', + // ), + // staleness: UpdateFeatureDto.shape.staleness.describe( + // 'Updated feature staleness configuration', + // ), }) export const UpdateFeatureStatusArgsSchema = z.object({ @@ -376,14 +396,12 @@ const variablesDescription = export const CreateVariationArgsSchema = z.object({ feature_key: z.string().describe('Feature key to create variation for'), - key: schemas.CreateVariationDto.shape.key.describe( + key: CreateVariationDto.shape.key.describe( 'Unique variation key (lowercase letters, numbers, dots, dashes, underscores only)', ), - name: schemas.CreateVariationDto.shape.name, + name: CreateVariationDto.shape.name, variables: - schemas.CreateVariationDto.shape.variables.describe( - variablesDescription, - ), + CreateVariationDto.shape.variables.describe(variablesDescription), }) export const UpdateVariationArgsSchema = z.object({ @@ -391,10 +409,10 @@ export const UpdateVariationArgsSchema = z.object({ .string() .describe('Feature key that the variation belongs to'), variation_key: z.string().describe('key to identify variation to update'), - key: schemas.UpdateFeatureVariationDto.shape.key.describe( + key: UpdateFeatureVariationDto.shape.key.describe( 'Updated variation key (lowercase letters, numbers, dots, dashes, underscores only)', ), - name: schemas.UpdateFeatureVariationDto.shape.name, + name: UpdateFeatureVariationDto.shape.name, variables: z .record( z.union([ @@ -421,8 +439,8 @@ export const UpdateFeatureTargetingArgsSchema = z.object({ environment_key: z .string() .describe('Environment key to update targeting in'), - status: schemas.UpdateFeatureConfigDto.shape.status, - targets: schemas.UpdateFeatureConfigDto.shape.targets.describe( + status: UpdateFeatureConfigDto.shape.status, + targets: UpdateFeatureConfigDto.shape.targets.describe( 'Updated array of targeting rules/targets for the feature', ), }) @@ -554,12 +572,12 @@ export const ListCustomPropertiesArgsSchema = z.object({ }) export const UpsertCustomPropertyArgsSchema = z.object({ - name: schemas.CreateCustomPropertyDto.shape.name, - key: schemas.CreateCustomPropertyDto.shape.key.describe( + name: CreateCustomPropertyDto.shape.name, + key: CreateCustomPropertyDto.shape.key.describe( 'Unique custom property key (lowercase letters, numbers, dots, dashes, underscores only)', ), - type: schemas.CreateCustomPropertyDto.shape.type, - propertyKey: schemas.CreateCustomPropertyDto.shape.propertyKey.describe( + type: CreateCustomPropertyDto.shape.type, + propertyKey: CreateCustomPropertyDto.shape.propertyKey.describe( 'Property key to associate with the custom property', ), }) @@ -570,9 +588,9 @@ export const UpdateCustomPropertyArgsSchema = z.object({ .max(100) .regex(/^[a-z0-9-_.]+$/) .describe('key to identify property to update'), - name: schemas.UpdateCustomPropertyDto.shape.name, - propertyKey: schemas.UpdateCustomPropertyDto.shape.propertyKey, - type: schemas.UpdateCustomPropertyDto.shape.type, + name: UpdateCustomPropertyDto.shape.name, + propertyKey: UpdateCustomPropertyDto.shape.propertyKey, + type: UpdateCustomPropertyDto.shape.type, }) export const DeleteCustomPropertyArgsSchema = z.object({ diff --git a/src/ui/prompts/environmentPrompts.ts b/src/ui/prompts/environmentPrompts.ts index b272eea4d..a7dad2da4 100644 --- a/src/ui/prompts/environmentPrompts.ts +++ b/src/ui/prompts/environmentPrompts.ts @@ -33,7 +33,7 @@ export const environmentChoices = async ( input.projectKey, ) choices = environments - .map((environment) => { + .map((environment: Environment) => { const name = environment.name ? `${environment.name} ${chalk.dim(`(${environment.key})`)}` : environment.key @@ -43,7 +43,7 @@ export const environmentChoices = async ( } }) .sort( - (a, b) => + (a: { value: Environment }, b: { value: Environment }) => EnvironmentTypeValue[a.value.type] - EnvironmentTypeValue[b.value.type], ) diff --git a/src/ui/prompts/variablePrompts.ts b/src/ui/prompts/variablePrompts.ts index 5fdc9dd84..9859e79ef 100644 --- a/src/ui/prompts/variablePrompts.ts +++ b/src/ui/prompts/variablePrompts.ts @@ -35,7 +35,7 @@ export const variableChoices = async ( const variables = await fetchVariables(input.token, input.projectKey, { perPage: 1000, }) - choices = variables.map((variable) => { + choices = variables.map((variable: Variable) => { const name = variable.name ? `${variable.name} ${chalk.dim(`(${variable.key})`)}` : variable.key diff --git a/tsconfig.json b/tsconfig.json index 0a811006a..e4d9f3b3b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,8 +5,8 @@ "lib": ["ES2022"], "outDir": "dist", "rootDir": "src", - "declaration": true, - "declarationMap": true, + "declaration": false, + "declarationMap": false, "sourceMap": true, "strict": true, "strictPropertyInitialization": false, @@ -21,7 +21,7 @@ "resolveJsonModule": true, "isolatedModules": true, "incremental": true, - "composite": true, + "composite": false, "tsBuildInfoFile": "./dist/.tsbuildinfo" }, "include": ["src/**/*"], diff --git a/yarn.lock b/yarn.lock index a2ea59d5d..646526b81 100644 --- a/yarn.lock +++ b/yarn.lock @@ -667,50 +667,50 @@ __metadata: languageName: node linkType: hard -"@cloudflare/unenv-preset@npm:2.6.2": - version: 2.6.2 - resolution: "@cloudflare/unenv-preset@npm:2.6.2" +"@cloudflare/unenv-preset@npm:2.7.3": + version: 2.7.3 + resolution: "@cloudflare/unenv-preset@npm:2.7.3" peerDependencies: - unenv: 2.0.0-rc.19 - workerd: ^1.20250802.0 + unenv: 2.0.0-rc.21 + workerd: ^1.20250828.1 peerDependenciesMeta: workerd: optional: true - checksum: 10c0/d9230c241551f09abf25c61205ad300da7f834c16b431f69facae34e52ca66a46f7844b3d32bfff799c93337b3ab612eeb35841f1836f94bc747f17c0947cd44 + checksum: 10c0/13d0fdf2183d1c55e3f5dd02c42619df61b130fa772a1add25d46680fa43adda952408449ba83b79bc045ac55409892ac002c8d52d457d8b20c2c7cf0749eeb2 languageName: node linkType: hard -"@cloudflare/workerd-darwin-64@npm:1.20250816.0": - version: 1.20250816.0 - resolution: "@cloudflare/workerd-darwin-64@npm:1.20250816.0" +"@cloudflare/workerd-darwin-64@npm:1.20250906.0": + version: 1.20250906.0 + resolution: "@cloudflare/workerd-darwin-64@npm:1.20250906.0" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@cloudflare/workerd-darwin-arm64@npm:1.20250816.0": - version: 1.20250816.0 - resolution: "@cloudflare/workerd-darwin-arm64@npm:1.20250816.0" +"@cloudflare/workerd-darwin-arm64@npm:1.20250906.0": + version: 1.20250906.0 + resolution: "@cloudflare/workerd-darwin-arm64@npm:1.20250906.0" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@cloudflare/workerd-linux-64@npm:1.20250816.0": - version: 1.20250816.0 - resolution: "@cloudflare/workerd-linux-64@npm:1.20250816.0" +"@cloudflare/workerd-linux-64@npm:1.20250906.0": + version: 1.20250906.0 + resolution: "@cloudflare/workerd-linux-64@npm:1.20250906.0" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@cloudflare/workerd-linux-arm64@npm:1.20250816.0": - version: 1.20250816.0 - resolution: "@cloudflare/workerd-linux-arm64@npm:1.20250816.0" +"@cloudflare/workerd-linux-arm64@npm:1.20250906.0": + version: 1.20250906.0 + resolution: "@cloudflare/workerd-linux-arm64@npm:1.20250906.0" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@cloudflare/workerd-windows-64@npm:1.20250816.0": - version: 1.20250816.0 - resolution: "@cloudflare/workerd-windows-64@npm:1.20250816.0" +"@cloudflare/workerd-windows-64@npm:1.20250906.0": + version: 1.20250906.0 + resolution: "@cloudflare/workerd-windows-64@npm:1.20250906.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -821,7 +821,7 @@ __metadata: jose: "npm:^6.0.12" oauth4webapi: "npm:^3.6.1" vitest: "npm:^3.2.4" - wrangler: "npm:^4.31.0" + wrangler: "npm:^4.36.0" languageName: unknown linkType: soft @@ -7682,9 +7682,9 @@ __metadata: languageName: node linkType: hard -"miniflare@npm:4.20250816.1": - version: 4.20250816.1 - resolution: "miniflare@npm:4.20250816.1" +"miniflare@npm:4.20250906.1": + version: 4.20250906.1 + resolution: "miniflare@npm:4.20250906.1" dependencies: "@cspotcode/source-map-support": "npm:0.8.1" acorn: "npm:8.14.0" @@ -7693,14 +7693,14 @@ __metadata: glob-to-regexp: "npm:0.4.1" sharp: "npm:^0.33.5" stoppable: "npm:1.1.0" - undici: "npm:^7.10.0" - workerd: "npm:1.20250816.0" + undici: "npm:7.14.0" + workerd: "npm:1.20250906.0" ws: "npm:8.18.0" youch: "npm:4.1.0-beta.10" zod: "npm:3.22.3" bin: miniflare: bootstrap.js - checksum: 10c0/342a02c6fb8cded476b197fd1dd51579ad5ff7d77108df09f38ebd80903d9e2d7faf8e81c991c25165bdae94464ed40af21b91da86cebdb76d13136aa1e3ee63 + checksum: 10c0/681123793f23e7f1c8273d52e6a67874528ed5d3a877dcd72702fd89befedfba6bc5298fbaa0b94024cd41a0071ab47fcfafe4442cbc5623736fc70d3236db29 languageName: node linkType: hard @@ -10899,23 +10899,23 @@ __metadata: languageName: node linkType: hard -"undici@npm:^7.10.0": - version: 7.13.0 - resolution: "undici@npm:7.13.0" - checksum: 10c0/8865d40b141f073215a6763aad5d1b2f4bd4e252600e93e68055d6c5d23a8a0e5782669236b2ecfa4d415d1d969d9c4623ff1c0386d32fa60088a19ffa58c611 +"undici@npm:7.14.0": + version: 7.14.0 + resolution: "undici@npm:7.14.0" + checksum: 10c0/4beab6a5bfb89add9e90195aee6bc993708afbabad33bff7da791b5334a6e26a591c29938822d2fb8f69ae0ad8d580d64e03247b11157af9f820d5bd9f8f16e7 languageName: node linkType: hard -"unenv@npm:2.0.0-rc.19": - version: 2.0.0-rc.19 - resolution: "unenv@npm:2.0.0-rc.19" +"unenv@npm:2.0.0-rc.21": + version: 2.0.0-rc.21 + resolution: "unenv@npm:2.0.0-rc.21" dependencies: defu: "npm:^6.1.4" exsolve: "npm:^1.0.7" ohash: "npm:^2.0.11" pathe: "npm:^2.0.3" ufo: "npm:^1.6.1" - checksum: 10c0/6c104af99097704e3d65562e2ec3ed876a1846df0b61b4e0714e99128d6dd6103d7022d6425bb0bfc9f6f453c52d09d152ff31f83ec118188503a9e33677bc3c + checksum: 10c0/2fea6efed952314652f1c56c2bfcee1c1731a45409825ee8fd216f2781d289d8a98e4742b049fc33bbad888ca4b1a8f192297a7667cbcc0d97c04dfc12ade5a3 languageName: node linkType: hard @@ -11433,15 +11433,15 @@ __metadata: languageName: node linkType: hard -"workerd@npm:1.20250816.0": - version: 1.20250816.0 - resolution: "workerd@npm:1.20250816.0" +"workerd@npm:1.20250906.0": + version: 1.20250906.0 + resolution: "workerd@npm:1.20250906.0" dependencies: - "@cloudflare/workerd-darwin-64": "npm:1.20250816.0" - "@cloudflare/workerd-darwin-arm64": "npm:1.20250816.0" - "@cloudflare/workerd-linux-64": "npm:1.20250816.0" - "@cloudflare/workerd-linux-arm64": "npm:1.20250816.0" - "@cloudflare/workerd-windows-64": "npm:1.20250816.0" + "@cloudflare/workerd-darwin-64": "npm:1.20250906.0" + "@cloudflare/workerd-darwin-arm64": "npm:1.20250906.0" + "@cloudflare/workerd-linux-64": "npm:1.20250906.0" + "@cloudflare/workerd-linux-arm64": "npm:1.20250906.0" + "@cloudflare/workerd-windows-64": "npm:1.20250906.0" dependenciesMeta: "@cloudflare/workerd-darwin-64": optional: true @@ -11455,7 +11455,7 @@ __metadata: optional: true bin: workerd: bin/workerd - checksum: 10c0/ddb41844507a41bb7a8a315681947bc301d10c0bfe27b7bac6457148abf1af27df0a7a9ac840a5e049232c2760710dab4e62b4d36d3d07cbddafb05360b1014c + checksum: 10c0/14b9a5cd0e6abee0a0823e08ff6cc74f961b5ce7a0b2492f0ef4f9aaa81f0c35aac36b587c7d7e5780cd0002f8a853d4cd370154cacae298f4c671e1a842b0a3 languageName: node linkType: hard @@ -11466,21 +11466,21 @@ __metadata: languageName: node linkType: hard -"wrangler@npm:^4.31.0": - version: 4.32.0 - resolution: "wrangler@npm:4.32.0" +"wrangler@npm:^4.36.0": + version: 4.36.0 + resolution: "wrangler@npm:4.36.0" dependencies: "@cloudflare/kv-asset-handler": "npm:0.4.0" - "@cloudflare/unenv-preset": "npm:2.6.2" + "@cloudflare/unenv-preset": "npm:2.7.3" blake3-wasm: "npm:2.1.5" esbuild: "npm:0.25.4" fsevents: "npm:~2.3.2" - miniflare: "npm:4.20250816.1" + miniflare: "npm:4.20250906.1" path-to-regexp: "npm:6.3.0" - unenv: "npm:2.0.0-rc.19" - workerd: "npm:1.20250816.0" + unenv: "npm:2.0.0-rc.21" + workerd: "npm:1.20250906.0" peerDependencies: - "@cloudflare/workers-types": ^4.20250816.0 + "@cloudflare/workers-types": ^4.20250906.0 dependenciesMeta: fsevents: optional: true @@ -11490,7 +11490,7 @@ __metadata: bin: wrangler: bin/wrangler.js wrangler2: bin/wrangler.js - checksum: 10c0/8ef1410a513a0a82169e8d71e4a6195761dad1c0c620012d70530923aca2c6e106305e9675d8800899139c6f81a46c7d97046961bdca3c52b30decf5c0961b82 + checksum: 10c0/106a6d3547a06549400c7901f077fedfb75b67640c33821d0ef9dee4ef77e7891d5d16bf9bfa84884d93981c665695b02bd4c1f50d2686c524e2e41038a184a3 languageName: node linkType: hard