@stackframe/stack-shared 2.8.58 → 2.8.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/config/migrate-catalogs-to-product-lines.d.mts +12 -0
  2. package/dist/config/migrate-catalogs-to-product-lines.d.ts +12 -0
  3. package/dist/config/migrate-catalogs-to-product-lines.js +211 -0
  4. package/dist/config/migrate-catalogs-to-product-lines.js.map +1 -0
  5. package/dist/config/schema-fuzzer.test.js +17 -6
  6. package/dist/config/schema-fuzzer.test.js.map +1 -1
  7. package/dist/config/schema.d.mts +181 -157
  8. package/dist/config/schema.d.ts +181 -157
  9. package/dist/config/schema.js +39 -8
  10. package/dist/config/schema.js.map +1 -1
  11. package/dist/esm/config/migrate-catalogs-to-product-lines.js +186 -0
  12. package/dist/esm/config/migrate-catalogs-to-product-lines.js.map +1 -0
  13. package/dist/esm/config/schema-fuzzer.test.js +17 -6
  14. package/dist/esm/config/schema-fuzzer.test.js.map +1 -1
  15. package/dist/esm/config/schema.js +40 -9
  16. package/dist/esm/config/schema.js.map +1 -1
  17. package/dist/esm/interface/client-interface.js +111 -21
  18. package/dist/esm/interface/client-interface.js.map +1 -1
  19. package/dist/esm/interface/crud/products.js +12 -1
  20. package/dist/esm/interface/crud/products.js.map +1 -1
  21. package/dist/esm/interface/server-interface.js +38 -0
  22. package/dist/esm/interface/server-interface.js.map +1 -1
  23. package/dist/esm/known-errors.js +24 -0
  24. package/dist/esm/known-errors.js.map +1 -1
  25. package/dist/esm/schema-fields.js +1 -1
  26. package/dist/esm/schema-fields.js.map +1 -1
  27. package/dist/interface/client-interface.d.mts +31 -0
  28. package/dist/interface/client-interface.d.ts +31 -0
  29. package/dist/interface/client-interface.js +111 -21
  30. package/dist/interface/client-interface.js.map +1 -1
  31. package/dist/interface/crud/products.d.mts +77 -0
  32. package/dist/interface/crud/products.d.ts +77 -0
  33. package/dist/interface/crud/products.js +12 -1
  34. package/dist/interface/crud/products.js.map +1 -1
  35. package/dist/interface/server-interface.d.mts +23 -0
  36. package/dist/interface/server-interface.d.ts +23 -0
  37. package/dist/interface/server-interface.js +38 -0
  38. package/dist/interface/server-interface.js.map +1 -1
  39. package/dist/known-errors.d.mts +6 -0
  40. package/dist/known-errors.d.ts +6 -0
  41. package/dist/known-errors.js +24 -0
  42. package/dist/known-errors.js.map +1 -1
  43. package/dist/schema-fields.d.mts +4 -4
  44. package/dist/schema-fields.d.ts +4 -4
  45. package/dist/schema-fields.js +1 -1
  46. package/dist/schema-fields.js.map +1 -1
  47. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/config/schema.ts"],"sourcesContent":["// TODO: rename this file to spaghetti.ts because that's the kind of code here\n\n// IMPORTANT\n// WHENEVER YOU MAKE BACKWARDS-INCOMPATIBLE CHANGES TO THE CONFIG SCHEMA, YOU MUST UPDATE THE MIGRATION FUNCTIONS BELOW.\n// OTHERWISE THINGS WILL GO BOOM!!\n\nimport * as yup from \"yup\";\nimport { ALL_APPS } from \"../apps/apps-config\";\nimport { DEFAULT_EMAIL_TEMPLATES, DEFAULT_EMAIL_THEMES, DEFAULT_EMAIL_THEME_ID } from \"../helpers/emails\";\nimport * as schemaFields from \"../schema-fields\";\nimport { productSchema, userSpecifiedIdSchema, yupBoolean, yupDate, yupMixed, yupNever, yupNumber, yupObject, yupRecord, yupString, yupTuple, yupUnion } from \"../schema-fields\";\nimport { SUPPORTED_CURRENCIES } from \"../utils/currency-constants\";\nimport { StackAssertionError } from \"../utils/errors\";\nimport { allProviders } from \"../utils/oauth\";\nimport { DeepFilterUndefined, DeepMerge, DeepRequiredOrUndefined, filterUndefined, get, has, isObjectLike, mapValues, set, typedAssign, typedEntries, typedFromEntries } from \"../utils/objects\";\nimport { Result } from \"../utils/results\";\nimport { CollapseObjectUnion, Expand, IntersectAll, IsUnion, typeAssert, typeAssertExtends, typeAssertIs } from \"../utils/types\";\nimport { Config, NormalizationError, NormalizesTo, assertNormalized, getInvalidConfigReason, normalize } from \"./format\";\n\nexport const configLevels = ['project', 'branch', 'environment', 'organization'] as const;\nexport type ConfigLevel = typeof configLevels[number];\nconst permissionRegex = /^\\$?[a-z0-9_:]+$/;\nconst customPermissionRegex = /^[a-z0-9_:]+$/;\ndeclare module \"yup\" {\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n export interface CustomSchemaMetadata {\n stackConfigCanNoLongerBeOverridden?: true,\n }\n}\n\nfunction canNoLongerBeOverridden<T extends yup.AnyObjectSchema, K extends string[]>(schema: T, keys: K): yup.Schema<Omit<yup.InferType<T>, K[number]>, T['__context'], Omit<T['__default'], K[number]>, T['__flags']> {\n const notOmitted = schema.concat(yupObject(\n Object.fromEntries(keys.map(key => [key, schema.getNested(key).meta({ stackConfigCanNoLongerBeOverridden: true })]))\n ));\n return notOmitted as any;\n}\n\n/**\n * All fields that can be overridden at this level.\n */\nexport const projectConfigSchema = yupObject({\n sourceOfTruth: yupUnion(\n yupObject({\n type: yupString().oneOf(['hosted']).defined(),\n }),\n yupObject({\n type: yupString().oneOf(['neon']).defined(),\n connectionStrings: yupRecord(\n userSpecifiedIdSchema(\"connectionStringId\").defined(),\n yupString().defined(),\n ).defined(),\n }),\n yupObject({\n type: yupString().oneOf(['postgres']).defined(),\n connectionString: yupString().defined()\n }),\n ),\n});\n\n// --- NEW RBAC Schema ---\nconst branchRbacDefaultPermissions = yupRecord(\n yupString().matches(permissionRegex),\n yupBoolean().isTrue().optional(),\n);\n\nconst branchRbacSchema = yupObject({\n permissions: yupRecord(\n yupString().matches(customPermissionRegex),\n yupObject({\n description: yupString().optional(),\n scope: yupString().oneOf(['team', 'project']).optional(),\n containedPermissionIds: yupRecord(\n yupString().matches(permissionRegex),\n yupBoolean().isTrue().optional()\n ).optional(),\n }).optional(),\n ),\n defaultPermissions: yupObject({\n teamCreator: branchRbacDefaultPermissions,\n teamMember: branchRbacDefaultPermissions,\n signUp: branchRbacDefaultPermissions,\n }),\n});\n// --- END NEW RBAC Schema ---\n\n// --- NEW API Keys Schema ---\nconst branchApiKeysSchema = yupObject({\n enabled: yupObject({\n team: yupBoolean(),\n user: yupBoolean(),\n }),\n});\n// --- END NEW API Keys Schema ---\n\n// --- NEW Apps Schema ---\nconst appIds = Object.keys(ALL_APPS) as (keyof typeof ALL_APPS)[];\nconst branchAppsSchema = yupObject({\n installed: yupRecord(\n yupString().oneOf(appIds),\n yupObject({\n enabled: yupBoolean(),\n }),\n ).test(\n 'authentication-and-emails-enabled',\n 'authentication and emails must be installed and enabled',\n function(value) {\n const hasAuthentication = value['authentication'].enabled === true;\n const hasEmails = value['emails'].enabled === true;\n if (!hasAuthentication || !hasEmails) {\n return this.createError({\n message: 'authentication and emails must be installed and enabled',\n path: this.path,\n });\n }\n return true;\n }\n ),\n});\n// --- END NEW Apps Schema ---\n\n\nconst branchAuthSchema = yupObject({\n allowSignUp: yupBoolean(),\n password: yupObject({\n allowSignIn: yupBoolean(),\n }),\n otp: yupObject({\n allowSignIn: yupBoolean(),\n }),\n passkey: yupObject({\n allowSignIn: yupBoolean(),\n }),\n oauth: yupObject({\n accountMergeStrategy: yupString().oneOf(['link_method', 'raise_error', 'allow_duplicates']).optional(),\n providers: yupRecord(\n yupString().matches(permissionRegex),\n yupObject({\n type: yupString().oneOf(allProviders).optional(),\n allowSignIn: yupBoolean(),\n allowConnectedAccounts: yupBoolean(),\n }),\n ),\n }),\n});\n\nexport const branchPaymentsSchema = yupObject({\n autoPay: yupObject({\n interval: schemaFields.dayIntervalSchema,\n }).optional(),\n testMode: yupBoolean(),\n catalogs: yupRecord(\n userSpecifiedIdSchema(\"catalogId\"),\n yupObject({\n displayName: yupString().optional(),\n }),\n ).meta({ openapiField: { description: 'The catalogs that products can be in. All products in a catalog (besides add-ons) are mutually exclusive.', exampleValue: { \"catalog-id\": { displayName: \"My Catalog\" } } } }),\n products: yupRecord(\n userSpecifiedIdSchema(\"productId\"),\n productSchema,\n ),\n items: yupRecord(\n userSpecifiedIdSchema(\"itemId\"),\n yupObject({\n displayName: yupString().optional(),\n customerType: schemaFields.customerTypeSchema,\n }),\n ),\n});\n\nconst branchDomain = yupObject({\n allowLocalhost: yupBoolean(),\n});\n\nconst branchOnboardingSchema = yupObject({\n requireEmailVerification: yupBoolean(),\n});\n\n\nexport const branchConfigSchema = canNoLongerBeOverridden(projectConfigSchema, [\"sourceOfTruth\"]).concat(yupObject({\n rbac: branchRbacSchema,\n\n teams: yupObject({\n createPersonalTeamOnSignUp: yupBoolean(),\n allowClientTeamCreation: yupBoolean(),\n }),\n\n users: yupObject({\n allowClientUserDeletion: yupBoolean(),\n }),\n\n onboarding: branchOnboardingSchema,\n\n apiKeys: branchApiKeysSchema,\n\n apps: branchAppsSchema,\n\n domains: branchDomain,\n\n auth: branchAuthSchema,\n\n emails: yupObject({\n selectedThemeId: schemaFields.emailThemeSchema,\n themes: schemaFields.emailThemeListSchema,\n templates: schemaFields.emailTemplateListSchema,\n }),\n\n payments: branchPaymentsSchema,\n\n dataVault: yupObject({\n stores: yupRecord(\n userSpecifiedIdSchema(\"storeId\"),\n yupObject({\n displayName: yupString(),\n }),\n ),\n }),\n}));\n\n\nexport const environmentConfigSchema = branchConfigSchema.concat(yupObject({\n auth: branchConfigSchema.getNested(\"auth\").concat(yupObject({\n oauth: branchConfigSchema.getNested(\"auth\").getNested(\"oauth\").concat(yupObject({\n providers: yupRecord(\n yupString().matches(permissionRegex),\n yupObject({\n type: yupString().oneOf(allProviders).optional(),\n isShared: yupBoolean(),\n clientId: schemaFields.oauthClientIdSchema.optional(),\n clientSecret: schemaFields.oauthClientSecretSchema.optional(),\n facebookConfigId: schemaFields.oauthFacebookConfigIdSchema.optional(),\n microsoftTenantId: schemaFields.oauthMicrosoftTenantIdSchema.optional(),\n allowSignIn: yupBoolean().optional(),\n allowConnectedAccounts: yupBoolean().optional(),\n }),\n ),\n })),\n })),\n\n emails: branchConfigSchema.getNested(\"emails\").concat(yupObject({\n server: yupObject({\n isShared: yupBoolean(),\n provider: yupString().oneOf(['resend', 'smtp']).optional(),\n host: schemaFields.emailHostSchema.optional().nonEmpty(),\n port: schemaFields.emailPortSchema.optional(),\n username: schemaFields.emailUsernameSchema.optional().nonEmpty(),\n password: schemaFields.emailPasswordSchema.optional().nonEmpty(),\n senderName: schemaFields.emailSenderNameSchema.optional().nonEmpty(),\n senderEmail: schemaFields.emailSenderEmailSchema.optional().nonEmpty(),\n }),\n })),\n\n domains: branchConfigSchema.getNested(\"domains\").concat(yupObject({\n trustedDomains: yupRecord(\n userSpecifiedIdSchema(\"trustedDomainId\"),\n yupObject({\n baseUrl: schemaFields.wildcardUrlSchema.max(300), // TODO: replace with wildcardProtocolAndDomainSchema (this will require a migration as some configs have domains that are not valid wildcard protocol and domain patterns)\n handlerPath: schemaFields.handlerPathSchema.max(300),\n }),\n ),\n })),\n}));\n\nexport const organizationConfigSchema = environmentConfigSchema.concat(yupObject({}));\n\n\n// Migration functions\n//\n// These are used to migrate old config overrides to the new format on the database.\n//\n// THEY SHOULD NOT BE USED FOR ANY OTHER PURPOSE. They should not be used for default values. They should not be used\n// for sanitization. Instead, use the applicable functions for that.\n//\n// We run these migrations over the database when we do a big migration. USE THESE SPARINGLY. USE OTHER METHODS WHENEVER\n// POSSIBLE.\n//\n// The result of this function should be reproducible, and should not contain ANY randomness/non-determinism.\nexport function migrateConfigOverride(type: \"project\" | \"branch\" | \"environment\" | \"organization\", oldUnmigratedConfigOverride: any): any {\n const isBranchOrHigher = [\"branch\", \"environment\", \"organization\"].includes(type);\n const isEnvironmentOrHigher = [\"environment\", \"organization\"].includes(type);\n\n let res = oldUnmigratedConfigOverride;\n\n // BEGIN 2025-07-28: emails.theme is now emails.selectedThemeId\n if (isBranchOrHigher) {\n res = renameProperty(res, \"emails.theme\", \"selectedThemeId\");\n }\n // END\n\n // BEGIN 2025-07-28: domains.trustedDomains can no longer be an array\n if (isEnvironmentOrHigher) {\n res = mapProperty(res, p => p.join(\".\") === \"domains.trustedDomains\", (value) => {\n if (Array.isArray(value)) {\n return typedFromEntries(value.map((v, i) => [`${i}`, v]));\n }\n return value;\n });\n }\n // END\n\n // BEGIN 2025-07-28: themeList and templateList have been renamed (this was before the email release, so they're safe to remove)\n if (isBranchOrHigher) {\n res = removeProperty(res, p => p.join(\".\") === \"emails.themeList\");\n res = removeProperty(res, p => p.join(\".\") === \"emails.templateList\");\n }\n // END\n\n // BEGIN 2025-07-28: sourceOfTruth was mistakenly written to the environment config in some cases, so let's remove it\n if (type === \"environment\") {\n res = removeProperty(res, p => p.join(\".\") === \"sourceOfTruth\");\n }\n // END\n\n // BEGIN 2025-08-25: stripeAccountId and stripeAccountSetupComplete are unused, so let's remove them\n if (type === \"environment\") {\n res = removeProperty(res, p => p.join(\".\") === \"payments.stripeAccountId\");\n res = removeProperty(res, p => p.join(\".\") === \"payments.stripeAccountSetupComplete\");\n }\n // END\n\n // BEGIN 2025-08-25: payments.items.default is no longer used, so let's remove it\n if (isBranchOrHigher) {\n res = removeProperty(res, p => p.length === 4 && p[0] === \"payments\" && p[1] === \"items\" && p[3] === \"default\");\n }\n // END\n\n // BEGIN 2025-09-23: payments.offers is now payments.products\n if (isBranchOrHigher) {\n res = renameProperty(res, \"payments.offers\", \"products\");\n }\n // END\n\n // BEGIN 2025-09-23: payments.groups is now payments.catalogs\n if (isBranchOrHigher) {\n res = renameProperty(res, \"payments.groups\", \"catalogs\");\n }\n // END\n\n // BEGIN 2025-09-23: payments.products.*.groupId is now payments.products.*.catalogId\n if (isBranchOrHigher) {\n res = renameProperty(res, (p) => p.length === 4 && p[0] === \"payments\" && p[1] === \"products\" && p[3] === \"groupId\", (p) => \"catalogId\");\n }\n // END\n\n // BEGIN 2025-10-29: Removed workflows and everything associated with it\n if (isBranchOrHigher) {\n res = removeProperty(res, p => p[0] === \"workflows\");\n res = removeProperty(res, p => p[0] === \"apps\" && p[1] === \"installed\" && p[2] === \"workflows\");\n }\n // END\n\n // return the result\n return res;\n};\n\nfunction removeProperty(obj: Record<string, any>, pathCond: (path: (string | symbol)[]) => boolean): any {\n return mapProperty(obj, pathCond, () => undefined);\n}\n\nfunction mapProperty(obj: Record<string, any>, pathCond: (path: string[]) => boolean, mapper: (value: any) => any): any {\n const res: Record<string, any> = Array.isArray(obj) ? [] : {};\n for (const [key, value] of typedEntries(obj)) {\n const path = key.split(\".\");\n if (pathCond(path)) {\n const newValue = mapper(value);\n if (newValue !== undefined) {\n set(res, key, newValue);\n } else {\n // do nothing\n }\n } else if (isObjectLike(value)) {\n set(res, key, mapProperty(value, p => pathCond([...path, ...p]), mapper));\n } else {\n set(res, key, value);\n }\n }\n return res;\n}\nundefined?.test(\"mapProperty - basic property mapping\", ({ expect }) => {\n expect(mapProperty({ a: { b: { c: 1 } } }, p => p.join(\".\") === \"a.b.c\", (value) => value + 1)).toEqual({ a: { b: { c: 2 } } });\n expect(mapProperty({ a: { b: { c: 1 } } }, p => p.join(\".\") === \"a.b.d\", (value) => value + 1)).toEqual({ a: { b: { c: 1 } } });\n expect(mapProperty({ x: 5 }, p => p.join(\".\") === \"x\", (value) => value * 2)).toEqual({ x: 10 });\n expect(mapProperty({ a: { b: { c: 1 } } }, p => p.join(\".\") === \"b.c\", (value) => value * 10)).toEqual({ a: { b: { c: 1 } } });\n expect(mapProperty({ a: 1 }, p => p.join(\".\") === \"b.c\", (value) => value)).toEqual({ a: 1 });\n expect(mapProperty({ \"a.b\": { c: 1 } }, p => p.join(\".\") === \"a.b.c\", (value) => value + 1)).toEqual({ \"a.b\": { c: 2 } });\n\n expect(mapProperty({ a: { b: { c: 1 } } }, p => p.length === 3 && p[0] === \"a\" && p[1] === \"b\", (value) => value + 1)).toEqual({ a: { b: { c: 2 } } });\n});\n\nfunction renameProperty(obj: Record<string, any>, oldPath: string | ((path: string[]) => boolean), newName: string | ((path: string[]) => string)): any {\n const pathCond = typeof oldPath === \"function\" ? oldPath : (p: string[]) => p.join(\".\") === oldPath;\n const pathMapper = typeof newName === \"function\" ? newName : (p: string[]) => (newName as string);\n\n const res: Record<string, any> = Array.isArray(obj) ? [] : {};\n for (const [key, originalValue] of typedEntries(obj)) {\n const path = key.split(\".\");\n\n for (let i = 0; i < path.length; i++) {\n const pathPrefix = path.slice(0, i + 1);\n if (pathCond(pathPrefix)) {\n const name = pathMapper(pathPrefix);\n if (name.includes(\".\")) throw new StackAssertionError(`newName must not contain a dot. Provided: ${name}`);\n path[i] = name;\n }\n }\n\n const value = isObjectLike(originalValue) ? renameProperty(originalValue, p => pathCond([...path, ...p]), p => pathMapper([...path, ...p])) : originalValue;\n set(res, path.join(\".\"), value);\n }\n\n return res;\n}\nundefined?.test(\"renameProperty\", ({ expect }) => {\n // Basic\n expect(renameProperty({ a: 1 }, \"a\", \"b\")).toEqual({ b: 1 });\n expect(renameProperty({ b: { c: 1 } }, \"b.c\", \"d\")).toEqual({ b: { d: 1 } });\n expect(renameProperty({ a: { b: { c: 1 } } }, \"a.b.c\", \"d\")).toEqual({ a: { b: { d: 1 } } });\n expect(renameProperty({ a: { b: { c: 1 } } }, \"a.b.c.d\", \"e\")).toEqual({ a: { b: { c: 1 } } });\n expect(renameProperty({ a: { b: { c: 1 }, \"b.c\": 2 } }, \"b.c\", \"d\")).toEqual({ a: { b: { c: 1 }, \"b.c\": 2 } });\n expect(renameProperty({ a: { \"b.c.d\": 2 } }, \"a.b.c\", \"e\")).toEqual({ a: { \"b.e.d\": 2 } });\n expect(renameProperty({ a: { b: { c: 1 }, \"b.c\": 2 } }, \"a.b.c\", \"d\")).toEqual({ a: { b: { d: 1 }, \"b.d\": 2 } });\n expect(renameProperty({ a: { b: { c: 1, d: 2 } } }, \"a.b.c\", \"d\")).toEqual({ a: { b: { d: 2 } } });\n expect(renameProperty({ a: { b: { d: 2, c: 1 } } }, \"a.b.c\", \"d\")).toEqual({ a: { b: { d: 1 } } });\n\n // Functions\n expect(renameProperty({ a: 1 }, (p) => p.length === 1 && p[0] === \"a\", (p) => \"b\")).toEqual({ b: 1 });\n expect(renameProperty({ a: { b: { c: 1 } } }, (p) => p.length === 3 && p[0] === \"a\" && p[1] === \"b\" && p[2] === \"c\", (p) => \"d\")).toEqual({ a: { b: { d: 1 } } });\n expect(renameProperty({ a: { b: { c: 1 } } }, (p) => false, (p) => \"e\")).toEqual({ a: { b: { c: 1 } } });\n expect(renameProperty({ a: { b: { a: 1 } } }, (p) => p[p.length - 1] === \"a\", (p) => \"c\")).toEqual({ c: { b: { c: 1 } } });\n\n // Errors\n expect(() => renameProperty({ a: 1 }, \"a\", \"b.c\")).toThrow();\n});\n\n\n// Defaults\n// these are objects that are merged together to form the rendered config (see ./README.md)\n// Wherever an object could be used as a value, a function can instead be used to generate the default values on a per-key basis\n// To make sure you don't accidentally forget setting a default value, you must explicitly set fields with no default value to `undefined`.\n// NOTE: These values are the defaults of the schema, NOT the defaults for newly created projects. The values here signify what `null` means for each property. If you want new projects by default to have a certain value set to true, you should update the corresponding function in the backend instead.\nconst projectConfigDefaults = {\n sourceOfTruth: {\n type: 'hosted',\n connectionStrings: undefined,\n connectionString: undefined,\n },\n} as const satisfies DefaultsType<ProjectRenderedConfigBeforeDefaults, []>;\n\nconst branchConfigDefaults = {} as const satisfies DefaultsType<BranchRenderedConfigBeforeDefaults, [typeof projectConfigDefaults]>;\n\nconst environmentConfigDefaults = {} as const satisfies DefaultsType<EnvironmentRenderedConfigBeforeDefaults, [typeof branchConfigDefaults, typeof projectConfigDefaults]>;\n\nconst organizationConfigDefaults = {\n rbac: {\n permissions: (key: string) => ({\n containedPermissionIds: (key: string) => undefined,\n description: undefined,\n scope: undefined,\n }),\n defaultPermissions: {\n teamCreator: (key: string) => undefined,\n teamMember: (key: string) => undefined,\n signUp: (key: string) => undefined,\n },\n },\n\n apiKeys: {\n enabled: {\n team: false,\n user: false,\n },\n },\n\n apps: {\n installed: typedFromEntries(appIds.map(appId => [appId, { enabled: false }])) as Record<string, { enabled: boolean } | undefined>,\n },\n\n teams: {\n createPersonalTeamOnSignUp: false,\n allowClientTeamCreation: false,\n },\n\n users: {\n allowClientUserDeletion: false,\n },\n\n onboarding: {\n requireEmailVerification: false,\n },\n\n domains: {\n allowLocalhost: false,\n trustedDomains: (key: string) => ({\n baseUrl: undefined,\n handlerPath: '/handler',\n }) as const,\n },\n\n auth: {\n allowSignUp: true,\n password: {\n allowSignIn: false,\n },\n otp: {\n allowSignIn: false,\n },\n passkey: {\n allowSignIn: false,\n },\n oauth: {\n accountMergeStrategy: 'link_method',\n providers: (key: string) => ({\n type: undefined,\n isShared: true,\n allowSignIn: false,\n allowConnectedAccounts: false,\n clientId: undefined,\n clientSecret: undefined,\n facebookConfigId: undefined,\n microsoftTenantId: undefined,\n }),\n },\n },\n\n emails: {\n server: {\n isShared: true,\n provider: \"smtp\",\n host: undefined,\n port: undefined,\n username: undefined,\n password: undefined,\n senderName: undefined,\n senderEmail: undefined,\n },\n selectedThemeId: DEFAULT_EMAIL_THEME_ID,\n themes: typedAssign((key: string) => ({\n displayName: \"Unnamed Theme\",\n tsxSource: \"Error: Theme config is missing TypeScript source code.\",\n }), DEFAULT_EMAIL_THEMES),\n templates: typedAssign((key: string) => ({\n displayName: \"Unnamed Template\",\n tsxSource: \"Error: Template config is missing TypeScript source code.\",\n themeId: undefined,\n }), DEFAULT_EMAIL_TEMPLATES),\n },\n\n payments: {\n testMode: true,\n autoPay: undefined,\n catalogs: (key: string) => ({\n displayName: undefined,\n }),\n products: (key: string) => ({\n displayName: key,\n catalogId: undefined,\n customerType: \"user\",\n freeTrial: undefined,\n serverOnly: false,\n stackable: undefined,\n isAddOnTo: false,\n prices: (key: string) => ({\n ...typedFromEntries(SUPPORTED_CURRENCIES.map(currency => [currency.code, undefined])),\n interval: undefined,\n serverOnly: false,\n freeTrial: undefined,\n }),\n includedItems: (key: string) => ({\n quantity: 0,\n repeat: \"never\",\n expires: \"when-repeated\",\n }),\n } as const),\n items: (key: string) => ({\n displayName: key,\n customerType: \"user\",\n } as const)\n },\n\n dataVault: {\n stores: (key: string) => ({\n displayName: \"Unnamed Vault\",\n }),\n },\n} as const satisfies DefaultsType<OrganizationRenderedConfigBeforeDefaults, [typeof environmentConfigDefaults, typeof branchConfigDefaults, typeof projectConfigDefaults]>;\n\ntype _DeepOmitDefaultsImpl<T, U> = T extends object ? (\n (\n & /* keys that are both in T and U, *and* the key's value in U is not a subtype of the key's value in T */ { [K in { [Ki in keyof T & keyof U]: U[Ki] extends T[Ki] ? never : Ki }[keyof T & keyof U]]: DeepOmitDefaults<T[K], U[K] & object> }\n & /* keys that are in T but not in U */ { [K in Exclude<keyof T, keyof U>]: T[K] }\n )\n) : T;\ntype DeepOmitDefaults<T, U> = _DeepOmitDefaultsImpl<DeepFilterUndefined<T>, U>;\ntype DefaultsType<T, U extends any[]> = DeepReplaceAllowFunctionsForObjects<DeepOmitDefaults<DeepRequiredOrUndefined<T>, IntersectAll<{ [K in keyof U]: DeepReplaceFunctionsWithObjects<U[K]> }>>>;\ntypeAssertIs<DefaultsType<{ a: { b: Record<string, 123>, c: 456 } }, [{ a: { c: 456 } }]>, { a: { b: ((key: string) => 123) | Record<string, 123 | undefined> & ((key: string) => 123) } }>()();\n\ntype DeepReplaceAllowFunctionsForObjects<T> = T extends object\n ? (\n string extends keyof T\n ? ((arg: Exclude<keyof T, number>) => DeepReplaceAllowFunctionsForObjects<T[keyof T]>) & ({ [K in keyof T]?: DeepReplaceAllowFunctionsForObjects<T[K]> } | {})\n : { [K in keyof T]: DeepReplaceAllowFunctionsForObjects<T[K]> }\n )\n :\n T;\ntype ReplaceFunctionsWithObjects<T> = T & (T extends (arg: infer K extends string) => infer R ? Record<K, R> & object : unknown);\ntype DeepReplaceFunctionsWithObjects<T> = T extends object ? { [K in keyof ReplaceFunctionsWithObjects<T>]: DeepReplaceFunctionsWithObjects<ReplaceFunctionsWithObjects<T>[K]> } : T;\ntypeAssertIs<DeepReplaceFunctionsWithObjects<{ a: { b: 123 } & ((key: string) => number) }>, { a: { b: 123, [key: string]: number } }>()();\n\nfunction deepReplaceFunctionsWithObjects(obj: any): any {\n return mapValues({ ...obj }, v => (isObjectLike(v) ? deepReplaceFunctionsWithObjects(v as any) : v));\n}\nundefined?.test(\"deepReplaceFunctionsWithObjects\", ({ expect }) => {\n expect(deepReplaceFunctionsWithObjects(() => { })).toEqual({});\n expect(deepReplaceFunctionsWithObjects({ a: 3 })).toEqual({ a: 3 });\n expect(deepReplaceFunctionsWithObjects({ a: () => ({ b: 1 }) })).toEqual({ a: {} });\n expect(deepReplaceFunctionsWithObjects({ a: typedAssign(() => ({}), { b: { c: 1 } }) })).toEqual({ a: { b: { c: 1 } } });\n});\n\ntype ApplyDefaults<D extends object | ((key: string) => unknown), C extends object> = {} extends D ? C : DeepMerge<DeepReplaceFunctionsWithObjects<D>, C>; // the {} extends D makes TypeScript not recurse if the defaults are empty, hence allowing us more recursion until \"type instantiation too deep\" kicks in... it's a total hack, but it works, so hey?\nfunction applyDefaults<D extends object | ((key: string) => unknown), C extends object>(defaults: D, config: C): ApplyDefaults<D, C> {\n const res: any = deepReplaceFunctionsWithObjects(defaults);\n\n outer: for (const [key, mergeValue] of Object.entries(config)) {\n if (mergeValue == null) continue;\n if (!isObjectLike(mergeValue)) {\n set(res, key, mergeValue);\n } else {\n const keyParts = key.split(\".\");\n let baseValue: any = defaults;\n for (const [index, part] of keyParts.entries()) {\n baseValue = has(baseValue, part) ? get(baseValue, part) : (typeof baseValue === 'function' ? (baseValue as any)(part) : undefined);\n if (baseValue === undefined || !isObjectLike(baseValue)) {\n set(res, key, mergeValue);\n continue outer;\n }\n }\n set(res, key, applyDefaults(baseValue, mergeValue));\n }\n }\n return res as any;\n}\nundefined?.test(\"applyDefaults\", ({ expect }) => {\n // Basic\n expect(applyDefaults({ a: 1 }, { a: 2 })).toEqual({ a: 2 });\n expect(applyDefaults({ a: 1 }, { a: null })).toEqual({ a: 1 });\n expect(applyDefaults({}, { a: 1 })).toEqual({ a: 1 });\n expect(applyDefaults({ a: { b: 1 } }, { a: { b: 2 } })).toEqual({ a: { b: 2 } });\n expect(applyDefaults({ a: { b: 1 } }, { a: { c: 2 } })).toEqual({ a: { b: 1, c: 2 } });\n expect(applyDefaults({ a: { b: { c: 1, d: 2 } } }, { a: { b: { d: 3, e: 4 } } })).toEqual({ a: { b: { c: 1, d: 3, e: 4 } } });\n\n // Functions\n expect(applyDefaults((key: string) => ({ b: key }), { a: {} })).toEqual({ a: { b: \"a\" } });\n expect(applyDefaults((key: string) => ({ b: key }), { a: null })).toEqual({});\n expect(applyDefaults((key1: string) => (key2: string) => ({ a: key1, b: key2 }), { c: { d: {} } })).toEqual({ c: { d: { a: \"c\", b: \"d\" } } });\n expect(applyDefaults({ a: (key: string) => ({ b: key }) }, { a: { c: { d: 1 } } })).toEqual({ a: { c: { b: \"c\", d: 1 } } });\n expect(applyDefaults({ a: (key: string) => ({ b: key }) }, {})).toEqual({ a: {} });\n expect(applyDefaults({ a: (key: string) => ({ b: key }) }, { a: null })).toEqual({ a: {} });\n expect(applyDefaults({ a: { b: (key: string) => ({ b: key }) } }, {})).toEqual({ a: { b: {} } });\n expect(applyDefaults(typedAssign(() => ({ b: 1 }), { a: { b: 1, c: 2 } }), { a: {} })).toEqual({ a: { b: 1, c: 2 } });\n expect(applyDefaults(typedAssign(() => ({ b: 1 }), { a: { b: 1, c: 2 } }), { d: {} })).toEqual({ a: { b: 1, c: 2 }, d: { b: 1 } });\n\n // Dot notation\n expect(applyDefaults({ a: { b: 1 } }, { \"a.c\": 2 })).toEqual({ a: { b: 1 }, \"a.c\": 2 });\n expect(applyDefaults({ a: { b: 1 } }, { \"a.c\": null })).toEqual({ a: { b: 1 } });\n expect(applyDefaults({ a: 1 }, { \"a.b\": 2 })).toEqual({ a: 1, \"a.b\": 2 });\n expect(applyDefaults({ a: null }, { \"a.b\": 2 })).toEqual({ a: null, \"a.b\": 2 });\n expect(applyDefaults({ a: { b: { c: 1 } } }, { \"a.b\": { d: 2 } })).toEqual({ a: { b: { c: 1 } }, \"a.b\": { c: 1, d: 2 } });\n expect(applyDefaults({ a: { b: { c: 1 } } }, { \"a.b\": null })).toEqual({ a: { b: { c: 1 } } });\n expect(applyDefaults({ a: { b: { c: { d: 1 } } } }, { \"a.b.c\": {} })).toEqual({ a: { b: { c: { d: 1 } } }, \"a.b.c\": { d: 1 } });\n expect(applyDefaults({ a: () => ({ c: 1 }) }, { \"a.b\": { d: 2 } })).toEqual({ a: {}, \"a.b\": { c: 1, d: 2 } });\n expect(applyDefaults({ a: () => () => ({ d: 1 }) }, { \"a.b.c\": {} })).toEqual({ a: {}, \"a.b.c\": { d: 1 } });\n expect(applyDefaults({ a: { b: () => ({ c: 1, d: 2 }) } }, { \"a.b.x-y.c\": 3 })).toEqual({ a: { b: {} }, \"a.b.x-y.c\": 3 });\n});\n\nexport function applyProjectDefaults<T extends ProjectRenderedConfigBeforeDefaults>(config: T) {\n return applyDefaults(projectConfigDefaults, config);\n}\n\nexport function applyBranchDefaults<T extends BranchRenderedConfigBeforeDefaults>(config: T) {\n return applyDefaults(\n branchConfigDefaults,\n applyDefaults(\n projectConfigDefaults,\n config\n )\n );\n}\n\nexport function applyEnvironmentDefaults<T extends EnvironmentRenderedConfigBeforeDefaults>(config: T): ApplyDefaults<typeof environmentConfigDefaults, ApplyDefaults<typeof branchConfigDefaults, ApplyDefaults<typeof projectConfigDefaults, T>>> {\n return applyDefaults(\n environmentConfigDefaults,\n applyDefaults(\n branchConfigDefaults,\n applyDefaults(\n projectConfigDefaults,\n config\n ) as any\n ) as any\n ) as any;\n}\n\nexport function applyOrganizationDefaults(config: OrganizationRenderedConfigBeforeDefaults): ApplyDefaults<typeof organizationConfigDefaults, ApplyDefaults<typeof environmentConfigDefaults, ApplyDefaults<typeof branchConfigDefaults, ApplyDefaults<typeof projectConfigDefaults, OrganizationRenderedConfigBeforeDefaults>>>> {\n return applyDefaults(\n organizationConfigDefaults,\n applyDefaults(\n environmentConfigDefaults,\n applyDefaults(\n branchConfigDefaults,\n applyDefaults(\n projectConfigDefaults,\n config\n ) as any\n ) as any\n ) as any\n ) as any;\n}\n\n\nexport async function sanitizeProjectConfig<T extends ProjectRenderedConfigBeforeSanitization>(config: T) {\n assertNormalized(config);\n const oldSourceOfTruth = config.sourceOfTruth;\n const sourceOfTruth =\n oldSourceOfTruth.type === 'neon' && typeof oldSourceOfTruth.connectionStrings === 'object' ? {\n type: 'neon',\n connectionStrings: { ...filterUndefined(oldSourceOfTruth.connectionStrings) as Record<string, string> }\n } as const\n : oldSourceOfTruth.type === 'postgres' && typeof oldSourceOfTruth.connectionString === 'string' ? {\n type: 'postgres',\n connectionString: oldSourceOfTruth.connectionString,\n } as const\n : {\n type: 'hosted',\n } as const;\n\n return {\n ...config,\n sourceOfTruth,\n };\n}\n\nexport async function sanitizeBranchConfig<T extends BranchRenderedConfigBeforeSanitization>(config: T) {\n assertNormalized(config);\n const prepared = await sanitizeProjectConfig(config);\n return {\n ...prepared,\n };\n}\n\nexport async function sanitizeEnvironmentConfig<T extends EnvironmentRenderedConfigBeforeSanitization>(config: T) {\n assertNormalized(config);\n const prepared = await sanitizeBranchConfig(config);\n return {\n ...prepared,\n };\n}\n\nexport async function sanitizeOrganizationConfig(config: OrganizationRenderedConfigBeforeSanitization) {\n assertNormalized(config);\n const prepared = await sanitizeEnvironmentConfig(config);\n const themes: typeof prepared.emails.themes = {\n ...DEFAULT_EMAIL_THEMES,\n ...prepared.emails.themes,\n };\n const templates: typeof prepared.emails.templates = {\n ...DEFAULT_EMAIL_TEMPLATES,\n ...(config.emails.server.isShared ? {} : prepared.emails.templates),\n };\n const products = typedFromEntries(typedEntries(prepared.payments.products).map(([key, product]) => {\n const isAddOnTo = product.isAddOnTo === false ?\n false as const :\n typedFromEntries(Object.keys(product.isAddOnTo).map((key) => [key, true as const]));\n const prices = product.prices === \"include-by-default\" ?\n \"include-by-default\" as const :\n typedFromEntries(typedEntries(product.prices).map(([key, value]) => {\n const data = { serverOnly: false, ...(value ?? {}) };\n return [key, data];\n }));\n return [key, {\n ...product,\n isAddOnTo,\n prices,\n }];\n }));\n\n const appSortIndices = new Map(Object.keys(ALL_APPS).map((appId, index) => [appId, index]));\n\n return {\n ...prepared,\n emails: {\n ...prepared.emails,\n selectedThemeId: has(themes, prepared.emails.selectedThemeId) ? prepared.emails.selectedThemeId : DEFAULT_EMAIL_THEME_ID,\n themes,\n templates,\n },\n payments: {\n ...prepared.payments,\n products\n },\n apps: {\n installed: typedFromEntries(\n typedEntries(prepared.apps.installed)\n .sort(([a], [b]) => appSortIndices.get(a)! - appSortIndices.get(b)!)\n ),\n },\n };\n}\n\n\n/**\n * Does not require a base config, and hence solely relies on the override itself to validate the config. If it returns\n * no error, you know that the\n *\n * It's crucial that our DB never contains any configs that are not valid according to this function, as this would mean\n * that the config object does not satisfy the ValidatedToHaveNoConfigOverrideErrors type (which is used as an assumption\n * in a whole bunch of places in the code).\n */\nexport async function getConfigOverrideErrors<T extends yup.AnySchema>(schema: T, configOverride: unknown, options: { allowPropertiesThatCanNoLongerBeOverridden?: boolean } = {}): Promise<Result<null, string>> {\n // currently, we go over the schema and ensure that the general requirements for each property are satisfied\n // importantly, we cannot check any cross-property constraints, as those may change depending on the base config\n // also, since overrides can be empty, we cannot have any required properties (TODO: can we have required properties in nested objects? would that even make sense? think about it)\n if (typeof configOverride !== \"object\" || configOverride === null) {\n return Result.error(\"Config override must be a non-null object.\");\n }\n if (Object.getPrototypeOf(configOverride) !== Object.getPrototypeOf({})) {\n return Result.error(\"Config override must be plain old JavaScript object.\");\n }\n // Check config format\n const reason = getInvalidConfigReason(configOverride, { configName: 'override' });\n if (reason) return Result.error(\"Invalid config format: \" + reason);\n\n const getSubSchema = (schema: yup.AnySchema, key: string): yup.AnySchema | undefined => {\n const keyParts = key.split(\".\");\n if (!schema.hasNested(keyParts[0])) {\n return undefined;\n }\n const nestedSchema = schema.getNested(keyParts[0]);\n if (nestedSchema.meta()?.stackConfigCanNoLongerBeOverridden && !options.allowPropertiesThatCanNoLongerBeOverridden) {\n return undefined;\n }\n if (keyParts.length === 1) {\n return nestedSchema;\n } else {\n return getSubSchema(nestedSchema, keyParts.slice(1).join(\".\"));\n }\n };\n\n const getRestrictedSchemaBase = (path: string, schema: yup.AnySchema): yup.AnySchema => {\n const schemaInfo = schema.meta()?.stackSchemaInfo;\n switch (schemaInfo?.type) {\n case \"string\": {\n const stringSchema = schema as yup.StringSchema<any>;\n const description = stringSchema.describe();\n let res = yupString();\n if (description.tests.some(t => t.name === \"uuid\")) {\n res = res.uuid();\n }\n return res;\n }\n case \"number\": {\n return yupNumber();\n }\n case \"boolean\": {\n return yupBoolean();\n }\n case \"date\": {\n return yupDate();\n }\n case \"mixed\": {\n return yupMixed();\n }\n case \"array\": {\n throw new StackAssertionError(`Arrays are not supported in config JSON files (besides tuples). Use a record instead.`, { schemaInfo, schema });\n\n // This is how the implementation would look like, but we don't support arrays in config JSON files (besides tuples)\n // const arraySchema = schema as yup.ArraySchema<any, any, any, any>;\n // const innerType = arraySchema.innerType;\n // return yupArray(innerType ? getRestrictedSchema(path + \".[]\", innerType as any) : undefined);\n }\n case \"tuple\": {\n return yupTuple(schemaInfo.items.map((s, index) => getRestrictedSchema(path + `[${index}]`, s)) as any);\n }\n case \"union\": {\n const schemas = schemaInfo.items;\n const nonObjectSchemas = [...schemas.entries()].filter(([index, s]) => s.meta()?.stackSchemaInfo?.type !== \"object\");\n const objectSchemas = schemas.filter((s): s is yup.ObjectSchema<any> => s.meta()?.stackSchemaInfo?.type === \"object\");\n\n // merge all object schemas into a single schema\n const allObjectSchemaKeys = [...new Set(objectSchemas.flatMap(s => Object.keys(s.fields)))];\n const mergedObjectSchema = yupObject(\n Object.fromEntries(\n allObjectSchemaKeys.map(key => [key, yupUnion(\n ...objectSchemas.flatMap((s, index) => s.hasNested(key) ? [s.getNested(key)] : [])\n )])\n )\n );\n\n return yupUnion(\n ...nonObjectSchemas.map(([index, s]) => getRestrictedSchema(path + `|variant-${index}|`, s)),\n ...objectSchemas.length > 0 ? [getRestrictedSchema(path + (nonObjectSchemas.length > 0 ? `|variant|` : \"\"), mergedObjectSchema)] : [],\n );\n }\n case \"record\": {\n return yupRecord(getRestrictedSchema(path + \".key\", schemaInfo.keySchema) as any, getRestrictedSchema(path + \".value\", schemaInfo.valueSchema));\n }\n case \"object\": {\n const objectSchema = schema as yup.ObjectSchema<any>;\n return yupObject(\n Object.fromEntries(\n Object.entries(objectSchema.fields)\n .map(([key, value]) => [key, getRestrictedSchema(path + \".\" + key, value as any)])\n )\n );\n }\n case \"never\": {\n return yupNever();\n }\n default: {\n throw new StackAssertionError(`Unknown schema info at path ${path}: ${JSON.stringify(schemaInfo)}`, { schemaInfo, schema });\n }\n }\n };\n const getRestrictedSchema = (path: string, schema: yup.AnySchema): yup.AnySchema => {\n let restricted = getRestrictedSchemaBase(path, schema);\n restricted = restricted.nullable();\n const description = schema.describe();\n if (description.oneOf.length > 0) {\n restricted = restricted.oneOf(description.oneOf);\n }\n if (description.notOneOf.length > 0) {\n restricted = restricted.notOneOf(description.notOneOf);\n }\n return restricted;\n };\n\n for (const [key, value] of Object.entries(configOverride)) {\n if (value === undefined) continue;\n const subSchema = getSubSchema(schema, key);\n if (!subSchema) {\n // find smallest key prefix that is invalid\n const keySplit = key.split(\".\");\n for (let i = 0; i < keySplit.length; i++) {\n const prefix = keySplit.slice(0, i + 1).join(\".\");\n const subSchema = getSubSchema(schema, prefix);\n if (!subSchema) {\n return Result.error(`The key ${JSON.stringify(key)} is not valid (nested object not found in schema: ${JSON.stringify(prefix)}).`);\n }\n }\n throw new StackAssertionError(\"Something weird happened? Sub-schema for key is invalid but no prefix is invalid??\", { key, subSchema });\n }\n let restrictedSchema = getRestrictedSchema(key, subSchema);\n try {\n await restrictedSchema.validate(value, {\n strict: true,\n ...{\n // Although `path` is not part of the yup types, it is actually recognized and does the correct thing\n path: key\n },\n context: {\n noUnknownPathPrefixes: [''],\n },\n });\n } catch (error) {\n if (error instanceof yup.ValidationError) {\n return Result.error(error.message);\n }\n throw error;\n }\n }\n return Result.ok(null);\n}\nexport async function assertNoConfigOverrideErrors<T extends yup.AnySchema>(schema: T, config: unknown, options: { allowPropertiesThatCanNoLongerBeOverridden?: boolean, extraInfo?: any } = {}): Promise<void> {\n const res = await getConfigOverrideErrors(schema, config, options);\n if (res.status === \"error\") throw new StackAssertionError(`Config override is invalid — at a place where it should have already been validated! ${res.error}`, { options, config });\n}\ntype _ValidatedToHaveNoConfigOverrideErrorsImpl<T> =\n IsUnion<T & object> extends true ? _ValidatedToHaveNoConfigOverrideErrorsImpl<CollapseObjectUnion<T & object> | Exclude<T, object>>\n : T extends object ? (T extends any[] ? T : { [K in keyof T]+?: _ValidatedToHaveNoConfigOverrideErrorsImpl<T[K]> })\n : T;\nexport type ValidatedToHaveNoConfigOverrideErrors<T extends yup.AnySchema> = _ValidatedToHaveNoConfigOverrideErrorsImpl<yup.InferType<T>>;\ntypeAssertIs<_ValidatedToHaveNoConfigOverrideErrorsImpl<{ a: string } | { b: number } | boolean>, { a?: string, b?: number } | boolean>()();\ntypeAssertExtends<_ValidatedToHaveNoConfigOverrideErrorsImpl<\"abc\" | 123 | null>, \"abc\" | 123 | null>()();\ntypeAssertExtends<_ValidatedToHaveNoConfigOverrideErrorsImpl<{ a: { b: { c: string } | { d: number } } }>, { a?: { b?: { c?: string, d?: number } } }>()();\n\n/**\n * Checks whether there are any warnings in the incomplete config. A warning doesn't stop the config from being valid,\n * but may require action regardless.\n *\n * The DB can contain configs that are not valid according to this function, as long as they are valid according to\n * the getConfigOverrideErrors function. (This is necessary, because a changing base config may make an override invalid\n * that was previously valid.)\n */\nexport async function getIncompleteConfigWarnings<T extends yup.AnySchema>(schema: T, incompleteConfig: Config): Promise<Result<null, string>> {\n // every rendered config should also be a config override without errors (regardless of whether it has warnings or not)\n await assertNoConfigOverrideErrors(schema, incompleteConfig, { allowPropertiesThatCanNoLongerBeOverridden: true });\n\n let normalized: Config;\n try {\n normalized = normalize(incompleteConfig, { onDotIntoNull: \"empty-object\" });\n } catch (error) {\n if (error instanceof NormalizationError) {\n return Result.error(`Config is not normalizable. ` + error.message);\n }\n throw error;\n }\n\n // test the schema against the normalized config\n try {\n await schema.validate(normalized, {\n strict: true,\n context: {\n noUnknownPathPrefixes: [''],\n },\n });\n return Result.ok(null);\n } catch (error) {\n if (error instanceof yup.ValidationError) {\n return Result.error(error.message);\n }\n throw error;\n }\n}\nexport type ValidatedToHaveNoIncompleteConfigWarnings<T extends yup.AnySchema> = yup.InferType<T>;\n\n\n// Normalized overrides\n// ex.: { a?: { b?: number, c?: string }, d?: number }\nexport type ProjectConfigNormalizedOverride = Expand<ValidatedToHaveNoConfigOverrideErrors<typeof projectConfigSchema>>;\nexport type BranchConfigNormalizedOverride = Expand<ValidatedToHaveNoConfigOverrideErrors<typeof branchConfigSchema>>;\nexport type EnvironmentConfigNormalizedOverride = Expand<ValidatedToHaveNoConfigOverrideErrors<typeof environmentConfigSchema>>;\nexport type OrganizationConfigNormalizedOverride = Expand<ValidatedToHaveNoConfigOverrideErrors<typeof organizationConfigSchema>>;\n\n\n// Overrides\n// ex.: { a?: null | { b?: null | number, c: string }, d?: null | number, \"a.b\"?: number, \"a.c\"?: string }\nexport type ProjectConfigOverride = NormalizesTo<ProjectConfigNormalizedOverride>;\nexport type BranchConfigOverride = NormalizesTo<BranchConfigNormalizedOverride>;\nexport type EnvironmentConfigOverride = NormalizesTo<EnvironmentConfigNormalizedOverride>;\nexport type OrganizationConfigOverride = NormalizesTo<OrganizationConfigNormalizedOverride>;\n\n// Override overrides (used to update the overrides)\n// ex.: { a?: null | { b?: null | number, c?: string }, d?: null | number, \"a.b\"?: number, \"a.c\"?: string }\nexport type ProjectConfigOverrideOverride = ProjectConfigOverride;\nexport type BranchConfigOverrideOverride = BranchConfigOverride;\nexport type EnvironmentConfigOverrideOverride = EnvironmentConfigOverride;\nexport type OrganizationConfigOverrideOverride = OrganizationConfigOverride;\n\n// Incomplete configs\n// note that we infer these types from the override types, not from the schema types directly, as there is no guarantee\n// that all configs in the DB satisfy the schema (the only guarantee we make is that this once *used* to be true)\nexport type ProjectIncompleteConfig = Expand<ProjectConfigNormalizedOverride>;\nexport type BranchIncompleteConfig = Expand<ProjectIncompleteConfig & BranchConfigNormalizedOverride>;\nexport type EnvironmentIncompleteConfig = Expand<BranchIncompleteConfig & EnvironmentConfigNormalizedOverride>;\nexport type OrganizationIncompleteConfig = Expand<EnvironmentIncompleteConfig & OrganizationConfigNormalizedOverride>;\n\n\n// Rendered configs before defaults, normalization, and sanitization\ntype ProjectRenderedConfigBeforeDefaults = Omit<ProjectIncompleteConfig,\n | keyof BranchConfigNormalizedOverride\n | keyof EnvironmentConfigNormalizedOverride\n | keyof OrganizationConfigNormalizedOverride\n>;\ntype BranchRenderedConfigBeforeDefaults = Omit<BranchIncompleteConfig,\n | keyof EnvironmentConfigNormalizedOverride\n | keyof OrganizationConfigNormalizedOverride\n>;\ntype EnvironmentRenderedConfigBeforeDefaults = Omit<EnvironmentIncompleteConfig,\n | keyof OrganizationConfigNormalizedOverride\n>;\ntype OrganizationRenderedConfigBeforeDefaults = OrganizationIncompleteConfig;\n\n\n// Rendered configs before sanitization\ntype ProjectRenderedConfigBeforeSanitization = Expand<Awaited<ReturnType<typeof applyProjectDefaults<ProjectRenderedConfigBeforeDefaults>>>>;\ntype BranchRenderedConfigBeforeSanitization = Expand<Awaited<ReturnType<typeof applyBranchDefaults<BranchRenderedConfigBeforeDefaults>>>>;\ntype EnvironmentRenderedConfigBeforeSanitization = Expand<Awaited<ReturnType<typeof applyEnvironmentDefaults<EnvironmentRenderedConfigBeforeDefaults>>>>;\ntype OrganizationRenderedConfigBeforeSanitization = Expand<Awaited<ReturnType<typeof applyOrganizationDefaults>>>;\n\n// Rendered configs after defaults, normalization, and sanitization\nexport type ProjectRenderedConfig = Expand<Awaited<ReturnType<typeof sanitizeProjectConfig<ProjectRenderedConfigBeforeSanitization>>>>;\nexport type BranchRenderedConfig = Expand<Awaited<ReturnType<typeof sanitizeBranchConfig<BranchRenderedConfigBeforeSanitization>>>>;\nexport type EnvironmentRenderedConfig = Expand<Awaited<ReturnType<typeof sanitizeEnvironmentConfig<EnvironmentRenderedConfigBeforeSanitization>>>>;\nexport type OrganizationRenderedConfig = Expand<Awaited<ReturnType<typeof sanitizeOrganizationConfig>>>;\n\n// Complete config\nexport type CompleteConfig = OrganizationRenderedConfig;\n\n// Type assertions (just to make sure the types are correct)\nconst __assertEmptyObjectIsValidProjectOverride: ProjectConfigOverride = {};\nconst __assertEmptyObjectIsValidBranchOverride: BranchConfigOverride = {};\nconst __assertEmptyObjectIsValidEnvironmentOverride: EnvironmentConfigOverride = {};\nconst __assertEmptyObjectIsValidOrganizationOverride: OrganizationConfigOverride = {};\ntypeAssertExtends<ProjectRenderedConfig, { \"sourceOfTruth\": any }>()();\ntypeAssertExtends<BranchRenderedConfig, { \"sourceOfTruth\": any }>()();\ntypeAssertExtends<EnvironmentRenderedConfig, { \"sourceOfTruth\": any }>()();\ntypeAssertExtends<OrganizationRenderedConfig, { \"sourceOfTruth\": any }>()();\ntypeAssert<BranchRenderedConfig extends { \"domains\": any } ? false : true>()();\ntypeAssert<EnvironmentRenderedConfig extends { \"domains\": any } ? false : true>()();\ntypeAssertExtends<OrganizationRenderedConfig, { \"domains\": any }>()();\n"],"mappings":"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","names":["key","schema","subSchema"]}
