@hexclave/shared 1.0.44 → 1.0.46
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.
- package/dist/{admin-interface-BSW1mzGs.d.ts → admin-interface-DQcggLpw.d.ts} +7 -9
- package/dist/admin-interface-DQcggLpw.d.ts.map +1 -0
- package/dist/ai/unified-prompts/reminders.js +1 -2
- package/dist/ai/unified-prompts/reminders.js.map +1 -1
- package/dist/{client-interface-iIw4nU5k.d.ts → client-interface-BQz4jNAC.d.ts} +4 -4
- package/dist/{client-interface-iIw4nU5k.d.ts.map → client-interface-BQz4jNAC.d.ts.map} +1 -1
- package/dist/config/schema.d.ts +1 -1
- package/dist/config-authoring.d.ts +1 -1
- package/dist/dates-BRAvSk6L.d.ts +40 -0
- package/dist/{dates-B6ne9iOR.d.ts.map → dates-BRAvSk6L.d.ts.map} +1 -1
- package/dist/{email-outbox-B1wmVPRG.d.ts → email-outbox-CYmVerum.d.ts} +45 -45
- package/dist/{email-outbox-B1wmVPRG.d.ts.map → email-outbox-CYmVerum.d.ts.map} +1 -1
- package/dist/esm/ai/unified-prompts/reminders.js +1 -1
- package/dist/esm/interface/admin-interface.d.ts +0 -2
- package/dist/esm/interface/admin-interface.d.ts.map +1 -1
- package/dist/esm/interface/admin-interface.js +0 -12
- package/dist/esm/interface/admin-interface.js.map +1 -1
- package/dist/esm/interface/conversations.d.ts +21 -21
- package/dist/esm/interface/crud/email-outbox.d.ts +44 -44
- package/dist/esm/interface/server-interface.d.ts +2 -0
- package/dist/esm/interface/server-interface.d.ts.map +1 -1
- package/dist/esm/interface/server-interface.js +12 -0
- package/dist/esm/interface/server-interface.js.map +1 -1
- package/dist/esm/schema-fields.d.ts.map +1 -1
- package/dist/esm/schema-fields.js +2 -2
- package/dist/esm/schema-fields.js.map +1 -1
- package/dist/esm/utils/currencies.d.ts +16 -1
- package/dist/esm/utils/currencies.d.ts.map +1 -1
- package/dist/esm/utils/currencies.js +24 -1
- package/dist/esm/utils/currencies.js.map +1 -1
- package/dist/esm/utils/dates.d.ts +18 -1
- package/dist/esm/utils/dates.d.ts.map +1 -1
- package/dist/esm/utils/dates.js +36 -15
- package/dist/esm/utils/dates.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/interface/admin-interface.d.ts +1 -1
- package/dist/interface/admin-interface.js +0 -12
- package/dist/interface/admin-interface.js.map +1 -1
- package/dist/interface/client-interface.d.ts +1 -1
- package/dist/interface/conversations.d.ts +21 -21
- package/dist/interface/crud/email-outbox.d.ts +1 -1
- package/dist/interface/crud/products.d.ts +1 -1
- package/dist/interface/crud/transactions.d.ts +1 -1
- package/dist/interface/server-interface.d.ts +1 -1
- package/dist/interface/server-interface.js +12 -0
- package/dist/interface/server-interface.js.map +1 -1
- package/dist/{products-Bs74ld-v.d.ts → products-D4o8A2W0.d.ts} +2 -2
- package/dist/{products-Bs74ld-v.d.ts.map → products-D4o8A2W0.d.ts.map} +1 -1
- package/dist/{schema-DIefUvKi.d.ts → schema-Daq0b_sf.d.ts} +2 -2
- package/dist/{schema-DIefUvKi.d.ts.map → schema-Daq0b_sf.d.ts.map} +1 -1
- package/dist/{schema-fields-DqGQ4kF7.d.ts → schema-fields-DZtDQEEO.d.ts} +2 -2
- package/dist/schema-fields-DZtDQEEO.d.ts.map +1 -0
- package/dist/schema-fields.d.ts +1 -1
- package/dist/schema-fields.js +2 -2
- package/dist/schema-fields.js.map +1 -1
- package/dist/{server-interface-CgpxsLT_.d.ts → server-interface-BjY-eS4Q.d.ts} +6 -4
- package/dist/server-interface-BjY-eS4Q.d.ts.map +1 -0
- package/dist/{sessions-d8qtvBUB.d.ts → sessions-CI-0TBQb.d.ts} +2 -2
- package/dist/{sessions-d8qtvBUB.d.ts.map → sessions-CI-0TBQb.d.ts.map} +1 -1
- package/dist/sessions.d.ts +1 -1
- package/dist/{transactions-DhnbvGH5.d.ts → transactions-CHNUJ42J.d.ts} +2 -2
- package/dist/{transactions-DhnbvGH5.d.ts.map → transactions-CHNUJ42J.d.ts.map} +1 -1
- package/dist/utils/currencies.d.ts +16 -1
- package/dist/utils/currencies.d.ts.map +1 -1
- package/dist/utils/currencies.js +24 -0
- package/dist/utils/currencies.js.map +1 -1
- package/dist/utils/dates.d.ts +2 -2
- package/dist/utils/dates.js +36 -14
- package/dist/utils/dates.js.map +1 -1
- package/package.json +1 -1
- package/src/interface/admin-interface.ts +0 -20
- package/src/interface/server-interface.ts +20 -0
- package/src/schema-fields.ts +13 -2
- package/src/utils/currencies.tsx +69 -0
- package/src/utils/dates.tsx +104 -15
- package/dist/admin-interface-BSW1mzGs.d.ts.map +0 -1
- package/dist/dates-B6ne9iOR.d.ts +0 -23
- package/dist/schema-fields-DqGQ4kF7.d.ts.map +0 -1
- package/dist/server-interface-CgpxsLT_.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-fields.js","names":["yup","normalizeCountryCode","isValidCountryCode"],"sources":["../../src/schema-fields.ts"],"sourcesContent":["import * as yup from \"yup\";\nimport { KnownErrors } from \"./known-errors\";\nimport { isBase64 } from \"./utils/bytes\";\nimport { isValidCountryCode, normalizeCountryCode } from \"./utils/country-codes\";\nimport { SUPPORTED_CURRENCIES, type Currency, type MoneyAmount } from \"./utils/currency-constants\";\nimport type { DayInterval, Interval } from \"./utils/dates\";\nimport { getProcessEnv } from \"./utils/env\";\nimport { HexclaveAssertionError } from \"./utils/errors\";\nimport { decodeBasicAuthorizationHeader } from \"./utils/http\";\nimport { allProviders } from \"./utils/oauth\";\nimport { deepPlainClone, omit, typedFromEntries } from \"./utils/objects\";\nimport { deindent } from \"./utils/strings\";\nimport { isValidHostnameWithWildcards, isValidUrl } from \"./utils/urls\";\nimport { isUuid } from \"./utils/uuids\";\n\nexport { isValidCountryCode, normalizeCountryCode, validateCountryCode } from \"./utils/country-codes\";\n\nconst MAX_IMAGE_SIZE_BASE64_BYTES = 1_000_000; // 1MB\n\ndeclare module \"yup\" {\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface StringSchema<TType, TContext, TDefault, TFlags> {\n nonEmpty(message?: string): StringSchema<TType, TContext, TDefault, TFlags>,\n empty(): StringSchema<TType, TContext, TDefault, TFlags>,\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface Schema<TType, TContext, TDefault, TFlags> {\n hasNested<K extends keyof NonNullable<TType>>(path: K): boolean,\n getNested<K extends keyof NonNullable<TType>>(path: K): yup.Schema<NonNullable<TType>[K], TContext, TDefault, TFlags>,\n\n // the default types for concat kinda suck, so let's fix that\n concat<U extends yup.AnySchema>(schema: U): yup.Schema<Omit<NonNullable<TType>, keyof yup.InferType<U>> & yup.InferType<U> | (TType & (null | undefined)), TContext, Omit<NonNullable<TDefault>, keyof U['__default']> & U['__default'] | (TDefault & (null | undefined)), TFlags>,\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n export interface CustomSchemaMetadata {\n hexclaveSchemaInfo?:\n | {\n type: \"object\" | \"array\" | \"string\" | \"number\" | \"boolean\" | \"date\" | \"mixed\" | \"never\",\n }\n | {\n type: \"tuple\",\n items: yup.AnySchema[],\n }\n | {\n type: \"union\",\n items: yup.AnySchema[],\n }\n | {\n type: \"record\",\n keySchema: yup.StringSchema<any>,\n valueSchema: yup.AnySchema,\n },\n }\n}\n\n// eslint-disable-next-line no-restricted-syntax\nyup.addMethod(yup.string, \"nonEmpty\", function (message?: string) {\n return this.test(\n \"non-empty\",\n message ?? (({ path }) => `${path} must not be empty`),\n (value) => {\n return value !== \"\";\n }\n );\n});\n\nyup.addMethod(yup.Schema, \"hasNested\", function (path: any) {\n if (!path.match(/^[a-zA-Z0-9_$:-]*$/)) throw new HexclaveAssertionError(`yupSchema.hasNested can currently only be used with alphanumeric keys, underscores, dollar signs, colons, and hyphens. Fix this in the future. Provided key: ${JSON.stringify(path)}`);\n const schemaInfo = this.meta()?.hexclaveSchemaInfo as any;\n if (schemaInfo?.type === \"record\") {\n return schemaInfo.keySchema.isValidSync(path);\n } else if (schemaInfo?.type === \"union\") {\n return schemaInfo.items.some((s: any) => s.hasNested(path));\n } else {\n try {\n yup.reach(this, path);\n return true as any;\n } catch (e) {\n if (e instanceof Error && e.message.includes(\"The schema does not contain the path\")) {\n return false as any;\n }\n throw e;\n }\n }\n});\n\nyup.addMethod(yup.Schema, \"getNested\", function (path: any) {\n if (!path.match(/^[a-zA-Z0-9_$:-]*$/)) throw new HexclaveAssertionError(`yupSchema.getNested can currently only be used with alphanumeric keys, underscores, dollar signs, colons, and hyphens. Fix this in the future. Provided key: ${JSON.stringify(path)}`);\n\n if (!this.hasNested(path as never)) throw new HexclaveAssertionError(`Tried to call yupSchema.getNested, but key is not present in the schema. Provided key: ${path}`, { path, schema: this });\n\n const schemaInfo = this.meta()?.hexclaveSchemaInfo;\n if (schemaInfo?.type === \"record\") {\n return schemaInfo.valueSchema;\n } else if (schemaInfo?.type === \"union\") {\n const schemasWithNested = schemaInfo.items.filter((s: any) => s.hasNested(path));\n return yupUnion(...schemasWithNested.map(s => s.getNested(path)));\n } else {\n return yup.reach(this, path) as any;\n }\n});\n\nimport.meta.vitest?.test(\"hasNested\", ({ expect }) => {\n expect(yupObject({ a: yupString() }).hasNested(\"a\")).toBe(true);\n expect(yupObject({}).hasNested(\"a\" as never)).toBe(false);\n expect(yupRecord(yupString(), yupString()).hasNested(\"a\")).toBe(true);\n expect(yupRecord(yupString().oneOf([\"a\"]), yupString()).hasNested(\"b\")).toBe(false);\n expect(yupUnion(yupString(), yupNumber()).hasNested(\"a\" as any)).toBe(false);\n expect(yupUnion(yupString(), yupObject({ b: yupNumber() })).hasNested(\"a\" as never)).toBe(false);\n expect(yupUnion(yupString(), yupObject({ a: yupNumber() })).hasNested(\"a\" as never)).toBe(true);\n});\nimport.meta.vitest?.test(\"getNested\", ({ expect }) => {\n expect(yupObject({ a: yupNumber() }).getNested(\"a\").describe().type).toEqual(\"number\");\n expect(() => yupObject({}).getNested(\"a\" as never)).toThrow();\n expect(() => yupObject({ a: yupObject({ b: yupString() }) }).getNested(\"a.b\" as never)).toThrow();\n expect(yupRecord(yupString().oneOf([\"a\"]), yupNumber()).getNested(\"a\").describe().type).toEqual(\"number\");\n expect(() => yupRecord(yupString().oneOf([\"a\"]), yupString()).getNested(\"b\" as never)).toThrow();\n expect(yupUnion(yupString(), yupObject({ a: yupNumber() })).getNested(\"a\" as never).describe().type).toEqual(\"mixed\");\n expect(yupUnion(yupObject({ a: yupString() }), yupObject({ a: yupNumber() })).getNested(\"a\").describe().type).toEqual(\"mixed\");\n});\n\nexport async function yupValidate<S extends yup.ISchema<any>>(\n schema: S,\n obj: unknown,\n options?: yup.ValidateOptions & { currentUserId?: string | null }\n): Promise<yup.InferType<S>> {\n try {\n return await schema.validate(obj, {\n ...omit(options ?? {}, ['currentUserId']),\n context: {\n ...options?.context,\n hexclaveAllowUserIdMe: options?.currentUserId !== undefined,\n },\n });\n } catch (error) {\n if (error instanceof ReplaceFieldWithOwnUserId) {\n const currentUserId = options?.currentUserId;\n if (!currentUserId) throw new KnownErrors.CannotGetOwnUserWithoutUser();\n\n // parse yup path\n let pathRemaining = error.path;\n const fieldPath = [];\n while (pathRemaining.length > 0) {\n if (pathRemaining.startsWith(\"[\")) {\n const index = pathRemaining.indexOf(\"]\");\n if (index < 0) throw new HexclaveAssertionError(\"Invalid path\");\n fieldPath.push(JSON.parse(pathRemaining.slice(1, index)));\n pathRemaining = pathRemaining.slice(index + 1);\n } else {\n let dotIndex = pathRemaining.indexOf(\".\");\n if (dotIndex === -1) dotIndex = pathRemaining.length;\n fieldPath.push(pathRemaining.slice(0, dotIndex));\n pathRemaining = pathRemaining.slice(dotIndex + 1);\n }\n }\n\n const newObj = deepPlainClone(obj);\n let it = newObj;\n for (const field of fieldPath.slice(0, -1)) {\n if (!Object.prototype.hasOwnProperty.call(it, field)) {\n throw new HexclaveAssertionError(`Segment ${field} of path ${error.path} not found in object`);\n }\n it = (it as any)[field];\n }\n (it as any)[fieldPath[fieldPath.length - 1]] = currentUserId;\n\n return await yupValidate(schema, newObj, options);\n }\n throw error;\n }\n}\n\nconst _idDescription = (identify: string) => `The unique identifier of the ${identify}`;\nconst _displayNameDescription = (identify: string) => `Human-readable ${identify} display name. This is not a unique identifier.`;\nconst _clientMetaDataDescription = (identify: string) => `Client metadata. Used as a data store, accessible from the client side. Do not store information that should not be exposed to the client.`;\nconst _clientReadOnlyMetaDataDescription = (identify: string) => `Client read-only, server-writable metadata. Used as a data store, accessible from the client side. Do not store information that should not be exposed to the client. The client can read this data, but cannot modify it. This is useful for things like subscription status.`;\nconst _profileImageUrlDescription = (identify: string) => `URL of the profile image for ${identify}. Can be a Base64 encoded image. Must be smaller than 100KB. Please compress and crop to a square before passing in.`;\nconst _serverMetaDataDescription = (identify: string) => `Server metadata. Used as a data store, only accessible from the server side. You can store secret information related to the ${identify} here.`;\nconst _atMillisDescription = (identify: string) => `(the number of milliseconds since epoch, January 1, 1970, UTC)`;\nconst _createdAtMillisDescription = (identify: string) => `The time the ${identify} was created ${_atMillisDescription(identify)}`;\nconst _signedUpAtMillisDescription = `The time the user signed up ${_atMillisDescription}`;\nconst _lastActiveAtMillisDescription = `The time the user was last active ${_atMillisDescription}`;\n\n\ndeclare const HexclaveAdaptSentinel: unique symbol;\nexport type HexclaveAdaptSentinel = typeof HexclaveAdaptSentinel;\n\n// Built-in replacements\nexport function yupString<A extends string, B extends yup.Maybe<yup.AnyObject> = yup.AnyObject>(...args: Parameters<typeof yup.string<A, B>>) {\n // eslint-disable-next-line no-restricted-syntax\n return yup.string(...args).meta({ hexclaveSchemaInfo: { type: \"string\" } });\n}\nexport function yupNumber<A extends number, B extends yup.Maybe<yup.AnyObject> = yup.AnyObject>(...args: Parameters<typeof yup.number<A, B>>) {\n // eslint-disable-next-line no-restricted-syntax\n return yup.number(...args).meta({ hexclaveSchemaInfo: { type: \"number\" } });\n}\nexport function yupBoolean<A extends boolean, B extends yup.Maybe<yup.AnyObject> = yup.AnyObject>(...args: Parameters<typeof yup.boolean<A, B>>) {\n // eslint-disable-next-line no-restricted-syntax\n return yup.boolean(...args).meta({ hexclaveSchemaInfo: { type: \"boolean\" } });\n}\n/**\n * @deprecated, use number of milliseconds since epoch instead\n */\nexport function yupDate<A extends Date, B extends yup.Maybe<yup.AnyObject> = yup.AnyObject>(...args: Parameters<typeof yup.date<A, B>>) {\n // eslint-disable-next-line no-restricted-syntax\n return yup.date(...args).meta({ hexclaveSchemaInfo: { type: \"date\" } });\n}\nfunction _yupMixedInternal<A extends {}>(...args: Parameters<typeof yup.mixed<A>>) {\n // eslint-disable-next-line no-restricted-syntax\n return yup.mixed(...args);\n}\nexport function yupMixed<A extends {}>(...args: Parameters<typeof yup.mixed<A>>) {\n return _yupMixedInternal(...args).meta({ hexclaveSchemaInfo: { type: \"mixed\" } });\n}\nexport function yupArray<A extends yup.Maybe<yup.AnyObject> = yup.AnyObject, B = any>(...args: Parameters<typeof yup.array<A, B>>) {\n // eslint-disable-next-line no-restricted-syntax\n return yup.array(...args).meta({ hexclaveSchemaInfo: { type: \"array\" } });\n}\nexport function yupTuple<T extends [unknown, ...unknown[]]>(schemas: { [K in keyof T]: yup.Schema<T[K]> }) {\n if (schemas.length === 0) throw new Error('yupTuple must have at least one schema');\n // eslint-disable-next-line no-restricted-syntax\n return yup.tuple<T>(schemas as any).meta({ hexclaveSchemaInfo: { type: \"tuple\", items: schemas } });\n}\nexport function yupObjectWithAutoDefault<A extends yup.Maybe<yup.AnyObject>, B extends yup.ObjectShape>(...args: Parameters<typeof yup.object<A, B>>) {\n // eslint-disable-next-line no-restricted-syntax\n const object = yup.object(...args).test(\n 'no-unknown-object-properties',\n ({ path }) => `${path} contains unknown properties`,\n (value: any, context) => {\n if (context.options.context?.noUnknownPathPrefixes?.some((prefix: string) => context.path.startsWith(prefix))) {\n if (context.schema.spec.noUnknown !== false) {\n const availableKeys = new Set(Object.keys(context.schema.fields));\n const unknownKeys = Object.keys(value ?? {}).filter(key => !availableKeys.has(key));\n if (unknownKeys.length > 0) {\n // TODO \"did you mean XYZ\"\n return context.createError({\n message: `${context.path || \"Object\"} contains unknown properties: ${unknownKeys.join(', ')}`,\n path: context.path,\n params: { unknownKeys, availableKeys },\n });\n }\n }\n }\n return true;\n },\n ).meta({ hexclaveSchemaInfo: { type: \"object\" } });\n return object;\n}\nexport function yupObject<A extends yup.Maybe<yup.AnyObject>, B extends yup.ObjectShape>(...args: Parameters<typeof yup.object<A, B>>) {\n // we don't want to update the type of `object` to have a default flag\n const object = yupObjectWithAutoDefault(...args);\n return object.default(undefined) as any as typeof object;\n}\n\nexport function yupNever(): yup.MixedSchema<never> {\n return _yupMixedInternal().meta({ hexclaveSchemaInfo: { type: \"never\" } }).test('never', 'This value should never be reached', () => false) as any;\n}\n\nexport function yupUnion<T extends yup.AnySchema[]>(...args: T): yup.MixedSchema<yup.InferType<T[number]>> {\n if (args.length === 0) throw new Error('yupUnion must have at least one schema');\n\n return _yupMixedInternal().meta({ hexclaveSchemaInfo: { type: \"union\", items: args } }).test('is-one-of', 'Invalid value', async (value, context) => {\n if (value == null) return true;\n const errors = [];\n for (const schema of args) {\n try {\n await yupValidate(schema, value, context.options);\n return true;\n } catch (e) {\n errors.push(e);\n }\n }\n return context.createError({\n message: deindent`\n ${context.path} is not matched by any of the provided schemas:\n ${errors.map((e: any, i) => deindent`\n Schema ${i}:\n ${e.errors.join('\\n')}\n `).join('\\n')}`,\n path: context.path,\n });\n });\n}\n\nexport function yupRecord<K extends yup.StringSchema, T extends yup.AnySchema>(\n keySchema: K,\n valueSchema: T,\n): yup.MixedSchema<Record<yup.InferType<K> & string, yup.InferType<T>>> {\n return yupObject().meta({ hexclaveSchemaInfo: { type: \"record\", keySchema, valueSchema } }).unknown(true).test(\n 'record',\n '${path} must be a record of valid values',\n async function (value: unknown, context: yup.TestContext) {\n if (value == null) return true;\n const { path, createError } = this as any;\n if (typeof value !== 'object') {\n return createError({ message: `${path} must be an object` });\n }\n\n // Validate each property using the provided valueSchema\n for (const key of Object.keys(value)) {\n // Validate the key\n await yupValidate(keySchema, key, context.options);\n\n // Validate the value\n try {\n await yupValidate(valueSchema, (value as Record<string, unknown>)[key], {\n ...context.options,\n context: {\n ...context.options.context,\n path: path ? `${path}.${key}` : key,\n },\n });\n } catch (e: any) {\n return createError({\n path: path ? `${path}.${key}` : key,\n message: e.message,\n });\n }\n }\n\n return true;\n },\n ) as any;\n}\n\nexport function ensureObjectSchema<T extends yup.AnyObject>(schema: yup.Schema<T>): yup.ObjectSchema<T> & typeof schema {\n if (!(schema instanceof yup.ObjectSchema)) throw new HexclaveAssertionError(`assertObjectSchema: schema is not an ObjectSchema: ${schema.describe().type}`);\n return schema as any;\n}\n\n// Common\nexport const adaptSchema = yupMixed<HexclaveAdaptSentinel>();\n/**\n * Yup's URL schema does not recognize some URLs (including `http://localhost`) as a valid URL. This schema is a workaround for that.\n */\nexport const urlSchema = yupString().test({\n name: 'no-spaces',\n message: (params) => `${params.path} contains spaces`,\n test: (value) => value == null || !value.includes(' ')\n}).test({\n name: 'url',\n message: (params) => `${params.path} is not a valid URL`,\n test: (value) => value == null || isValidUrl(value)\n});\n/**\n * URL schema that supports wildcard patterns in hostnames (e.g., \"https://*.example.com\", \"http://*:8080\")\n */\nexport const wildcardUrlSchema = yupString().test({\n name: 'no-spaces',\n message: (params) => `${params.path} contains spaces`,\n test: (value) => value == null || !value.includes(' ')\n}).test({\n name: 'wildcard-url',\n message: (params) => `${params.path} is not a valid URL or wildcard URL pattern`,\n test: (value) => {\n if (value == null) return true;\n\n // If it doesn't contain wildcards, use the regular URL validation\n if (!value.includes('*')) {\n return isValidUrl(value);\n }\n\n // For wildcard URLs, validate the structure by replacing wildcards with placeholders\n try {\n const PLACEHOLDER = 'wildcard-placeholder';\n // Replace wildcards with valid placeholders for URL parsing\n const normalizedUrl = value.replace(/\\*/g, PLACEHOLDER);\n const url = new URL(normalizedUrl);\n\n // Only allow wildcards in the hostname; reject anywhere else\n if (\n url.username.includes(PLACEHOLDER) ||\n url.password.includes(PLACEHOLDER) ||\n url.pathname.includes(PLACEHOLDER) ||\n url.search.includes(PLACEHOLDER) ||\n url.hash.includes(PLACEHOLDER)\n ) {\n return false;\n }\n\n // Only http/https are acceptable\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n return false;\n }\n\n // Extract original hostname pattern from the input\n const hostPattern = url.hostname.split(PLACEHOLDER).join('*');\n\n // Validate the wildcard hostname pattern using the existing function\n return isValidHostnameWithWildcards(hostPattern);\n } catch (e) {\n return false;\n }\n }\n});\nexport const wildcardProtocolAndDomainSchema = wildcardUrlSchema.test({\n name: 'is-protocol-and-domain',\n message: (params) => `${params.path} must be a protocol and domain (with optional port) without any path, query parameters, or hash`,\n test: (value) => {\n if (value == null) return true;\n try {\n const PLACEHOLDER = 'wildcard-placeholder';\n // Replace wildcards with valid placeholders for URL parsing\n const normalized = value.replace(/\\*/g, PLACEHOLDER);\n const url = new URL(normalized);\n return url.protocol !== '' && url.hostname !== '' && url.pathname === '/' && url.search === '' && url.hash === '';\n } catch (e) {\n return false;\n }\n }\n});\nexport const jsonSchema = yupMixed().nullable().defined().transform((value) => JSON.parse(JSON.stringify(value)));\nexport const jsonStringSchema = yupString().test(\"json\", (params) => `${params.path} is not valid JSON`, (value) => {\n if (value == null) return true;\n try {\n JSON.parse(value);\n return true;\n } catch (error) {\n return false;\n }\n});\nexport const jsonStringOrEmptySchema = yupString().test(\"json\", (params) => `${params.path} is not valid JSON`, (value) => {\n if (!value) return true;\n try {\n JSON.parse(value);\n return true;\n } catch (error) {\n return false;\n }\n});\nexport const base64Schema = yupString().test(\"is-base64\", (params) => `${params.path} is not valid base64`, (value) => {\n if (value == null) return true;\n return isBase64(value);\n});\nexport const passwordSchema = yupString().max(70);\nexport const countryCodeSchema = yupString().transform((value) => typeof value === \"string\" ? normalizeCountryCode(value) : value).test({\n name: \"country-code\",\n message: (params) => `${params.path} must be a 2-letter country code`,\n test: (value) => value == null || isValidCountryCode(value),\n});\nimport.meta.vitest?.test(\"countryCodeSchema\", async ({ expect }) => {\n await expect(countryCodeSchema.validate(\" us \")).resolves.toBe(\"US\");\n await expect(countryCodeSchema.validate(\"usa\")).rejects.toThrow(\"must be a 2-letter country code\");\n});\nexport const intervalSchema = yupTuple<Interval>([yupNumber().min(0).integer().defined(), yupString().oneOf(['millisecond', 'second', 'minute', 'hour', 'day', 'week', 'month', 'year']).defined()]);\nexport const dayIntervalSchema = yupTuple<DayInterval>([yupNumber().min(0).integer().defined(), yupString().oneOf(['day', 'week', 'month', 'year']).defined()]);\nexport const intervalOrNeverSchema = yupUnion(intervalSchema.defined(), yupString().oneOf(['never']).defined());\nexport const dayIntervalOrNeverSchema = yupUnion(dayIntervalSchema.defined(), yupString().oneOf(['never']).defined());\n/**\n * This schema is useful for fields where the user can specify the ID, such as price IDs. It is particularly common\n * for IDs in the config schema.\n *\n * Valid IDs:\n * - Must contain only letters, numbers, underscores, and hyphens\n * - Must not start with a hyphen\n * - Maximum length of 63 characters\n */\nexport const USER_SPECIFIED_ID_PATTERN = /^[a-zA-Z0-9_][a-zA-Z0-9_-]*$/;\nexport const USER_SPECIFIED_ID_MAX_LENGTH = 63;\n\n/**\n * Checks if the given string is a valid user-specified ID.\n */\nexport function isValidUserSpecifiedId(id: string): boolean {\n return id.length > 0 && id.length <= USER_SPECIFIED_ID_MAX_LENGTH && USER_SPECIFIED_ID_PATTERN.test(id);\n}\n\n/**\n * Gets the error message for an invalid user-specified ID.\n */\nexport function getUserSpecifiedIdErrorMessage(idName: `${string}Id`): string {\n return `${idName} must contain only letters, numbers, underscores, and hyphens, and not start with a hyphen`;\n}\n\n/**\n * Sanitizes user input to create a valid user-specified ID.\n * Converts to lowercase and replaces invalid characters with hyphens.\n * Strips leading hyphens.\n */\nexport function sanitizeUserSpecifiedId(input: string): string {\n // Convert to lowercase, replace invalid characters with empty string (or hyphen for spaces)\n const sanitized = input\n .replace(/\\s+/g, '-') // Replace spaces with hyphens\n .replace(/[^a-zA-Z0-9_-]/g, ''); // Remove other invalid characters\n\n // Strip leading hyphens\n return sanitized.replace(/^-+/, '');\n}\n\nexport const userSpecifiedIdSchema = (idName: `${string}Id`) => yupString().max(USER_SPECIFIED_ID_MAX_LENGTH).matches(USER_SPECIFIED_ID_PATTERN, getUserSpecifiedIdErrorMessage(idName));\n\n/**\n * Validates that a value is a decimal string like `\"9.99\"` or `\"1000\"` (see `MoneyAmount`).\n *\n * Currency amounts are always strings in `\"<integer>\"` or `\"<integer>.<decimals>\"` format — never\n * cent integers or minor-unit numbers. For example, `\"9.99\"` means $9.99, not `999`.\n */\nexport const moneyAmountSchema = (currency: Currency) => yupString<MoneyAmount>().test('money-amount', 'Invalid money amount', (value, context) => {\n if (value == null) return true;\n const regex = /^([0-9]+)(\\.([0-9]+))?$/;\n const match = value.match(regex);\n if (!match) return context.createError({ message: 'Money amount must be in the format of <number> or <number>.<number>' });\n const whole = match[1];\n const decimals = match[3];\n if (decimals && decimals.length > currency.decimals) return context.createError({ message: `Too many decimals; ${currency.code} only has ${currency.decimals} decimals` });\n if (whole !== '0' && whole.startsWith('0')) return context.createError({ message: 'Money amount must not have leading zeros' });\n return true;\n});\n\n\n/**\n * A stricter email schema that does some additional checks for UX input. (Some emails are allowed by the spec, for\n * example `test@localhost` or `abc@gmail`, but almost certainly a user input error.)\n *\n * Note that some users in the DB have an email that doesn't match this regex, so most of the time you should use\n * `emailSchema` instead until we do the DB migration.\n */\n// eslint-disable-next-line no-restricted-syntax\nexport const strictEmailSchema = (message: string | undefined) => yupString().email(message).max(256).matches(/^[^.]+(\\.[^.]+)*@.*\\.[^.][^.]+$/, message);\n// eslint-disable-next-line no-restricted-syntax\nexport const emailSchema = yupString().email();\n\nimport.meta.vitest?.test('strictEmailSchema', ({ expect }) => {\n const validEmails = [\n \"a@example.com\",\n \"abc@example.com\",\n \"a.b@example.com\",\n \"throwaway.mail+token@example.com\",\n \"email-alt-dash@demo-mail.com\",\n \"test-account@weird-domain.net\",\n \"%!~&+{}=|`#@domain.test\",\n \"admin@a.longtldexample\",\n ];\n for (const email of validEmails) {\n expect(strictEmailSchema(undefined).validateSync(email)).toBe(email);\n }\n const invalidEmails = [\n \"test@localhost\",\n \"test@gmail\",\n \"test@gmail.com.a\",\n \"test@gmail.a\",\n \"test.@example.com\",\n \"test..test@example.com\",\n \".test@example.com\",\n ];\n for (const email of invalidEmails) {\n expect(() => strictEmailSchema(undefined).validateSync(email)).toThrow();\n }\n});\n\n// Request auth\nexport const clientOrHigherAuthTypeSchema = yupString().oneOf(['client', 'server', 'admin']).defined();\nexport const serverOrHigherAuthTypeSchema = yupString().oneOf(['server', 'admin']).defined();\nexport const adminAuthTypeSchema = yupString().oneOf(['admin']).defined();\n\n// Projects\nexport const projectIdSchema = yupString().test((v) => v === undefined || v === \"internal\" || isUuid(v)).meta({ openapiField: { description: _idDescription('project'), exampleValue: 'e0b52f4d-dece-408c-af49-d23061bb0f8d' } });\nexport const projectBranchIdSchema = yupString().nonEmpty().max(255).meta({ openapiField: { description: _idDescription('project branch'), exampleValue: 'main' } });\nexport const projectDisplayNameSchema = yupString().meta({ openapiField: { description: _displayNameDescription('project'), exampleValue: 'MyMusic' } });\nexport const projectLogoUrlSchema = urlSchema.max(MAX_IMAGE_SIZE_BASE64_BYTES).meta({ openapiField: { description: 'URL of the logo for the project. This is usually a close to 1:1 image of the company logo.', exampleValue: 'https://example.com/logo.png' } });\nexport const projectLogoFullUrlSchema = urlSchema.max(MAX_IMAGE_SIZE_BASE64_BYTES).meta({ openapiField: { description: 'URL of the full logo for the project. This is usually a vertical image with the logo and the company name.', exampleValue: 'https://example.com/full-logo.png' } });\nexport const projectLogoDarkModeUrlSchema = urlSchema.max(MAX_IMAGE_SIZE_BASE64_BYTES).meta({ openapiField: { description: 'URL of the dark mode logo for the project. This is usually a close to 1:1 image of the company logo optimized for dark backgrounds.', exampleValue: 'https://example.com/logo-dark.png' } });\nexport const projectLogoFullDarkModeUrlSchema = urlSchema.max(MAX_IMAGE_SIZE_BASE64_BYTES).meta({ openapiField: { description: 'URL of the dark mode full logo for the project. This is usually a vertical image with the logo and the company name optimized for dark backgrounds.', exampleValue: 'https://example.com/full-logo-dark.png' } });\nexport const projectDescriptionSchema = yupString().nullable().meta({ openapiField: { description: 'A human readable description of the project', exampleValue: 'A music streaming service' } });\nexport const projectCreatedAtMillisSchema = yupNumber().meta({ openapiField: { description: _createdAtMillisDescription('project'), exampleValue: 1630000000000 } });\nexport const projectIsProductionModeSchema = yupBoolean().meta({ openapiField: { description: 'Whether the project is in production mode', exampleValue: true } });\nexport const projectOnboardingStatusValues = [\n \"config_choice\",\n \"apps_selection\",\n \"auth_setup\",\n \"domain_setup\",\n \"email_theme_setup\",\n \"payments_setup\",\n \"welcome\",\n \"completed\",\n] as const;\nexport type ProjectOnboardingStatus = typeof projectOnboardingStatusValues[number];\nexport const projectOnboardingStatusSchema = yupString().oneOf(projectOnboardingStatusValues).meta({\n openapiField: {\n description: \"The current dashboard onboarding stage for this project.\",\n exampleValue: \"config_choice\",\n },\n});\n// Project config\nexport const projectConfigIdSchema = yupString().meta({ openapiField: { description: _idDescription('project config'), exampleValue: 'd09201f0-54f5-40bd-89ff-6d1815ddad24' } });\nexport const projectAllowLocalhostSchema = yupBoolean().meta({ openapiField: { description: 'Whether localhost is allowed as a domain for this project. Should only be allowed in development mode', exampleValue: true } });\nexport const projectCreateTeamOnSignUpSchema = yupBoolean().meta({ openapiField: { description: 'Whether a team should be created for each user that signs up', exampleValue: true } });\nexport const projectMagicLinkEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether magic link authentication is enabled for this project', exampleValue: true } });\nexport const projectPasskeyEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether passkey authentication is enabled for this project', exampleValue: true } });\nexport const projectClientTeamCreationEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether client users can create teams', exampleValue: true } });\nexport const projectClientUserDeletionEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether client users can delete their own account from the client', exampleValue: true } });\nexport const projectSignUpEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether users can sign up new accounts, or whether they are only allowed to sign in to existing accounts. Regardless of this option, the server API can always create new users with the `POST /users` endpoint.', exampleValue: true } });\nexport const projectCredentialEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether email password authentication is enabled for this project', exampleValue: true } });\n// Project OAuth config\nexport const oauthIdSchema = yupString().oneOf(allProviders).meta({ openapiField: { description: `OAuth provider ID, one of ${allProviders.map(x => `\\`${x}\\``).join(', ')}`, exampleValue: 'google' } });\nexport const oauthEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether the OAuth provider is enabled. If an provider is first enabled, then disabled, it will be shown in the list but with enabled=false', exampleValue: true } });\nexport const oauthTypeSchema = yupString().oneOf(['shared', 'standard']).meta({ openapiField: { description: 'OAuth provider type, one of shared, standard. \"shared\" uses Stack shared OAuth keys and it is only meant for development. \"standard\" uses your own OAuth keys and will show your logo and company name when signing in with the provider.', exampleValue: 'standard' } });\nexport const oauthClientIdSchema = yupString().meta({ openapiField: { description: 'OAuth client ID. Needs to be specified when using type=\"standard\"', exampleValue: 'google-oauth-client-id' } });\nexport const oauthClientSecretSchema = yupString().meta({ openapiField: { description: 'OAuth client secret. Needs to be specified when using type=\"standard\"', exampleValue: 'google-oauth-client-secret' } });\nexport const oauthCustomCallbackUrlSchema = urlSchema.meta({ openapiField: { description: 'The OAuth redirect/callback URL sent to the provider. When omitted, the default callback URL is used. Cannot be set for shared providers.', exampleValue: 'https://api.hexclave.com/api/v1/auth/oauth/callback/google' } });\nexport const oauthFacebookConfigIdSchema = yupString().meta({ openapiField: { description: 'The configuration id for Facebook business login (for things like ads and marketing). This is only required if you are using the standard OAuth with Facebook and you are using Facebook business login.' } });\nexport const oauthMicrosoftTenantIdSchema = yupString().meta({ openapiField: { description: 'The Microsoft tenant id for Microsoft directory. This is only required if you are using the standard OAuth with Microsoft and you have an Azure AD tenant.' } });\nexport const oauthAppleBundleIdsSchema = yupArray(yupString().defined()).meta({ openapiField: { description: 'Apple Bundle IDs for native iOS/macOS apps. Required for native Sign In with Apple (in addition to web Apple OAuth which uses the Client ID/Services ID).', exampleValue: ['com.example.ios', 'com.example.macos'] } });\nexport const oauthAppleBundleIdSchema = yupString().defined().meta({ openapiField: { description: 'Apple Bundle ID for native iOS/macOS apps.', exampleValue: 'com.example.ios' } });\nexport const oauthAccountMergeStrategySchema = yupString().oneOf(['link_method', 'raise_error', 'allow_duplicates']).meta({ openapiField: { description: 'Determines how to handle OAuth logins that match an existing user by email. `link_method` adds the OAuth method to the existing user. `raise_error` rejects the login with an error. `allow_duplicates` creates a new user.', exampleValue: 'link_method' } });\nexport const oauthIssuerUrlSchema = urlSchema.meta({ openapiField: { description: 'OIDC issuer URL for custom OIDC providers. Must support OIDC discovery (/.well-known/openid-configuration). Only used when type is \"custom_oidc\".', exampleValue: 'https://accounts.google.com' } });\nexport const oauthScopeSchema = yupString().meta({ openapiField: { description: 'Space-separated OAuth scopes to request from the custom OIDC provider. Defaults to \"openid email profile\" if not specified.', exampleValue: 'openid email profile' } });\n// Project email config\nexport const emailTypeSchema = yupString().oneOf(['shared', 'standard']).meta({ openapiField: { description: 'Email provider type, one of shared, standard. \"shared\" uses Stack shared email provider and it is only meant for development. \"standard\" uses your own email server and will have your email address as the sender.', exampleValue: 'standard' } });\nexport const emailSenderNameSchema = yupString().meta({ openapiField: { description: 'Email sender name. Needs to be specified when using type=\"standard\"', exampleValue: 'Stack' } });\nexport const emailHostSchema = yupString().meta({ openapiField: { description: 'Email host. Needs to be specified when using type=\"standard\"', exampleValue: 'smtp.your-domain.com' } });\nexport const emailPortSchema = yupNumber().min(0).max(65535).meta({ openapiField: { description: 'Email port. Needs to be specified when using type=\"standard\"', exampleValue: 587 } });\nexport const emailUsernameSchema = yupString().meta({ openapiField: { description: 'Email username. Needs to be specified when using type=\"standard\"', exampleValue: 'smtp-email' } });\nexport const emailSenderEmailSchema = emailSchema.meta({ openapiField: { description: 'Email sender email. Needs to be specified when using type=\"standard\"', exampleValue: 'example@your-domain.com' } });\n// SMTP credentials are stored encrypted (not bcrypt-hashed like user passwords), so they don't\n// need the 70-char bcrypt limit from passwordSchema. Some providers (e.g. ZeptoMail) generate\n// passwords well over 100 chars.\nexport const emailPasswordSchema = yupString().max(256).meta({ openapiField: { description: 'Email password. Needs to be specified when using type=\"standard\"', exampleValue: 'your-email-password' } });\n// Project domain config\nexport const handlerPathSchema = yupString().test('is-handler-path', 'Handler path must start with /', (value) => value?.startsWith('/')).meta({ openapiField: { description: 'Handler path. If you did not setup a custom handler path, it should be \"/handler\" by default. It needs to start with /', exampleValue: '/handler' } });\n// Project email theme config\nexport const emailThemeSchema = yupString().meta({ openapiField: { description: 'Email theme id for the project. Determines the visual style of emails sent by the project.' } });\nexport const emailThemeListSchema = yupRecord(\n yupString().uuid(),\n yupObject({\n displayName: yupString().meta({ openapiField: { description: 'Email theme name', exampleValue: 'Default Light' } }).defined(),\n tsxSource: yupString().meta({ openapiField: { description: 'Email theme source code tsx component' } }).defined(),\n })\n).meta({ openapiField: { description: 'Record of email theme IDs to their display name and source code' } });\nexport const templateThemeIdSchema = yupMixed<string | false>().test((v: any) => v === undefined || v === false || v === null || (typeof v === 'string' && isUuid(v))).meta({ openapiField: { description: 'Email theme id for the template' } }).optional();\nexport const emailTemplateListSchema = yupRecord(\n yupString().uuid(),\n yupObject({\n displayName: yupString().meta({ openapiField: { description: 'Email template name', exampleValue: 'Email Verification' } }).defined(),\n tsxSource: yupString().meta({ openapiField: { description: 'Email template source code tsx component' } }).defined(),\n // themeId can be one of three values:\n // 1. A valid theme id\n // 2. false, which means the template uses no theme\n // 3. undefined/not given, which means the template uses the project's active theme\n themeId: templateThemeIdSchema,\n })\n).meta({ openapiField: { description: 'Record of email template IDs to their display name and source code' } });\n\n// Custom dashboards\nexport const customDashboardsSchema = yupRecord(\n yupString().uuid(),\n yupObject({\n displayName: yupString().meta({ openapiField: { description: 'Custom dashboard name', exampleValue: 'User Growth Dashboard' } }).defined(),\n tsxSource: yupString().meta({ openapiField: { description: 'Custom dashboard source code tsx component' } }).defined(),\n })\n).meta({ openapiField: { description: 'Record of custom dashboard IDs to their display name and source code' } });\n\n// Payments\nexport const customerTypeSchema = yupString().oneOf(['user', 'team', 'custom']);\nconst validateHasAtLeastOneSupportedCurrency = (value: Record<string, unknown> | null, context: any) => {\n if (!value) return true;\n const currencies = Object.keys(value).filter(key => SUPPORTED_CURRENCIES.some(c => c.code === key));\n if (currencies.length === 0) {\n return context.createError({ message: \"At least one currency is required\" });\n }\n return true;\n};\n/**\n * Schema for a single product price. Each currency field (USD, EUR, etc.) is a decimal string\n * like `\"9.99\"` or `\"1000\"` — never cent integers. See `MoneyAmount` for the exact format.\n */\nexport const productPriceSchema = yupObject({\n ...typedFromEntries(SUPPORTED_CURRENCIES.map(currency => [currency.code, moneyAmountSchema(currency).optional()])),\n interval: dayIntervalSchema.optional(),\n serverOnly: yupBoolean(),\n freeTrial: dayIntervalSchema.optional(),\n}).test(\"at-least-one-currency\", (value, context) => validateHasAtLeastOneSupportedCurrency(value, context));\nexport const pricesSchema = yupRecord(\n userSpecifiedIdSchema(\"priceId\"),\n productPriceSchema,\n);\nexport const productSchema = yupObject({\n displayName: yupString(),\n productLineId: userSpecifiedIdSchema(\"productLineId\").optional().meta({ openapiField: { description: 'The ID of the product line this product belongs to. Within a product line, all products are mutually exclusive unless they are an add-on to another product in the product line.', exampleValue: 'product-line-id' } }),\n isAddOnTo: yupUnion(\n yupBoolean().isFalse(),\n yupRecord(\n userSpecifiedIdSchema(\"productId\"),\n yupBoolean().isTrue().defined(),\n ),\n ).optional().meta({ openapiField: { description: 'The products that this product is an add-on to. If this is set, the customer must already have one of the products in the record to be able to purchase this product.', exampleValue: { \"product-id\": true } } }),\n customerType: customerTypeSchema.defined(),\n freeTrial: dayIntervalSchema.optional(),\n serverOnly: yupBoolean(),\n stackable: yupBoolean(),\n prices: pricesSchema.defined(),\n includedItems: yupRecord(\n userSpecifiedIdSchema(\"itemId\"),\n yupObject({\n quantity: yupNumber().defined(),\n repeat: dayIntervalOrNeverSchema.optional(),\n expires: yupString().oneOf(['never', 'when-purchase-expires', 'when-repeated']).optional(),\n }),\n ),\n});\n\nconst productMetadataExample = { featureFlag: true, source: 'marketing-campaign' } as const;\n\nexport const productClientMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientMetaDataDescription('product'), exampleValue: productMetadataExample } });\nexport const productClientReadOnlyMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientReadOnlyMetaDataDescription('product'), exampleValue: productMetadataExample } });\nexport const productServerMetadataSchema = jsonSchema.meta({ openapiField: { description: _serverMetaDataDescription('product'), exampleValue: productMetadataExample } });\n\nexport const productSchemaWithMetadata = productSchema.concat(yupObject({\n clientMetadata: productClientMetadataSchema.optional(),\n clientReadOnlyMetadata: productClientReadOnlyMetadataSchema.optional(),\n serverMetadata: productServerMetadataSchema.optional(),\n}));\n\nexport const inlineProductSchema = yupObject({\n display_name: yupString().defined(),\n customer_type: customerTypeSchema.defined(),\n free_trial: dayIntervalSchema.optional(),\n server_only: yupBoolean().default(true),\n stackable: yupBoolean().default(false),\n prices: yupRecord(\n userSpecifiedIdSchema(\"priceId\"),\n yupObject({\n ...typedFromEntries(SUPPORTED_CURRENCIES.map(currency => [currency.code, moneyAmountSchema(currency).optional()])),\n interval: dayIntervalSchema.optional(),\n free_trial: dayIntervalSchema.optional(),\n }).test(\"at-least-one-currency\", (value, context) => validateHasAtLeastOneSupportedCurrency(value, context)),\n ),\n included_items: yupRecord(\n userSpecifiedIdSchema(\"itemId\"),\n yupObject({\n quantity: yupNumber(),\n repeat: dayIntervalOrNeverSchema.optional(),\n expires: yupString().oneOf(['never', 'when-purchase-expires', 'when-repeated']).optional(),\n }),\n ),\n client_metadata: productClientMetadataSchema.optional(),\n client_read_only_metadata: productClientReadOnlyMetadataSchema.optional(),\n server_metadata: productServerMetadataSchema.optional(),\n});\n\n// Users\nexport class ReplaceFieldWithOwnUserId extends Error {\n constructor(public readonly path: string) {\n super(`This error should be caught by whoever validated the schema, and the field in the path '${path}' should be replaced with the current user's id. This is a workaround to yup not providing access to the context inside the transform function.`);\n }\n}\nconst userIdMeSentinelUuid = \"cad564fd-f81b-43f4-b390-98abf3fcc17e\";\nexport const userIdOrMeSchema = yupString().uuid().transform(v => {\n if (v === \"me\") return userIdMeSentinelUuid;\n else return v;\n}).test((v, context) => {\n if (!(\"hexclaveAllowUserIdMe\" in (context.options.context ?? {}))) throw new HexclaveAssertionError('userIdOrMeSchema is not allowed in this context. Make sure you\\'re using yupValidate from schema-fields.ts to validate, instead of schema.validate(...).');\n if (!context.options.context?.hexclaveAllowUserIdMe) throw new HexclaveAssertionError('userIdOrMeSchema is not allowed in this context. Make sure you\\'re passing in the currentUserId option in yupValidate.');\n if (v === userIdMeSentinelUuid) throw new ReplaceFieldWithOwnUserId(context.path);\n return true;\n}).meta({ openapiField: { description: 'The ID of the user, or the special value `me` for the currently authenticated user', exampleValue: '3241a285-8329-4d69-8f3d-316e08cf140c' } });\nexport const userIdSchema = yupString().uuid().meta({ openapiField: { description: _idDescription('user'), exampleValue: '3241a285-8329-4d69-8f3d-316e08cf140c' } });\nexport const primaryEmailSchema = emailSchema.meta({ openapiField: { description: 'Primary email', exampleValue: 'johndoe@example.com' } });\nexport const primaryEmailAuthEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether the primary email is used for authentication. If this is set to `false`, the user will not be able to sign in with the primary email with password or OTP', exampleValue: true } });\nexport const primaryEmailVerifiedSchema = yupBoolean().meta({ openapiField: { description: 'Whether the primary email has been verified to belong to this user', exampleValue: true } });\nexport const userDisplayNameSchema = yupString().nullable().max(256).meta({ openapiField: { description: _displayNameDescription('user'), exampleValue: 'John Doe' } });\nexport const selectedTeamIdSchema = yupString().uuid().meta({ openapiField: { description: 'ID of the team currently selected by the user', exampleValue: 'team-id' } });\nexport const profileImageUrlSchema = urlSchema.max(MAX_IMAGE_SIZE_BASE64_BYTES).meta({ openapiField: { description: _profileImageUrlDescription('user'), exampleValue: 'https://example.com/image.jpg' } });\nexport const signedUpAtMillisSchema = yupNumber().meta({ openapiField: { description: _signedUpAtMillisDescription, exampleValue: 1630000000000 } });\nexport const userClientMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientMetaDataDescription('user'), exampleValue: { key: 'value' } } });\nexport const userClientReadOnlyMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientReadOnlyMetaDataDescription('user'), exampleValue: { key: 'value' } } });\nexport const userServerMetadataSchema = jsonSchema.meta({ openapiField: { description: _serverMetaDataDescription('user'), exampleValue: { key: 'value' } } });\nexport const userOAuthProviderSchema = yupObject({\n id: yupString().defined(),\n type: yupString().oneOf(allProviders).defined(),\n provider_user_id: yupString().defined(),\n});\nexport const userLastActiveAtMillisSchema = yupNumber().nullable().meta({ openapiField: { description: _lastActiveAtMillisDescription, exampleValue: 1630000000000 } });\nexport const userPasskeyAuthEnabledSchema = yupBoolean().meta({ openapiField: { hidden: true, description: 'Whether the user has passkeys enabled', exampleValue: false } });\nexport const userOtpAuthEnabledSchema = yupBoolean().meta({ openapiField: { hidden: true, description: 'Whether the user has OTP/magic link enabled. ', exampleValue: true } });\nexport const userOtpAuthEnabledMutationSchema = yupBoolean().meta({ openapiField: { hidden: true, description: 'Whether the user has OTP/magic link enabled. Note that only accounts with verified emails can sign-in with OTP.', exampleValue: true } });\nexport const userHasPasswordSchema = yupBoolean().meta({ openapiField: { hidden: true, description: 'Whether the user has a password set. If the user does not have a password set, they will not be able to sign in with email/password.', exampleValue: true } });\nexport const userPasswordMutationSchema = passwordSchema.nullable().meta({ openapiField: { description: 'Sets the user\\'s password. Doing so revokes all current sessions.', exampleValue: 'my-new-password' } }).max(70);\nexport const userPasswordHashMutationSchema = yupString()\n .nonEmpty()\n .meta({ openapiField: { description: 'If `password` is not given, sets the user\\'s password hash to the given string in Modular Crypt Format (ex.: `$2a$10$VIhIOofSMqGdGlL4wzE//e.77dAQGqNtF/1dT7bqCrVtQuInWy2qi`). Doing so revokes all current sessions.' } }); // we don't set an exampleValue here because it's exclusive with the password field and having both would break the generated example\nexport const userTotpSecretMutationSchema = base64Schema.nullable().meta({ openapiField: { description: 'Enables 2FA and sets a TOTP secret for the user. Set to null to disable 2FA.', exampleValue: 'dG90cC1zZWNyZXQ=' } });\n\n// Auth\nexport const restrictedReasonTypes = [\"anonymous\", \"email_not_verified\", \"restricted_by_administrator\"] as const;\nexport type RestrictedReasonType = typeof restrictedReasonTypes[number];\nexport const restrictedReasonSchema = yupObject({\n type: yupString().oneOf(restrictedReasonTypes).defined(),\n});\nexport type RestrictedReason = yup.InferType<typeof restrictedReasonSchema>;\n\nexport const accessTokenPayloadSchema = yupObject({\n sub: yupString().defined(),\n exp: yupNumber().optional(),\n iat: yupNumber().defined(),\n iss: yupString().defined(),\n aud: yupString().defined(),\n project_id: yupString().defined(),\n branch_id: yupString().defined(),\n refresh_token_id: yupString().defined(),\n role: yupString().oneOf([\"authenticated\"]).defined(),\n name: yupString().defined().nullable(),\n email: yupString().defined().nullable(),\n email_verified: yupBoolean().defined(),\n selected_team_id: yupString().defined().nullable(),\n signed_up_at: yupNumber().defined(),\n is_anonymous: yupBoolean().defined(),\n is_restricted: yupBoolean().defined(),\n restricted_reason: restrictedReasonSchema.defined().nullable(),\n requires_totp_mfa: yupBoolean().defined(),\n});\nexport const signInEmailSchema = strictEmailSchema(undefined).meta({ openapiField: { description: 'The email to sign in with.', exampleValue: 'johndoe@example.com' } });\nexport const emailOtpSignInCallbackUrlSchema = urlSchema.meta({ openapiField: { description: 'The base callback URL to construct the magic link from. A query parameter `code` with the verification code will be appended to it. The page should then make a request to the `/auth/otp/sign-in` endpoint.', exampleValue: 'https://example.com/handler/magic-link-callback' } });\nexport const emailVerificationCallbackUrlSchema = urlSchema.meta({ openapiField: { description: 'The base callback URL to construct a verification link for the verification e-mail. A query parameter `code` with the verification code will be appended to it. The page should then make a request to the `/contact-channels/verify` endpoint.', exampleValue: 'https://example.com/handler/email-verification' } });\nexport const accessTokenResponseSchema = yupString().meta({ openapiField: { description: 'Short-lived access token that can be used to authenticate the user', exampleValue: 'eyJhmMiJB2TO...diI4QT' } });\nexport const refreshTokenResponseSchema = yupString().meta({ openapiField: { description: 'Long-lived refresh token that can be used to obtain a new access token', exampleValue: 'i8ns3aq2...14y' } });\nexport const signInResponseSchema = yupObject({\n refresh_token: refreshTokenResponseSchema.defined(),\n access_token: accessTokenResponseSchema.defined(),\n is_new_user: yupBoolean().meta({ openapiField: { description: 'Whether the user is a new user', exampleValue: true } }).defined(),\n user_id: userIdSchema.defined(),\n});\n\n// Permissions\nexport const teamSystemPermissions = [\n '$update_team',\n '$delete_team',\n '$read_members',\n '$remove_members',\n '$invite_members',\n '$manage_api_keys',\n] as const;\nexport const permissionDefinitionIdSchema = yupString()\n .matches(/^\\$?[a-z0-9_:]+$/, 'Only lowercase letters, numbers, \":\", \"_\" and optional \"$\" at the beginning are allowed')\n .test('is-system-permission', 'System permissions must start with a dollar sign', (value, ctx) => {\n if (!value) return true;\n if (value.startsWith('$') && !teamSystemPermissions.includes(value as any)) {\n return ctx.createError({ message: 'Invalid system permission' });\n }\n return true;\n })\n .meta({ openapiField: { description: `The permission ID used to uniquely identify a permission. Can either be a custom permission with lowercase letters, numbers, \\`:\\`, and \\`_\\` characters, or one of the system permissions: ${teamSystemPermissions.map(x => `\\`${x}\\``).join(', ')}`, exampleValue: 'read_secret_info' } });\nexport const customPermissionDefinitionIdSchema = yupString()\n .matches(/^[a-z0-9_:]+$/, 'Only lowercase letters, numbers, \":\", \"_\" are allowed')\n .meta({ openapiField: { description: 'The permission ID used to uniquely identify a permission. Can only contain lowercase letters, numbers, \":\", and \"_\" characters', exampleValue: 'read_secret_info' } });\nexport const teamPermissionDescriptionSchema = yupString().meta({ openapiField: { description: 'A human-readable description of the permission', exampleValue: 'Read secret information' } });\nexport const containedPermissionIdsSchema = yupArray(permissionDefinitionIdSchema.defined()).meta({ openapiField: { description: 'The IDs of the permissions that are contained in this permission', exampleValue: ['read_public_info'] } });\n\n// Teams\nexport const teamIdSchema = yupString().uuid().meta({ openapiField: { description: _idDescription('team'), exampleValue: 'ad962777-8244-496a-b6a2-e0c6a449c79e' } });\nexport const teamDisplayNameSchema = yupString().meta({ openapiField: { description: _displayNameDescription('team'), exampleValue: 'My Team' } });\nexport const teamProfileImageUrlSchema = urlSchema.max(1000000).meta({ openapiField: { description: _profileImageUrlDescription('team'), exampleValue: 'https://example.com/image.jpg' } });\nexport const teamClientMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientMetaDataDescription('team'), exampleValue: { key: 'value' } } });\nexport const teamClientReadOnlyMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientReadOnlyMetaDataDescription('team'), exampleValue: { key: 'value' } } });\nexport const teamServerMetadataSchema = jsonSchema.meta({ openapiField: { description: _serverMetaDataDescription('team'), exampleValue: { key: 'value' } } });\nexport const teamCreatedAtMillisSchema = yupNumber().meta({ openapiField: { description: _createdAtMillisDescription('team'), exampleValue: 1630000000000 } });\nexport const teamInvitationEmailSchema = emailSchema.meta({ openapiField: { description: 'The email of the user to invite.', exampleValue: 'johndoe@example.com' } });\nexport const teamInvitationCallbackUrlSchema = urlSchema.meta({ openapiField: { description: 'The base callback URL to construct an invite link with. A query parameter `code` with the verification code will be appended to it. The page should then make a request to the `/team-invitations/accept` endpoint.', exampleValue: 'https://example.com/handler/team-invitation' } });\nexport const teamCreatorUserIdSchema = userIdOrMeSchema.meta({ openapiField: { description: 'The ID of the creator of the team. If not specified, the user will not be added to the team. Can be either \"me\" or the ID of the user. Only used on the client side.', exampleValue: 'me' } });\n\n// Team member profiles\nexport const teamMemberDisplayNameSchema = yupString().meta({ openapiField: { description: _displayNameDescription('team member') + ' Note that this is separate from the display_name of the user.', exampleValue: 'John Doe' } });\nexport const teamMemberProfileImageUrlSchema = urlSchema.max(1000000).meta({ openapiField: { description: _profileImageUrlDescription('team member'), exampleValue: 'https://example.com/image.jpg' } });\n\n// Contact channels\nexport const contactChannelIdSchema = yupString().uuid().meta({ openapiField: { description: _idDescription('contact channel'), exampleValue: 'b3d396b8-c574-4c80-97b3-50031675ceb2' } });\nexport const contactChannelTypeSchema = yupString().oneOf(['email']).meta({ openapiField: { description: `The type of the contact channel. Currently only \"email\" is supported.`, exampleValue: 'email' } });\nexport const contactChannelValueSchema = yupString().when('type', {\n is: 'email',\n then: (schema) => schema.email(),\n}).meta({ openapiField: { description: 'The value of the contact channel. For email, this should be a valid email address.', exampleValue: 'johndoe@example.com' } });\nexport const contactChannelUsedForAuthSchema = yupBoolean().meta({ openapiField: { description: 'Whether the contact channel is used for authentication. If this is set to `true`, the user will be able to sign in with the contact channel with password or OTP.', exampleValue: true } });\nexport const contactChannelIsVerifiedSchema = yupBoolean().meta({ openapiField: { description: 'Whether the contact channel has been verified. If this is set to `true`, the contact channel has been verified to belong to the user.', exampleValue: true } });\nexport const contactChannelIsPrimarySchema = yupBoolean().meta({ openapiField: { description: 'Whether the contact channel is the primary contact channel. If this is set to `true`, it will be used for authentication and notifications by default.', exampleValue: true } });\n\n// OAuth providers\nexport const oauthProviderIdSchema = yupString().uuid().meta({ openapiField: { description: _idDescription('OAuth provider'), exampleValue: 'b3d396b8-c574-4c80-97b3-50031675ceb2' } });\nexport const oauthProviderEmailSchema = emailSchema.meta({ openapiField: { description: 'Email of the OAuth provider. This is used to display and identify the OAuth provider in the UI.', exampleValue: 'test@gmail.com' } });\nexport const oauthProviderTypeSchema = yupString().oneOf(allProviders).meta({ openapiField: { description: `OAuth provider type, one of ${allProviders.map(x => `\\`${x}\\``).join(', ')}`, exampleValue: 'google' } });\nexport const oauthProviderAllowSignInSchema = yupBoolean().meta({ openapiField: { description: 'Whether the user can use this OAuth provider to sign in. Only one OAuth provider per type can have this set to `true`.', exampleValue: true } });\nexport const oauthProviderAllowConnectedAccountsSchema = yupBoolean().meta({ openapiField: { description: 'Whether the user can use this OAuth provider as connected account. Multiple OAuth providers per type can have this set to `true`.', exampleValue: true } });\nexport const oauthProviderAccountIdSchema = yupString().meta({ openapiField: { description: 'Account ID of the OAuth provider. This uniquely identifies the account on the provider side.', exampleValue: 'google-account-id-12345' } });\nexport const oauthProviderProviderConfigIdSchema = yupString().meta({ openapiField: { description: 'Provider config ID of the OAuth provider. This uniquely identifies the provider config on config.json file', exampleValue: 'google' } });\n\nexport const configAgentSafeErrorMessages = [\n \"The config agent failed to apply the change.\",\n \"Sandbox session expired. Please retry the update.\",\n \"Failed to commit and push the config changes.\",\n \"The GitHub branch changed before the config commit could be pushed. Retry the update to apply the same changes on the latest branch.\",\n] as const;\nexport type ConfigAgentSafeErrorMessage = typeof configAgentSafeErrorMessages[number];\nexport const configAgentSafeErrorMessageSchema = yupString().oneOf(configAgentSafeErrorMessages);\n\n// Headers\nexport const basicAuthorizationHeaderSchema = yupString().test('is-basic-authorization-header', 'Authorization header must be in the format \"Basic <base64>\"', (value) => {\n if (!value) return true;\n return decodeBasicAuthorizationHeader(value) !== null;\n});\n\n// Neon integration\nexport const neonAuthorizationHeaderSchema = basicAuthorizationHeaderSchema.test('is-authorization-header', 'Invalid client_id:client_secret values; did you use the correct values for the integration?', (value) => {\n if (!value) return true;\n const decoded = decodeBasicAuthorizationHeader(value);\n if (decoded === null) return true;\n const [clientId, clientSecret] = decoded;\n for (const neonClientConfig of JSON.parse(getProcessEnv(\"STACK_INTEGRATION_CLIENTS_CONFIG\") || '[]')) {\n if (clientId === neonClientConfig.client_id && clientSecret === neonClientConfig.client_secret) return true;\n }\n return false;\n});\nimport.meta.vitest?.test(\"neonAuthorizationHeaderSchema handles malformed Basic auth as a validation error\", async ({ expect }) => {\n await expect(neonAuthorizationHeaderSchema.validate(\"Basic\", { abortEarly: false })).rejects.toThrow('Authorization header must be in the format \"Basic <base64>\"');\n});\n\n// Utils\nexport function yupDefinedWhen<S extends yup.AnyObject>(\n schema: S,\n triggers: Record<string, any>,\n): S {\n const entries = Object.entries(triggers);\n return schema.when(entries.map(([key]) => key), {\n is: (...values: any[]) => entries.every(([key, value], index) => value === values[index]),\n then: (schema: S) => schema.defined(),\n otherwise: (schema: S) => schema.optional()\n });\n}\n\nexport function yupDefinedAndNonEmptyWhen<S extends yup.StringSchema>(\n schema: S,\n triggers: Record<string, any>,\n): S {\n const entries = Object.entries(triggers);\n return schema.when(entries.map(([key]) => key), {\n is: (...values: any[]) => entries.every(([key, value], index) => value === values[index]),\n then: (schema: S) => schema.defined().nonEmpty(),\n otherwise: (schema: S) => schema.optional()\n });\n}\n\n// `source` describes only WHERE a branch's config came from. The ephemeral state\n// of the dashboard→GitHub config agent lives separately in `configAgentRunSchema`\n// (its own DB column), so it doesn't pollute the source descriptor.\nexport const branchConfigSourceSchema = yupUnion(\n yupObject({\n type: yupString().oneOf([\"pushed-from-github\"]).defined(),\n owner: yupString().defined(),\n repo: yupString().defined(),\n branch: yupString().defined(),\n commit_hash: yupString().defined(),\n config_file_path: yupString().defined(),\n workflow_path: yupString().optional(),\n }),\n yupObject({\n type: yupString().oneOf([\"pushed-from-unknown\"]).defined(),\n }),\n yupObject({\n type: yupString().oneOf([\"unlinked\"]).defined(),\n }),\n);\n\n/**\n * State of a single dashboard→GitHub config agent run, so the dashboard can poll for\n * progress and surface the resulting commit (or error). Each run is one row in the\n * `ConfigAgentRun` table, addressed by `id`; runs are NOT serialized, so many can\n * target the same branch at once and GitHub catches conflicts at push time.\n */\nexport const configAgentRunSchema = yupObject({\n // The run's id (the `ConfigAgentRun` row id). The dashboard polls/cancels/commits this specific run by id.\n id: yupString().uuid().defined(),\n // \"running\": agent is working; \"awaiting_review\": agent done, diff ready, waiting for the user to commit;\n // \"success\" | \"no-change\" | \"error\" | \"cancelled\": terminal.\n status: yupString().oneOf([\"running\", \"awaiting_review\", \"success\", \"no-change\", \"error\", \"cancelled\"]).defined(),\n started_at: yupNumber().defined(),\n finished_at: yupNumber().optional(),\n commit_url: urlSchema.optional(),\n error: configAgentSafeErrorMessageSchema.optional(),\n // Vercel Sandbox id of the in-flight run, recorded only while `status` is \"running\"\n // so a cancel request (a different invocation) can hard-stop the sandbox. Cleared once\n // the change set is captured (\"awaiting_review\") or the run goes terminal.\n sandbox_id: yupString().optional(),\n // A short, SANITIZED live activity feed (recent agent actions, e.g. \"Editing\n // hexclave.config.ts\", \"Running: git push\"). Never file contents, tool inputs, or tokens.\n progress: yupString().optional(),\n // Current stage, for the dashboard progress bar. Absent once terminal.\n stage: yupString().oneOf([\"initializing_sandbox\", \"cloning_repo\", \"agent_making_changes\", \"awaiting_review\"]).optional(),\n // The git unified diff produced by the agent, set when status becomes \"awaiting_review\".\n diff: yupString().optional(),\n});\nexport type ConfigAgentRunApi = yup.InferType<typeof configAgentRunSchema>;\n\nimport.meta.vitest?.test(\"configAgentRunSchema only allows safe config-agent error messages\", async ({ expect }) => {\n expect(await configAgentRunSchema.isValid({\n id: \"00000000-0000-0000-0000-000000000000\",\n status: \"error\",\n started_at: 1,\n error: \"The config agent failed to apply the change.\",\n })).toMatchInlineSnapshot(`true`);\n\n expect(await configAgentRunSchema.isValid({\n id: \"00000000-0000-0000-0000-000000000000\",\n status: \"error\",\n started_at: 1,\n error: \"ENOENT: tokenized internal failure\",\n })).toMatchInlineSnapshot(`false`);\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"schema-fields.js","names":["yup","normalizeCountryCode","isValidCountryCode"],"sources":["../../src/schema-fields.ts"],"sourcesContent":["import * as yup from \"yup\";\nimport { KnownErrors } from \"./known-errors\";\nimport { isBase64 } from \"./utils/bytes\";\nimport { isValidCountryCode, normalizeCountryCode } from \"./utils/country-codes\";\nimport { SUPPORTED_CURRENCIES, type Currency, type MoneyAmount } from \"./utils/currency-constants\";\nimport type { DayInterval, Interval } from \"./utils/dates\";\nimport { getProcessEnv } from \"./utils/env\";\nimport { HexclaveAssertionError } from \"./utils/errors\";\nimport { decodeBasicAuthorizationHeader } from \"./utils/http\";\nimport { allProviders } from \"./utils/oauth\";\nimport { deepPlainClone, omit, typedFromEntries } from \"./utils/objects\";\nimport { deindent } from \"./utils/strings\";\nimport { isValidHostnameWithWildcards, isValidUrl } from \"./utils/urls\";\nimport { isUuid } from \"./utils/uuids\";\n\nexport { isValidCountryCode, normalizeCountryCode, validateCountryCode } from \"./utils/country-codes\";\n\nconst MAX_IMAGE_SIZE_BASE64_BYTES = 1_000_000; // 1MB\n\ndeclare module \"yup\" {\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface StringSchema<TType, TContext, TDefault, TFlags> {\n nonEmpty(message?: string): StringSchema<TType, TContext, TDefault, TFlags>,\n empty(): StringSchema<TType, TContext, TDefault, TFlags>,\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n interface Schema<TType, TContext, TDefault, TFlags> {\n hasNested<K extends keyof NonNullable<TType>>(path: K): boolean,\n getNested<K extends keyof NonNullable<TType>>(path: K): yup.Schema<NonNullable<TType>[K], TContext, TDefault, TFlags>,\n\n // the default types for concat kinda suck, so let's fix that\n concat<U extends yup.AnySchema>(schema: U): yup.Schema<Omit<NonNullable<TType>, keyof yup.InferType<U>> & yup.InferType<U> | (TType & (null | undefined)), TContext, Omit<NonNullable<TDefault>, keyof U['__default']> & U['__default'] | (TDefault & (null | undefined)), TFlags>,\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-definitions\n export interface CustomSchemaMetadata {\n hexclaveSchemaInfo?:\n | {\n type: \"object\" | \"array\" | \"string\" | \"number\" | \"boolean\" | \"date\" | \"mixed\" | \"never\",\n }\n | {\n type: \"tuple\",\n items: yup.AnySchema[],\n }\n | {\n type: \"union\",\n items: yup.AnySchema[],\n }\n | {\n type: \"record\",\n keySchema: yup.StringSchema<any>,\n valueSchema: yup.AnySchema,\n },\n }\n}\n\n// eslint-disable-next-line no-restricted-syntax\nyup.addMethod(yup.string, \"nonEmpty\", function (message?: string) {\n return this.test(\n \"non-empty\",\n message ?? (({ path }) => `${path} must not be empty`),\n (value) => {\n return value !== \"\";\n }\n );\n});\n\nyup.addMethod(yup.Schema, \"hasNested\", function (path: any) {\n if (!path.match(/^[a-zA-Z0-9_$:-]*$/)) throw new HexclaveAssertionError(`yupSchema.hasNested can currently only be used with alphanumeric keys, underscores, dollar signs, colons, and hyphens. Fix this in the future. Provided key: ${JSON.stringify(path)}`);\n const schemaInfo = this.meta()?.hexclaveSchemaInfo as any;\n if (schemaInfo?.type === \"record\") {\n return schemaInfo.keySchema.isValidSync(path);\n } else if (schemaInfo?.type === \"union\") {\n return schemaInfo.items.some((s: any) => s.hasNested(path));\n } else {\n try {\n yup.reach(this, path);\n return true as any;\n } catch (e) {\n if (e instanceof Error && e.message.includes(\"The schema does not contain the path\")) {\n return false as any;\n }\n throw e;\n }\n }\n});\n\nyup.addMethod(yup.Schema, \"getNested\", function (path: any) {\n if (!path.match(/^[a-zA-Z0-9_$:-]*$/)) throw new HexclaveAssertionError(`yupSchema.getNested can currently only be used with alphanumeric keys, underscores, dollar signs, colons, and hyphens. Fix this in the future. Provided key: ${JSON.stringify(path)}`);\n\n if (!this.hasNested(path as never)) throw new HexclaveAssertionError(`Tried to call yupSchema.getNested, but key is not present in the schema. Provided key: ${path}`, { path, schema: this });\n\n const schemaInfo = this.meta()?.hexclaveSchemaInfo;\n if (schemaInfo?.type === \"record\") {\n return schemaInfo.valueSchema;\n } else if (schemaInfo?.type === \"union\") {\n const schemasWithNested = schemaInfo.items.filter((s: any) => s.hasNested(path));\n return yupUnion(...schemasWithNested.map(s => s.getNested(path)));\n } else {\n return yup.reach(this, path) as any;\n }\n});\n\nimport.meta.vitest?.test(\"hasNested\", ({ expect }) => {\n expect(yupObject({ a: yupString() }).hasNested(\"a\")).toBe(true);\n expect(yupObject({}).hasNested(\"a\" as never)).toBe(false);\n expect(yupRecord(yupString(), yupString()).hasNested(\"a\")).toBe(true);\n expect(yupRecord(yupString().oneOf([\"a\"]), yupString()).hasNested(\"b\")).toBe(false);\n expect(yupUnion(yupString(), yupNumber()).hasNested(\"a\" as any)).toBe(false);\n expect(yupUnion(yupString(), yupObject({ b: yupNumber() })).hasNested(\"a\" as never)).toBe(false);\n expect(yupUnion(yupString(), yupObject({ a: yupNumber() })).hasNested(\"a\" as never)).toBe(true);\n});\nimport.meta.vitest?.test(\"getNested\", ({ expect }) => {\n expect(yupObject({ a: yupNumber() }).getNested(\"a\").describe().type).toEqual(\"number\");\n expect(() => yupObject({}).getNested(\"a\" as never)).toThrow();\n expect(() => yupObject({ a: yupObject({ b: yupString() }) }).getNested(\"a.b\" as never)).toThrow();\n expect(yupRecord(yupString().oneOf([\"a\"]), yupNumber()).getNested(\"a\").describe().type).toEqual(\"number\");\n expect(() => yupRecord(yupString().oneOf([\"a\"]), yupString()).getNested(\"b\" as never)).toThrow();\n expect(yupUnion(yupString(), yupObject({ a: yupNumber() })).getNested(\"a\" as never).describe().type).toEqual(\"mixed\");\n expect(yupUnion(yupObject({ a: yupString() }), yupObject({ a: yupNumber() })).getNested(\"a\").describe().type).toEqual(\"mixed\");\n});\n\nexport async function yupValidate<S extends yup.ISchema<any>>(\n schema: S,\n obj: unknown,\n options?: yup.ValidateOptions & { currentUserId?: string | null }\n): Promise<yup.InferType<S>> {\n try {\n return await schema.validate(obj, {\n ...omit(options ?? {}, ['currentUserId']),\n context: {\n ...options?.context,\n hexclaveAllowUserIdMe: options?.currentUserId !== undefined,\n },\n });\n } catch (error) {\n if (error instanceof ReplaceFieldWithOwnUserId) {\n const currentUserId = options?.currentUserId;\n if (!currentUserId) throw new KnownErrors.CannotGetOwnUserWithoutUser();\n\n // parse yup path\n let pathRemaining = error.path;\n const fieldPath = [];\n while (pathRemaining.length > 0) {\n if (pathRemaining.startsWith(\"[\")) {\n const index = pathRemaining.indexOf(\"]\");\n if (index < 0) throw new HexclaveAssertionError(\"Invalid path\");\n fieldPath.push(JSON.parse(pathRemaining.slice(1, index)));\n pathRemaining = pathRemaining.slice(index + 1);\n } else {\n let dotIndex = pathRemaining.indexOf(\".\");\n if (dotIndex === -1) dotIndex = pathRemaining.length;\n fieldPath.push(pathRemaining.slice(0, dotIndex));\n pathRemaining = pathRemaining.slice(dotIndex + 1);\n }\n }\n\n const newObj = deepPlainClone(obj);\n let it = newObj;\n for (const field of fieldPath.slice(0, -1)) {\n if (!Object.prototype.hasOwnProperty.call(it, field)) {\n throw new HexclaveAssertionError(`Segment ${field} of path ${error.path} not found in object`);\n }\n it = (it as any)[field];\n }\n (it as any)[fieldPath[fieldPath.length - 1]] = currentUserId;\n\n return await yupValidate(schema, newObj, options);\n }\n throw error;\n }\n}\n\nconst _idDescription = (identify: string) => `The unique identifier of the ${identify}`;\nconst _displayNameDescription = (identify: string) => `Human-readable ${identify} display name. This is not a unique identifier.`;\nconst _clientMetaDataDescription = (identify: string) => `Client metadata. Used as a data store, accessible from the client side. Do not store information that should not be exposed to the client.`;\nconst _clientReadOnlyMetaDataDescription = (identify: string) => `Client read-only, server-writable metadata. Used as a data store, accessible from the client side. Do not store information that should not be exposed to the client. The client can read this data, but cannot modify it. This is useful for things like subscription status.`;\nconst _profileImageUrlDescription = (identify: string) => `URL of the profile image for ${identify}. Can be a Base64 encoded image. Must be smaller than 100KB. Please compress and crop to a square before passing in.`;\nconst _serverMetaDataDescription = (identify: string) => `Server metadata. Used as a data store, only accessible from the server side. You can store secret information related to the ${identify} here.`;\nconst _atMillisDescription = (identify: string) => `(the number of milliseconds since epoch, January 1, 1970, UTC)`;\nconst _createdAtMillisDescription = (identify: string) => `The time the ${identify} was created ${_atMillisDescription(identify)}`;\nconst _signedUpAtMillisDescription = `The time the user signed up ${_atMillisDescription}`;\nconst _lastActiveAtMillisDescription = `The time the user was last active ${_atMillisDescription}`;\n\n\ndeclare const HexclaveAdaptSentinel: unique symbol;\nexport type HexclaveAdaptSentinel = typeof HexclaveAdaptSentinel;\n\n// Built-in replacements\nexport function yupString<A extends string, B extends yup.Maybe<yup.AnyObject> = yup.AnyObject>(...args: Parameters<typeof yup.string<A, B>>) {\n // eslint-disable-next-line no-restricted-syntax\n return yup.string(...args).meta({ hexclaveSchemaInfo: { type: \"string\" } });\n}\nexport function yupNumber<A extends number, B extends yup.Maybe<yup.AnyObject> = yup.AnyObject>(...args: Parameters<typeof yup.number<A, B>>) {\n // eslint-disable-next-line no-restricted-syntax\n return yup.number(...args).meta({ hexclaveSchemaInfo: { type: \"number\" } });\n}\nexport function yupBoolean<A extends boolean, B extends yup.Maybe<yup.AnyObject> = yup.AnyObject>(...args: Parameters<typeof yup.boolean<A, B>>) {\n // eslint-disable-next-line no-restricted-syntax\n return yup.boolean(...args).meta({ hexclaveSchemaInfo: { type: \"boolean\" } });\n}\n/**\n * @deprecated, use number of milliseconds since epoch instead\n */\nexport function yupDate<A extends Date, B extends yup.Maybe<yup.AnyObject> = yup.AnyObject>(...args: Parameters<typeof yup.date<A, B>>) {\n // eslint-disable-next-line no-restricted-syntax\n return yup.date(...args).meta({ hexclaveSchemaInfo: { type: \"date\" } });\n}\nfunction _yupMixedInternal<A extends {}>(...args: Parameters<typeof yup.mixed<A>>) {\n // eslint-disable-next-line no-restricted-syntax\n return yup.mixed(...args);\n}\nexport function yupMixed<A extends {}>(...args: Parameters<typeof yup.mixed<A>>) {\n return _yupMixedInternal(...args).meta({ hexclaveSchemaInfo: { type: \"mixed\" } });\n}\nexport function yupArray<A extends yup.Maybe<yup.AnyObject> = yup.AnyObject, B = any>(...args: Parameters<typeof yup.array<A, B>>) {\n // eslint-disable-next-line no-restricted-syntax\n return yup.array(...args).meta({ hexclaveSchemaInfo: { type: \"array\" } });\n}\nexport function yupTuple<T extends [unknown, ...unknown[]]>(schemas: { [K in keyof T]: yup.Schema<T[K]> }) {\n if (schemas.length === 0) throw new Error('yupTuple must have at least one schema');\n // eslint-disable-next-line no-restricted-syntax\n return yup.tuple<T>(schemas as any).meta({ hexclaveSchemaInfo: { type: \"tuple\", items: schemas } });\n}\nexport function yupObjectWithAutoDefault<A extends yup.Maybe<yup.AnyObject>, B extends yup.ObjectShape>(...args: Parameters<typeof yup.object<A, B>>) {\n // eslint-disable-next-line no-restricted-syntax\n const object = yup.object(...args).test(\n 'no-unknown-object-properties',\n ({ path }) => `${path} contains unknown properties`,\n (value: any, context) => {\n if (context.options.context?.noUnknownPathPrefixes?.some((prefix: string) => context.path.startsWith(prefix))) {\n if (context.schema.spec.noUnknown !== false) {\n const availableKeys = new Set(Object.keys(context.schema.fields));\n const unknownKeys = Object.keys(value ?? {}).filter(key => !availableKeys.has(key));\n if (unknownKeys.length > 0) {\n // TODO \"did you mean XYZ\"\n return context.createError({\n message: `${context.path || \"Object\"} contains unknown properties: ${unknownKeys.join(', ')}`,\n path: context.path,\n params: { unknownKeys, availableKeys },\n });\n }\n }\n }\n return true;\n },\n ).meta({ hexclaveSchemaInfo: { type: \"object\" } });\n return object;\n}\nexport function yupObject<A extends yup.Maybe<yup.AnyObject>, B extends yup.ObjectShape>(...args: Parameters<typeof yup.object<A, B>>) {\n // we don't want to update the type of `object` to have a default flag\n const object = yupObjectWithAutoDefault(...args);\n return object.default(undefined) as any as typeof object;\n}\n\nexport function yupNever(): yup.MixedSchema<never> {\n return _yupMixedInternal().meta({ hexclaveSchemaInfo: { type: \"never\" } }).test('never', 'This value should never be reached', () => false) as any;\n}\n\nexport function yupUnion<T extends yup.AnySchema[]>(...args: T): yup.MixedSchema<yup.InferType<T[number]>> {\n if (args.length === 0) throw new Error('yupUnion must have at least one schema');\n\n return _yupMixedInternal().meta({ hexclaveSchemaInfo: { type: \"union\", items: args } }).test('is-one-of', 'Invalid value', async (value, context) => {\n if (value == null) return true;\n const errors = [];\n for (const schema of args) {\n try {\n await yupValidate(schema, value, context.options);\n return true;\n } catch (e) {\n errors.push(e);\n }\n }\n return context.createError({\n message: deindent`\n ${context.path} is not matched by any of the provided schemas:\n ${errors.map((e: any, i) => deindent`\n Schema ${i}:\n ${e.errors.join('\\n')}\n `).join('\\n')}`,\n path: context.path,\n });\n });\n}\n\nexport function yupRecord<K extends yup.StringSchema, T extends yup.AnySchema>(\n keySchema: K,\n valueSchema: T,\n): yup.MixedSchema<Record<yup.InferType<K> & string, yup.InferType<T>>> {\n return yupObject().meta({ hexclaveSchemaInfo: { type: \"record\", keySchema, valueSchema } }).unknown(true).test(\n 'record',\n '${path} must be a record of valid values',\n async function (value: unknown, context: yup.TestContext) {\n if (value == null) return true;\n const { path, createError } = this as any;\n if (typeof value !== 'object') {\n return createError({ message: `${path} must be an object` });\n }\n\n // Validate each property using the provided valueSchema\n for (const key of Object.keys(value)) {\n // Validate the key\n await yupValidate(keySchema, key, context.options);\n\n // Validate the value\n try {\n await yupValidate(valueSchema, (value as Record<string, unknown>)[key], {\n ...context.options,\n context: {\n ...context.options.context,\n path: path ? `${path}.${key}` : key,\n },\n });\n } catch (e: any) {\n return createError({\n path: path ? `${path}.${key}` : key,\n message: e.message,\n });\n }\n }\n\n return true;\n },\n ) as any;\n}\n\nexport function ensureObjectSchema<T extends yup.AnyObject>(schema: yup.Schema<T>): yup.ObjectSchema<T> & typeof schema {\n if (!(schema instanceof yup.ObjectSchema)) throw new HexclaveAssertionError(`assertObjectSchema: schema is not an ObjectSchema: ${schema.describe().type}`);\n return schema as any;\n}\n\n// Common\nexport const adaptSchema = yupMixed<HexclaveAdaptSentinel>();\n/**\n * Yup's URL schema does not recognize some URLs (including `http://localhost`) as a valid URL. This schema is a workaround for that.\n */\nexport const urlSchema = yupString().test({\n name: 'no-spaces',\n message: (params) => `${params.path} contains spaces`,\n test: (value) => value == null || !value.includes(' ')\n}).test({\n name: 'url',\n message: (params) => `${params.path} is not a valid URL`,\n test: (value) => value == null || isValidUrl(value)\n});\n/**\n * URL schema that supports wildcard patterns in hostnames (e.g., \"https://*.example.com\", \"http://*:8080\")\n */\nexport const wildcardUrlSchema = yupString().test({\n name: 'no-spaces',\n message: (params) => `${params.path} contains spaces`,\n test: (value) => value == null || !value.includes(' ')\n}).test({\n name: 'wildcard-url',\n message: (params) => `${params.path} is not a valid URL or wildcard URL pattern`,\n test: (value) => {\n if (value == null) return true;\n\n // If it doesn't contain wildcards, use the regular URL validation\n if (!value.includes('*')) {\n return isValidUrl(value);\n }\n\n // For wildcard URLs, validate the structure by replacing wildcards with placeholders\n try {\n const PLACEHOLDER = 'wildcard-placeholder';\n // Replace wildcards with valid placeholders for URL parsing\n const normalizedUrl = value.replace(/\\*/g, PLACEHOLDER);\n const url = new URL(normalizedUrl);\n\n // Only allow wildcards in the hostname; reject anywhere else\n if (\n url.username.includes(PLACEHOLDER) ||\n url.password.includes(PLACEHOLDER) ||\n url.pathname.includes(PLACEHOLDER) ||\n url.search.includes(PLACEHOLDER) ||\n url.hash.includes(PLACEHOLDER)\n ) {\n return false;\n }\n\n // Only http/https are acceptable\n if (url.protocol !== 'http:' && url.protocol !== 'https:') {\n return false;\n }\n\n // Extract original hostname pattern from the input\n const hostPattern = url.hostname.split(PLACEHOLDER).join('*');\n\n // Validate the wildcard hostname pattern using the existing function\n return isValidHostnameWithWildcards(hostPattern);\n } catch (e) {\n return false;\n }\n }\n});\nexport const wildcardProtocolAndDomainSchema = wildcardUrlSchema.test({\n name: 'is-protocol-and-domain',\n message: (params) => `${params.path} must be a protocol and domain (with optional port) without any path, query parameters, or hash`,\n test: (value) => {\n if (value == null) return true;\n try {\n const PLACEHOLDER = 'wildcard-placeholder';\n // Replace wildcards with valid placeholders for URL parsing\n const normalized = value.replace(/\\*/g, PLACEHOLDER);\n const url = new URL(normalized);\n return url.protocol !== '' && url.hostname !== '' && url.pathname === '/' && url.search === '' && url.hash === '';\n } catch (e) {\n return false;\n }\n }\n});\nexport const jsonSchema = yupMixed().nullable().defined().transform((value) => JSON.parse(JSON.stringify(value)));\nexport const jsonStringSchema = yupString().test(\"json\", (params) => `${params.path} is not valid JSON`, (value) => {\n if (value == null) return true;\n try {\n JSON.parse(value);\n return true;\n } catch (error) {\n return false;\n }\n});\nexport const jsonStringOrEmptySchema = yupString().test(\"json\", (params) => `${params.path} is not valid JSON`, (value) => {\n if (!value) return true;\n try {\n JSON.parse(value);\n return true;\n } catch (error) {\n return false;\n }\n});\nexport const base64Schema = yupString().test(\"is-base64\", (params) => `${params.path} is not valid base64`, (value) => {\n if (value == null) return true;\n return isBase64(value);\n});\nexport const passwordSchema = yupString().max(70);\nexport const countryCodeSchema = yupString().transform((value) => typeof value === \"string\" ? normalizeCountryCode(value) : value).test({\n name: \"country-code\",\n message: (params) => `${params.path} must be a 2-letter country code`,\n test: (value) => value == null || isValidCountryCode(value),\n});\nimport.meta.vitest?.test(\"countryCodeSchema\", async ({ expect }) => {\n await expect(countryCodeSchema.validate(\" us \")).resolves.toBe(\"US\");\n await expect(countryCodeSchema.validate(\"usa\")).rejects.toThrow(\"must be a 2-letter country code\");\n});\n// Interval counts must be >= 1: a zero-length interval is meaningless for billing\n// intervals, free trials, and item repeats alike, and a zero repeat interval in\n// particular makes the bulldozer tick loop spin forever on a never-advancing\n// trigger (see apps/bulldozer-js repeatIntervalMs).\nexport const intervalSchema = yupTuple<Interval>([yupNumber().min(1).integer().defined(), yupString().oneOf(['millisecond', 'second', 'minute', 'hour', 'day', 'week', 'month', 'year']).defined()]);\nexport const dayIntervalSchema = yupTuple<DayInterval>([yupNumber().min(1).integer().defined(), yupString().oneOf(['day', 'week', 'month', 'year']).defined()]);\nexport const intervalOrNeverSchema = yupUnion(intervalSchema.defined(), yupString().oneOf(['never']).defined());\nexport const dayIntervalOrNeverSchema = yupUnion(dayIntervalSchema.defined(), yupString().oneOf(['never']).defined());\nimport.meta.vitest?.test(\"interval schemas reject a zero/negative count\", async ({ expect }) => {\n await expect(intervalSchema.validate([1, \"day\"])).resolves.toEqual([1, \"day\"]);\n await expect(dayIntervalSchema.validate([2, \"month\"])).resolves.toEqual([2, \"month\"]);\n await expect(intervalSchema.validate([0, \"day\"])).rejects.toThrow();\n await expect(dayIntervalSchema.validate([0, \"month\"])).rejects.toThrow();\n await expect(dayIntervalSchema.validate([-1, \"day\"])).rejects.toThrow();\n});\n/**\n * This schema is useful for fields where the user can specify the ID, such as price IDs. It is particularly common\n * for IDs in the config schema.\n *\n * Valid IDs:\n * - Must contain only letters, numbers, underscores, and hyphens\n * - Must not start with a hyphen\n * - Maximum length of 63 characters\n */\nexport const USER_SPECIFIED_ID_PATTERN = /^[a-zA-Z0-9_][a-zA-Z0-9_-]*$/;\nexport const USER_SPECIFIED_ID_MAX_LENGTH = 63;\n\n/**\n * Checks if the given string is a valid user-specified ID.\n */\nexport function isValidUserSpecifiedId(id: string): boolean {\n return id.length > 0 && id.length <= USER_SPECIFIED_ID_MAX_LENGTH && USER_SPECIFIED_ID_PATTERN.test(id);\n}\n\n/**\n * Gets the error message for an invalid user-specified ID.\n */\nexport function getUserSpecifiedIdErrorMessage(idName: `${string}Id`): string {\n return `${idName} must contain only letters, numbers, underscores, and hyphens, and not start with a hyphen`;\n}\n\n/**\n * Sanitizes user input to create a valid user-specified ID.\n * Converts to lowercase and replaces invalid characters with hyphens.\n * Strips leading hyphens.\n */\nexport function sanitizeUserSpecifiedId(input: string): string {\n // Convert to lowercase, replace invalid characters with empty string (or hyphen for spaces)\n const sanitized = input\n .replace(/\\s+/g, '-') // Replace spaces with hyphens\n .replace(/[^a-zA-Z0-9_-]/g, ''); // Remove other invalid characters\n\n // Strip leading hyphens\n return sanitized.replace(/^-+/, '');\n}\n\nexport const userSpecifiedIdSchema = (idName: `${string}Id`) => yupString().max(USER_SPECIFIED_ID_MAX_LENGTH).matches(USER_SPECIFIED_ID_PATTERN, getUserSpecifiedIdErrorMessage(idName));\n\n/**\n * Validates that a value is a decimal string like `\"9.99\"` or `\"1000\"` (see `MoneyAmount`).\n *\n * Currency amounts are always strings in `\"<integer>\"` or `\"<integer>.<decimals>\"` format — never\n * cent integers or minor-unit numbers. For example, `\"9.99\"` means $9.99, not `999`.\n */\nexport const moneyAmountSchema = (currency: Currency) => yupString<MoneyAmount>().test('money-amount', 'Invalid money amount', (value, context) => {\n if (value == null) return true;\n const regex = /^([0-9]+)(\\.([0-9]+))?$/;\n const match = value.match(regex);\n if (!match) return context.createError({ message: 'Money amount must be in the format of <number> or <number>.<number>' });\n const whole = match[1];\n const decimals = match[3];\n if (decimals && decimals.length > currency.decimals) return context.createError({ message: `Too many decimals; ${currency.code} only has ${currency.decimals} decimals` });\n if (whole !== '0' && whole.startsWith('0')) return context.createError({ message: 'Money amount must not have leading zeros' });\n return true;\n});\n\n\n/**\n * A stricter email schema that does some additional checks for UX input. (Some emails are allowed by the spec, for\n * example `test@localhost` or `abc@gmail`, but almost certainly a user input error.)\n *\n * Note that some users in the DB have an email that doesn't match this regex, so most of the time you should use\n * `emailSchema` instead until we do the DB migration.\n */\n// eslint-disable-next-line no-restricted-syntax\nexport const strictEmailSchema = (message: string | undefined) => yupString().email(message).max(256).matches(/^[^.]+(\\.[^.]+)*@.*\\.[^.][^.]+$/, message);\n// eslint-disable-next-line no-restricted-syntax\nexport const emailSchema = yupString().email();\n\nimport.meta.vitest?.test('strictEmailSchema', ({ expect }) => {\n const validEmails = [\n \"a@example.com\",\n \"abc@example.com\",\n \"a.b@example.com\",\n \"throwaway.mail+token@example.com\",\n \"email-alt-dash@demo-mail.com\",\n \"test-account@weird-domain.net\",\n \"%!~&+{}=|`#@domain.test\",\n \"admin@a.longtldexample\",\n ];\n for (const email of validEmails) {\n expect(strictEmailSchema(undefined).validateSync(email)).toBe(email);\n }\n const invalidEmails = [\n \"test@localhost\",\n \"test@gmail\",\n \"test@gmail.com.a\",\n \"test@gmail.a\",\n \"test.@example.com\",\n \"test..test@example.com\",\n \".test@example.com\",\n ];\n for (const email of invalidEmails) {\n expect(() => strictEmailSchema(undefined).validateSync(email)).toThrow();\n }\n});\n\n// Request auth\nexport const clientOrHigherAuthTypeSchema = yupString().oneOf(['client', 'server', 'admin']).defined();\nexport const serverOrHigherAuthTypeSchema = yupString().oneOf(['server', 'admin']).defined();\nexport const adminAuthTypeSchema = yupString().oneOf(['admin']).defined();\n\n// Projects\nexport const projectIdSchema = yupString().test((v) => v === undefined || v === \"internal\" || isUuid(v)).meta({ openapiField: { description: _idDescription('project'), exampleValue: 'e0b52f4d-dece-408c-af49-d23061bb0f8d' } });\nexport const projectBranchIdSchema = yupString().nonEmpty().max(255).meta({ openapiField: { description: _idDescription('project branch'), exampleValue: 'main' } });\nexport const projectDisplayNameSchema = yupString().meta({ openapiField: { description: _displayNameDescription('project'), exampleValue: 'MyMusic' } });\nexport const projectLogoUrlSchema = urlSchema.max(MAX_IMAGE_SIZE_BASE64_BYTES).meta({ openapiField: { description: 'URL of the logo for the project. This is usually a close to 1:1 image of the company logo.', exampleValue: 'https://example.com/logo.png' } });\nexport const projectLogoFullUrlSchema = urlSchema.max(MAX_IMAGE_SIZE_BASE64_BYTES).meta({ openapiField: { description: 'URL of the full logo for the project. This is usually a vertical image with the logo and the company name.', exampleValue: 'https://example.com/full-logo.png' } });\nexport const projectLogoDarkModeUrlSchema = urlSchema.max(MAX_IMAGE_SIZE_BASE64_BYTES).meta({ openapiField: { description: 'URL of the dark mode logo for the project. This is usually a close to 1:1 image of the company logo optimized for dark backgrounds.', exampleValue: 'https://example.com/logo-dark.png' } });\nexport const projectLogoFullDarkModeUrlSchema = urlSchema.max(MAX_IMAGE_SIZE_BASE64_BYTES).meta({ openapiField: { description: 'URL of the dark mode full logo for the project. This is usually a vertical image with the logo and the company name optimized for dark backgrounds.', exampleValue: 'https://example.com/full-logo-dark.png' } });\nexport const projectDescriptionSchema = yupString().nullable().meta({ openapiField: { description: 'A human readable description of the project', exampleValue: 'A music streaming service' } });\nexport const projectCreatedAtMillisSchema = yupNumber().meta({ openapiField: { description: _createdAtMillisDescription('project'), exampleValue: 1630000000000 } });\nexport const projectIsProductionModeSchema = yupBoolean().meta({ openapiField: { description: 'Whether the project is in production mode', exampleValue: true } });\nexport const projectOnboardingStatusValues = [\n \"config_choice\",\n \"apps_selection\",\n \"auth_setup\",\n \"domain_setup\",\n \"email_theme_setup\",\n \"payments_setup\",\n \"welcome\",\n \"completed\",\n] as const;\nexport type ProjectOnboardingStatus = typeof projectOnboardingStatusValues[number];\nexport const projectOnboardingStatusSchema = yupString().oneOf(projectOnboardingStatusValues).meta({\n openapiField: {\n description: \"The current dashboard onboarding stage for this project.\",\n exampleValue: \"config_choice\",\n },\n});\n// Project config\nexport const projectConfigIdSchema = yupString().meta({ openapiField: { description: _idDescription('project config'), exampleValue: 'd09201f0-54f5-40bd-89ff-6d1815ddad24' } });\nexport const projectAllowLocalhostSchema = yupBoolean().meta({ openapiField: { description: 'Whether localhost is allowed as a domain for this project. Should only be allowed in development mode', exampleValue: true } });\nexport const projectCreateTeamOnSignUpSchema = yupBoolean().meta({ openapiField: { description: 'Whether a team should be created for each user that signs up', exampleValue: true } });\nexport const projectMagicLinkEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether magic link authentication is enabled for this project', exampleValue: true } });\nexport const projectPasskeyEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether passkey authentication is enabled for this project', exampleValue: true } });\nexport const projectClientTeamCreationEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether client users can create teams', exampleValue: true } });\nexport const projectClientUserDeletionEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether client users can delete their own account from the client', exampleValue: true } });\nexport const projectSignUpEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether users can sign up new accounts, or whether they are only allowed to sign in to existing accounts. Regardless of this option, the server API can always create new users with the `POST /users` endpoint.', exampleValue: true } });\nexport const projectCredentialEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether email password authentication is enabled for this project', exampleValue: true } });\n// Project OAuth config\nexport const oauthIdSchema = yupString().oneOf(allProviders).meta({ openapiField: { description: `OAuth provider ID, one of ${allProviders.map(x => `\\`${x}\\``).join(', ')}`, exampleValue: 'google' } });\nexport const oauthEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether the OAuth provider is enabled. If an provider is first enabled, then disabled, it will be shown in the list but with enabled=false', exampleValue: true } });\nexport const oauthTypeSchema = yupString().oneOf(['shared', 'standard']).meta({ openapiField: { description: 'OAuth provider type, one of shared, standard. \"shared\" uses Stack shared OAuth keys and it is only meant for development. \"standard\" uses your own OAuth keys and will show your logo and company name when signing in with the provider.', exampleValue: 'standard' } });\nexport const oauthClientIdSchema = yupString().meta({ openapiField: { description: 'OAuth client ID. Needs to be specified when using type=\"standard\"', exampleValue: 'google-oauth-client-id' } });\nexport const oauthClientSecretSchema = yupString().meta({ openapiField: { description: 'OAuth client secret. Needs to be specified when using type=\"standard\"', exampleValue: 'google-oauth-client-secret' } });\nexport const oauthCustomCallbackUrlSchema = urlSchema.meta({ openapiField: { description: 'The OAuth redirect/callback URL sent to the provider. When omitted, the default callback URL is used. Cannot be set for shared providers.', exampleValue: 'https://api.hexclave.com/api/v1/auth/oauth/callback/google' } });\nexport const oauthFacebookConfigIdSchema = yupString().meta({ openapiField: { description: 'The configuration id for Facebook business login (for things like ads and marketing). This is only required if you are using the standard OAuth with Facebook and you are using Facebook business login.' } });\nexport const oauthMicrosoftTenantIdSchema = yupString().meta({ openapiField: { description: 'The Microsoft tenant id for Microsoft directory. This is only required if you are using the standard OAuth with Microsoft and you have an Azure AD tenant.' } });\nexport const oauthAppleBundleIdsSchema = yupArray(yupString().defined()).meta({ openapiField: { description: 'Apple Bundle IDs for native iOS/macOS apps. Required for native Sign In with Apple (in addition to web Apple OAuth which uses the Client ID/Services ID).', exampleValue: ['com.example.ios', 'com.example.macos'] } });\nexport const oauthAppleBundleIdSchema = yupString().defined().meta({ openapiField: { description: 'Apple Bundle ID for native iOS/macOS apps.', exampleValue: 'com.example.ios' } });\nexport const oauthAccountMergeStrategySchema = yupString().oneOf(['link_method', 'raise_error', 'allow_duplicates']).meta({ openapiField: { description: 'Determines how to handle OAuth logins that match an existing user by email. `link_method` adds the OAuth method to the existing user. `raise_error` rejects the login with an error. `allow_duplicates` creates a new user.', exampleValue: 'link_method' } });\nexport const oauthIssuerUrlSchema = urlSchema.meta({ openapiField: { description: 'OIDC issuer URL for custom OIDC providers. Must support OIDC discovery (/.well-known/openid-configuration). Only used when type is \"custom_oidc\".', exampleValue: 'https://accounts.google.com' } });\nexport const oauthScopeSchema = yupString().meta({ openapiField: { description: 'Space-separated OAuth scopes to request from the custom OIDC provider. Defaults to \"openid email profile\" if not specified.', exampleValue: 'openid email profile' } });\n// Project email config\nexport const emailTypeSchema = yupString().oneOf(['shared', 'standard']).meta({ openapiField: { description: 'Email provider type, one of shared, standard. \"shared\" uses Stack shared email provider and it is only meant for development. \"standard\" uses your own email server and will have your email address as the sender.', exampleValue: 'standard' } });\nexport const emailSenderNameSchema = yupString().meta({ openapiField: { description: 'Email sender name. Needs to be specified when using type=\"standard\"', exampleValue: 'Stack' } });\nexport const emailHostSchema = yupString().meta({ openapiField: { description: 'Email host. Needs to be specified when using type=\"standard\"', exampleValue: 'smtp.your-domain.com' } });\nexport const emailPortSchema = yupNumber().min(0).max(65535).meta({ openapiField: { description: 'Email port. Needs to be specified when using type=\"standard\"', exampleValue: 587 } });\nexport const emailUsernameSchema = yupString().meta({ openapiField: { description: 'Email username. Needs to be specified when using type=\"standard\"', exampleValue: 'smtp-email' } });\nexport const emailSenderEmailSchema = emailSchema.meta({ openapiField: { description: 'Email sender email. Needs to be specified when using type=\"standard\"', exampleValue: 'example@your-domain.com' } });\n// SMTP credentials are stored encrypted (not bcrypt-hashed like user passwords), so they don't\n// need the 70-char bcrypt limit from passwordSchema. Some providers (e.g. ZeptoMail) generate\n// passwords well over 100 chars.\nexport const emailPasswordSchema = yupString().max(256).meta({ openapiField: { description: 'Email password. Needs to be specified when using type=\"standard\"', exampleValue: 'your-email-password' } });\n// Project domain config\nexport const handlerPathSchema = yupString().test('is-handler-path', 'Handler path must start with /', (value) => value?.startsWith('/')).meta({ openapiField: { description: 'Handler path. If you did not setup a custom handler path, it should be \"/handler\" by default. It needs to start with /', exampleValue: '/handler' } });\n// Project email theme config\nexport const emailThemeSchema = yupString().meta({ openapiField: { description: 'Email theme id for the project. Determines the visual style of emails sent by the project.' } });\nexport const emailThemeListSchema = yupRecord(\n yupString().uuid(),\n yupObject({\n displayName: yupString().meta({ openapiField: { description: 'Email theme name', exampleValue: 'Default Light' } }).defined(),\n tsxSource: yupString().meta({ openapiField: { description: 'Email theme source code tsx component' } }).defined(),\n })\n).meta({ openapiField: { description: 'Record of email theme IDs to their display name and source code' } });\nexport const templateThemeIdSchema = yupMixed<string | false>().test((v: any) => v === undefined || v === false || v === null || (typeof v === 'string' && isUuid(v))).meta({ openapiField: { description: 'Email theme id for the template' } }).optional();\nexport const emailTemplateListSchema = yupRecord(\n yupString().uuid(),\n yupObject({\n displayName: yupString().meta({ openapiField: { description: 'Email template name', exampleValue: 'Email Verification' } }).defined(),\n tsxSource: yupString().meta({ openapiField: { description: 'Email template source code tsx component' } }).defined(),\n // themeId can be one of three values:\n // 1. A valid theme id\n // 2. false, which means the template uses no theme\n // 3. undefined/not given, which means the template uses the project's active theme\n themeId: templateThemeIdSchema,\n })\n).meta({ openapiField: { description: 'Record of email template IDs to their display name and source code' } });\n\n// Custom dashboards\nexport const customDashboardsSchema = yupRecord(\n yupString().uuid(),\n yupObject({\n displayName: yupString().meta({ openapiField: { description: 'Custom dashboard name', exampleValue: 'User Growth Dashboard' } }).defined(),\n tsxSource: yupString().meta({ openapiField: { description: 'Custom dashboard source code tsx component' } }).defined(),\n })\n).meta({ openapiField: { description: 'Record of custom dashboard IDs to their display name and source code' } });\n\n// Payments\nexport const customerTypeSchema = yupString().oneOf(['user', 'team', 'custom']);\nconst validateHasAtLeastOneSupportedCurrency = (value: Record<string, unknown> | null, context: any) => {\n if (!value) return true;\n const currencies = Object.keys(value).filter(key => SUPPORTED_CURRENCIES.some(c => c.code === key));\n if (currencies.length === 0) {\n return context.createError({ message: \"At least one currency is required\" });\n }\n return true;\n};\n/**\n * Schema for a single product price. Each currency field (USD, EUR, etc.) is a decimal string\n * like `\"9.99\"` or `\"1000\"` — never cent integers. See `MoneyAmount` for the exact format.\n */\nexport const productPriceSchema = yupObject({\n ...typedFromEntries(SUPPORTED_CURRENCIES.map(currency => [currency.code, moneyAmountSchema(currency).optional()])),\n interval: dayIntervalSchema.optional(),\n serverOnly: yupBoolean(),\n freeTrial: dayIntervalSchema.optional(),\n}).test(\"at-least-one-currency\", (value, context) => validateHasAtLeastOneSupportedCurrency(value, context));\nexport const pricesSchema = yupRecord(\n userSpecifiedIdSchema(\"priceId\"),\n productPriceSchema,\n);\nexport const productSchema = yupObject({\n displayName: yupString(),\n productLineId: userSpecifiedIdSchema(\"productLineId\").optional().meta({ openapiField: { description: 'The ID of the product line this product belongs to. Within a product line, all products are mutually exclusive unless they are an add-on to another product in the product line.', exampleValue: 'product-line-id' } }),\n isAddOnTo: yupUnion(\n yupBoolean().isFalse(),\n yupRecord(\n userSpecifiedIdSchema(\"productId\"),\n yupBoolean().isTrue().defined(),\n ),\n ).optional().meta({ openapiField: { description: 'The products that this product is an add-on to. If this is set, the customer must already have one of the products in the record to be able to purchase this product.', exampleValue: { \"product-id\": true } } }),\n customerType: customerTypeSchema.defined(),\n freeTrial: dayIntervalSchema.optional(),\n serverOnly: yupBoolean(),\n stackable: yupBoolean(),\n prices: pricesSchema.defined(),\n includedItems: yupRecord(\n userSpecifiedIdSchema(\"itemId\"),\n yupObject({\n quantity: yupNumber().defined(),\n repeat: dayIntervalOrNeverSchema.optional(),\n expires: yupString().oneOf(['never', 'when-purchase-expires', 'when-repeated']).optional(),\n }),\n ),\n});\n\nconst productMetadataExample = { featureFlag: true, source: 'marketing-campaign' } as const;\n\nexport const productClientMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientMetaDataDescription('product'), exampleValue: productMetadataExample } });\nexport const productClientReadOnlyMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientReadOnlyMetaDataDescription('product'), exampleValue: productMetadataExample } });\nexport const productServerMetadataSchema = jsonSchema.meta({ openapiField: { description: _serverMetaDataDescription('product'), exampleValue: productMetadataExample } });\n\nexport const productSchemaWithMetadata = productSchema.concat(yupObject({\n clientMetadata: productClientMetadataSchema.optional(),\n clientReadOnlyMetadata: productClientReadOnlyMetadataSchema.optional(),\n serverMetadata: productServerMetadataSchema.optional(),\n}));\n\nexport const inlineProductSchema = yupObject({\n display_name: yupString().defined(),\n customer_type: customerTypeSchema.defined(),\n free_trial: dayIntervalSchema.optional(),\n server_only: yupBoolean().default(true),\n stackable: yupBoolean().default(false),\n prices: yupRecord(\n userSpecifiedIdSchema(\"priceId\"),\n yupObject({\n ...typedFromEntries(SUPPORTED_CURRENCIES.map(currency => [currency.code, moneyAmountSchema(currency).optional()])),\n interval: dayIntervalSchema.optional(),\n free_trial: dayIntervalSchema.optional(),\n }).test(\"at-least-one-currency\", (value, context) => validateHasAtLeastOneSupportedCurrency(value, context)),\n ),\n included_items: yupRecord(\n userSpecifiedIdSchema(\"itemId\"),\n yupObject({\n quantity: yupNumber(),\n repeat: dayIntervalOrNeverSchema.optional(),\n expires: yupString().oneOf(['never', 'when-purchase-expires', 'when-repeated']).optional(),\n }),\n ),\n client_metadata: productClientMetadataSchema.optional(),\n client_read_only_metadata: productClientReadOnlyMetadataSchema.optional(),\n server_metadata: productServerMetadataSchema.optional(),\n});\n\n// Users\nexport class ReplaceFieldWithOwnUserId extends Error {\n constructor(public readonly path: string) {\n super(`This error should be caught by whoever validated the schema, and the field in the path '${path}' should be replaced with the current user's id. This is a workaround to yup not providing access to the context inside the transform function.`);\n }\n}\nconst userIdMeSentinelUuid = \"cad564fd-f81b-43f4-b390-98abf3fcc17e\";\nexport const userIdOrMeSchema = yupString().uuid().transform(v => {\n if (v === \"me\") return userIdMeSentinelUuid;\n else return v;\n}).test((v, context) => {\n if (!(\"hexclaveAllowUserIdMe\" in (context.options.context ?? {}))) throw new HexclaveAssertionError('userIdOrMeSchema is not allowed in this context. Make sure you\\'re using yupValidate from schema-fields.ts to validate, instead of schema.validate(...).');\n if (!context.options.context?.hexclaveAllowUserIdMe) throw new HexclaveAssertionError('userIdOrMeSchema is not allowed in this context. Make sure you\\'re passing in the currentUserId option in yupValidate.');\n if (v === userIdMeSentinelUuid) throw new ReplaceFieldWithOwnUserId(context.path);\n return true;\n}).meta({ openapiField: { description: 'The ID of the user, or the special value `me` for the currently authenticated user', exampleValue: '3241a285-8329-4d69-8f3d-316e08cf140c' } });\nexport const userIdSchema = yupString().uuid().meta({ openapiField: { description: _idDescription('user'), exampleValue: '3241a285-8329-4d69-8f3d-316e08cf140c' } });\nexport const primaryEmailSchema = emailSchema.meta({ openapiField: { description: 'Primary email', exampleValue: 'johndoe@example.com' } });\nexport const primaryEmailAuthEnabledSchema = yupBoolean().meta({ openapiField: { description: 'Whether the primary email is used for authentication. If this is set to `false`, the user will not be able to sign in with the primary email with password or OTP', exampleValue: true } });\nexport const primaryEmailVerifiedSchema = yupBoolean().meta({ openapiField: { description: 'Whether the primary email has been verified to belong to this user', exampleValue: true } });\nexport const userDisplayNameSchema = yupString().nullable().max(256).meta({ openapiField: { description: _displayNameDescription('user'), exampleValue: 'John Doe' } });\nexport const selectedTeamIdSchema = yupString().uuid().meta({ openapiField: { description: 'ID of the team currently selected by the user', exampleValue: 'team-id' } });\nexport const profileImageUrlSchema = urlSchema.max(MAX_IMAGE_SIZE_BASE64_BYTES).meta({ openapiField: { description: _profileImageUrlDescription('user'), exampleValue: 'https://example.com/image.jpg' } });\nexport const signedUpAtMillisSchema = yupNumber().meta({ openapiField: { description: _signedUpAtMillisDescription, exampleValue: 1630000000000 } });\nexport const userClientMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientMetaDataDescription('user'), exampleValue: { key: 'value' } } });\nexport const userClientReadOnlyMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientReadOnlyMetaDataDescription('user'), exampleValue: { key: 'value' } } });\nexport const userServerMetadataSchema = jsonSchema.meta({ openapiField: { description: _serverMetaDataDescription('user'), exampleValue: { key: 'value' } } });\nexport const userOAuthProviderSchema = yupObject({\n id: yupString().defined(),\n type: yupString().oneOf(allProviders).defined(),\n provider_user_id: yupString().defined(),\n});\nexport const userLastActiveAtMillisSchema = yupNumber().nullable().meta({ openapiField: { description: _lastActiveAtMillisDescription, exampleValue: 1630000000000 } });\nexport const userPasskeyAuthEnabledSchema = yupBoolean().meta({ openapiField: { hidden: true, description: 'Whether the user has passkeys enabled', exampleValue: false } });\nexport const userOtpAuthEnabledSchema = yupBoolean().meta({ openapiField: { hidden: true, description: 'Whether the user has OTP/magic link enabled. ', exampleValue: true } });\nexport const userOtpAuthEnabledMutationSchema = yupBoolean().meta({ openapiField: { hidden: true, description: 'Whether the user has OTP/magic link enabled. Note that only accounts with verified emails can sign-in with OTP.', exampleValue: true } });\nexport const userHasPasswordSchema = yupBoolean().meta({ openapiField: { hidden: true, description: 'Whether the user has a password set. If the user does not have a password set, they will not be able to sign in with email/password.', exampleValue: true } });\nexport const userPasswordMutationSchema = passwordSchema.nullable().meta({ openapiField: { description: 'Sets the user\\'s password. Doing so revokes all current sessions.', exampleValue: 'my-new-password' } }).max(70);\nexport const userPasswordHashMutationSchema = yupString()\n .nonEmpty()\n .meta({ openapiField: { description: 'If `password` is not given, sets the user\\'s password hash to the given string in Modular Crypt Format (ex.: `$2a$10$VIhIOofSMqGdGlL4wzE//e.77dAQGqNtF/1dT7bqCrVtQuInWy2qi`). Doing so revokes all current sessions.' } }); // we don't set an exampleValue here because it's exclusive with the password field and having both would break the generated example\nexport const userTotpSecretMutationSchema = base64Schema.nullable().meta({ openapiField: { description: 'Enables 2FA and sets a TOTP secret for the user. Set to null to disable 2FA.', exampleValue: 'dG90cC1zZWNyZXQ=' } });\n\n// Auth\nexport const restrictedReasonTypes = [\"anonymous\", \"email_not_verified\", \"restricted_by_administrator\"] as const;\nexport type RestrictedReasonType = typeof restrictedReasonTypes[number];\nexport const restrictedReasonSchema = yupObject({\n type: yupString().oneOf(restrictedReasonTypes).defined(),\n});\nexport type RestrictedReason = yup.InferType<typeof restrictedReasonSchema>;\n\nexport const accessTokenPayloadSchema = yupObject({\n sub: yupString().defined(),\n exp: yupNumber().optional(),\n iat: yupNumber().defined(),\n iss: yupString().defined(),\n aud: yupString().defined(),\n project_id: yupString().defined(),\n branch_id: yupString().defined(),\n refresh_token_id: yupString().defined(),\n role: yupString().oneOf([\"authenticated\"]).defined(),\n name: yupString().defined().nullable(),\n email: yupString().defined().nullable(),\n email_verified: yupBoolean().defined(),\n selected_team_id: yupString().defined().nullable(),\n signed_up_at: yupNumber().defined(),\n is_anonymous: yupBoolean().defined(),\n is_restricted: yupBoolean().defined(),\n restricted_reason: restrictedReasonSchema.defined().nullable(),\n requires_totp_mfa: yupBoolean().defined(),\n});\nexport const signInEmailSchema = strictEmailSchema(undefined).meta({ openapiField: { description: 'The email to sign in with.', exampleValue: 'johndoe@example.com' } });\nexport const emailOtpSignInCallbackUrlSchema = urlSchema.meta({ openapiField: { description: 'The base callback URL to construct the magic link from. A query parameter `code` with the verification code will be appended to it. The page should then make a request to the `/auth/otp/sign-in` endpoint.', exampleValue: 'https://example.com/handler/magic-link-callback' } });\nexport const emailVerificationCallbackUrlSchema = urlSchema.meta({ openapiField: { description: 'The base callback URL to construct a verification link for the verification e-mail. A query parameter `code` with the verification code will be appended to it. The page should then make a request to the `/contact-channels/verify` endpoint.', exampleValue: 'https://example.com/handler/email-verification' } });\nexport const accessTokenResponseSchema = yupString().meta({ openapiField: { description: 'Short-lived access token that can be used to authenticate the user', exampleValue: 'eyJhmMiJB2TO...diI4QT' } });\nexport const refreshTokenResponseSchema = yupString().meta({ openapiField: { description: 'Long-lived refresh token that can be used to obtain a new access token', exampleValue: 'i8ns3aq2...14y' } });\nexport const signInResponseSchema = yupObject({\n refresh_token: refreshTokenResponseSchema.defined(),\n access_token: accessTokenResponseSchema.defined(),\n is_new_user: yupBoolean().meta({ openapiField: { description: 'Whether the user is a new user', exampleValue: true } }).defined(),\n user_id: userIdSchema.defined(),\n});\n\n// Permissions\nexport const teamSystemPermissions = [\n '$update_team',\n '$delete_team',\n '$read_members',\n '$remove_members',\n '$invite_members',\n '$manage_api_keys',\n] as const;\nexport const permissionDefinitionIdSchema = yupString()\n .matches(/^\\$?[a-z0-9_:]+$/, 'Only lowercase letters, numbers, \":\", \"_\" and optional \"$\" at the beginning are allowed')\n .test('is-system-permission', 'System permissions must start with a dollar sign', (value, ctx) => {\n if (!value) return true;\n if (value.startsWith('$') && !teamSystemPermissions.includes(value as any)) {\n return ctx.createError({ message: 'Invalid system permission' });\n }\n return true;\n })\n .meta({ openapiField: { description: `The permission ID used to uniquely identify a permission. Can either be a custom permission with lowercase letters, numbers, \\`:\\`, and \\`_\\` characters, or one of the system permissions: ${teamSystemPermissions.map(x => `\\`${x}\\``).join(', ')}`, exampleValue: 'read_secret_info' } });\nexport const customPermissionDefinitionIdSchema = yupString()\n .matches(/^[a-z0-9_:]+$/, 'Only lowercase letters, numbers, \":\", \"_\" are allowed')\n .meta({ openapiField: { description: 'The permission ID used to uniquely identify a permission. Can only contain lowercase letters, numbers, \":\", and \"_\" characters', exampleValue: 'read_secret_info' } });\nexport const teamPermissionDescriptionSchema = yupString().meta({ openapiField: { description: 'A human-readable description of the permission', exampleValue: 'Read secret information' } });\nexport const containedPermissionIdsSchema = yupArray(permissionDefinitionIdSchema.defined()).meta({ openapiField: { description: 'The IDs of the permissions that are contained in this permission', exampleValue: ['read_public_info'] } });\n\n// Teams\nexport const teamIdSchema = yupString().uuid().meta({ openapiField: { description: _idDescription('team'), exampleValue: 'ad962777-8244-496a-b6a2-e0c6a449c79e' } });\nexport const teamDisplayNameSchema = yupString().meta({ openapiField: { description: _displayNameDescription('team'), exampleValue: 'My Team' } });\nexport const teamProfileImageUrlSchema = urlSchema.max(1000000).meta({ openapiField: { description: _profileImageUrlDescription('team'), exampleValue: 'https://example.com/image.jpg' } });\nexport const teamClientMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientMetaDataDescription('team'), exampleValue: { key: 'value' } } });\nexport const teamClientReadOnlyMetadataSchema = jsonSchema.meta({ openapiField: { description: _clientReadOnlyMetaDataDescription('team'), exampleValue: { key: 'value' } } });\nexport const teamServerMetadataSchema = jsonSchema.meta({ openapiField: { description: _serverMetaDataDescription('team'), exampleValue: { key: 'value' } } });\nexport const teamCreatedAtMillisSchema = yupNumber().meta({ openapiField: { description: _createdAtMillisDescription('team'), exampleValue: 1630000000000 } });\nexport const teamInvitationEmailSchema = emailSchema.meta({ openapiField: { description: 'The email of the user to invite.', exampleValue: 'johndoe@example.com' } });\nexport const teamInvitationCallbackUrlSchema = urlSchema.meta({ openapiField: { description: 'The base callback URL to construct an invite link with. A query parameter `code` with the verification code will be appended to it. The page should then make a request to the `/team-invitations/accept` endpoint.', exampleValue: 'https://example.com/handler/team-invitation' } });\nexport const teamCreatorUserIdSchema = userIdOrMeSchema.meta({ openapiField: { description: 'The ID of the creator of the team. If not specified, the user will not be added to the team. Can be either \"me\" or the ID of the user. Only used on the client side.', exampleValue: 'me' } });\n\n// Team member profiles\nexport const teamMemberDisplayNameSchema = yupString().meta({ openapiField: { description: _displayNameDescription('team member') + ' Note that this is separate from the display_name of the user.', exampleValue: 'John Doe' } });\nexport const teamMemberProfileImageUrlSchema = urlSchema.max(1000000).meta({ openapiField: { description: _profileImageUrlDescription('team member'), exampleValue: 'https://example.com/image.jpg' } });\n\n// Contact channels\nexport const contactChannelIdSchema = yupString().uuid().meta({ openapiField: { description: _idDescription('contact channel'), exampleValue: 'b3d396b8-c574-4c80-97b3-50031675ceb2' } });\nexport const contactChannelTypeSchema = yupString().oneOf(['email']).meta({ openapiField: { description: `The type of the contact channel. Currently only \"email\" is supported.`, exampleValue: 'email' } });\nexport const contactChannelValueSchema = yupString().when('type', {\n is: 'email',\n then: (schema) => schema.email(),\n}).meta({ openapiField: { description: 'The value of the contact channel. For email, this should be a valid email address.', exampleValue: 'johndoe@example.com' } });\nexport const contactChannelUsedForAuthSchema = yupBoolean().meta({ openapiField: { description: 'Whether the contact channel is used for authentication. If this is set to `true`, the user will be able to sign in with the contact channel with password or OTP.', exampleValue: true } });\nexport const contactChannelIsVerifiedSchema = yupBoolean().meta({ openapiField: { description: 'Whether the contact channel has been verified. If this is set to `true`, the contact channel has been verified to belong to the user.', exampleValue: true } });\nexport const contactChannelIsPrimarySchema = yupBoolean().meta({ openapiField: { description: 'Whether the contact channel is the primary contact channel. If this is set to `true`, it will be used for authentication and notifications by default.', exampleValue: true } });\n\n// OAuth providers\nexport const oauthProviderIdSchema = yupString().uuid().meta({ openapiField: { description: _idDescription('OAuth provider'), exampleValue: 'b3d396b8-c574-4c80-97b3-50031675ceb2' } });\nexport const oauthProviderEmailSchema = emailSchema.meta({ openapiField: { description: 'Email of the OAuth provider. This is used to display and identify the OAuth provider in the UI.', exampleValue: 'test@gmail.com' } });\nexport const oauthProviderTypeSchema = yupString().oneOf(allProviders).meta({ openapiField: { description: `OAuth provider type, one of ${allProviders.map(x => `\\`${x}\\``).join(', ')}`, exampleValue: 'google' } });\nexport const oauthProviderAllowSignInSchema = yupBoolean().meta({ openapiField: { description: 'Whether the user can use this OAuth provider to sign in. Only one OAuth provider per type can have this set to `true`.', exampleValue: true } });\nexport const oauthProviderAllowConnectedAccountsSchema = yupBoolean().meta({ openapiField: { description: 'Whether the user can use this OAuth provider as connected account. Multiple OAuth providers per type can have this set to `true`.', exampleValue: true } });\nexport const oauthProviderAccountIdSchema = yupString().meta({ openapiField: { description: 'Account ID of the OAuth provider. This uniquely identifies the account on the provider side.', exampleValue: 'google-account-id-12345' } });\nexport const oauthProviderProviderConfigIdSchema = yupString().meta({ openapiField: { description: 'Provider config ID of the OAuth provider. This uniquely identifies the provider config on config.json file', exampleValue: 'google' } });\n\nexport const configAgentSafeErrorMessages = [\n \"The config agent failed to apply the change.\",\n \"Sandbox session expired. Please retry the update.\",\n \"Failed to commit and push the config changes.\",\n \"The GitHub branch changed before the config commit could be pushed. Retry the update to apply the same changes on the latest branch.\",\n] as const;\nexport type ConfigAgentSafeErrorMessage = typeof configAgentSafeErrorMessages[number];\nexport const configAgentSafeErrorMessageSchema = yupString().oneOf(configAgentSafeErrorMessages);\n\n// Headers\nexport const basicAuthorizationHeaderSchema = yupString().test('is-basic-authorization-header', 'Authorization header must be in the format \"Basic <base64>\"', (value) => {\n if (!value) return true;\n return decodeBasicAuthorizationHeader(value) !== null;\n});\n\n// Neon integration\nexport const neonAuthorizationHeaderSchema = basicAuthorizationHeaderSchema.test('is-authorization-header', 'Invalid client_id:client_secret values; did you use the correct values for the integration?', (value) => {\n if (!value) return true;\n const decoded = decodeBasicAuthorizationHeader(value);\n if (decoded === null) return true;\n const [clientId, clientSecret] = decoded;\n for (const neonClientConfig of JSON.parse(getProcessEnv(\"STACK_INTEGRATION_CLIENTS_CONFIG\") || '[]')) {\n if (clientId === neonClientConfig.client_id && clientSecret === neonClientConfig.client_secret) return true;\n }\n return false;\n});\nimport.meta.vitest?.test(\"neonAuthorizationHeaderSchema handles malformed Basic auth as a validation error\", async ({ expect }) => {\n await expect(neonAuthorizationHeaderSchema.validate(\"Basic\", { abortEarly: false })).rejects.toThrow('Authorization header must be in the format \"Basic <base64>\"');\n});\n\n// Utils\nexport function yupDefinedWhen<S extends yup.AnyObject>(\n schema: S,\n triggers: Record<string, any>,\n): S {\n const entries = Object.entries(triggers);\n return schema.when(entries.map(([key]) => key), {\n is: (...values: any[]) => entries.every(([key, value], index) => value === values[index]),\n then: (schema: S) => schema.defined(),\n otherwise: (schema: S) => schema.optional()\n });\n}\n\nexport function yupDefinedAndNonEmptyWhen<S extends yup.StringSchema>(\n schema: S,\n triggers: Record<string, any>,\n): S {\n const entries = Object.entries(triggers);\n return schema.when(entries.map(([key]) => key), {\n is: (...values: any[]) => entries.every(([key, value], index) => value === values[index]),\n then: (schema: S) => schema.defined().nonEmpty(),\n otherwise: (schema: S) => schema.optional()\n });\n}\n\n// `source` describes only WHERE a branch's config came from. The ephemeral state\n// of the dashboard→GitHub config agent lives separately in `configAgentRunSchema`\n// (its own DB column), so it doesn't pollute the source descriptor.\nexport const branchConfigSourceSchema = yupUnion(\n yupObject({\n type: yupString().oneOf([\"pushed-from-github\"]).defined(),\n owner: yupString().defined(),\n repo: yupString().defined(),\n branch: yupString().defined(),\n commit_hash: yupString().defined(),\n config_file_path: yupString().defined(),\n workflow_path: yupString().optional(),\n }),\n yupObject({\n type: yupString().oneOf([\"pushed-from-unknown\"]).defined(),\n }),\n yupObject({\n type: yupString().oneOf([\"unlinked\"]).defined(),\n }),\n);\n\n/**\n * State of a single dashboard→GitHub config agent run, so the dashboard can poll for\n * progress and surface the resulting commit (or error). Each run is one row in the\n * `ConfigAgentRun` table, addressed by `id`; runs are NOT serialized, so many can\n * target the same branch at once and GitHub catches conflicts at push time.\n */\nexport const configAgentRunSchema = yupObject({\n // The run's id (the `ConfigAgentRun` row id). The dashboard polls/cancels/commits this specific run by id.\n id: yupString().uuid().defined(),\n // \"running\": agent is working; \"awaiting_review\": agent done, diff ready, waiting for the user to commit;\n // \"success\" | \"no-change\" | \"error\" | \"cancelled\": terminal.\n status: yupString().oneOf([\"running\", \"awaiting_review\", \"success\", \"no-change\", \"error\", \"cancelled\"]).defined(),\n started_at: yupNumber().defined(),\n finished_at: yupNumber().optional(),\n commit_url: urlSchema.optional(),\n error: configAgentSafeErrorMessageSchema.optional(),\n // Vercel Sandbox id of the in-flight run, recorded only while `status` is \"running\"\n // so a cancel request (a different invocation) can hard-stop the sandbox. Cleared once\n // the change set is captured (\"awaiting_review\") or the run goes terminal.\n sandbox_id: yupString().optional(),\n // A short, SANITIZED live activity feed (recent agent actions, e.g. \"Editing\n // hexclave.config.ts\", \"Running: git push\"). Never file contents, tool inputs, or tokens.\n progress: yupString().optional(),\n // Current stage, for the dashboard progress bar. Absent once terminal.\n stage: yupString().oneOf([\"initializing_sandbox\", \"cloning_repo\", \"agent_making_changes\", \"awaiting_review\"]).optional(),\n // The git unified diff produced by the agent, set when status becomes \"awaiting_review\".\n diff: yupString().optional(),\n});\nexport type ConfigAgentRunApi = yup.InferType<typeof configAgentRunSchema>;\n\nimport.meta.vitest?.test(\"configAgentRunSchema only allows safe config-agent error messages\", async ({ expect }) => {\n expect(await configAgentRunSchema.isValid({\n id: \"00000000-0000-0000-0000-000000000000\",\n status: \"error\",\n started_at: 1,\n error: \"The config agent failed to apply the change.\",\n })).toMatchInlineSnapshot(`true`);\n\n expect(await configAgentRunSchema.isValid({\n id: \"00000000-0000-0000-0000-000000000000\",\n status: \"error\",\n started_at: 1,\n error: \"ENOENT: tokenized internal failure\",\n })).toMatchInlineSnapshot(`false`);\n});\n"],"mappings":"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"}
|
|
@@ -3,6 +3,21 @@ import { Currency, MoneyAmount, SUPPORTED_CURRENCIES } from "./currency-constant
|
|
|
3
3
|
//#region src/utils/currencies.d.ts
|
|
4
4
|
type SupportedCurrency = (typeof SUPPORTED_CURRENCIES)[number];
|
|
5
5
|
declare function moneyAmountToStripeUnits(amount: MoneyAmount, currency: Currency): number;
|
|
6
|
+
/**
|
|
7
|
+
* Inverse of `moneyAmountToStripeUnits`: formats an integer minor-unit amount
|
|
8
|
+
* (e.g. cents) back into the canonical decimal money string for the currency.
|
|
9
|
+
* E.g. for USD (2 decimals): 5000 → "50.00", 1 → "0.01"; for JPY (0 decimals):
|
|
10
|
+
* 500 → "500".
|
|
11
|
+
*
|
|
12
|
+
* Prefer this over `String(number)` whenever an amount is scaled: money math
|
|
13
|
+
* must happen in integer minor units, because float multiplication like
|
|
14
|
+
* `19.99 * 3` yields `59.97000000000001`, which `moneyAmountSchema` then rejects
|
|
15
|
+
* for having more than the currency's allowed decimals.
|
|
16
|
+
*
|
|
17
|
+
* Money amounts are non-negative (see `MoneyAmount`), so a negative input is a
|
|
18
|
+
* programming error and throws rather than silently dropping the sign.
|
|
19
|
+
*/
|
|
20
|
+
declare function stripeUnitsToMoneyAmount(stripeUnits: number, currency: Currency): MoneyAmount;
|
|
6
21
|
//#endregion
|
|
7
|
-
export { SupportedCurrency, moneyAmountToStripeUnits };
|
|
22
|
+
export { SupportedCurrency, moneyAmountToStripeUnits, stripeUnitsToMoneyAmount };
|
|
8
23
|
//# sourceMappingURL=currencies.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"currencies.d.ts","names":[],"sources":["../../../src/utils/currencies.tsx"],"mappings":";;;KAIY,iBAAA,WAA4B,oBAAoB;AAAA,iBAE5C,wBAAA,CAAyB,MAAA,EAAQ,WAAA,EAAa,QAAA,EAAU,QAAQ"}
|
|
1
|
+
{"version":3,"file":"currencies.d.ts","names":[],"sources":["../../../src/utils/currencies.tsx"],"mappings":";;;KAIY,iBAAA,WAA4B,oBAAoB;AAAA,iBAE5C,wBAAA,CAAyB,MAAA,EAAQ,WAAA,EAAa,QAAA,EAAU,QAAQ;AAFhF;;;;AAA4D;AAE5D;;;;;;;;;AAFA,iBA8BgB,wBAAA,CAAyB,WAAA,UAAqB,QAAA,EAAU,QAAA,GAAW,WAAW"}
|
|
@@ -9,7 +9,30 @@ function moneyAmountToStripeUnits(amount, currency) {
|
|
|
9
9
|
const paddedFractional = fractional.padEnd(currency.decimals, "0");
|
|
10
10
|
return Number.parseInt(whole + paddedFractional, 10);
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Inverse of `moneyAmountToStripeUnits`: formats an integer minor-unit amount
|
|
14
|
+
* (e.g. cents) back into the canonical decimal money string for the currency.
|
|
15
|
+
* E.g. for USD (2 decimals): 5000 → "50.00", 1 → "0.01"; for JPY (0 decimals):
|
|
16
|
+
* 500 → "500".
|
|
17
|
+
*
|
|
18
|
+
* Prefer this over `String(number)` whenever an amount is scaled: money math
|
|
19
|
+
* must happen in integer minor units, because float multiplication like
|
|
20
|
+
* `19.99 * 3` yields `59.97000000000001`, which `moneyAmountSchema` then rejects
|
|
21
|
+
* for having more than the currency's allowed decimals.
|
|
22
|
+
*
|
|
23
|
+
* Money amounts are non-negative (see `MoneyAmount`), so a negative input is a
|
|
24
|
+
* programming error and throws rather than silently dropping the sign.
|
|
25
|
+
*/
|
|
26
|
+
function stripeUnitsToMoneyAmount(stripeUnits, currency) {
|
|
27
|
+
if (!Number.isFinite(stripeUnits) || Math.trunc(stripeUnits) !== stripeUnits) throw new HexclaveAssertionError("Stripe units must be an integer", { stripeUnits });
|
|
28
|
+
if (stripeUnits < 0) throw new HexclaveAssertionError("Money amounts are non-negative; cannot represent negative stripe units", { stripeUnits });
|
|
29
|
+
if (currency.stripeDecimals !== currency.decimals) throw new HexclaveAssertionError("unimplemented: TODO support different decimal configurations");
|
|
30
|
+
const decimals = currency.decimals;
|
|
31
|
+
if (decimals === 0) return `${stripeUnits}`;
|
|
32
|
+
const padded = stripeUnits.toString().padStart(decimals + 1, "0");
|
|
33
|
+
return `${padded.slice(0, padded.length - decimals)}.${padded.slice(padded.length - decimals)}`;
|
|
34
|
+
}
|
|
12
35
|
//#endregion
|
|
13
|
-
export { moneyAmountToStripeUnits };
|
|
36
|
+
export { moneyAmountToStripeUnits, stripeUnitsToMoneyAmount };
|
|
14
37
|
|
|
15
38
|
//# sourceMappingURL=currencies.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"currencies.js","names":[],"sources":["../../../src/utils/currencies.tsx"],"sourcesContent":["import { moneyAmountSchema } from \"../schema-fields\";\nimport { SUPPORTED_CURRENCIES, type Currency, type MoneyAmount } from \"./currency-constants\";\nimport { HexclaveAssertionError } from \"./errors\";\n\nexport type SupportedCurrency = (typeof SUPPORTED_CURRENCIES)[number];\n\nexport function moneyAmountToStripeUnits(amount: MoneyAmount, currency: Currency): number {\n const validated = moneyAmountSchema(currency).defined().validateSync(amount);\n if (currency.stripeDecimals !== currency.decimals) {\n throw new HexclaveAssertionError(\"unimplemented: TODO support different decimal configurations\");\n }\n // `moneyAmountSchema` accepts strings with 0..currency.decimals fractional\n // digits, so we must right-pad the fractional part before stripping the dot.\n // A naïve `replace('.', '')` underweights inputs like \"5\" → 5 (should be 500\n // for USD) and \"0.5\" → 5 (should be 50).\n const [whole, fractional = \"\"] = validated.split(\".\");\n const paddedFractional = fractional.padEnd(currency.decimals, \"0\");\n return Number.parseInt(whole + paddedFractional, 10);\n}\n\nimport.meta.vitest?.describe(\"moneyAmountToStripeUnits\", (test) => {\n const USD = SUPPORTED_CURRENCIES.find((c) => c.code === \"USD\")!;\n\n test(\"converts fully-padded USD amounts\", ({ expect }) => {\n expect(moneyAmountToStripeUnits(\"5.00\" as MoneyAmount, USD)).toBe(500);\n expect(moneyAmountToStripeUnits(\"0.01\" as MoneyAmount, USD)).toBe(1);\n expect(moneyAmountToStripeUnits(\"12.34\" as MoneyAmount, USD)).toBe(1234);\n });\n\n test(\"converts whole-number USD amounts (no decimals)\", ({ expect }) => {\n expect(moneyAmountToStripeUnits(\"5\" as MoneyAmount, USD)).toBe(500);\n expect(moneyAmountToStripeUnits(\"10\" as MoneyAmount, USD)).toBe(1000);\n expect(moneyAmountToStripeUnits(\"0\" as MoneyAmount, USD)).toBe(0);\n });\n\n test(\"converts USD amounts with one decimal digit\", ({ expect }) => {\n expect(moneyAmountToStripeUnits(\"5.5\" as MoneyAmount, USD)).toBe(550);\n expect(moneyAmountToStripeUnits(\"0.5\" as MoneyAmount, USD)).toBe(50);\n });\n\n test(\"matches stripeUnitsToMoneyAmount round-trip\", ({ expect }) => {\n for (const cents of [0, 1, 5, 50, 99, 100, 1234, 100000]) {\n const padded = `${Math.floor(cents / 100)}.${(cents % 100).toString().padStart(2, \"0\")}` as MoneyAmount;\n expect(moneyAmountToStripeUnits(padded, USD)).toBe(cents);\n }\n });\n\n test(\"rejects invalid money strings via schema\", ({ expect }) => {\n expect(() => moneyAmountToStripeUnits(\"abc\" as MoneyAmount, USD)).toThrow();\n expect(() => moneyAmountToStripeUnits(\"5.555\" as MoneyAmount, USD)).toThrow();\n expect(() => moneyAmountToStripeUnits(\"05\" as MoneyAmount, USD)).toThrow();\n });\n});\n"],"mappings":";;;;AAMA,SAAgB,yBAAyB,QAAqB,UAA4B;CACxF,MAAM,YAAY,kBAAkB,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,aAAa,MAAM;CAC3E,IAAI,SAAS,mBAAmB,SAAS,UACvC,MAAM,IAAI,uBAAuB,8DAA8D;CAMjG,MAAM,CAAC,OAAO,aAAa,MAAM,UAAU,MAAM,GAAG;CACpD,MAAM,mBAAmB,WAAW,OAAO,SAAS,UAAU,GAAG;CACjE,OAAO,OAAO,SAAS,QAAQ,kBAAkB,EAAE;AACrD"}
|
|
1
|
+
{"version":3,"file":"currencies.js","names":[],"sources":["../../../src/utils/currencies.tsx"],"sourcesContent":["import { moneyAmountSchema } from \"../schema-fields\";\nimport { SUPPORTED_CURRENCIES, type Currency, type MoneyAmount } from \"./currency-constants\";\nimport { HexclaveAssertionError } from \"./errors\";\n\nexport type SupportedCurrency = (typeof SUPPORTED_CURRENCIES)[number];\n\nexport function moneyAmountToStripeUnits(amount: MoneyAmount, currency: Currency): number {\n const validated = moneyAmountSchema(currency).defined().validateSync(amount);\n if (currency.stripeDecimals !== currency.decimals) {\n throw new HexclaveAssertionError(\"unimplemented: TODO support different decimal configurations\");\n }\n // `moneyAmountSchema` accepts strings with 0..currency.decimals fractional\n // digits, so we must right-pad the fractional part before stripping the dot.\n // A naïve `replace('.', '')` underweights inputs like \"5\" → 5 (should be 500\n // for USD) and \"0.5\" → 5 (should be 50).\n const [whole, fractional = \"\"] = validated.split(\".\");\n const paddedFractional = fractional.padEnd(currency.decimals, \"0\");\n return Number.parseInt(whole + paddedFractional, 10);\n}\n\n/**\n * Inverse of `moneyAmountToStripeUnits`: formats an integer minor-unit amount\n * (e.g. cents) back into the canonical decimal money string for the currency.\n * E.g. for USD (2 decimals): 5000 → \"50.00\", 1 → \"0.01\"; for JPY (0 decimals):\n * 500 → \"500\".\n *\n * Prefer this over `String(number)` whenever an amount is scaled: money math\n * must happen in integer minor units, because float multiplication like\n * `19.99 * 3` yields `59.97000000000001`, which `moneyAmountSchema` then rejects\n * for having more than the currency's allowed decimals.\n *\n * Money amounts are non-negative (see `MoneyAmount`), so a negative input is a\n * programming error and throws rather than silently dropping the sign.\n */\nexport function stripeUnitsToMoneyAmount(stripeUnits: number, currency: Currency): MoneyAmount {\n if (!Number.isFinite(stripeUnits) || Math.trunc(stripeUnits) !== stripeUnits) {\n throw new HexclaveAssertionError(\"Stripe units must be an integer\", { stripeUnits });\n }\n if (stripeUnits < 0) {\n throw new HexclaveAssertionError(\"Money amounts are non-negative; cannot represent negative stripe units\", { stripeUnits });\n }\n if (currency.stripeDecimals !== currency.decimals) {\n throw new HexclaveAssertionError(\"unimplemented: TODO support different decimal configurations\");\n }\n const decimals = currency.decimals;\n if (decimals === 0) return `${stripeUnits}` as MoneyAmount;\n // Pad so there's always at least one integer digit plus `decimals` fractional\n // digits, then split at the dot position.\n const padded = stripeUnits.toString().padStart(decimals + 1, \"0\");\n const integerPart = padded.slice(0, padded.length - decimals);\n const fractionalPart = padded.slice(padded.length - decimals);\n return `${integerPart}.${fractionalPart}` as MoneyAmount;\n}\n\nimport.meta.vitest?.describe(\"moneyAmountToStripeUnits\", (test) => {\n const USD = SUPPORTED_CURRENCIES.find((c) => c.code === \"USD\")!;\n\n test(\"converts fully-padded USD amounts\", ({ expect }) => {\n expect(moneyAmountToStripeUnits(\"5.00\" as MoneyAmount, USD)).toBe(500);\n expect(moneyAmountToStripeUnits(\"0.01\" as MoneyAmount, USD)).toBe(1);\n expect(moneyAmountToStripeUnits(\"12.34\" as MoneyAmount, USD)).toBe(1234);\n });\n\n test(\"converts whole-number USD amounts (no decimals)\", ({ expect }) => {\n expect(moneyAmountToStripeUnits(\"5\" as MoneyAmount, USD)).toBe(500);\n expect(moneyAmountToStripeUnits(\"10\" as MoneyAmount, USD)).toBe(1000);\n expect(moneyAmountToStripeUnits(\"0\" as MoneyAmount, USD)).toBe(0);\n });\n\n test(\"converts USD amounts with one decimal digit\", ({ expect }) => {\n expect(moneyAmountToStripeUnits(\"5.5\" as MoneyAmount, USD)).toBe(550);\n expect(moneyAmountToStripeUnits(\"0.5\" as MoneyAmount, USD)).toBe(50);\n });\n\n test(\"matches stripeUnitsToMoneyAmount round-trip\", ({ expect }) => {\n for (const cents of [0, 1, 5, 50, 99, 100, 1234, 100000]) {\n const padded = `${Math.floor(cents / 100)}.${(cents % 100).toString().padStart(2, \"0\")}` as MoneyAmount;\n expect(moneyAmountToStripeUnits(padded, USD)).toBe(cents);\n }\n });\n\n test(\"rejects invalid money strings via schema\", ({ expect }) => {\n expect(() => moneyAmountToStripeUnits(\"abc\" as MoneyAmount, USD)).toThrow();\n expect(() => moneyAmountToStripeUnits(\"5.555\" as MoneyAmount, USD)).toThrow();\n expect(() => moneyAmountToStripeUnits(\"05\" as MoneyAmount, USD)).toThrow();\n });\n});\n\nimport.meta.vitest?.describe(\"stripeUnitsToMoneyAmount\", (test) => {\n const USD = SUPPORTED_CURRENCIES.find((c) => c.code === \"USD\")!;\n const JPY = SUPPORTED_CURRENCIES.find((c) => c.code === \"JPY\")!;\n\n test(\"formats USD minor units as a 2-decimal string\", ({ expect }) => {\n expect(stripeUnitsToMoneyAmount(5000, USD)).toBe(\"50.00\");\n expect(stripeUnitsToMoneyAmount(1, USD)).toBe(\"0.01\");\n expect(stripeUnitsToMoneyAmount(100, USD)).toBe(\"1.00\");\n expect(stripeUnitsToMoneyAmount(0, USD)).toBe(\"0.00\");\n });\n\n test(\"formats 0-decimal currencies without a dot\", ({ expect }) => {\n expect(stripeUnitsToMoneyAmount(500, JPY)).toBe(\"500\");\n expect(stripeUnitsToMoneyAmount(0, JPY)).toBe(\"0\");\n });\n\n test(\"round-trips with moneyAmountToStripeUnits\", ({ expect }) => {\n for (const cents of [0, 1, 5, 50, 99, 100, 1234, 100000]) {\n expect(moneyAmountToStripeUnits(stripeUnitsToMoneyAmount(cents, USD), USD)).toBe(cents);\n }\n });\n\n test(\"scaling in minor units avoids float artifacts\", ({ expect }) => {\n // 19.99 * 3 in float is 59.97000000000001; via minor units it is exact.\n const scaled = moneyAmountToStripeUnits(\"19.99\" as MoneyAmount, USD) * 3;\n expect(stripeUnitsToMoneyAmount(scaled, USD)).toBe(\"59.97\");\n });\n\n test(\"rejects non-integer and negative inputs\", ({ expect }) => {\n expect(() => stripeUnitsToMoneyAmount(1.5, USD)).toThrow();\n expect(() => stripeUnitsToMoneyAmount(-1, USD)).toThrow();\n expect(() => stripeUnitsToMoneyAmount(Number.NaN, USD)).toThrow();\n });\n});\n"],"mappings":";;;;AAMA,SAAgB,yBAAyB,QAAqB,UAA4B;CACxF,MAAM,YAAY,kBAAkB,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAC,aAAa,MAAM;CAC3E,IAAI,SAAS,mBAAmB,SAAS,UACvC,MAAM,IAAI,uBAAuB,8DAA8D;CAMjG,MAAM,CAAC,OAAO,aAAa,MAAM,UAAU,MAAM,GAAG;CACpD,MAAM,mBAAmB,WAAW,OAAO,SAAS,UAAU,GAAG;CACjE,OAAO,OAAO,SAAS,QAAQ,kBAAkB,EAAE;AACrD;;;;;;;;;;;;;;;AAgBA,SAAgB,yBAAyB,aAAqB,UAAiC;CAC7F,IAAI,CAAC,OAAO,SAAS,WAAW,KAAK,KAAK,MAAM,WAAW,MAAM,aAC/D,MAAM,IAAI,uBAAuB,mCAAmC,EAAE,YAAY,CAAC;CAErF,IAAI,cAAc,GAChB,MAAM,IAAI,uBAAuB,0EAA0E,EAAE,YAAY,CAAC;CAE5H,IAAI,SAAS,mBAAmB,SAAS,UACvC,MAAM,IAAI,uBAAuB,8DAA8D;CAEjG,MAAM,WAAW,SAAS;CAC1B,IAAI,aAAa,GAAG,OAAO,GAAG;CAG9B,MAAM,SAAS,YAAY,SAAS,CAAC,CAAC,SAAS,WAAW,GAAG,GAAG;CAGhE,OAAO,GAFa,OAAO,MAAM,GAAG,OAAO,SAAS,QAEhC,EAAE,GADC,OAAO,MAAM,OAAO,SAAS,QACd;AACxC"}
|
|
@@ -18,6 +18,23 @@ declare function subtractInterval(date: Date, interval: Interval): Date;
|
|
|
18
18
|
declare function addInterval(date: Date, interval: Interval): Date;
|
|
19
19
|
declare const FAR_FUTURE_DATE: Date;
|
|
20
20
|
declare function getIntervalsElapsed(anchor: Date, to: Date, repeat: DayInterval): number;
|
|
21
|
+
/**
|
|
22
|
+
* The UTC millis of the `occurrence`-th (1-based) repeat of `interval` after `anchorMillis`.
|
|
23
|
+
*
|
|
24
|
+
* Each boundary is computed from the *original* anchor (never by stepping off the previous, possibly
|
|
25
|
+
* clamped, boundary) so the anchor's day-of-month is preserved across resets: a Jan 31 anchor yields
|
|
26
|
+
* Feb 28, Mar 31, Apr 30, ... (matching Stripe's billing-cycle behavior) rather than drifting to
|
|
27
|
+
* Feb 28, Mar 28, ... . Month/year overflow (e.g. Jan 31 -> Feb) is clamped to the target month's
|
|
28
|
+
* last day. Day/week are exact multiples (no calendar involved, so no drift possible).
|
|
29
|
+
*
|
|
30
|
+
* Everything is done in UTC (unlike `addInterval`, which uses local-time Date accessors) so the
|
|
31
|
+
* result is deterministic regardless of the server's timezone — this is relied upon by bulldozer
|
|
32
|
+
* folds, which must be reproducible across machines.
|
|
33
|
+
*
|
|
34
|
+
* `occurrence` 0 returns the anchor itself; `getIntervalsElapsed` counts these same boundaries, so
|
|
35
|
+
* the two are always consistent for a given DayInterval.
|
|
36
|
+
*/
|
|
37
|
+
declare function nthDayIntervalMillis(anchorMillis: number, interval: DayInterval, occurrence: number): number;
|
|
21
38
|
//#endregion
|
|
22
|
-
export { DayInterval, FAR_FUTURE_DATE, Interval, addInterval, fromNow, fromNowDetailed, getInputDatetimeLocalString, getIntervalsElapsed, isWeekend, subtractInterval };
|
|
39
|
+
export { DayInterval, FAR_FUTURE_DATE, Interval, addInterval, fromNow, fromNowDetailed, getInputDatetimeLocalString, getIntervalsElapsed, isWeekend, nthDayIntervalMillis, subtractInterval };
|
|
23
40
|
//# sourceMappingURL=dates.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dates.d.ts","names":[],"sources":["../../../src/utils/dates.tsx"],"mappings":";iBAIgB,SAAA,CAAU,IAAU,EAAJ,IAAI;AAAA,iBAuBpB,OAAA,CAAQ,IAAU,EAAJ,IAAI;AAAA,iBAiClB,eAAA,CAAgB,IAAA,EAAM,IAAI;EACxC,MAAA;EAzD8B;AAAI;AAuBpC;EAsCE,kBAAA;AAAA;;AAtCgC;AAiClC;iBAkDgB,2BAAA,CAA4B,IAAU,EAAJ,IAAI;AAAA,KAkC1C,QAAA;AAAA,KACA,WAAA;AAAA,iBA+CI,gBAAA,CAAiB,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,QAAA,GAAW,IAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"dates.d.ts","names":[],"sources":["../../../src/utils/dates.tsx"],"mappings":";iBAIgB,SAAA,CAAU,IAAU,EAAJ,IAAI;AAAA,iBAuBpB,OAAA,CAAQ,IAAU,EAAJ,IAAI;AAAA,iBAiClB,eAAA,CAAgB,IAAA,EAAM,IAAI;EACxC,MAAA;EAzD8B;AAAI;AAuBpC;EAsCE,kBAAA;AAAA;;AAtCgC;AAiClC;iBAkDgB,2BAAA,CAA4B,IAAU,EAAJ,IAAI;AAAA,KAkC1C,QAAA;AAAA,KACA,WAAA;AAAA,iBA+CI,gBAAA,CAAiB,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,QAAA,GAAW,IAAA;AAAA,iBASlD,WAAA,CAAY,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,QAAA,GAAW,IAAA;AAAA,cAIhD,eAAA,EAAe,IAA6B;AAAA,iBAgBzC,mBAAA,CAAoB,MAAA,EAAQ,IAAA,EAAM,EAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,WAAA;;AA5JhD;AA6CpB;;;;AAAsD;AAkCtD;;;;AAAoB;AACpB;;;;iBA6HgB,oBAAA,CAAqB,YAAA,UAAsB,QAAA,EAAU,WAAW,EAAE,UAAA"}
|