1
+ {"version":3,"sources":["../../../src/config/schema.ts"],"sourcesContent":["// TODO: rename this file to spaghetti.ts because that's the kind of code here\n\n// IMPORTANT\n// WHENEVER YOU MAKE BACKWARDS-INCOMPATIBLE CHANGES TO THE CONFIG SCHEMA, YOU MUST UPDATE THE MIGRATION FUNCTIONS BELOW.\n// OTHERWISE THINGS WILL GO BOOM!!\n\nimport * as yup from \"yup\";\nimport { ALL_APPS } from \"../apps/apps-config\";\nimport { DEFAULT_EMAIL_TEMPLATES, DEFAULT_EMAIL_THEMES, DEFAULT_EMAIL_THEME_ID } from \"../helpers/emails\";\nimport * as schemaFields from \"../schema-fields\";\nimport { productSchema, userSpecifiedIdSchema, yupBoolean, yupDate, yupMixed, yupNever, yupNumber, yupObject, yupRecord, yupString, yupTuple, yupUnion } from \"../schema-fields\";\nimport { SUPPORTED_CURRENCIES } from \"../utils/currency-constants\";\nimport { StackAssertionError } from \"../utils/errors\";\nimport { allProviders } from \"../utils/oauth\";\nimport { DeepFilterUndefined, DeepMerge, DeepRequiredOrUndefined, filterUndefined, get, getOrUndefined, has, isObjectLike, mapValues, set, typedAssign, typedEntries, typedFromEntries } from \"../utils/objects\";\nimport { Result } from \"../utils/results\";\nimport { CollapseObjectUnion, Expand, IntersectAll, IsUnion, typeAssert, typeAssertExtends, typeAssertIs } from \"../utils/types\";\nimport { Config, NormalizationError, NormalizesTo, assertNormalized, getInvalidConfigReason, normalize } from \"./format\";\nimport { migrateCatalogsToProductLines } from \"./migrate-catalogs-to-product-lines\";\n\nexport const configLevels = ['project', 'branch', 'environment', 'organization'] as const;\nexport type ConfigLevel = typeof configLevels[number];\nconst permissionRegex = /^\\$?[a-z0-9_:]+$/;\nconst customPermissionRegex = /^[a-z0-9_:]+$/;\ndeclare module \"yup\" {\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n export interface CustomSchemaMetadata {\n stackConfigCanNoLongerBeOverridden?: true,\n }\n}\n\nfunction canNoLongerBeOverridden<T extends yup.AnyObjectSchema, K extends string[]>(schema: T, keys: K): yup.Schema<Omit<yup.InferType<T>, K[number]>, T['__context'], Omit<T['__default'], K[number]>, T['__flags']> {\n const notOmitted = schema.concat(yupObject(\n Object.fromEntries(keys.map(key => [key, schema.getNested(key).meta({ stackConfigCanNoLongerBeOverridden: true })]))\n ));\n return notOmitted as any;\n}\n\n/**\n * All fields that can be overridden at this level.\n */\nexport const projectConfigSchema = yupObject({\n sourceOfTruth: yupUnion(\n yupObject({\n type: yupString().oneOf(['hosted']).defined(),\n }),\n yupObject({\n type: yupString().oneOf(['neon']).defined(),\n connectionStrings: yupRecord(\n userSpecifiedIdSchema(\"connectionStringId\").defined(),\n yupString().defined(),\n ).defined(),\n }),\n yupObject({\n type: yupString().oneOf(['postgres']).defined(),\n connectionString: yupString().defined()\n }),\n ),\n});\n\n// --- NEW RBAC Schema ---\nconst branchRbacDefaultPermissions = yupRecord(\n yupString().matches(permissionRegex),\n yupBoolean().isTrue().optional(),\n);\n\nconst branchRbacSchema = yupObject({\n permissions: yupRecord(\n yupString().matches(customPermissionRegex),\n yupObject({\n description: yupString().optional(),\n scope: yupString().oneOf(['team', 'project']).optional(),\n containedPermissionIds: yupRecord(\n yupString().matches(permissionRegex),\n yupBoolean().isTrue().optional()\n ).optional(),\n }).optional(),\n ),\n defaultPermissions: yupObject({\n teamCreator: branchRbacDefaultPermissions,\n teamMember: branchRbacDefaultPermissions,\n signUp: branchRbacDefaultPermissions,\n }),\n});\n// --- END NEW RBAC Schema ---\n\n// --- NEW API Keys Schema ---\nconst branchApiKeysSchema = yupObject({\n enabled: yupObject({\n team: yupBoolean(),\n user: yupBoolean(),\n }),\n});\n// --- END NEW API Keys Schema ---\n\n// --- NEW Apps Schema ---\nconst appIds = Object.keys(ALL_APPS) as (keyof typeof ALL_APPS)[];\nconst branchAppsSchema = yupObject({\n installed: yupRecord(\n yupString().oneOf(appIds),\n yupObject({\n enabled: yupBoolean(),\n }),\n ).test(\n 'authentication-and-emails-enabled',\n 'authentication and emails must be installed and enabled',\n function(value) {\n const hasAuthentication = value['authentication'].enabled === true;\n const hasEmails = value['emails'].enabled === true;\n if (!hasAuthentication || !hasEmails) {\n return this.createError({\n message: 'authentication and emails must be installed and enabled',\n path: this.path,\n });\n }\n return true;\n }\n ),\n});\n// --- END NEW Apps Schema ---\n\n\nconst branchAuthSchema = yupObject({\n allowSignUp: yupBoolean(),\n password: yupObject({\n allowSignIn: yupBoolean(),\n }),\n otp: yupObject({\n allowSignIn: yupBoolean(),\n }),\n passkey: yupObject({\n allowSignIn: yupBoolean(),\n }),\n oauth: yupObject({\n accountMergeStrategy: yupString().oneOf(['link_method', 'raise_error', 'allow_duplicates']).optional(),\n providers: yupRecord(\n yupString().matches(permissionRegex),\n yupObject({\n type: yupString().oneOf(allProviders).optional(),\n allowSignIn: yupBoolean(),\n allowConnectedAccounts: yupBoolean(),\n }),\n ),\n }),\n});\n\nexport const branchPaymentsSchema = yupObject({\n blockNewPurchases: yupBoolean(),\n autoPay: yupObject({\n interval: schemaFields.dayIntervalSchema,\n }).optional(),\n testMode: yupBoolean(),\n productLines: yupRecord(\n userSpecifiedIdSchema(\"productLineId\"),\n yupObject({\n displayName: yupString().optional(),\n customerType: schemaFields.customerTypeSchema,\n }),\n ).meta({ openapiField: { description: 'The product lines that products can be in. All products in a product line (besides add-ons) are mutually exclusive.', exampleValue: { \"product-line-id\": { displayName: \"My Product Line\", customerType: \"user\" } } } }),\n products: yupRecord(\n userSpecifiedIdSchema(\"productId\"),\n productSchema,\n ),\n items: yupRecord(\n userSpecifiedIdSchema(\"itemId\"),\n yupObject({\n displayName: yupString().optional(),\n customerType: schemaFields.customerTypeSchema,\n }),\n ),\n}).optional().test(\n 'product-customer-type-matches-product-line',\n 'Product customer type must match its product line customer type',\n function(this: yup.TestContext<yup.AnyObject>, value) {\n if (!value) return true;\n for (const [productId, product] of Object.entries(value.products)) {\n if (!product.productLineId) continue;\n const productLine = getOrUndefined(value.productLines, product.productLineId);\n if (productLine === undefined) {\n return this.createError({\n message: `Product \"${productId}\" specifies product line ID \"${product.productLineId}\", but that product line does not exist`,\n path: `${this.path}.products.${productId}.productLineId`,\n });\n }\n if (product.customerType !== productLine.customerType) {\n return this.createError({\n message: `Product \"${productId}\" has customer type \"${product.customerType}\" but its product line \"${product.productLineId}\" has customer type \"${productLine.customerType}\"`,\n path: `${this.path}.products.${productId}.customerType`,\n });\n }\n }\n return true;\n }\n);\n\nconst branchDomain = yupObject({\n allowLocalhost: yupBoolean(),\n});\n\nconst branchOnboardingSchema = yupObject({\n requireEmailVerification: yupBoolean(),\n});\n\n\nexport const branchConfigSchema = canNoLongerBeOverridden(projectConfigSchema, [\"sourceOfTruth\"]).concat(yupObject({\n rbac: branchRbacSchema,\n\n teams: yupObject({\n createPersonalTeamOnSignUp: yupBoolean(),\n allowClientTeamCreation: yupBoolean(),\n }),\n\n users: yupObject({\n allowClientUserDeletion: yupBoolean(),\n }),\n\n onboarding: branchOnboardingSchema,\n\n apiKeys: branchApiKeysSchema,\n\n apps: branchAppsSchema,\n\n domains: branchDomain,\n\n auth: branchAuthSchema,\n\n emails: yupObject({\n selectedThemeId: schemaFields.emailThemeSchema,\n themes: schemaFields.emailThemeListSchema,\n templates: schemaFields.emailTemplateListSchema,\n }),\n\n payments: branchPaymentsSchema,\n\n dataVault: yupObject({\n stores: yupRecord(\n userSpecifiedIdSchema(\"storeId\"),\n yupObject({\n displayName: yupString(),\n }),\n ),\n }),\n}));\n\n\nexport const environmentConfigSchema = branchConfigSchema.concat(yupObject({\n auth: branchConfigSchema.getNested(\"auth\").concat(yupObject({\n oauth: branchConfigSchema.getNested(\"auth\").getNested(\"oauth\").concat(yupObject({\n providers: yupRecord(\n yupString().matches(permissionRegex),\n yupObject({\n type: yupString().oneOf(allProviders).optional(),\n isShared: yupBoolean(),\n clientId: schemaFields.oauthClientIdSchema.optional(),\n clientSecret: schemaFields.oauthClientSecretSchema.optional(),\n facebookConfigId: schemaFields.oauthFacebookConfigIdSchema.optional(),\n microsoftTenantId: schemaFields.oauthMicrosoftTenantIdSchema.optional(),\n allowSignIn: yupBoolean().optional(),\n allowConnectedAccounts: yupBoolean().optional(),\n }),\n ),\n })),\n })),\n\n emails: branchConfigSchema.getNested(\"emails\").concat(yupObject({\n server: yupObject({\n isShared: yupBoolean(),\n provider: yupString().oneOf(['resend', 'smtp']).optional(),\n host: schemaFields.emailHostSchema.optional().nonEmpty(),\n port: schemaFields.emailPortSchema.optional(),\n username: schemaFields.emailUsernameSchema.optional().nonEmpty(),\n password: schemaFields.emailPasswordSchema.optional().nonEmpty(),\n senderName: schemaFields.emailSenderNameSchema.optional().nonEmpty(),\n senderEmail: schemaFields.emailSenderEmailSchema.optional().nonEmpty(),\n }),\n })),\n\n domains: branchConfigSchema.getNested(\"domains\").concat(yupObject({\n trustedDomains: yupRecord(\n userSpecifiedIdSchema(\"trustedDomainId\"),\n yupObject({\n baseUrl: schemaFields.wildcardUrlSchema.max(300), // TODO: replace with wildcardProtocolAndDomainSchema (this will require a migration as some configs have domains that are not valid wildcard protocol and domain patterns)\n handlerPath: schemaFields.handlerPathSchema.max(300),\n }),\n ),\n })),\n}));\n\nexport const organizationConfigSchema = environmentConfigSchema.concat(yupObject({}));\n\n\n// Migration functions\n//\n// These are used to migrate old config overrides to the new format on the database.\n//\n// THEY SHOULD NOT BE USED FOR ANY OTHER PURPOSE. They should not be used for default values. They should not be used\n// for sanitization. Instead, use the applicable functions for that.\n//\n// We run these migrations over the database when we do a big migration. USE THESE SPARINGLY. USE OTHER METHODS WHENEVER\n// POSSIBLE.\n//\n// The result of this function should be reproducible, and should not contain ANY randomness/non-determinism.\nexport function migrateConfigOverride(type: \"project\" | \"branch\" | \"environment\" | \"organization\", oldUnmigratedConfigOverride: any): any {\n const isBranchOrHigher = [\"branch\", \"environment\", \"organization\"].includes(type);\n const isEnvironmentOrHigher = [\"environment\", \"organization\"].includes(type);\n\n let res = oldUnmigratedConfigOverride;\n\n // BEGIN 2025-07-28: emails.theme is now emails.selectedThemeId\n if (isBranchOrHigher) {\n res = renameProperty(res, \"emails.theme\", \"selectedThemeId\");\n }\n // END\n\n // BEGIN 2025-07-28: domains.trustedDomains can no longer be an array\n if (isEnvironmentOrHigher) {\n res = mapProperty(res, p => p.join(\".\") === \"domains.trustedDomains\", (value) => {\n if (Array.isArray(value)) {\n return typedFromEntries(value.map((v, i) => [`${i}`, v]));\n }\n return value;\n });\n }\n // END\n\n // BEGIN 2025-07-28: themeList and templateList have been renamed (this was before the email release, so they're safe to remove)\n if (isBranchOrHigher) {\n res = removeProperty(res, p => p.join(\".\") === \"emails.themeList\");\n res = removeProperty(res, p => p.join(\".\") === \"emails.templateList\");\n }\n // END\n\n // BEGIN 2025-07-28: sourceOfTruth was mistakenly written to the environment config in some cases, so let's remove it\n if (type === \"environment\") {\n res = removeProperty(res, p => p.join(\".\") === \"sourceOfTruth\");\n }\n // END\n\n // BEGIN 2025-08-25: stripeAccountId and stripeAccountSetupComplete are unused, so let's remove them\n if (type === \"environment\") {\n res = removeProperty(res, p => p.join(\".\") === \"payments.stripeAccountId\");\n res = removeProperty(res, p => p.join(\".\") === \"payments.stripeAccountSetupComplete\");\n }\n // END\n\n // BEGIN 2025-08-25: payments.items.default is no longer used, so let's remove it\n if (isBranchOrHigher) {\n res = removeProperty(res, p => p.length === 4 && p[0] === \"payments\" && p[1] === \"items\" && p[3] === \"default\");\n }\n // END\n\n // BEGIN 2025-09-23: payments.offers is now payments.products\n if (isBranchOrHigher) {\n res = renameProperty(res, \"payments.offers\", \"products\");\n }\n // END\n\n // BEGIN 2025-09-23: payments.groups is now payments.catalogs\n if (isBranchOrHigher) {\n res = renameProperty(res, \"payments.groups\", \"catalogs\");\n }\n // END\n\n // BEGIN 2025-09-23: payments.products.*.groupId is now payments.products.*.catalogId\n if (isBranchOrHigher) {\n res = renameProperty(res, (p) => p.length === 4 && p[0] === \"payments\" && p[1] === \"products\" && p[3] === \"groupId\", (p) => \"catalogId\");\n }\n // END\n\n // BEGIN 2025-10-29: Removed workflows and everything associated with it\n if (isBranchOrHigher) {\n res = removeProperty(res, p => p[0] === \"workflows\");\n res = removeProperty(res, p => p[0] === \"apps\" && p[1] === \"installed\" && p[2] === \"workflows\");\n }\n // END\n\n // BEGIN 2026-01-14: payments.catalogs is now payments.productLines (with customerType inferred from products) and payments.products.*.catalogId is now payments.products.*.productLineId\n if (isBranchOrHigher) {\n res = migrateCatalogsToProductLines(res);\n }\n // END\n\n // return the result\n return res;\n};\n\nfunction removeProperty(obj: Record<string, any>, pathCond: (path: (string | symbol)[]) => boolean): any {\n return mapProperty(obj, pathCond, () => undefined);\n}\n\nfunction mapProperty(obj: Record<string, any>, pathCond: (path: string[]) => boolean, mapper: (value: any) => any): any {\n const res: Record<string, any> = Array.isArray(obj) ? [] : {};\n for (const [key, value] of typedEntries(obj)) {\n const path = key.split(\".\");\n if (pathCond(path)) {\n const newValue = mapper(value);\n if (newValue !== undefined) {\n set(res, key, newValue);\n } else {\n // do nothing\n }\n } else if (isObjectLike(value)) {\n set(res, key, mapProperty(value, p => pathCond([...path, ...p]), mapper));\n } else {\n set(res, key, value);\n }\n }\n return res;\n}\nundefined?.test(\"mapProperty - basic property mapping\", ({ expect }) => {\n expect(mapProperty({ a: { b: { c: 1 } } }, p => p.join(\".\") === \"a.b.c\", (value) => value + 1)).toEqual({ a: { b: { c: 2 } } });\n expect(mapProperty({ a: { b: { c: 1 } } }, p => p.join(\".\") === \"a.b.d\", (value) => value + 1)).toEqual({ a: { b: { c: 1 } } });\n expect(mapProperty({ x: 5 }, p => p.join(\".\") === \"x\", (value) => value * 2)).toEqual({ x: 10 });\n expect(mapProperty({ a: { b: { c: 1 } } }, p => p.join(\".\") === \"b.c\", (value) => value * 10)).toEqual({ a: { b: { c: 1 } } });\n expect(mapProperty({ a: 1 }, p => p.join(\".\") === \"b.c\", (value) => value)).toEqual({ a: 1 });\n expect(mapProperty({ \"a.b\": { c: 1 } }, p => p.join(\".\") === \"a.b.c\", (value) => value + 1)).toEqual({ \"a.b\": { c: 2 } });\n\n expect(mapProperty({ a: { b: { c: 1 } } }, p => p.length === 3 && p[0] === \"a\" && p[1] === \"b\", (value) => value + 1)).toEqual({ a: { b: { c: 2 } } });\n});\n\nfunction renameProperty(obj: Record<string, any>, oldPath: string | ((path: string[]) => boolean), newName: string | ((path: string[]) => string)): any {\n const pathCond = typeof oldPath === \"function\" ? oldPath : (p: string[]) => p.join(\".\") === oldPath;\n const pathMapper = typeof newName === \"function\" ? newName : (p: string[]) => (newName as string);\n\n const res: Record<string, any> = Array.isArray(obj) ? [] : {};\n for (const [key, originalValue] of typedEntries(obj)) {\n const path = key.split(\".\");\n\n for (let i = 0; i < path.length; i++) {\n const pathPrefix = path.slice(0, i + 1);\n if (pathCond(pathPrefix)) {\n const name = pathMapper(pathPrefix);\n if (name.includes(\".\")) throw new StackAssertionError(`newName must not contain a dot. Provided: ${name}`);\n path[i] = name;\n }\n }\n\n const value = isObjectLike(originalValue) ? renameProperty(originalValue, p => pathCond([...path, ...p]), p => pathMapper([...path, ...p])) : originalValue;\n set(res, path.join(\".\"), value);\n }\n\n return res;\n}\nundefined?.test(\"renameProperty\", ({ expect }) => {\n // Basic\n expect(renameProperty({ a: 1 }, \"a\", \"b\")).toEqual({ b: 1 });\n expect(renameProperty({ b: { c: 1 } }, \"b.c\", \"d\")).toEqual({ b: { d: 1 } });\n expect(renameProperty({ a: { b: { c: 1 } } }, \"a.b.c\", \"d\")).toEqual({ a: { b: { d: 1 } } });\n expect(renameProperty({ a: { b: { c: 1 } } }, \"a.b.c.d\", \"e\")).toEqual({ a: { b: { c: 1 } } });\n expect(renameProperty({ a: { b: { c: 1 }, \"b.c\": 2 } }, \"b.c\", \"d\")).toEqual({ a: { b: { c: 1 }, \"b.c\": 2 } });\n expect(renameProperty({ a: { \"b.c.d\": 2 } }, \"a.b.c\", \"e\")).toEqual({ a: { \"b.e.d\": 2 } });\n expect(renameProperty({ a: { b: { c: 1 }, \"b.c\": 2 } }, \"a.b.c\", \"d\")).toEqual({ a: { b: { d: 1 }, \"b.d\": 2 } });\n expect(renameProperty({ a: { b: { c: 1, d: 2 } } }, \"a.b.c\", \"d\")).toEqual({ a: { b: { d: 2 } } });\n expect(renameProperty({ a: { b: { d: 2, c: 1 } } }, \"a.b.c\", \"d\")).toEqual({ a: { b: { d: 1 } } });\n\n // Functions\n expect(renameProperty({ a: 1 }, (p) => p.length === 1 && p[0] === \"a\", (p) => \"b\")).toEqual({ b: 1 });\n expect(renameProperty({ a: { b: { c: 1 } } }, (p) => p.length === 3 && p[0] === \"a\" && p[1] === \"b\" && p[2] === \"c\", (p) => \"d\")).toEqual({ a: { b: { d: 1 } } });\n expect(renameProperty({ a: { b: { c: 1 } } }, (p) => false, (p) => \"e\")).toEqual({ a: { b: { c: 1 } } });\n expect(renameProperty({ a: { b: { a: 1 } } }, (p) => p[p.length - 1] === \"a\", (p) => \"c\")).toEqual({ c: { b: { c: 1 } } });\n\n // Errors\n expect(() => renameProperty({ a: 1 }, \"a\", \"b.c\")).toThrow();\n});\n\n\n// Defaults\n// these are objects that are merged together to form the rendered config (see ./README.md)\n// Wherever an object could be used as a value, a function can instead be used to generate the default values on a per-key basis\n// To make sure you don't accidentally forget setting a default value, you must explicitly set fields with no default value to `undefined`.\n// NOTE: These values are the defaults of the schema, NOT the defaults for newly created projects. The values here signify what `null` means for each property. If you want new projects by default to have a certain value set to true, you should update the corresponding function in the backend instead.\nconst projectConfigDefaults = {\n sourceOfTruth: {\n type: 'hosted',\n connectionStrings: undefined,\n connectionString: undefined,\n },\n} as const satisfies DefaultsType<ProjectRenderedConfigBeforeDefaults, []>;\n\nconst branchConfigDefaults = {} as const satisfies DefaultsType<BranchRenderedConfigBeforeDefaults, [typeof projectConfigDefaults]>;\n\nconst environmentConfigDefaults = {} as const satisfies DefaultsType<EnvironmentRenderedConfigBeforeDefaults, [typeof branchConfigDefaults, typeof projectConfigDefaults]>;\n\nconst organizationConfigDefaults = {\n rbac: {\n permissions: (key: string) => ({\n containedPermissionIds: (key: string) => undefined,\n description: undefined,\n scope: undefined,\n }),\n defaultPermissions: {\n teamCreator: (key: string) => undefined,\n teamMember: (key: string) => undefined,\n signUp: (key: string) => undefined,\n },\n },\n\n apiKeys: {\n enabled: {\n team: false,\n user: false,\n },\n },\n\n apps: {\n installed: typedFromEntries(appIds.map(appId => [appId, { enabled: false }])) as Record<string, { enabled: boolean } | undefined>,\n },\n\n teams: {\n createPersonalTeamOnSignUp: false,\n allowClientTeamCreation: false,\n },\n\n users: {\n allowClientUserDeletion: false,\n },\n\n onboarding: {\n requireEmailVerification: false,\n },\n\n domains: {\n allowLocalhost: false,\n trustedDomains: (key: string) => ({\n baseUrl: undefined,\n handlerPath: '/handler',\n }) as const,\n },\n\n auth: {\n allowSignUp: true,\n password: {\n allowSignIn: false,\n },\n otp: {\n allowSignIn: false,\n },\n passkey: {\n allowSignIn: false,\n },\n oauth: {\n accountMergeStrategy: 'link_method',\n providers: (key: string) => ({\n type: undefined,\n isShared: true,\n allowSignIn: false,\n allowConnectedAccounts: false,\n clientId: undefined,\n clientSecret: undefined,\n facebookConfigId: undefined,\n microsoftTenantId: undefined,\n }),\n },\n },\n\n emails: {\n server: {\n isShared: true,\n provider: \"smtp\",\n host: undefined,\n port: undefined,\n username: undefined,\n password: undefined,\n senderName: undefined,\n senderEmail: undefined,\n },\n selectedThemeId: DEFAULT_EMAIL_THEME_ID,\n themes: typedAssign((key: string) => ({\n displayName: \"Unnamed Theme\",\n tsxSource: \"Error: Theme config is missing TypeScript source code.\",\n }), DEFAULT_EMAIL_THEMES),\n templates: typedAssign((key: string) => ({\n displayName: \"Unnamed Template\",\n tsxSource: \"Error: Template config is missing TypeScript source code.\",\n themeId: undefined,\n }), DEFAULT_EMAIL_TEMPLATES),\n },\n\n payments: {\n blockNewPurchases: false,\n testMode: true,\n autoPay: undefined,\n productLines: (key: string) => ({\n displayName: undefined,\n customerType: undefined,\n }),\n products: (key: string) => ({\n displayName: key,\n productLineId: undefined,\n customerType: \"user\",\n freeTrial: undefined,\n serverOnly: false,\n stackable: undefined,\n isAddOnTo: false,\n prices: (key: string) => ({\n ...typedFromEntries(SUPPORTED_CURRENCIES.map(currency => [currency.code, undefined])),\n interval: undefined,\n serverOnly: false,\n freeTrial: undefined,\n }),\n includedItems: (key: string) => ({\n quantity: 0,\n repeat: \"never\",\n expires: \"when-repeated\",\n }),\n } as const),\n items: (key: string) => ({\n displayName: key,\n customerType: \"user\",\n } as const)\n },\n\n dataVault: {\n stores: (key: string) => ({\n displayName: \"Unnamed Vault\",\n }),\n },\n} as const satisfies DefaultsType<OrganizationRenderedConfigBeforeDefaults, [typeof environmentConfigDefaults, typeof branchConfigDefaults, typeof projectConfigDefaults]>;\n\ntype _DeepOmitDefaultsImpl<T, U> = T extends object ? (\n (\n & /* keys that are both in T and U, *and* the key's value in U is not a subtype of the key's value in T */ { [K in { [Ki in keyof T & keyof U]: U[Ki] extends T[Ki] ? never : Ki }[keyof T & keyof U]]: DeepOmitDefaults<T[K], U[K] & object> }\n & /* keys that are in T but not in U */ { [K in Exclude<keyof T, keyof U>]: T[K] }\n )\n) : T;\ntype DeepOmitDefaults<T, U> = _DeepOmitDefaultsImpl<DeepFilterUndefined<T>, U>;\ntype DefaultsType<T, U extends any[]> = DeepReplaceAllowFunctionsForObjects<DeepOmitDefaults<DeepRequiredOrUndefined<T>, IntersectAll<{ [K in keyof U]: DeepReplaceFunctionsWithObjects<U[K]> }>>>;\ntypeAssertIs<DefaultsType<{ a: { b: Record<string, 123>, c: 456 } }, [{ a: { c: 456 } }]>, { a: { b: ((key: string) => 123) | Record<string, 123 | undefined> & ((key: string) => 123) } }>()();\n\ntype DeepReplaceAllowFunctionsForObjects<T> = T extends object\n ? (\n string extends keyof T\n ? ((arg: Exclude<keyof T, number>) => DeepReplaceAllowFunctionsForObjects<T[keyof T]>) & ({ [K in keyof T]?: DeepReplaceAllowFunctionsForObjects<T[K]> } | {})\n : { [K in keyof T]: DeepReplaceAllowFunctionsForObjects<T[K]> }\n )\n :\n T;\ntype ReplaceFunctionsWithObjects<T> = T & (T extends (arg: infer K extends string) => infer R ? Record<K, R> & object : unknown);\ntype DeepReplaceFunctionsWithObjects<T> = T extends object ? { [K in keyof ReplaceFunctionsWithObjects<T>]: DeepReplaceFunctionsWithObjects<ReplaceFunctionsWithObjects<T>[K]> } : T;\ntypeAssertIs<DeepReplaceFunctionsWithObjects<{ a: { b: 123 } & ((key: string) => number) }>, { a: { b: 123, [key: string]: number } }>()();\n\nfunction deepReplaceFunctionsWithObjects(obj: any): any {\n return mapValues({ ...obj }, v => (isObjectLike(v) ? deepReplaceFunctionsWithObjects(v as any) : v));\n}\nundefined?.test(\"deepReplaceFunctionsWithObjects\", ({ expect }) => {\n expect(deepReplaceFunctionsWithObjects(() => { })).toEqual({});\n expect(deepReplaceFunctionsWithObjects({ a: 3 })).toEqual({ a: 3 });\n expect(deepReplaceFunctionsWithObjects({ a: () => ({ b: 1 }) })).toEqual({ a: {} });\n expect(deepReplaceFunctionsWithObjects({ a: typedAssign(() => ({}), { b: { c: 1 } }) })).toEqual({ a: { b: { c: 1 } } });\n});\n\ntype ApplyDefaults<D extends object | ((key: string) => unknown), C extends object> = {} extends D ? C : DeepMerge<DeepReplaceFunctionsWithObjects<D>, C>; // the {} extends D makes TypeScript not recurse if the defaults are empty, hence allowing us more recursion until \"type instantiation too deep\" kicks in... it's a total hack, but it works, so hey?\nfunction applyDefaults<D extends object | ((key: string) => unknown), C extends object>(defaults: D, config: C): ApplyDefaults<D, C> {\n const res: any = deepReplaceFunctionsWithObjects(defaults);\n\n outer: for (const [key, mergeValue] of Object.entries(config)) {\n if (mergeValue == null) continue;\n if (!isObjectLike(mergeValue)) {\n set(res, key, mergeValue);\n } else {\n const keyParts = key.split(\".\");\n let baseValue: any = defaults;\n for (const [index, part] of keyParts.entries()) {\n baseValue = has(baseValue, part) ? get(baseValue, part) : (typeof baseValue === 'function' ? (baseValue as any)(part) : undefined);\n if (baseValue === undefined || !isObjectLike(baseValue)) {\n set(res, key, mergeValue);\n continue outer;\n }\n }\n set(res, key, applyDefaults(baseValue, mergeValue));\n }\n }\n return res as any;\n}\nundefined?.test(\"applyDefaults\", ({ expect }) => {\n // Basic\n expect(applyDefaults({ a: 1 }, { a: 2 })).toEqual({ a: 2 });\n expect(applyDefaults({ a: 1 }, { a: null })).toEqual({ a: 1 });\n expect(applyDefaults({}, { a: 1 })).toEqual({ a: 1 });\n expect(applyDefaults({ a: { b: 1 } }, { a: { b: 2 } })).toEqual({ a: { b: 2 } });\n expect(applyDefaults({ a: { b: 1 } }, { a: { c: 2 } })).toEqual({ a: { b: 1, c: 2 } });\n expect(applyDefaults({ a: { b: { c: 1, d: 2 } } }, { a: { b: { d: 3, e: 4 } } })).toEqual({ a: { b: { c: 1, d: 3, e: 4 } } });\n\n // Functions\n expect(applyDefaults((key: string) => ({ b: key }), { a: {} })).toEqual({ a: { b: \"a\" } });\n expect(applyDefaults((key: string) => ({ b: key }), { a: null })).toEqual({});\n expect(applyDefaults((key1: string) => (key2: string) => ({ a: key1, b: key2 }), { c: { d: {} } })).toEqual({ c: { d: { a: \"c\", b: \"d\" } } });\n expect(applyDefaults({ a: (key: string) => ({ b: key }) }, { a: { c: { d: 1 } } })).toEqual({ a: { c: { b: \"c\", d: 1 } } });\n expect(applyDefaults({ a: (key: string) => ({ b: key }) }, {})).toEqual({ a: {} });\n expect(applyDefaults({ a: (key: string) => ({ b: key }) }, { a: null })).toEqual({ a: {} });\n expect(applyDefaults({ a: { b: (key: string) => ({ b: key }) } }, {})).toEqual({ a: { b: {} } });\n expect(applyDefaults(typedAssign(() => ({ b: 1 }), { a: { b: 1, c: 2 } }), { a: {} })).toEqual({ a: { b: 1, c: 2 } });\n expect(applyDefaults(typedAssign(() => ({ b: 1 }), { a: { b: 1, c: 2 } }), { d: {} })).toEqual({ a: { b: 1, c: 2 }, d: { b: 1 } });\n\n // Dot notation\n expect(applyDefaults({ a: { b: 1 } }, { \"a.c\": 2 })).toEqual({ a: { b: 1 }, \"a.c\": 2 });\n expect(applyDefaults({ a: { b: 1 } }, { \"a.c\": null })).toEqual({ a: { b: 1 } });\n expect(applyDefaults({ a: 1 }, { \"a.b\": 2 })).toEqual({ a: 1, \"a.b\": 2 });\n expect(applyDefaults({ a: null }, { \"a.b\": 2 })).toEqual({ a: null, \"a.b\": 2 });\n expect(applyDefaults({ a: { b: { c: 1 } } }, { \"a.b\": { d: 2 } })).toEqual({ a: { b: { c: 1 } }, \"a.b\": { c: 1, d: 2 } });\n expect(applyDefaults({ a: { b: { c: 1 } } }, { \"a.b\": null })).toEqual({ a: { b: { c: 1 } } });\n expect(applyDefaults({ a: { b: { c: { d: 1 } } } }, { \"a.b.c\": {} })).toEqual({ a: { b: { c: { d: 1 } } }, \"a.b.c\": { d: 1 } });\n expect(applyDefaults({ a: () => ({ c: 1 }) }, { \"a.b\": { d: 2 } })).toEqual({ a: {}, \"a.b\": { c: 1, d: 2 } });\n expect(applyDefaults({ a: () => () => ({ d: 1 }) }, { \"a.b.c\": {} })).toEqual({ a: {}, \"a.b.c\": { d: 1 } });\n expect(applyDefaults({ a: { b: () => ({ c: 1, d: 2 }) } }, { \"a.b.x-y.c\": 3 })).toEqual({ a: { b: {} }, \"a.b.x-y.c\": 3 });\n});\n\nexport function applyProjectDefaults<T extends ProjectRenderedConfigBeforeDefaults>(config: T) {\n return applyDefaults(projectConfigDefaults, config);\n}\n\nexport function applyBranchDefaults<T extends BranchRenderedConfigBeforeDefaults>(config: T) {\n return applyDefaults(\n branchConfigDefaults,\n applyDefaults(\n projectConfigDefaults,\n config\n )\n );\n}\n\nexport function applyEnvironmentDefaults<T extends EnvironmentRenderedConfigBeforeDefaults>(config: T): ApplyDefaults<typeof environmentConfigDefaults, ApplyDefaults<typeof branchConfigDefaults, ApplyDefaults<typeof projectConfigDefaults, T>>> {\n return applyDefaults(\n environmentConfigDefaults,\n applyDefaults(\n branchConfigDefaults,\n applyDefaults(\n projectConfigDefaults,\n config\n ) as any\n ) as any\n ) as any;\n}\n\nexport function applyOrganizationDefaults(config: OrganizationRenderedConfigBeforeDefaults): ApplyDefaults<typeof organizationConfigDefaults, ApplyDefaults<typeof environmentConfigDefaults, ApplyDefaults<typeof branchConfigDefaults, ApplyDefaults<typeof projectConfigDefaults, OrganizationRenderedConfigBeforeDefaults>>>> {\n return applyDefaults(\n organizationConfigDefaults,\n applyDefaults(\n environmentConfigDefaults,\n applyDefaults(\n branchConfigDefaults,\n applyDefaults(\n projectConfigDefaults,\n config\n ) as any\n ) as any\n ) as any\n ) as any;\n}\n\n\nexport async function sanitizeProjectConfig<T extends ProjectRenderedConfigBeforeSanitization>(config: T) {\n assertNormalized(config);\n const oldSourceOfTruth = config.sourceOfTruth;\n const sourceOfTruth =\n oldSourceOfTruth.type === 'neon' && typeof oldSourceOfTruth.connectionStrings === 'object' ? {\n type: 'neon',\n connectionStrings: { ...filterUndefined(oldSourceOfTruth.connectionStrings) as Record<string, string> }\n } as const\n : oldSourceOfTruth.type === 'postgres' && typeof oldSourceOfTruth.connectionString === 'string' ? {\n type: 'postgres',\n connectionString: oldSourceOfTruth.connectionString,\n } as const\n : {\n type: 'hosted',\n } as const;\n\n return {\n ...config,\n sourceOfTruth,\n };\n}\n\nexport async function sanitizeBranchConfig<T extends BranchRenderedConfigBeforeSanitization>(config: T) {\n assertNormalized(config);\n const prepared = await sanitizeProjectConfig(config);\n return {\n ...prepared,\n };\n}\n\nexport async function sanitizeEnvironmentConfig<T extends EnvironmentRenderedConfigBeforeSanitization>(config: T) {\n assertNormalized(config);\n const prepared = await sanitizeBranchConfig(config);\n return {\n ...prepared,\n };\n}\n\nexport async function sanitizeOrganizationConfig(config: OrganizationRenderedConfigBeforeSanitization) {\n assertNormalized(config);\n const prepared = await sanitizeEnvironmentConfig(config);\n const themes: typeof prepared.emails.themes = {\n ...DEFAULT_EMAIL_THEMES,\n ...prepared.emails.themes,\n };\n const templates: typeof prepared.emails.templates = {\n ...DEFAULT_EMAIL_TEMPLATES,\n ...(config.emails.server.isShared ? {} : prepared.emails.templates),\n };\n const products = typedFromEntries(typedEntries(prepared.payments.products).map(([key, product]) => {\n const isAddOnTo = product.isAddOnTo === false ?\n false as const :\n typedFromEntries(Object.keys(product.isAddOnTo).map((key) => [key, true as const]));\n const prices = product.prices === \"include-by-default\" ?\n \"include-by-default\" as const :\n typedFromEntries(typedEntries(product.prices).map(([key, value]) => {\n const data = { serverOnly: false, ...(value ?? {}) };\n return [key, data];\n }));\n return [key, {\n ...product,\n isAddOnTo,\n prices,\n }];\n }));\n\n const appSortIndices = new Map(Object.keys(ALL_APPS).map((appId, index) => [appId, index]));\n\n return {\n ...prepared,\n emails: {\n ...prepared.emails,\n selectedThemeId: has(themes, prepared.emails.selectedThemeId) ? prepared.emails.selectedThemeId : DEFAULT_EMAIL_THEME_ID,\n themes,\n templates,\n },\n payments: {\n ...prepared.payments,\n products\n },\n apps: {\n installed: typedFromEntries(\n typedEntries(prepared.apps.installed)\n .sort(([a], [b]) => appSortIndices.get(a)! - appSortIndices.get(b)!)\n ),\n },\n };\n}\n\n\n/**\n * Does not require a base config, and hence solely relies on the override itself to validate the config. If it returns\n * no error, you know that the\n *\n * It's crucial that our DB never contains any configs that are not valid according to this function, as this would mean\n * that the config object does not satisfy the ValidatedToHaveNoConfigOverrideErrors type (which is used as an assumption\n * in a whole bunch of places in the code).\n */\nexport async function getConfigOverrideErrors<T extends yup.AnySchema>(schema: T, configOverride: unknown, options: { allowPropertiesThatCanNoLongerBeOverridden?: boolean } = {}): Promise<Result<null, string>> {\n // currently, we go over the schema and ensure that the general requirements for each property are satisfied\n // importantly, we cannot check any cross-property constraints, as those may change depending on the base config\n // also, since overrides can be empty, we cannot have any required properties (TODO: can we have required properties in nested objects? would that even make sense? think about it)\n if (typeof configOverride !== \"object\" || configOverride === null) {\n return Result.error(\"Config override must be a non-null object.\");\n }\n if (Object.getPrototypeOf(configOverride) !== Object.getPrototypeOf({})) {\n return Result.error(\"Config override must be plain old JavaScript object.\");\n }\n // Check config format\n const reason = getInvalidConfigReason(configOverride, { configName: 'override' });\n if (reason) return Result.error(\"Invalid config format: \" + reason);\n\n const getSubSchema = (schema: yup.AnySchema, key: string): yup.AnySchema | undefined => {\n const keyParts = key.split(\".\");\n if (!schema.hasNested(keyParts[0])) {\n return undefined;\n }\n const nestedSchema = schema.getNested(keyParts[0]);\n if (nestedSchema.meta()?.stackConfigCanNoLongerBeOverridden && !options.allowPropertiesThatCanNoLongerBeOverridden) {\n return undefined;\n }\n if (keyParts.length === 1) {\n return nestedSchema;\n } else {\n return getSubSchema(nestedSchema, keyParts.slice(1).join(\".\"));\n }\n };\n\n const getRestrictedSchemaBase = (path: string, schema: yup.AnySchema): yup.AnySchema => {\n const schemaInfo = schema.meta()?.stackSchemaInfo;\n switch (schemaInfo?.type) {\n case \"string\": {\n const stringSchema = schema as yup.StringSchema<any>;\n const description = stringSchema.describe();\n let res = yupString();\n if (description.tests.some(t => t.name === \"uuid\")) {\n res = res.uuid();\n }\n return res;\n }\n case \"number\": {\n return yupNumber();\n }\n case \"boolean\": {\n return yupBoolean();\n }\n case \"date\": {\n return yupDate();\n }\n case \"mixed\": {\n return yupMixed();\n }\n case \"array\": {\n throw new StackAssertionError(`Arrays are not supported in config JSON files (besides tuples). Use a record instead.`, { schemaInfo, schema });\n\n // This is how the implementation would look like, but we don't support arrays in config JSON files (besides tuples)\n // const arraySchema = schema as yup.ArraySchema<any, any, any, any>;\n // const innerType = arraySchema.innerType;\n // return yupArray(innerType ? getRestrictedSchema(path + \".[]\", innerType as any) : undefined);\n }\n case \"tuple\": {\n return yupTuple(schemaInfo.items.map((s, index) => getRestrictedSchema(path + `[${index}]`, s)) as any);\n }\n case \"union\": {\n const schemas = schemaInfo.items;\n const nonObjectSchemas = [...schemas.entries()].filter(([index, s]) => s.meta()?.stackSchemaInfo?.type !== \"object\");\n const objectSchemas = schemas.filter((s): s is yup.ObjectSchema<any> => s.meta()?.stackSchemaInfo?.type === \"object\");\n\n // merge all object schemas into a single schema\n const allObjectSchemaKeys = [...new Set(objectSchemas.flatMap(s => Object.keys(s.fields)))];\n const mergedObjectSchema = yupObject(\n Object.fromEntries(\n allObjectSchemaKeys.map(key => [key, yupUnion(\n ...objectSchemas.flatMap((s, index) => s.hasNested(key) ? [s.getNested(key)] : [])\n )])\n )\n );\n\n return yupUnion(\n ...nonObjectSchemas.map(([index, s]) => getRestrictedSchema(path + `|variant-${index}|`, s)),\n ...objectSchemas.length > 0 ? [getRestrictedSchema(path + (nonObjectSchemas.length > 0 ? `|variant|` : \"\"), mergedObjectSchema)] : [],\n );\n }\n case \"record\": {\n return yupRecord(getRestrictedSchema(path + \".key\", schemaInfo.keySchema) as any, getRestrictedSchema(path + \".value\", schemaInfo.valueSchema));\n }\n case \"object\": {\n const objectSchema = schema as yup.ObjectSchema<any>;\n return yupObject(\n Object.fromEntries(\n Object.entries(objectSchema.fields)\n .map(([key, value]) => [key, getRestrictedSchema(path + \".\" + key, value as any)])\n )\n );\n }\n case \"never\": {\n return yupNever();\n }\n default: {\n throw new StackAssertionError(`Unknown schema info at path ${path}: ${JSON.stringify(schemaInfo)}`, { schemaInfo, schema });\n }\n }\n };\n const getRestrictedSchema = (path: string, schema: yup.AnySchema): yup.AnySchema => {\n let restricted = getRestrictedSchemaBase(path, schema);\n restricted = restricted.nullable();\n const description = schema.describe();\n if (description.oneOf.length > 0) {\n restricted = restricted.oneOf(description.oneOf);\n }\n if (description.notOneOf.length > 0) {\n restricted = restricted.notOneOf(description.notOneOf);\n }\n return restricted;\n };\n\n for (const [key, value] of Object.entries(configOverride)) {\n if (value === undefined) continue;\n const subSchema = getSubSchema(schema, key);\n if (!subSchema) {\n // find smallest key prefix that is invalid\n const keySplit = key.split(\".\");\n for (let i = 0; i < keySplit.length; i++) {\n const prefix = keySplit.slice(0, i + 1).join(\".\");\n const subSchema = getSubSchema(schema, prefix);\n if (!subSchema) {\n return Result.error(`The key ${JSON.stringify(key)} is not valid (nested object not found in schema: ${JSON.stringify(prefix)}).`);\n }\n }\n throw new StackAssertionError(\"Something weird happened? Sub-schema for key is invalid but no prefix is invalid??\", { key, subSchema });\n }\n let restrictedSchema = getRestrictedSchema(key, subSchema);\n try {\n await restrictedSchema.validate(value, {\n strict: true,\n ...{\n // Although `path` is not part of the yup types, it is actually recognized and does the correct thing\n path: key\n },\n context: {\n noUnknownPathPrefixes: [''],\n },\n });\n } catch (error) {\n if (error instanceof yup.ValidationError) {\n return Result.error(error.message);\n }\n throw error;\n }\n }\n return Result.ok(null);\n}\nexport async function assertNoConfigOverrideErrors<T extends yup.AnySchema>(schema: T, config: unknown, options: { allowPropertiesThatCanNoLongerBeOverridden?: boolean, extraInfo?: any } = {}): Promise<void> {\n const res = await getConfigOverrideErrors(schema, config, options);\n if (res.status === \"error\") throw new StackAssertionError(`Config override is invalid — at a place where it should have already been validated! ${res.error}`, { options, config });\n}\ntype _ValidatedToHaveNoConfigOverrideErrorsImpl<T> =\n IsUnion<T & object> extends true ? _ValidatedToHaveNoConfigOverrideErrorsImpl<CollapseObjectUnion<T & object> | Exclude<T, object>>\n : T extends object ? (T extends any[] ? T : { [K in keyof T]+?: _ValidatedToHaveNoConfigOverrideErrorsImpl<T[K]> })\n : T;\nexport type ValidatedToHaveNoConfigOverrideErrors<T extends yup.AnySchema> = _ValidatedToHaveNoConfigOverrideErrorsImpl<yup.InferType<T>>;\ntypeAssertIs<_ValidatedToHaveNoConfigOverrideErrorsImpl<{ a: string } | { b: number } | boolean>, { a?: string, b?: number } | boolean>()();\ntypeAssertExtends<_ValidatedToHaveNoConfigOverrideErrorsImpl<\"abc\" | 123 | null>, \"abc\" | 123 | null>()();\ntypeAssertExtends<_ValidatedToHaveNoConfigOverrideErrorsImpl<{ a: { b: { c: string } | { d: number } } }>, { a?: { b?: { c?: string, d?: number } } }>()();\n\n/**\n * Checks whether there are any warnings in the incomplete config. A warning doesn't stop the config from being valid,\n * but may require action regardless.\n *\n * The DB can contain configs that are not valid according to this function, as long as they are valid according to\n * the getConfigOverrideErrors function. (This is necessary, because a changing base config may make an override invalid\n * that was previously valid.)\n */\nexport async function getIncompleteConfigWarnings<T extends yup.AnySchema>(schema: T, incompleteConfig: Config): Promise<Result<null, string>> {\n // every rendered config should also be a config override without errors (regardless of whether it has warnings or not)\n await assertNoConfigOverrideErrors(schema, incompleteConfig, { allowPropertiesThatCanNoLongerBeOverridden: true });\n\n let normalized: Config;\n try {\n normalized = normalize(incompleteConfig, { onDotIntoNull: \"empty-object\" });\n } catch (error) {\n if (error instanceof NormalizationError) {\n return Result.error(`Config is not normalizable. ` + error.message);\n }\n throw error;\n }\n\n // test the schema against the normalized config\n try {\n await schema.validate(normalized, {\n strict: true,\n context: {\n noUnknownPathPrefixes: [''],\n },\n });\n return Result.ok(null);\n } catch (error) {\n if (error instanceof yup.ValidationError) {\n return Result.error(error.message);\n }\n throw error;\n }\n}\nexport type ValidatedToHaveNoIncompleteConfigWarnings<T extends yup.AnySchema> = yup.InferType<T>;\n\n\n// Normalized overrides\n// ex.: { a?: { b?: number, c?: string }, d?: number }\nexport type ProjectConfigNormalizedOverride = Expand<ValidatedToHaveNoConfigOverrideErrors<typeof projectConfigSchema>>;\nexport type BranchConfigNormalizedOverride = Expand<ValidatedToHaveNoConfigOverrideErrors<typeof branchConfigSchema>>;\nexport type EnvironmentConfigNormalizedOverride = Expand<ValidatedToHaveNoConfigOverrideErrors<typeof environmentConfigSchema>>;\nexport type OrganizationConfigNormalizedOverride = Expand<ValidatedToHaveNoConfigOverrideErrors<typeof organizationConfigSchema>>;\n\n\n// Overrides\n// ex.: { a?: null | { b?: null | number, c: string }, d?: null | number, \"a.b\"?: number, \"a.c\"?: string }\nexport type ProjectConfigOverride = NormalizesTo<ProjectConfigNormalizedOverride>;\nexport type BranchConfigOverride = NormalizesTo<BranchConfigNormalizedOverride>;\nexport type EnvironmentConfigOverride = NormalizesTo<EnvironmentConfigNormalizedOverride>;\nexport type OrganizationConfigOverride = NormalizesTo<OrganizationConfigNormalizedOverride>;\n\n// Override overrides (used to update the overrides)\n// ex.: { a?: null | { b?: null | number, c?: string }, d?: null | number, \"a.b\"?: number, \"a.c\"?: string }\nexport type ProjectConfigOverrideOverride = ProjectConfigOverride;\nexport type BranchConfigOverrideOverride = BranchConfigOverride;\nexport type EnvironmentConfigOverrideOverride = EnvironmentConfigOverride;\nexport type OrganizationConfigOverrideOverride = OrganizationConfigOverride;\n\n// Incomplete configs\n// note that we infer these types from the override types, not from the schema types directly, as there is no guarantee\n// that all configs in the DB satisfy the schema (the only guarantee we make is that this once *used* to be true)\nexport type ProjectIncompleteConfig = Expand<ProjectConfigNormalizedOverride>;\nexport type BranchIncompleteConfig = Expand<ProjectIncompleteConfig & BranchConfigNormalizedOverride>;\nexport type EnvironmentIncompleteConfig = Expand<BranchIncompleteConfig & EnvironmentConfigNormalizedOverride>;\nexport type OrganizationIncompleteConfig = Expand<EnvironmentIncompleteConfig & OrganizationConfigNormalizedOverride>;\n\n\n// Rendered configs before defaults, normalization, and sanitization\ntype ProjectRenderedConfigBeforeDefaults = Omit<ProjectIncompleteConfig,\n | keyof BranchConfigNormalizedOverride\n | keyof EnvironmentConfigNormalizedOverride\n | keyof OrganizationConfigNormalizedOverride\n>;\ntype BranchRenderedConfigBeforeDefaults = Omit<BranchIncompleteConfig,\n | keyof EnvironmentConfigNormalizedOverride\n | keyof OrganizationConfigNormalizedOverride\n>;\ntype EnvironmentRenderedConfigBeforeDefaults = Omit<EnvironmentIncompleteConfig,\n | keyof OrganizationConfigNormalizedOverride\n>;\ntype OrganizationRenderedConfigBeforeDefaults = OrganizationIncompleteConfig;\n\n\n// Rendered configs before sanitization\ntype ProjectRenderedConfigBeforeSanitization = Expand<Awaited<ReturnType<typeof applyProjectDefaults<ProjectRenderedConfigBeforeDefaults>>>>;\ntype BranchRenderedConfigBeforeSanitization = Expand<Awaited<ReturnType<typeof applyBranchDefaults<BranchRenderedConfigBeforeDefaults>>>>;\ntype EnvironmentRenderedConfigBeforeSanitization = Expand<Awaited<ReturnType<typeof applyEnvironmentDefaults<EnvironmentRenderedConfigBeforeDefaults>>>>;\ntype OrganizationRenderedConfigBeforeSanitization = Expand<Awaited<ReturnType<typeof applyOrganizationDefaults>>>;\n\n// Rendered configs after defaults, normalization, and sanitization\nexport type ProjectRenderedConfig = Expand<Awaited<ReturnType<typeof sanitizeProjectConfig<ProjectRenderedConfigBeforeSanitization>>>>;\nexport type BranchRenderedConfig = Expand<Awaited<ReturnType<typeof sanitizeBranchConfig<BranchRenderedConfigBeforeSanitization>>>>;\nexport type EnvironmentRenderedConfig = Expand<Awaited<ReturnType<typeof sanitizeEnvironmentConfig<EnvironmentRenderedConfigBeforeSanitization>>>>;\nexport type OrganizationRenderedConfig = Expand<Awaited<ReturnType<typeof sanitizeOrganizationConfig>>>;\n\n// Complete config\nexport type CompleteConfig = OrganizationRenderedConfig;\n\n// Type assertions (just to make sure the types are correct)\nconst __assertEmptyObjectIsValidProjectOverride: ProjectConfigOverride = {};\nconst __assertEmptyObjectIsValidBranchOverride: BranchConfigOverride = {};\nconst __assertEmptyObjectIsValidEnvironmentOverride: EnvironmentConfigOverride = {};\nconst __assertEmptyObjectIsValidOrganizationOverride: OrganizationConfigOverride = {};\ntypeAssertExtends<ProjectRenderedConfig, { \"sourceOfTruth\": any }>()();\ntypeAssertExtends<BranchRenderedConfig, { \"sourceOfTruth\": any }>()();\ntypeAssertExtends<EnvironmentRenderedConfig, { \"sourceOfTruth\": any }>()();\ntypeAssertExtends<OrganizationRenderedConfig, { \"sourceOfTruth\": any }>()();\ntypeAssert<BranchRenderedConfig extends { \"domains\": any } ? false : true>()();\ntypeAssert<EnvironmentRenderedConfig extends { \"domains\": any } ? false : true>()();\ntypeAssertExtends<OrganizationRenderedConfig, { \"domains\": any }>()();\n"],"mappings":"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","names":["key","schema","subSchema"]}
@@ -105,21 +105,25 @@ var StackClientInterface = class {
105
105
  if (!("publishableClientKey" in this.options)) {
106
106
  throw new Error("Admin session token is currently not supported for fetching new access token. Did you try to log in on a StackApp initiated with the admin session?");
107
107
  }
108
+ const tokenEndpoint = this.getApiUrl() + "/auth/oauth/token";
108
109
  const as = {
109
110
  issuer: this.options.getBaseUrl(),
110
111
  algorithm: "oauth2",
111
- token_endpoint: this.getApiUrl() + "/auth/oauth/token"
112
+ token_endpoint: tokenEndpoint
112
113
  };
113
114
  const client = {
114
115
  client_id: this.projectId,
115
- client_secret: this.options.publishableClientKey,
116
- token_endpoint_auth_method: "client_secret_post"
116
+ client_secret: this.options.publishableClientKey
117
117
  };
118
+ const clientAuthentication = oauth.ClientSecretPost(this.options.publishableClientKey);
119
+ const allowInsecure = tokenEndpoint.startsWith("http://");
118
120
  const response = await this._networkRetryException(async () => {
119
121
  const rawResponse = await oauth.refreshTokenGrantRequest(
120
122
  as,
121
123
  client,
122
- refreshToken.token
124
+ clientAuthentication,
125
+ refreshToken.token,
126
+ allowInsecure ? { [oauth.allowInsecureRequests]: true } : void 0
123
127
  );
124
128
  const response2 = await this._processResponse(rawResponse);
125
129
  if (response2.status === "error") {
@@ -136,9 +140,18 @@ var StackClientInterface = class {
136
140
  return response2.data;
137
141
  });
138
142
  if (!response) return null;
139
- const result = await oauth.processRefreshTokenResponse(as, client, response);
140
- if (oauth.isOAuth2Error(result)) {
141
- throw new StackAssertionError("OAuth error", { result });
143
+ let result;
144
+ try {
145
+ result = await oauth.processRefreshTokenResponse(as, client, response);
146
+ } catch (e) {
147
+ if (e instanceof oauth.ResponseBodyError) {
148
+ throw new StackAssertionError("ResponseBodyError when processing refresh token response", {
149
+ cause: e.cause,
150
+ code: e.code,
151
+ error: e.error
152
+ });
153
+ }
154
+ throw new StackAssertionError("Unexpected error when processing refresh token response", { cause: e });
142
155
  }
143
156
  if (!result.access_token) {
144
157
  throw new StackAssertionError("Access token not found in token endpoint response, this is weird!");
@@ -766,35 +779,56 @@ var StackClientInterface = class {
766
779
  if (!("publishableClientKey" in this.options)) {
767
780
  throw new Error("Admin session token is currently not supported for OAuth");
768
781
  }
782
+ const tokenEndpoint = this.getApiUrl() + "/auth/oauth/token";
769
783
  const as = {
770
784
  issuer: this.options.getBaseUrl(),
771
785
  algorithm: "oauth2",
772
- token_endpoint: this.getApiUrl() + "/auth/oauth/token"
786
+ token_endpoint: tokenEndpoint
773
787
  };
774
788
  const client = {
775
789
  client_id: this.projectId,
776
- client_secret: this.options.publishableClientKey,
777
- token_endpoint_auth_method: "client_secret_post"
790
+ client_secret: this.options.publishableClientKey
778
791
  };
779
- const params = await this._networkRetryException(
780
- async () => oauth.validateAuthResponse(as, client, options.oauthParams, options.state)
781
- );
782
- if (oauth.isOAuth2Error(params)) {
783
- throw new StackAssertionError("Error validating outer OAuth response", { params });
792
+ const clientAuthentication = oauth.ClientSecretPost(this.options.publishableClientKey);
793
+ const allowInsecure = tokenEndpoint.startsWith("http://");
794
+ let params;
795
+ try {
796
+ params = oauth.validateAuthResponse(as, client, options.oauthParams, options.state);
797
+ } catch (e) {
798
+ if (e instanceof oauth.AuthorizationResponseError) {
799
+ throw new StackAssertionError("Authorization response error when validating outer OAuth response", {
800
+ //cause is a URLSearchParams object for this error, so we need to serialize it better
801
+ cause: Object.fromEntries(e.cause),
802
+ code: e.code,
803
+ error: e.error
804
+ });
805
+ }
806
+ throw new StackAssertionError("Unexpected error when validating outer OAuth response", { cause: e });
784
807
  }
785
808
  const response = await oauth.authorizationCodeGrantRequest(
786
809
  as,
787
810
  client,
811
+ clientAuthentication,
788
812
  params,
789
813
  options.redirectUri,
790
- options.codeVerifier
814
+ options.codeVerifier,
815
+ allowInsecure ? { [oauth.allowInsecureRequests]: true } : void 0
791
816
  );
792
- const result = await oauth.processAuthorizationCodeOAuth2Response(as, client, response);
793
- if (oauth.isOAuth2Error(result)) {
794
- if ("code" in result && result.code === "MULTI_FACTOR_AUTHENTICATION_REQUIRED") {
795
- throw new KnownErrors.MultiFactorAuthenticationRequired(result.details.attempt_code);
817
+ let result;
818
+ try {
819
+ result = await oauth.processAuthorizationCodeResponse(as, client, response);
820
+ } catch (e) {
821
+ if (e instanceof oauth.ResponseBodyError) {
822
+ if (e.cause.code === "MULTI_FACTOR_AUTHENTICATION_REQUIRED") {
823
+ throw new KnownErrors.MultiFactorAuthenticationRequired(e.cause.details.attempt_code);
824
+ }
825
+ throw new StackAssertionError("Outer OAuth error during authorization code response", {
826
+ cause: e.cause,
827
+ code: e.code,
828
+ error: e.error
829
+ });
796
830
  }
797
- throw new StackAssertionError("Outer OAuth error during authorization code response", { result });
831
+ throw new StackAssertionError("Unexpected error when processing authorization code response", { cause: e });
798
832
  }
799
833
  return {
800
834
  newUser: result.is_new_user,
@@ -1352,6 +1386,24 @@ var StackClientInterface = class {
1352
1386
  session
1353
1387
  );
1354
1388
  }
1389
+ async switchSubscription(options, session) {
1390
+ await this.sendClientRequest(
1391
+ urlString`/payments/products/${options.customer_type}/${options.customer_id}/switch`,
1392
+ {
1393
+ method: "POST",
1394
+ headers: {
1395
+ "content-type": "application/json"
1396
+ },
1397
+ body: JSON.stringify({
1398
+ from_product_id: options.from_product_id,
1399
+ to_product_id: options.to_product_id,
1400
+ price_id: options.price_id,
1401
+ quantity: options.quantity
1402
+ })
1403
+ },
1404
+ session
1405
+ );
1406
+ }
1355
1407
  async createCheckoutUrl(customer_type, customer_id, productIdOrInline, session, returnUrl) {
1356
1408
  const productBody = typeof productIdOrInline === "string" ? { product_id: productIdOrInline } : { inline_product: productIdOrInline };
1357
1409
  const response = await this.sendClientRequest(
@@ -1368,6 +1420,44 @@ var StackClientInterface = class {
1368
1420
  const { url } = await response.json();
1369
1421
  return url;
1370
1422
  }
1423
+ async getCustomerBilling(customerType, customerId, session) {
1424
+ const response = await this.sendClientRequest(
1425
+ urlString`/payments/billing/${customerType}/${customerId}`,
1426
+ {},
1427
+ session
1428
+ );
1429
+ return await response.json();
1430
+ }
1431
+ async createCustomerPaymentMethodSetupIntent(customerType, customerId, session) {
1432
+ const response = await this.sendClientRequest(
1433
+ urlString`/payments/payment-method/${customerType}/${customerId}/setup-intent`,
1434
+ {
1435
+ method: "POST",
1436
+ headers: {
1437
+ "content-type": "application/json"
1438
+ },
1439
+ body: JSON.stringify({})
1440
+ },
1441
+ session
1442
+ );
1443
+ return await response.json();
1444
+ }
1445
+ async setDefaultCustomerPaymentMethodFromSetupIntent(customerType, customerId, setupIntentId, session) {
1446
+ const response = await this.sendClientRequest(
1447
+ urlString`/payments/payment-method/${customerType}/${customerId}/set-default`,
1448
+ {
1449
+ method: "POST",
1450
+ headers: {
1451
+ "content-type": "application/json"
1452
+ },
1453
+ body: JSON.stringify({
1454
+ setup_intent_id: setupIntentId
1455
+ })
1456
+ },
1457
+ session
1458
+ );
1459
+ return await response.json();
1460
+ }
1371
1461
  async transferProject(internalProjectSession, projectIdToTransfer, newTeamId) {
1372
1462
  if (this.options.projectId !== "internal") {
1373
1463
  throw new StackAssertionError("StackClientInterface.transferProject() is only available for internal projects (please specify the project ID in the constructor)");