@tailor-platform/sdk 1.47.0 → 1.47.1
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/CHANGELOG.md +12 -0
- package/dist/{actor-DhXSqWTW.d.mts → actor-jk4-f0yp.d.mts} +2 -2
- package/dist/{application-TasSqBTD.mjs → application-C7H7y0hS.mjs} +46 -64
- package/dist/application-C7H7y0hS.mjs.map +1 -0
- package/dist/application-Csq5jxYP.mjs +4 -0
- package/dist/{brand-Ll48SMXe.mjs → brand-D-d15jx3.mjs} +1 -1
- package/dist/{brand-Ll48SMXe.mjs.map → brand-D-d15jx3.mjs.map} +1 -1
- package/dist/cli/index.mjs +8 -8
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lib.mjs +3 -3
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/skills.mjs.map +1 -1
- package/dist/{client-DYSkSLRr.mjs → client-DCqdtFte.mjs} +1 -1
- package/dist/client-DbyKSN1F.mjs +1061 -0
- package/dist/client-DbyKSN1F.mjs.map +1 -0
- package/dist/configure/index.d.mts +2 -2
- package/dist/configure/index.mjs +5 -5
- package/dist/configure/index.mjs.map +1 -1
- package/dist/{crashreport-CKJwnWsX.mjs → crashreport-CNSw_BrJ.mjs} +2 -2
- package/dist/{crashreport-CKJwnWsX.mjs.map → crashreport-CNSw_BrJ.mjs.map} +1 -1
- package/dist/{crashreport-B8lVOx0U.mjs → crashreport-DXGFd16F.mjs} +1 -1
- package/dist/enum-constants-C3KSpsYj.mjs.map +1 -1
- package/dist/errors-wNQxQQBH.mjs.map +1 -1
- package/dist/{field-BY2vbJ8f.mjs → field-DLSIuMTu.mjs} +1 -1
- package/dist/{field-BY2vbJ8f.mjs.map → field-DLSIuMTu.mjs.map} +1 -1
- package/dist/file-utils-DjNi_3U_.mjs.map +1 -1
- package/dist/{index-BoU_52Du.d.mts → index-DB8EapT-.d.mts} +5 -13
- package/dist/interceptor-CBsqEWDK.mjs.map +1 -1
- package/dist/{job-BOvKyNdT.mjs → job-R5C2Hfcc.mjs} +2 -3
- package/dist/job-R5C2Hfcc.mjs.map +1 -0
- package/dist/kysely/index.mjs.map +1 -1
- package/dist/kysely-type-B8aRz_oC.mjs.map +1 -1
- package/dist/logger-DTNAMYGy.mjs.map +1 -1
- package/dist/mock-BP-9O5On.mjs.map +1 -1
- package/dist/multiline-e3IpANmS.mjs.map +1 -1
- package/dist/package-json-6Px8bDpG.mjs.map +1 -1
- package/dist/plugin/index.d.mts +1 -1
- package/dist/plugin/index.mjs.map +1 -1
- package/dist/repl-editor-CZpLlOBj.mjs.map +1 -1
- package/dist/{runtime-DDYL2Zf1.mjs → runtime-XjP6JMmP.mjs} +10 -7
- package/dist/{runtime-DDYL2Zf1.mjs.map → runtime-XjP6JMmP.mjs.map} +1 -1
- package/dist/seed/index.mjs.map +1 -1
- package/dist/seed-DrKY5yIF.mjs.map +1 -1
- package/dist/service-obEU5gSM.mjs.map +1 -1
- package/dist/{tailordb-Bg9-TZj1.mjs → tailordb-DjlNUV6u.mjs} +3 -3
- package/dist/{tailordb-Bg9-TZj1.mjs.map → tailordb-DjlNUV6u.mjs.map} +1 -1
- package/dist/telemetry-DcL8Fsm_.mjs.map +1 -1
- package/dist/types-DoIG6Nij.mjs +5 -0
- package/dist/{types-Duhhsx3R.mjs → types-sir9UPht.mjs} +2 -2
- package/dist/{types-Duhhsx3R.mjs.map → types-sir9UPht.mjs.map} +1 -1
- package/dist/utils/test/index.d.mts +1 -1
- package/dist/utils/test/index.mjs +1 -1
- package/dist/utils/test/index.mjs.map +1 -1
- package/dist/vitest/environment.mjs.map +1 -1
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/vitest/setup.mjs.map +1 -1
- package/docs/services/workflow.md +0 -5
- package/package.json +6 -5
- package/dist/application-CN9Htzup.mjs +0 -4
- package/dist/application-TasSqBTD.mjs.map +0 -1
- package/dist/client-COfsXV69.mjs +0 -16447
- package/dist/client-COfsXV69.mjs.map +0 -1
- package/dist/job-BOvKyNdT.mjs.map +0 -1
- package/dist/types-BnphjkIJ.mjs +0 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tailordb-Bg9-TZj1.mjs","names":[],"sources":["../src/configure/services/tailordb/schema.ts","../src/configure/services/tailordb/permission.ts"],"sourcesContent":["import { cloneDeep } from \"es-toolkit\";\nimport {\n type AllowedValues,\n type AllowedValuesOutput,\n mapAllowedValues,\n} from \"@/configure/types/field\";\nimport { brandValue } from \"@/utils/brand\";\nimport type { TailorTypeGqlPermission, TailorTypePermission } from \"./permission\";\nimport type { Hook, Hooks, ExcludeNestedDBFields, TypeFeatures } from \"./types\";\nimport type { FieldOptions, FieldOutput, TailorFieldType, TailorToTs } from \"@/types/field-types\";\nimport type { output, InferFieldsOutput, Prettify } from \"@/types/helpers\";\nimport type { PluginAttachment, PluginConfigs } from \"@/types/plugin\";\nimport type {\n TailorDBField as TailorDBFieldBase,\n TailorDBType as TailorDBTypeBase,\n} from \"@/types/tailor-db-field\";\nimport type { TailorField as TailorFieldMinimal } from \"@/types/tailor-field\";\nimport type {\n DBFieldMetadata,\n DefinedDBFieldMetadata,\n SerialConfig,\n IndexDef,\n TailorDBTypeMetadata,\n RawRelationConfig,\n RelationType,\n} from \"@/types/tailordb\";\nimport type { RawPermissions } from \"@/types/tailordb.generated\";\nimport type { InferredAttributeMap, TailorUser } from \"@/types/user\";\nimport type { FieldValidateInput, ValidateConfig, Validators } from \"@/types/validation\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n// Helper alias: DB fields can be arbitrarily nested, so we intentionally keep this loose.\n// oxlint-disable-next-line no-explicit-any\nexport type TailorAnyDBField = TailorDBField<any, any>;\n\n// Helper alias\n// oxlint-disable-next-line no-explicit-any\nexport type TailorAnyDBType = TailorDBType<any, any>;\n\n/**\n * Full TailorDBField interface with builder methods.\n * Extends the minimal structural interface from types/ with fluent API methods.\n */\nexport interface TailorDBField<\n Defined extends DefinedDBFieldMetadata = DefinedDBFieldMetadata,\n // oxlint-disable-next-line no-explicit-any\n Output = any,\n> extends Omit<TailorDBFieldBase<Defined, Output>, \"fields\"> {\n readonly fields: Record<string, TailorAnyDBField>;\n _metadata: DBFieldMetadata;\n\n /**\n * Parse and validate a value against this field's validation rules\n */\n parse(args: FieldParseArgs): StandardSchemaV1.Result<Output>;\n\n /**\n * Internal parse method that tracks field path for nested validation\n * @private\n */\n _parseInternal(args: FieldParseInternalArgs): StandardSchemaV1.Result<Output>;\n\n /**\n * typeName is not available on TailorDB fields.\n * Use typeName on pipeline fields (t.enum / t.object) instead.\n */\n typeName(this: never, typeName: string): never;\n\n /**\n * Set a description for the field\n */\n description<CurrentDefined extends Defined>(\n this: CurrentDefined extends { description: unknown }\n ? never\n : TailorFieldMinimal<CurrentDefined, Output>,\n description: string,\n ): TailorDBField<Prettify<CurrentDefined & { description: true }>, Output>;\n\n /**\n * Define a relation to another type.\n */\n relation<S extends RelationType, T extends TailorAnyDBType, CurrentDefined extends Defined>(\n this: CurrentDefined extends { relation: unknown }\n ? never\n : TailorDBField<CurrentDefined, Output>,\n config: RelationConfig<S, T>,\n ): TailorDBField<\n S extends \"oneToOne\" | \"1-1\"\n ? Prettify<CurrentDefined & { unique: true; index: true; relation: true }>\n : Prettify<CurrentDefined & { index: true; relation: true }>,\n Output\n >;\n\n /**\n * Define a self-referencing relation\n */\n relation<S extends RelationSelfConfig, CurrentDefined extends Defined>(\n this: CurrentDefined extends { relation: unknown }\n ? never\n : TailorDBField<CurrentDefined, Output>,\n config: S,\n ): TailorDBField<\n S[\"type\"] extends \"oneToOne\" | \"1-1\"\n ? Prettify<CurrentDefined & { unique: true; index: true; relation: true }>\n : Prettify<CurrentDefined & { index: true; relation: true }>,\n Output\n >;\n\n /**\n * Add an index to the field\n */\n index<CurrentDefined extends Defined>(\n this: CurrentDefined extends { index: unknown }\n ? never\n : CurrentDefined extends { array: true }\n ? never\n : TailorDBField<CurrentDefined, Output>,\n ): TailorDBField<Prettify<CurrentDefined & { index: true }>, Output>;\n\n /**\n * Make the field unique (also adds an index)\n */\n unique<CurrentDefined extends Defined>(\n this: CurrentDefined extends { unique: unknown }\n ? never\n : CurrentDefined extends { array: true }\n ? never\n : TailorDBField<CurrentDefined, Output>,\n ): TailorDBField<Prettify<CurrentDefined & { unique: true; index: true }>, Output>;\n\n /**\n * Enable vector search on the field (string type only)\n */\n vector<CurrentDefined extends Defined>(\n this: CurrentDefined extends { vector: unknown }\n ? never\n : CurrentDefined extends { type: \"string\"; array: false }\n ? TailorDBField<CurrentDefined, Output>\n : never,\n ): TailorDBField<Prettify<CurrentDefined & { vector: true }>, Output>;\n\n /**\n * Add hooks for create/update operations on this field.\n */\n hooks<CurrentDefined extends Defined, const H extends Hook<unknown, Output>>(\n this: CurrentDefined extends { hooks: unknown }\n ? never\n : CurrentDefined extends { type: \"nested\" }\n ? never\n : TailorDBField<CurrentDefined, Output>,\n hooks: H,\n ): TailorDBField<\n Prettify<\n CurrentDefined & {\n hooks?: {\n create: H extends { create: unknown } ? true : false;\n update: H extends { update: unknown } ? true : false;\n };\n serial: false;\n }\n >,\n Output\n >;\n\n /**\n * Add validation functions to the field.\n */\n validate<CurrentDefined extends Defined>(\n this: CurrentDefined extends { validate: unknown }\n ? never\n : TailorDBField<CurrentDefined, Output>,\n ...validate: FieldValidateInput<Output>[]\n ): TailorDBField<Prettify<CurrentDefined & { validate: true }>, Output>;\n\n /**\n * Configure serial/auto-increment behavior\n */\n serial<CurrentDefined extends Defined>(\n this: CurrentDefined extends { serial: unknown }\n ? never\n : Output extends null\n ? never\n : CurrentDefined extends { type: \"integer\" | \"string\"; array: false }\n ? TailorDBField<CurrentDefined, Output>\n : never,\n config: SerialConfig<CurrentDefined[\"type\"] & (\"integer\" | \"string\")>,\n ): TailorDBField<\n Prettify<\n CurrentDefined & {\n serial: true;\n hooks: { create: false; update: false };\n }\n >,\n Output\n >;\n\n /**\n * Clone the field with optional overrides for field options\n */\n clone<const NewOpt extends FieldOptions>(\n options?: NewOpt,\n ): TailorDBField<\n Prettify<\n Omit<Defined, \"array\"> & {\n array: NewOpt extends { array: true } ? true : Defined[\"array\"];\n }\n >,\n FieldOutput<TailorToTs[Defined[\"type\"]], NewOpt>\n >;\n}\n\n/**\n * Full TailorDBType interface with builder methods.\n * Extends the minimal structural interface from types/ with fluent API methods.\n */\nexport interface TailorDBType<\n // oxlint-disable-next-line no-explicit-any\n Fields extends Record<string, TailorAnyDBField> = any,\n User extends object = InferredAttributeMap,\n> extends TailorDBTypeBase<Fields, User> {\n _description?: string;\n\n hooks(hooks: Hooks<Fields>): TailorDBType<Fields, User>;\n validate(validators: Validators<Fields>): TailorDBType<Fields, User>;\n features(features: Omit<TypeFeatures, \"pluralForm\">): TailorDBType<Fields, User>;\n indexes(...indexes: IndexDef<TailorDBType<Fields, User>>[]): TailorDBType<Fields, User>;\n files<const F extends string>(\n files: Record<F, string> & Partial<Record<keyof output<TailorDBType<Fields, User>>, never>>,\n ): TailorDBType<Fields, User>;\n permission<\n U extends object = User,\n P extends TailorTypePermission<U, output<TailorDBType<Fields, User>>> = TailorTypePermission<\n U,\n output<TailorDBType<Fields, User>>\n >,\n >(\n permission: P,\n ): TailorDBType<Fields, U>;\n gqlPermission<\n U extends object = User,\n P extends TailorTypeGqlPermission<U> = TailorTypeGqlPermission<U>,\n >(\n permission: P,\n ): TailorDBType<Fields, U>;\n description(description: string): TailorDBType<Fields, User>;\n pickFields<K extends keyof Fields>(keys: K[]): Pick<Fields, K>;\n pickFields<K extends keyof Fields, const Opt extends FieldOptions>(\n keys: K[],\n options: Opt,\n ): {\n [P in K]: Fields[P] extends TailorDBField<infer D, infer _O>\n ? TailorDBField<\n Omit<D, \"array\"> & {\n array: Opt extends { array: true } ? true : D[\"array\"];\n },\n FieldOutput<TailorToTs[D[\"type\"]], Opt>\n >\n : never;\n };\n omitFields<K extends keyof Fields>(keys: K[]): Omit<Fields, K>;\n plugin<P extends keyof PluginConfigs<keyof Fields & string>>(config: {\n [K in P]: PluginConfigs<keyof Fields & string>[K];\n }): TailorDBType<Fields, User>;\n}\n\nexport type TailorDBInstance<\n // oxlint-disable-next-line no-explicit-any\n Fields extends Record<string, TailorAnyDBField> = any,\n User extends object = InferredAttributeMap,\n> = TailorDBType<Fields, User>;\n\ninterface RelationConfig<S extends RelationType, T extends TailorDBType> {\n type: S;\n toward: {\n type: T;\n as?: string;\n key?: keyof T[\"fields\"] & string;\n };\n backward?: string;\n}\n\n// Special config variant for self-referencing relations\ntype RelationSelfConfig = {\n type: RelationType;\n toward: {\n type: \"self\";\n as?: string;\n key?: string;\n };\n backward?: string;\n};\n\nfunction isRelationSelfConfig(\n config: RelationConfig<RelationType, TailorDBType> | RelationSelfConfig,\n): config is RelationSelfConfig {\n return config.toward.type === \"self\";\n}\n\nconst regex = {\n uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n date: /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})$/,\n time: /^(?<hour>\\d{2}):(?<minute>\\d{2})$/,\n datetime:\n /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})T(?<hour>\\d{2}):(?<minute>\\d{2}):(?<second>\\d{2})(.(?<millisec>\\d{3}))?Z$/,\n decimal: /^-?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/,\n} as const;\n\ntype FieldParseArgs = {\n value: unknown;\n data: unknown;\n user: TailorUser;\n};\n\ntype FieldValidateValueArgs<T extends TailorFieldType> = {\n value: TailorToTs[T];\n data: unknown;\n user: TailorUser;\n pathArray: string[];\n};\n\ntype FieldParseInternalArgs = {\n // Runtime input is unknown/untyped; we validate and narrow it inside the parser.\n // oxlint-disable-next-line no-explicit-any\n value: any;\n data: unknown;\n user: TailorUser;\n pathArray: string[];\n};\n\n/**\n * Creates a new TailorDBField instance.\n * @param type - Field type\n * @param options - Field options\n * @param fields - Nested fields for object-like types\n * @param values - Allowed values for enum-like fields\n * @returns A new TailorDBField\n */\nfunction createTailorDBField<\n const T extends TailorFieldType,\n const TOptions extends FieldOptions,\n const OutputBase = TailorToTs[T],\n>(\n type: T,\n options?: TOptions,\n fields?: Record<string, TailorAnyDBField>,\n values?: AllowedValues,\n): TailorDBField<\n { type: T; array: TOptions extends { array: true } ? true : false },\n FieldOutput<OutputBase, TOptions>\n> {\n type FieldType = TailorDBField<\n { type: T; array: TOptions extends { array: true } ? true : false },\n FieldOutput<OutputBase, TOptions>\n >;\n\n const _metadata: DBFieldMetadata = { required: true };\n let _rawRelation: RawRelationConfig | undefined;\n\n if (options) {\n if (options.optional === true) {\n _metadata.required = false;\n }\n if (options.array === true) {\n _metadata.array = true;\n }\n }\n if (values) {\n _metadata.allowedValues = mapAllowedValues(values);\n }\n\n /**\n * Validate a single value (not an array element)\n * Used internally for array element validation\n * @param args - Value, context data, and user\n * @returns Array of validation issues\n */\n function validateValue(args: FieldValidateValueArgs<T>): StandardSchemaV1.Issue[] {\n const { value, data, user, pathArray } = args;\n const issues: StandardSchemaV1.Issue[] = [];\n\n // Type-specific validation\n switch (type) {\n case \"string\":\n if (typeof value !== \"string\") {\n issues.push({\n message: `Expected a string: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"integer\":\n if (typeof value !== \"number\" || !Number.isInteger(value)) {\n issues.push({\n message: `Expected an integer: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"float\":\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n issues.push({\n message: `Expected a number: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n issues.push({\n message: `Expected a boolean: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"uuid\":\n if (typeof value !== \"string\" || !regex.uuid.test(value)) {\n issues.push({\n message: `Expected a valid UUID: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"date\":\n if (typeof value !== \"string\" || !regex.date.test(value)) {\n issues.push({\n message: `Expected to match \"yyyy-MM-dd\" format: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"datetime\":\n if (typeof value !== \"string\" || !regex.datetime.test(value)) {\n issues.push({\n message: `Expected to match ISO format: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"time\":\n if (typeof value !== \"string\" || !regex.time.test(value)) {\n issues.push({\n message: `Expected to match \"HH:mm\" format: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"decimal\":\n if (typeof value !== \"string\" || !regex.decimal.test(value)) {\n issues.push({\n message: `Expected a decimal string: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"enum\":\n if (field._metadata.allowedValues) {\n const allowedValues = field._metadata.allowedValues.map((v) => v.value);\n if (typeof value !== \"string\" || !allowedValues.includes(value)) {\n issues.push({\n message: `Must be one of [${allowedValues.join(\", \")}]: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n }\n break;\n\n case \"nested\":\n // Validate nested object fields\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value) ||\n value instanceof Date\n ) {\n issues.push({\n message: `Expected an object: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n } else if (field.fields && Object.keys(field.fields).length > 0) {\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n const fieldValue = value?.[fieldName];\n const result = nestedField._parseInternal({\n value: fieldValue,\n data,\n user,\n pathArray: pathArray.concat(fieldName),\n });\n if (result.issues) {\n issues.push(...result.issues);\n }\n }\n }\n break;\n }\n\n // Custom validation functions\n const validateFns = field._metadata.validate;\n if (validateFns && validateFns.length > 0) {\n for (const validateInput of validateFns) {\n const { fn, message } =\n typeof validateInput === \"function\"\n ? { fn: validateInput, message: \"Validation failed\" }\n : { fn: validateInput[0], message: validateInput[1] };\n\n if (!fn({ value, data, user })) {\n issues.push({\n message,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n }\n }\n\n return issues;\n }\n\n /**\n * Internal parse method that tracks field path for nested validation\n * @param args - Parse arguments\n * @returns Parse result with value or issues\n */\n function parseInternal(\n args: FieldParseInternalArgs,\n ): StandardSchemaV1.Result<FieldOutput<OutputBase, TOptions>> {\n const { value, data, user, pathArray } = args;\n const issues: StandardSchemaV1.Issue[] = [];\n\n // 1. Check required/optional\n const isNullOrUndefined = value === null || value === undefined;\n if (field._metadata.required && isNullOrUndefined) {\n issues.push({\n message: \"Required field is missing\",\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n return { issues };\n }\n\n // If optional and null/undefined, skip further validation and normalize to null\n if (!field._metadata.required && isNullOrUndefined) {\n return { value: value ?? null };\n }\n\n // 2. Check array type\n if (field._metadata.array) {\n if (!Array.isArray(value)) {\n issues.push({\n message: \"Expected an array\",\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n return { issues };\n }\n\n // Validate each array element (without array flag)\n for (let i = 0; i < value.length; i++) {\n const elementValue = value[i];\n const elementPath = pathArray.concat(`[${i}]`);\n\n // Validate element with same type but without array flag\n const elementIssues = validateValue({\n value: elementValue,\n data,\n user,\n pathArray: elementPath,\n });\n if (elementIssues.length > 0) {\n issues.push(...elementIssues);\n }\n }\n\n if (issues.length > 0) {\n return { issues };\n }\n return { value: value as FieldOutput<OutputBase, TOptions> };\n }\n\n // 3. Type-specific validation and custom validation\n const valueIssues = validateValue({ value, data, user, pathArray });\n issues.push(...valueIssues);\n\n if (issues.length > 0) {\n return { issues };\n }\n\n return { value };\n }\n\n function cloneWith(metadataUpdates: Partial<DBFieldMetadata>) {\n const cloned = field.clone();\n Object.assign(cloned._metadata, metadataUpdates);\n return cloned;\n }\n\n const field: FieldType = {\n type,\n fields: (fields ?? {}) as Record<string, TailorAnyDBField>,\n _defined: undefined as unknown as {\n type: T;\n array: TOptions extends { array: true } ? true : false;\n },\n _output: undefined as FieldOutput<OutputBase, TOptions>,\n _metadata,\n\n get metadata() {\n return { ...this._metadata };\n },\n\n get rawRelation(): Readonly<RawRelationConfig> | undefined {\n return _rawRelation ? { ..._rawRelation, toward: { ..._rawRelation.toward } } : undefined;\n },\n\n description(description: string) {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ description }) as any;\n },\n\n // oxlint-disable-next-line no-explicit-any\n typeName: ((typeName: string) => cloneWith({ typeName })) as any,\n\n validate(...validateInputs: FieldValidateInput<FieldOutput<OutputBase, TOptions>>[]) {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ validate: validateInputs }) as any;\n },\n\n parse(args: FieldParseArgs): StandardSchemaV1.Result<FieldOutput<OutputBase, TOptions>> {\n return parseInternal({\n value: args.value,\n data: args.data,\n user: args.user,\n pathArray: [],\n });\n },\n\n _parseInternal: parseInternal,\n\n // TailorDBField specific methods\n relation(config: RelationConfig<RelationType, TailorDBType> | RelationSelfConfig) {\n const cloned = field.clone();\n const targetType = isRelationSelfConfig(config) ? \"self\" : config.toward.type.name;\n // oxlint-disable-next-line no-explicit-any\n (cloned as any)._setRawRelation({\n type: config.type,\n toward: {\n type: targetType,\n as: config.toward.as,\n key: config.toward.key,\n },\n backward: config.backward,\n });\n // oxlint-disable-next-line no-explicit-any\n return cloned as any;\n },\n\n index() {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ index: true }) as any;\n },\n\n unique() {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ unique: true, index: true }) as any;\n },\n\n vector() {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ vector: true }) as any;\n },\n\n hooks(hooks: Hook<unknown, FieldOutput<OutputBase, TOptions>>) {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ hooks }) as any;\n },\n\n serial(config: SerialConfig) {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ serial: config }) as any;\n },\n\n clone(cloneOptions?: FieldOptions) {\n // Deep clone nested object fields if present\n let clonedFields = fields;\n if (fields) {\n const cloned: Record<string, TailorAnyDBField> = {};\n for (const [key, field] of Object.entries(fields)) {\n cloned[key] = field.clone();\n }\n clonedFields = cloned;\n }\n\n // Create a new field with cloned configuration\n const clonedField = createTailorDBField(type, options, clonedFields, values);\n\n // Deep copy metadata using cloneDeep (preserves function references)\n Object.assign(clonedField._metadata, cloneDeep(this._metadata));\n\n // Apply new options if provided\n if (cloneOptions) {\n if (cloneOptions.optional !== undefined) {\n clonedField._metadata.required = !cloneOptions.optional;\n }\n if (cloneOptions.array !== undefined) {\n clonedField._metadata.array = cloneOptions.array;\n }\n }\n\n // Copy raw relation if exists\n if (_rawRelation) {\n const clonedRawRelation = cloneDeep(_rawRelation);\n // oxlint-disable-next-line no-explicit-any\n (clonedField as any)._setRawRelation(clonedRawRelation);\n }\n\n // oxlint-disable-next-line no-explicit-any\n return clonedField as any;\n },\n\n // Internal method for clone to set rawRelation\n // @ts-ignore - Internal method not in interface\n _setRawRelation(relation: RawRelationConfig) {\n _rawRelation = relation;\n },\n };\n\n return field;\n}\n\nconst createField = createTailorDBField;\n\n/**\n * Create a UUID field.\n * @param options - Field configuration options\n * @returns A UUID field\n * @example db.uuid()\n * @example db.uuid({ optional: true })\n */\nfunction uuid<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"uuid\", options);\n}\n\n/**\n * Create a string field.\n * @param options - Field configuration options\n * @returns A string field\n * @example db.string()\n * @example db.string({ optional: true })\n */\nfunction string<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"string\", options);\n}\n\n/**\n * Create a boolean field.\n * Note: The method name is `bool` but creates a `boolean` type field.\n * @param options - Field configuration options\n * @returns A boolean field\n * @example db.bool()\n * @example db.bool({ optional: true })\n */\nfunction bool<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"boolean\", options);\n}\n\n/**\n * Create an integer field.\n * @param options - Field configuration options\n * @returns An integer field\n * @example db.int()\n * @example db.int({ optional: true })\n */\nfunction int<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"integer\", options);\n}\n\n/**\n * Create a float (decimal number) field.\n * @param options - Field configuration options\n * @returns A float field\n * @example db.float()\n * @example db.float({ optional: true })\n */\nfunction float<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"float\", options);\n}\n\ninterface DecimalFieldOptions extends FieldOptions {\n scale?: number;\n}\n\n/**\n * Create a decimal field (stored as string for precision).\n * @param options - Field configuration options including optional scale (0-12)\n * @returns A decimal field\n * @example db.decimal()\n * @example db.decimal({ scale: 2 })\n * @example db.decimal({ scale: 2, optional: true })\n */\nfunction decimal<const Opt extends DecimalFieldOptions>(options?: Opt) {\n if (options?.scale !== undefined) {\n if (!Number.isInteger(options.scale) || options.scale < 0 || options.scale > 12) {\n throw new Error(\"scale must be an integer between 0 and 12\");\n }\n }\n const field = createField(\"decimal\", options);\n if (options?.scale !== undefined) {\n field._metadata.scale = options.scale;\n }\n return field;\n}\n\n/**\n * Create a date field (date only, no time component).\n * Format: \"yyyy-MM-dd\"\n * @param options - Field configuration options\n * @returns A date field\n * @example db.date()\n */\nfunction date<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"date\", options);\n}\n\n/**\n * Create a datetime field (date and time).\n * Format: ISO 8601 \"yyyy-MM-ddTHH:mm:ssZ\"\n * @param options - Field configuration options\n * @returns A datetime field\n * @example db.datetime()\n */\nfunction datetime<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"datetime\", options);\n}\n\n/**\n * Create a time field (time only, no date component).\n * Format: \"HH:mm\"\n * @param options - Field configuration options\n * @returns A time field\n * @example db.time()\n */\nfunction time<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"time\", options);\n}\n\n/**\n * Create an enum field with a fixed set of allowed string values.\n * @param values - Array of allowed string values, or array of `{ value, description }` objects\n * @param options - Field configuration options\n * @returns An enum field\n * @example db.enum([\"active\", \"inactive\", \"suspended\"])\n * @example db.enum([\"small\", \"medium\", \"large\"], { optional: true })\n */\nfunction _enum<const V extends AllowedValues, const Opt extends FieldOptions>(\n values: V,\n options?: Opt,\n): TailorDBField<\n { type: \"enum\"; array: Opt extends { array: true } ? true : false },\n FieldOutput<AllowedValuesOutput<V>, Opt>\n> {\n return createField<\"enum\", Opt, AllowedValuesOutput<V>>(\"enum\", options, undefined, values);\n}\n\n/**\n * Create a nested object field with sub-fields.\n * @param fields - Record of nested field definitions\n * @param options - Field configuration options\n * @returns A nested object field\n * @example db.object({ street: db.string(), city: db.string(), zip: db.string() })\n * @example db.object({ name: db.string() }, { optional: true })\n */\nfunction object<\n const F extends Record<string, TailorAnyDBField> & ExcludeNestedDBFields<F>,\n const Opt extends FieldOptions,\n>(fields: F, options?: Opt) {\n return createField(\"nested\", options, fields) as unknown as TailorDBField<\n { type: \"nested\"; array: Opt extends { array: true } ? true : false },\n FieldOutput<InferFieldsOutput<F>, Opt>\n >;\n}\n\n/**\n * Creates a new TailorDBType instance.\n * @param name - Type name\n * @param fields - Field definitions\n * @param options - Type options\n * @param options.pluralForm - Optional plural form\n * @param options.description - Optional description\n * @returns A new TailorDBType\n */\nfunction createTailorDBType<\n // oxlint-disable-next-line no-explicit-any\n const Fields extends Record<string, TailorAnyDBField> = any,\n User extends object = InferredAttributeMap,\n>(\n name: string,\n fields: Fields,\n options: { pluralForm?: string; description?: string },\n): TailorDBType<Fields, User> {\n let _description = options.description;\n let _settings: TypeFeatures = {};\n let _indexes: IndexDef<TailorDBType<Fields, User>>[] = [];\n const _permissions: RawPermissions = {};\n let _files: Record<string, string> = {};\n const _plugins: PluginAttachment[] = [];\n\n if (options.pluralForm) {\n if (name === options.pluralForm) {\n throw new Error(`The name and the plural form must be different. name=${name}`);\n }\n _settings.pluralForm = options.pluralForm;\n }\n\n const dbType: TailorDBType<Fields, User> = {\n name,\n fields: { ...fields },\n _output: null as unknown as InferFieldsOutput<Fields>,\n _description,\n\n get metadata(): TailorDBTypeMetadata {\n // Convert indexes to the format expected by the manifest\n const indexes: Record<string, { fields: string[]; unique?: boolean }> = {};\n if (_indexes && _indexes.length > 0) {\n _indexes.forEach((index) => {\n const fieldNames = index.fields.map((field) => String(field));\n const key = index.name || `idx_${fieldNames.join(\"_\")}`;\n indexes[key] = {\n fields: fieldNames,\n unique: index.unique,\n };\n });\n }\n\n return {\n name: this.name,\n description: _description,\n settings: _settings,\n permissions: _permissions,\n files: _files,\n ...(Object.keys(indexes).length > 0 && { indexes }),\n };\n },\n\n hooks(hooks: Hooks<Fields>) {\n // `Hooks<Fields>` is strongly typed, but `Object.entries()` loses that information.\n // oxlint-disable-next-line no-explicit-any\n Object.entries(hooks).forEach(([fieldName, fieldHooks]: [string, any]) => {\n (this.fields as Record<string, TailorAnyDBField>)[fieldName] =\n this.fields[fieldName].hooks(fieldHooks);\n });\n return this;\n },\n\n validate(validators: Validators<Fields>) {\n Object.entries(validators).forEach(([fieldName, fieldValidators]) => {\n const field = this.fields[fieldName] as TailorAnyDBField;\n\n const validators = fieldValidators as\n | FieldValidateInput<unknown>\n | FieldValidateInput<unknown>[];\n\n const isValidateConfig = (v: unknown): v is ValidateConfig<unknown> => {\n return Array.isArray(v) && v.length === 2 && typeof v[1] === \"string\";\n };\n\n let updatedField: TailorAnyDBField;\n if (Array.isArray(validators)) {\n if (isValidateConfig(validators)) {\n updatedField = field.validate(validators);\n } else {\n updatedField = field.validate(...validators);\n }\n } else {\n updatedField = field.validate(validators);\n }\n (this.fields as Record<string, TailorAnyDBField>)[fieldName] = updatedField;\n });\n return this;\n },\n\n features(features: Omit<TypeFeatures, \"pluralForm\">) {\n _settings = {\n ..._settings,\n ...features,\n };\n return this;\n },\n\n indexes(...indexes: IndexDef<TailorDBType<Fields, User>>[]) {\n _indexes = indexes;\n return this;\n },\n\n files<const F extends string>(\n files: Record<F, string> & Partial<Record<keyof output<TailorDBType<Fields, User>>, never>>,\n ) {\n _files = files;\n return this;\n },\n\n permission<\n U extends object = User,\n P extends TailorTypePermission<U, output<TailorDBType<Fields, User>>> = TailorTypePermission<\n U,\n output<TailorDBType<Fields, User>>\n >,\n >(permission: P) {\n const ret = this as TailorDBType<Fields, U>;\n _permissions.record = permission as RawPermissions[\"record\"];\n return ret;\n },\n\n gqlPermission<\n U extends object = User,\n P extends TailorTypeGqlPermission<U> = TailorTypeGqlPermission<U>,\n >(permission: P) {\n const ret = this as TailorDBType<Fields, U>;\n _permissions.gql = permission as RawPermissions[\"gql\"];\n return ret;\n },\n\n description(description: string) {\n _description = description;\n this._description = description;\n return this;\n },\n\n pickFields<K extends keyof Fields, const Opt extends FieldOptions>(keys: K[], options?: Opt) {\n const result = {} as Record<K, TailorAnyDBField>;\n for (const key of keys) {\n if (options) {\n result[key] = this.fields[key].clone(options);\n } else {\n result[key] = this.fields[key];\n }\n }\n // oxlint-disable-next-line no-explicit-any\n return result as any;\n },\n\n omitFields<K extends keyof Fields>(keys: K[]): Omit<Fields, K> {\n const keysSet = new Set(keys);\n const result = {} as Record<string, TailorAnyDBField>;\n for (const key in this.fields) {\n if (Object.hasOwn(this.fields, key) && !keysSet.has(key as unknown as K)) {\n result[key] = this.fields[key];\n }\n }\n return result as Omit<Fields, K>;\n },\n\n get plugins(): PluginAttachment[] {\n return _plugins;\n },\n\n plugin<P extends keyof PluginConfigs<keyof Fields & string>>(config: {\n [K in P]: PluginConfigs<keyof Fields & string>[K];\n }): TailorDBType<Fields, User> {\n for (const [pluginId, pluginConfig] of Object.entries(config)) {\n _plugins.push({ pluginId, config: pluginConfig });\n }\n return this;\n },\n };\n\n return brandValue(dbType, \"tailordb-type\");\n}\n\nconst idField = uuid();\ntype idField = typeof idField;\ntype DBType<F extends { id?: never } & Record<string, TailorAnyDBField>> = TailorDBInstance<\n { id: idField } & F\n>;\n\n/**\n * Creates a new database type with the specified fields.\n * An `id` field (UUID) is automatically added to every type.\n * @param name - The name of the type, or a tuple of [name, pluralForm]\n * @param fields - The field definitions for the type\n * @returns A new TailorDBType instance\n * @example\n * export const user = db.type(\"User\", {\n * name: db.string(),\n * email: db.string(),\n * age: db.int({ optional: true }),\n * role: db.enum([\"admin\", \"member\"]),\n * ...db.fields.timestamps(),\n * });\n * // Always export both the value and type:\n * export type user = typeof user;\n */\nfunction dbType<const F extends { id?: never } & Record<string, TailorAnyDBField>>(\n name: string | [string, string],\n fields: F,\n): DBType<F>;\n/**\n * Creates a new database type with the specified fields and description.\n * An `id` field (UUID) is automatically added to every type.\n * @param name - The name of the type, or a tuple of [name, pluralForm]\n * @param description - A description of the type\n * @param fields - The field definitions for the type\n * @returns A new TailorDBType instance\n */\nfunction dbType<const F extends { id?: never } & Record<string, TailorAnyDBField>>(\n name: string | [string, string],\n description: string,\n fields: F,\n): DBType<F>;\nfunction dbType<const F extends { id?: never } & Record<string, TailorAnyDBField>>(\n name: string | [string, string],\n fieldsOrDescription: string | F,\n fields?: F,\n): DBType<F> {\n const typeName = Array.isArray(name) ? name[0] : name;\n const pluralForm = Array.isArray(name) ? name[1] : undefined;\n\n let description: string | undefined;\n let fieldDef: F;\n if (typeof fieldsOrDescription === \"string\") {\n description = fieldsOrDescription;\n fieldDef = fields as F;\n } else {\n fieldDef = fieldsOrDescription;\n }\n return createTailorDBType<{ id: idField } & F>(\n typeName,\n {\n id: idField,\n ...fieldDef,\n },\n { pluralForm, description },\n ) as DBType<F>;\n}\n\n/** TailorDB schema builder utilities for defining types and fields. */\nexport const db = {\n type: dbType,\n uuid,\n string,\n bool,\n int,\n float,\n decimal,\n date,\n datetime,\n time,\n enum: _enum,\n object,\n fields: {\n /**\n * Creates standard timestamp fields (createdAt, updatedAt) with auto-hooks.\n * createdAt is set on create, updatedAt is set on update.\n * @returns An object with createdAt and updatedAt fields\n * @example\n * const model = db.type(\"Model\", {\n * name: db.string(),\n * ...db.fields.timestamps(),\n * });\n */\n timestamps: () => ({\n createdAt: datetime()\n .hooks({ create: () => new Date() })\n .description(\"Record creation timestamp\"),\n updatedAt: datetime({ optional: true })\n .hooks({ update: () => new Date() })\n .description(\"Record last update timestamp\"),\n }),\n },\n};\n","import type { InferredAttributeMap } from \"@/types/user\";\n\n// --- Permission types (UX-focused, for configure layer) ---\n\n/**\n * Record-level permission configuration for a TailorDB type.\n * Defines create, read, update, and delete permissions.\n *\n * Prefer object format with explicit `conditions` and `permit` for readability.\n * Shorthand array format is supported for compatibility, but less readable.\n *\n * For update operations, use `newRecord`/`oldRecord` operands instead of `record`.\n * @example\n * const permission: TailorTypePermission = {\n * create: [{ conditions: [[{ user: \"_loggedIn\" }, \"=\", true]], permit: true }],\n * read: [{ conditions: [[{ record: \"isPublic\" }, \"=\", true]], permit: true }],\n * update: [{ conditions: [[{ newRecord: \"ownerId\" }, \"=\", { user: \"id\" }]], permit: true }],\n * delete: [{ conditions: [[{ record: \"ownerId\" }, \"=\", { user: \"id\" }]], permit: true }],\n * };\n */\nexport type TailorTypePermission<\n User extends object = InferredAttributeMap,\n Type extends object = object,\n> = {\n create: readonly ActionPermission<\"record\", User, Type, false>[];\n read: readonly ActionPermission<\"record\", User, Type, false>[];\n update: readonly ActionPermission<\"record\", User, Type, true>[];\n delete: readonly ActionPermission<\"record\", User, Type, false>[];\n};\n\ntype ActionPermission<\n Level extends \"record\" | \"gql\" = \"record\" | \"gql\",\n User extends object = InferredAttributeMap,\n Type extends object = object,\n Update extends boolean = boolean,\n> =\n | {\n conditions:\n | PermissionCondition<Level, User, Update, Type>\n | readonly PermissionCondition<Level, User, Update, Type>[];\n description?: string | undefined;\n permit?: boolean;\n }\n | readonly [...PermissionCondition<Level, User, Update, Type>, ...([] | [boolean])] // single array condition\n | readonly [...PermissionCondition<Level, User, Update, Type>[], ...([] | [boolean])]; // multiple array condition\n\nexport type TailorTypeGqlPermission<\n User extends object = InferredAttributeMap,\n Type extends object = object,\n> = readonly GqlPermissionPolicy<User, Type>[];\n\ntype GqlPermissionPolicy<\n User extends object = InferredAttributeMap,\n Type extends object = object,\n> = {\n conditions: readonly PermissionCondition<\"gql\", User, boolean, Type>[];\n actions: \"all\" | readonly GqlPermissionAction[];\n permit?: boolean;\n description?: string;\n};\n\ntype GqlPermissionAction = \"read\" | \"create\" | \"update\" | \"delete\" | \"aggregate\" | \"bulkUpsert\";\n\ntype EqualityOperator = \"=\" | \"!=\";\ntype ContainsOperator = \"in\" | \"not in\";\ntype HasAnyOperator = \"hasAny\" | \"not hasAny\";\n\n// Helper types for User field extraction\ntype StringFieldKeys<User extends object> = {\n [K in keyof User]: User[K] extends string ? K : never;\n}[keyof User];\n\ntype StringArrayFieldKeys<User extends object> = {\n [K in keyof User]: User[K] extends string[] ? K : never;\n}[keyof User];\n\ntype BooleanFieldKeys<User extends object> = {\n [K in keyof User]: User[K] extends boolean ? K : never;\n}[keyof User];\n\ntype BooleanArrayFieldKeys<User extends object> = {\n [K in keyof User]: User[K] extends boolean[] ? K : never;\n}[keyof User];\n\ntype UserStringOperand<User extends object = InferredAttributeMap> = {\n user: StringFieldKeys<User> | \"id\";\n};\n\ntype UserStringArrayOperand<User extends object = InferredAttributeMap> = {\n user: StringArrayFieldKeys<User>;\n};\n\ntype UserBooleanOperand<User extends object = InferredAttributeMap> = {\n user: BooleanFieldKeys<User> | \"_loggedIn\";\n};\n\ntype UserBooleanArrayOperand<User extends object = InferredAttributeMap> = {\n user: BooleanArrayFieldKeys<User>;\n};\n\ntype RecordOperand<Type extends object, Update extends boolean = false> = Update extends true\n ? { oldRecord: (keyof Type & string) | \"id\" } | { newRecord: (keyof Type & string) | \"id\" }\n : { record: (keyof Type & string) | \"id\" };\n\ntype StringEqualityCondition<\n Level extends \"record\" | \"gql\",\n User extends object,\n Update extends boolean,\n Type extends object,\n> =\n | (Level extends \"gql\" ? readonly [string, EqualityOperator, boolean] : never)\n | readonly [string, EqualityOperator, string]\n | readonly [UserStringOperand<User>, EqualityOperator, string]\n | readonly [string, EqualityOperator, UserStringOperand<User>]\n | (Level extends \"record\"\n ?\n | readonly [\n RecordOperand<Type, Update>,\n EqualityOperator,\n string | UserStringOperand<User>,\n ]\n | readonly [\n string | UserStringOperand<User>,\n EqualityOperator,\n RecordOperand<Type, Update>,\n ]\n : never);\n\ntype BooleanEqualityCondition<\n Level extends \"record\" | \"gql\",\n User extends object,\n Update extends boolean,\n Type extends object,\n> =\n | readonly [boolean, EqualityOperator, boolean]\n | readonly [UserBooleanOperand<User>, EqualityOperator, boolean]\n | readonly [boolean, EqualityOperator, UserBooleanOperand<User>]\n | (Level extends \"record\"\n ?\n | readonly [\n RecordOperand<Type, Update>,\n EqualityOperator,\n boolean | UserBooleanOperand<User>,\n ]\n | readonly [\n boolean | UserBooleanOperand<User>,\n EqualityOperator,\n RecordOperand<Type, Update>,\n ]\n : never);\n\ntype EqualityCondition<\n Level extends \"record\" | \"gql\" = \"record\",\n User extends object = InferredAttributeMap,\n Update extends boolean = boolean,\n Type extends object = object,\n> =\n | StringEqualityCondition<Level, User, Update, Type>\n | BooleanEqualityCondition<Level, User, Update, Type>;\n\ntype StringContainsCondition<\n Level extends \"record\" | \"gql\",\n User extends object,\n Update extends boolean,\n Type extends object,\n> =\n | readonly [string, ContainsOperator, string[]]\n | readonly [UserStringOperand<User>, ContainsOperator, string[]]\n | readonly [string, ContainsOperator, UserStringArrayOperand<User>]\n | (Level extends \"record\"\n ?\n | readonly [\n RecordOperand<Type, Update>,\n ContainsOperator,\n string[] | UserStringArrayOperand<User>,\n ]\n | readonly [\n string | UserStringOperand<User>,\n ContainsOperator,\n RecordOperand<Type, Update>,\n ]\n : never);\n\ntype BooleanContainsCondition<\n Level extends \"record\" | \"gql\",\n User extends object,\n Update extends boolean,\n Type extends object,\n> =\n | (Level extends \"gql\" ? readonly [string, ContainsOperator, boolean[]] : never)\n | readonly [boolean, ContainsOperator, boolean[]]\n | readonly [UserBooleanOperand<User>, ContainsOperator, boolean[]]\n | readonly [boolean, ContainsOperator, UserBooleanArrayOperand<User>]\n | (Level extends \"record\"\n ?\n | readonly [\n RecordOperand<Type, Update>,\n ContainsOperator,\n boolean[] | UserBooleanArrayOperand<User>,\n ]\n | readonly [\n boolean | UserBooleanOperand<User>,\n ContainsOperator,\n RecordOperand<Type, Update>,\n ]\n : never);\n\ntype ContainsCondition<\n Level extends \"record\" | \"gql\" = \"record\",\n User extends object = InferredAttributeMap,\n Update extends boolean = boolean,\n Type extends object = object,\n> =\n | StringContainsCondition<Level, User, Update, Type>\n | BooleanContainsCondition<Level, User, Update, Type>;\n\ntype HasAnyCondition<\n Level extends \"record\" | \"gql\",\n User extends object,\n Update extends boolean,\n Type extends object,\n> =\n | readonly [\n string[] | UserStringArrayOperand<User>,\n HasAnyOperator,\n string[] | UserStringArrayOperand<User>,\n ]\n | (Level extends \"record\"\n ?\n | readonly [\n RecordOperand<Type, Update>,\n HasAnyOperator,\n string[] | UserStringArrayOperand<User>,\n ]\n | readonly [\n string[] | UserStringArrayOperand<User>,\n HasAnyOperator,\n RecordOperand<Type, Update>,\n ]\n : never);\n\n/**\n * Type representing a permission condition that combines user attributes, record fields, and literal values using comparison operators.\n *\n * The User type is extended by `tailor.d.ts`, which is automatically generated when running `tailor-sdk generate`.\n * Attributes enabled in the config file's `auth.userProfile.attributes` (or\n * `auth.machineUserAttributes` when userProfile is omitted) become available as types.\n * @example\n * ```ts\n * // tailor.config.ts\n * export const auth = defineAuth(\"my-auth\", {\n * userProfile: {\n * type: user,\n * attributes: {\n * isAdmin: true,\n * roles: true,\n * }\n * }\n * });\n * ```\n */\nexport type PermissionCondition<\n Level extends \"record\" | \"gql\" = \"record\",\n User extends object = InferredAttributeMap,\n Update extends boolean = boolean,\n Type extends object = object,\n> =\n | EqualityCondition<Level, User, Update, Type>\n | ContainsCondition<Level, User, Update, Type>\n | HasAnyCondition<Level, User, Update, Type>;\n\n// --- Runtime constants ---\n\n/**\n * Grants full record-level access without any conditions.\n *\n * Unsafe and intended only for local development, prototyping, or tests.\n * Do not use this in production environments, as it effectively disables\n * authorization checks.\n */\nexport const unsafeAllowAllTypePermission: TailorTypePermission = {\n create: [{ conditions: [], permit: true }],\n read: [{ conditions: [], permit: true }],\n update: [{ conditions: [], permit: true }],\n delete: [{ conditions: [], permit: true }],\n};\n\n/**\n * Grants full GraphQL access (all actions) without any conditions.\n *\n * Unsafe and intended only for local development, prototyping, or tests.\n * Do not use this in production environments, as it effectively disables\n * authorization checks.\n */\nexport const unsafeAllowAllGqlPermission: TailorTypeGqlPermission = [\n { conditions: [], actions: \"all\", permit: true },\n];\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tailordb-DjlNUV6u.mjs","names":[],"sources":["../src/configure/services/tailordb/schema.ts","../src/configure/services/tailordb/permission.ts"],"sourcesContent":["import { cloneDeep } from \"es-toolkit\";\nimport {\n type AllowedValues,\n type AllowedValuesOutput,\n mapAllowedValues,\n} from \"@/configure/types/field\";\nimport { brandValue } from \"@/utils/brand\";\nimport type { TailorTypeGqlPermission, TailorTypePermission } from \"./permission\";\nimport type { Hook, Hooks, ExcludeNestedDBFields, TypeFeatures } from \"./types\";\nimport type { FieldOptions, FieldOutput, TailorFieldType, TailorToTs } from \"@/types/field-types\";\nimport type { output, InferFieldsOutput, Prettify } from \"@/types/helpers\";\nimport type { PluginAttachment, PluginConfigs } from \"@/types/plugin\";\nimport type {\n TailorDBField as TailorDBFieldBase,\n TailorDBType as TailorDBTypeBase,\n} from \"@/types/tailor-db-field\";\nimport type { TailorField as TailorFieldMinimal } from \"@/types/tailor-field\";\nimport type {\n DBFieldMetadata,\n DefinedDBFieldMetadata,\n SerialConfig,\n IndexDef,\n TailorDBTypeMetadata,\n RawRelationConfig,\n RelationType,\n} from \"@/types/tailordb\";\nimport type { RawPermissions } from \"@/types/tailordb.generated\";\nimport type { InferredAttributeMap, TailorUser } from \"@/types/user\";\nimport type { FieldValidateInput, ValidateConfig, Validators } from \"@/types/validation\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n// Helper alias: DB fields can be arbitrarily nested, so we intentionally keep this loose.\n// oxlint-disable-next-line no-explicit-any\nexport type TailorAnyDBField = TailorDBField<any, any>;\n\n// Helper alias\n// oxlint-disable-next-line no-explicit-any\nexport type TailorAnyDBType = TailorDBType<any, any>;\n\n/**\n * Full TailorDBField interface with builder methods.\n * Extends the minimal structural interface from types/ with fluent API methods.\n */\nexport interface TailorDBField<\n Defined extends DefinedDBFieldMetadata = DefinedDBFieldMetadata,\n // oxlint-disable-next-line no-explicit-any\n Output = any,\n> extends Omit<TailorDBFieldBase<Defined, Output>, \"fields\"> {\n readonly fields: Record<string, TailorAnyDBField>;\n _metadata: DBFieldMetadata;\n\n /**\n * Parse and validate a value against this field's validation rules\n */\n parse(args: FieldParseArgs): StandardSchemaV1.Result<Output>;\n\n /**\n * Internal parse method that tracks field path for nested validation\n * @private\n */\n _parseInternal(args: FieldParseInternalArgs): StandardSchemaV1.Result<Output>;\n\n /**\n * typeName is not available on TailorDB fields.\n * Use typeName on pipeline fields (t.enum / t.object) instead.\n */\n typeName(this: never, typeName: string): never;\n\n /**\n * Set a description for the field\n */\n description<CurrentDefined extends Defined>(\n this: CurrentDefined extends { description: unknown }\n ? never\n : TailorFieldMinimal<CurrentDefined, Output>,\n description: string,\n ): TailorDBField<Prettify<CurrentDefined & { description: true }>, Output>;\n\n /**\n * Define a relation to another type.\n */\n relation<S extends RelationType, T extends TailorAnyDBType, CurrentDefined extends Defined>(\n this: CurrentDefined extends { relation: unknown }\n ? never\n : TailorDBField<CurrentDefined, Output>,\n config: RelationConfig<S, T>,\n ): TailorDBField<\n S extends \"oneToOne\" | \"1-1\"\n ? Prettify<CurrentDefined & { unique: true; index: true; relation: true }>\n : Prettify<CurrentDefined & { index: true; relation: true }>,\n Output\n >;\n\n /**\n * Define a self-referencing relation\n */\n relation<S extends RelationSelfConfig, CurrentDefined extends Defined>(\n this: CurrentDefined extends { relation: unknown }\n ? never\n : TailorDBField<CurrentDefined, Output>,\n config: S,\n ): TailorDBField<\n S[\"type\"] extends \"oneToOne\" | \"1-1\"\n ? Prettify<CurrentDefined & { unique: true; index: true; relation: true }>\n : Prettify<CurrentDefined & { index: true; relation: true }>,\n Output\n >;\n\n /**\n * Add an index to the field\n */\n index<CurrentDefined extends Defined>(\n this: CurrentDefined extends { index: unknown }\n ? never\n : CurrentDefined extends { array: true }\n ? never\n : TailorDBField<CurrentDefined, Output>,\n ): TailorDBField<Prettify<CurrentDefined & { index: true }>, Output>;\n\n /**\n * Make the field unique (also adds an index)\n */\n unique<CurrentDefined extends Defined>(\n this: CurrentDefined extends { unique: unknown }\n ? never\n : CurrentDefined extends { array: true }\n ? never\n : TailorDBField<CurrentDefined, Output>,\n ): TailorDBField<Prettify<CurrentDefined & { unique: true; index: true }>, Output>;\n\n /**\n * Enable vector search on the field (string type only)\n */\n vector<CurrentDefined extends Defined>(\n this: CurrentDefined extends { vector: unknown }\n ? never\n : CurrentDefined extends { type: \"string\"; array: false }\n ? TailorDBField<CurrentDefined, Output>\n : never,\n ): TailorDBField<Prettify<CurrentDefined & { vector: true }>, Output>;\n\n /**\n * Add hooks for create/update operations on this field.\n */\n hooks<CurrentDefined extends Defined, const H extends Hook<unknown, Output>>(\n this: CurrentDefined extends { hooks: unknown }\n ? never\n : CurrentDefined extends { type: \"nested\" }\n ? never\n : TailorDBField<CurrentDefined, Output>,\n hooks: H,\n ): TailorDBField<\n Prettify<\n CurrentDefined & {\n hooks?: {\n create: H extends { create: unknown } ? true : false;\n update: H extends { update: unknown } ? true : false;\n };\n serial: false;\n }\n >,\n Output\n >;\n\n /**\n * Add validation functions to the field.\n */\n validate<CurrentDefined extends Defined>(\n this: CurrentDefined extends { validate: unknown }\n ? never\n : TailorDBField<CurrentDefined, Output>,\n ...validate: FieldValidateInput<Output>[]\n ): TailorDBField<Prettify<CurrentDefined & { validate: true }>, Output>;\n\n /**\n * Configure serial/auto-increment behavior\n */\n serial<CurrentDefined extends Defined>(\n this: CurrentDefined extends { serial: unknown }\n ? never\n : Output extends null\n ? never\n : CurrentDefined extends { type: \"integer\" | \"string\"; array: false }\n ? TailorDBField<CurrentDefined, Output>\n : never,\n config: SerialConfig<CurrentDefined[\"type\"] & (\"integer\" | \"string\")>,\n ): TailorDBField<\n Prettify<\n CurrentDefined & {\n serial: true;\n hooks: { create: false; update: false };\n }\n >,\n Output\n >;\n\n /**\n * Clone the field with optional overrides for field options\n */\n clone<const NewOpt extends FieldOptions>(\n options?: NewOpt,\n ): TailorDBField<\n Prettify<\n Omit<Defined, \"array\"> & {\n array: NewOpt extends { array: true } ? true : Defined[\"array\"];\n }\n >,\n FieldOutput<TailorToTs[Defined[\"type\"]], NewOpt>\n >;\n}\n\n/**\n * Full TailorDBType interface with builder methods.\n * Extends the minimal structural interface from types/ with fluent API methods.\n */\nexport interface TailorDBType<\n // oxlint-disable-next-line no-explicit-any\n Fields extends Record<string, TailorAnyDBField> = any,\n User extends object = InferredAttributeMap,\n> extends TailorDBTypeBase<Fields, User> {\n _description?: string;\n\n hooks(hooks: Hooks<Fields>): TailorDBType<Fields, User>;\n validate(validators: Validators<Fields>): TailorDBType<Fields, User>;\n features(features: Omit<TypeFeatures, \"pluralForm\">): TailorDBType<Fields, User>;\n indexes(...indexes: IndexDef<TailorDBType<Fields, User>>[]): TailorDBType<Fields, User>;\n files<const F extends string>(\n files: Record<F, string> & Partial<Record<keyof output<TailorDBType<Fields, User>>, never>>,\n ): TailorDBType<Fields, User>;\n permission<\n U extends object = User,\n P extends TailorTypePermission<U, output<TailorDBType<Fields, User>>> = TailorTypePermission<\n U,\n output<TailorDBType<Fields, User>>\n >,\n >(\n permission: P,\n ): TailorDBType<Fields, U>;\n gqlPermission<\n U extends object = User,\n P extends TailorTypeGqlPermission<U> = TailorTypeGqlPermission<U>,\n >(\n permission: P,\n ): TailorDBType<Fields, U>;\n description(description: string): TailorDBType<Fields, User>;\n pickFields<K extends keyof Fields>(keys: K[]): Pick<Fields, K>;\n pickFields<K extends keyof Fields, const Opt extends FieldOptions>(\n keys: K[],\n options: Opt,\n ): {\n [P in K]: Fields[P] extends TailorDBField<infer D, infer _O>\n ? TailorDBField<\n Omit<D, \"array\"> & {\n array: Opt extends { array: true } ? true : D[\"array\"];\n },\n FieldOutput<TailorToTs[D[\"type\"]], Opt>\n >\n : never;\n };\n omitFields<K extends keyof Fields>(keys: K[]): Omit<Fields, K>;\n plugin<P extends keyof PluginConfigs<keyof Fields & string>>(config: {\n [K in P]: PluginConfigs<keyof Fields & string>[K];\n }): TailorDBType<Fields, User>;\n}\n\nexport type TailorDBInstance<\n // oxlint-disable-next-line no-explicit-any\n Fields extends Record<string, TailorAnyDBField> = any,\n User extends object = InferredAttributeMap,\n> = TailorDBType<Fields, User>;\n\ninterface RelationConfig<S extends RelationType, T extends TailorDBType> {\n type: S;\n toward: {\n type: T;\n as?: string;\n key?: keyof T[\"fields\"] & string;\n };\n backward?: string;\n}\n\n// Special config variant for self-referencing relations\ntype RelationSelfConfig = {\n type: RelationType;\n toward: {\n type: \"self\";\n as?: string;\n key?: string;\n };\n backward?: string;\n};\n\nfunction isRelationSelfConfig(\n config: RelationConfig<RelationType, TailorDBType> | RelationSelfConfig,\n): config is RelationSelfConfig {\n return config.toward.type === \"self\";\n}\n\nconst regex = {\n uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n date: /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})$/,\n time: /^(?<hour>\\d{2}):(?<minute>\\d{2})$/,\n datetime:\n /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})T(?<hour>\\d{2}):(?<minute>\\d{2}):(?<second>\\d{2})(.(?<millisec>\\d{3}))?Z$/,\n decimal: /^-?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/,\n} as const;\n\ntype FieldParseArgs = {\n value: unknown;\n data: unknown;\n user: TailorUser;\n};\n\ntype FieldValidateValueArgs<T extends TailorFieldType> = {\n value: TailorToTs[T];\n data: unknown;\n user: TailorUser;\n pathArray: string[];\n};\n\ntype FieldParseInternalArgs = {\n // Runtime input is unknown/untyped; we validate and narrow it inside the parser.\n // oxlint-disable-next-line no-explicit-any\n value: any;\n data: unknown;\n user: TailorUser;\n pathArray: string[];\n};\n\n/**\n * Creates a new TailorDBField instance.\n * @param type - Field type\n * @param options - Field options\n * @param fields - Nested fields for object-like types\n * @param values - Allowed values for enum-like fields\n * @returns A new TailorDBField\n */\nfunction createTailorDBField<\n const T extends TailorFieldType,\n const TOptions extends FieldOptions,\n const OutputBase = TailorToTs[T],\n>(\n type: T,\n options?: TOptions,\n fields?: Record<string, TailorAnyDBField>,\n values?: AllowedValues,\n): TailorDBField<\n { type: T; array: TOptions extends { array: true } ? true : false },\n FieldOutput<OutputBase, TOptions>\n> {\n type FieldType = TailorDBField<\n { type: T; array: TOptions extends { array: true } ? true : false },\n FieldOutput<OutputBase, TOptions>\n >;\n\n const _metadata: DBFieldMetadata = { required: true };\n let _rawRelation: RawRelationConfig | undefined;\n\n if (options) {\n if (options.optional === true) {\n _metadata.required = false;\n }\n if (options.array === true) {\n _metadata.array = true;\n }\n }\n if (values) {\n _metadata.allowedValues = mapAllowedValues(values);\n }\n\n /**\n * Validate a single value (not an array element)\n * Used internally for array element validation\n * @param args - Value, context data, and user\n * @returns Array of validation issues\n */\n function validateValue(args: FieldValidateValueArgs<T>): StandardSchemaV1.Issue[] {\n const { value, data, user, pathArray } = args;\n const issues: StandardSchemaV1.Issue[] = [];\n\n // Type-specific validation\n switch (type) {\n case \"string\":\n if (typeof value !== \"string\") {\n issues.push({\n message: `Expected a string: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"integer\":\n if (typeof value !== \"number\" || !Number.isInteger(value)) {\n issues.push({\n message: `Expected an integer: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"float\":\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n issues.push({\n message: `Expected a number: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n issues.push({\n message: `Expected a boolean: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"uuid\":\n if (typeof value !== \"string\" || !regex.uuid.test(value)) {\n issues.push({\n message: `Expected a valid UUID: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"date\":\n if (typeof value !== \"string\" || !regex.date.test(value)) {\n issues.push({\n message: `Expected to match \"yyyy-MM-dd\" format: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"datetime\":\n if (typeof value !== \"string\" || !regex.datetime.test(value)) {\n issues.push({\n message: `Expected to match ISO format: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"time\":\n if (typeof value !== \"string\" || !regex.time.test(value)) {\n issues.push({\n message: `Expected to match \"HH:mm\" format: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"decimal\":\n if (typeof value !== \"string\" || !regex.decimal.test(value)) {\n issues.push({\n message: `Expected a decimal string: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"enum\":\n if (field._metadata.allowedValues) {\n const allowedValues = field._metadata.allowedValues.map((v) => v.value);\n if (typeof value !== \"string\" || !allowedValues.includes(value)) {\n issues.push({\n message: `Must be one of [${allowedValues.join(\", \")}]: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n }\n break;\n\n case \"nested\":\n // Validate nested object fields\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value) ||\n value instanceof Date\n ) {\n issues.push({\n message: `Expected an object: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n } else if (field.fields && Object.keys(field.fields).length > 0) {\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n const fieldValue = value?.[fieldName];\n const result = nestedField._parseInternal({\n value: fieldValue,\n data,\n user,\n pathArray: pathArray.concat(fieldName),\n });\n if (result.issues) {\n issues.push(...result.issues);\n }\n }\n }\n break;\n }\n\n // Custom validation functions\n const validateFns = field._metadata.validate;\n if (validateFns && validateFns.length > 0) {\n for (const validateInput of validateFns) {\n const { fn, message } =\n typeof validateInput === \"function\"\n ? { fn: validateInput, message: \"Validation failed\" }\n : { fn: validateInput[0], message: validateInput[1] };\n\n if (!fn({ value, data, user })) {\n issues.push({\n message,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n }\n }\n\n return issues;\n }\n\n /**\n * Internal parse method that tracks field path for nested validation\n * @param args - Parse arguments\n * @returns Parse result with value or issues\n */\n function parseInternal(\n args: FieldParseInternalArgs,\n ): StandardSchemaV1.Result<FieldOutput<OutputBase, TOptions>> {\n const { value, data, user, pathArray } = args;\n const issues: StandardSchemaV1.Issue[] = [];\n\n // 1. Check required/optional\n const isNullOrUndefined = value === null || value === undefined;\n if (field._metadata.required && isNullOrUndefined) {\n issues.push({\n message: \"Required field is missing\",\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n return { issues };\n }\n\n // If optional and null/undefined, skip further validation and normalize to null\n if (!field._metadata.required && isNullOrUndefined) {\n return { value: value ?? null };\n }\n\n // 2. Check array type\n if (field._metadata.array) {\n if (!Array.isArray(value)) {\n issues.push({\n message: \"Expected an array\",\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n return { issues };\n }\n\n // Validate each array element (without array flag)\n for (let i = 0; i < value.length; i++) {\n const elementValue = value[i];\n const elementPath = pathArray.concat(`[${i}]`);\n\n // Validate element with same type but without array flag\n const elementIssues = validateValue({\n value: elementValue,\n data,\n user,\n pathArray: elementPath,\n });\n if (elementIssues.length > 0) {\n issues.push(...elementIssues);\n }\n }\n\n if (issues.length > 0) {\n return { issues };\n }\n return { value: value as FieldOutput<OutputBase, TOptions> };\n }\n\n // 3. Type-specific validation and custom validation\n const valueIssues = validateValue({ value, data, user, pathArray });\n issues.push(...valueIssues);\n\n if (issues.length > 0) {\n return { issues };\n }\n\n return { value };\n }\n\n function cloneWith(metadataUpdates: Partial<DBFieldMetadata>) {\n const cloned = field.clone();\n Object.assign(cloned._metadata, metadataUpdates);\n return cloned;\n }\n\n const field: FieldType = {\n type,\n fields: (fields ?? {}) as Record<string, TailorAnyDBField>,\n _defined: undefined as unknown as {\n type: T;\n array: TOptions extends { array: true } ? true : false;\n },\n _output: undefined as FieldOutput<OutputBase, TOptions>,\n _metadata,\n\n get metadata() {\n return { ...this._metadata };\n },\n\n get rawRelation(): Readonly<RawRelationConfig> | undefined {\n return _rawRelation ? { ..._rawRelation, toward: { ..._rawRelation.toward } } : undefined;\n },\n\n description(description: string) {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ description }) as any;\n },\n\n // oxlint-disable-next-line no-explicit-any\n typeName: ((typeName: string) => cloneWith({ typeName })) as any,\n\n validate(...validateInputs: FieldValidateInput<FieldOutput<OutputBase, TOptions>>[]) {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ validate: validateInputs }) as any;\n },\n\n parse(args: FieldParseArgs): StandardSchemaV1.Result<FieldOutput<OutputBase, TOptions>> {\n return parseInternal({\n value: args.value,\n data: args.data,\n user: args.user,\n pathArray: [],\n });\n },\n\n _parseInternal: parseInternal,\n\n // TailorDBField specific methods\n relation(config: RelationConfig<RelationType, TailorDBType> | RelationSelfConfig) {\n const cloned = field.clone();\n const targetType = isRelationSelfConfig(config) ? \"self\" : config.toward.type.name;\n // oxlint-disable-next-line no-explicit-any\n (cloned as any)._setRawRelation({\n type: config.type,\n toward: {\n type: targetType,\n as: config.toward.as,\n key: config.toward.key,\n },\n backward: config.backward,\n });\n // oxlint-disable-next-line no-explicit-any\n return cloned as any;\n },\n\n index() {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ index: true }) as any;\n },\n\n unique() {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ unique: true, index: true }) as any;\n },\n\n vector() {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ vector: true }) as any;\n },\n\n hooks(hooks: Hook<unknown, FieldOutput<OutputBase, TOptions>>) {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ hooks }) as any;\n },\n\n serial(config: SerialConfig) {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ serial: config }) as any;\n },\n\n clone(cloneOptions?: FieldOptions) {\n // Deep clone nested object fields if present\n let clonedFields = fields;\n if (fields) {\n const cloned: Record<string, TailorAnyDBField> = {};\n for (const [key, field] of Object.entries(fields)) {\n cloned[key] = field.clone();\n }\n clonedFields = cloned;\n }\n\n // Create a new field with cloned configuration\n const clonedField = createTailorDBField(type, options, clonedFields, values);\n\n // Deep copy metadata using cloneDeep (preserves function references)\n Object.assign(clonedField._metadata, cloneDeep(this._metadata));\n\n // Apply new options if provided\n if (cloneOptions) {\n if (cloneOptions.optional !== undefined) {\n clonedField._metadata.required = !cloneOptions.optional;\n }\n if (cloneOptions.array !== undefined) {\n clonedField._metadata.array = cloneOptions.array;\n }\n }\n\n // Copy raw relation if exists\n if (_rawRelation) {\n const clonedRawRelation = cloneDeep(_rawRelation);\n // oxlint-disable-next-line no-explicit-any\n (clonedField as any)._setRawRelation(clonedRawRelation);\n }\n\n // oxlint-disable-next-line no-explicit-any\n return clonedField as any;\n },\n\n // Internal method for clone to set rawRelation\n // @ts-ignore - Internal method not in interface\n _setRawRelation(relation: RawRelationConfig) {\n _rawRelation = relation;\n },\n };\n\n return field;\n}\n\nconst createField = createTailorDBField;\n\n/**\n * Create a UUID field.\n * @param options - Field configuration options\n * @returns A UUID field\n * @example db.uuid()\n * @example db.uuid({ optional: true })\n */\nfunction uuid<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"uuid\", options);\n}\n\n/**\n * Create a string field.\n * @param options - Field configuration options\n * @returns A string field\n * @example db.string()\n * @example db.string({ optional: true })\n */\nfunction string<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"string\", options);\n}\n\n/**\n * Create a boolean field.\n * Note: The method name is `bool` but creates a `boolean` type field.\n * @param options - Field configuration options\n * @returns A boolean field\n * @example db.bool()\n * @example db.bool({ optional: true })\n */\nfunction bool<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"boolean\", options);\n}\n\n/**\n * Create an integer field.\n * @param options - Field configuration options\n * @returns An integer field\n * @example db.int()\n * @example db.int({ optional: true })\n */\nfunction int<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"integer\", options);\n}\n\n/**\n * Create a float (decimal number) field.\n * @param options - Field configuration options\n * @returns A float field\n * @example db.float()\n * @example db.float({ optional: true })\n */\nfunction float<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"float\", options);\n}\n\ninterface DecimalFieldOptions extends FieldOptions {\n scale?: number;\n}\n\n/**\n * Create a decimal field (stored as string for precision).\n * @param options - Field configuration options including optional scale (0-12)\n * @returns A decimal field\n * @example db.decimal()\n * @example db.decimal({ scale: 2 })\n * @example db.decimal({ scale: 2, optional: true })\n */\nfunction decimal<const Opt extends DecimalFieldOptions>(options?: Opt) {\n if (options?.scale !== undefined) {\n if (!Number.isInteger(options.scale) || options.scale < 0 || options.scale > 12) {\n throw new Error(\"scale must be an integer between 0 and 12\");\n }\n }\n const field = createField(\"decimal\", options);\n if (options?.scale !== undefined) {\n field._metadata.scale = options.scale;\n }\n return field;\n}\n\n/**\n * Create a date field (date only, no time component).\n * Format: \"yyyy-MM-dd\"\n * @param options - Field configuration options\n * @returns A date field\n * @example db.date()\n */\nfunction date<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"date\", options);\n}\n\n/**\n * Create a datetime field (date and time).\n * Format: ISO 8601 \"yyyy-MM-ddTHH:mm:ssZ\"\n * @param options - Field configuration options\n * @returns A datetime field\n * @example db.datetime()\n */\nfunction datetime<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"datetime\", options);\n}\n\n/**\n * Create a time field (time only, no date component).\n * Format: \"HH:mm\"\n * @param options - Field configuration options\n * @returns A time field\n * @example db.time()\n */\nfunction time<const Opt extends FieldOptions>(options?: Opt) {\n return createField(\"time\", options);\n}\n\n/**\n * Create an enum field with a fixed set of allowed string values.\n * @param values - Array of allowed string values, or array of `{ value, description }` objects\n * @param options - Field configuration options\n * @returns An enum field\n * @example db.enum([\"active\", \"inactive\", \"suspended\"])\n * @example db.enum([\"small\", \"medium\", \"large\"], { optional: true })\n */\nfunction _enum<const V extends AllowedValues, const Opt extends FieldOptions>(\n values: V,\n options?: Opt,\n): TailorDBField<\n { type: \"enum\"; array: Opt extends { array: true } ? true : false },\n FieldOutput<AllowedValuesOutput<V>, Opt>\n> {\n return createField<\"enum\", Opt, AllowedValuesOutput<V>>(\"enum\", options, undefined, values);\n}\n\n/**\n * Create a nested object field with sub-fields.\n * @param fields - Record of nested field definitions\n * @param options - Field configuration options\n * @returns A nested object field\n * @example db.object({ street: db.string(), city: db.string(), zip: db.string() })\n * @example db.object({ name: db.string() }, { optional: true })\n */\nfunction object<\n const F extends Record<string, TailorAnyDBField> & ExcludeNestedDBFields<F>,\n const Opt extends FieldOptions,\n>(fields: F, options?: Opt) {\n return createField(\"nested\", options, fields) as unknown as TailorDBField<\n { type: \"nested\"; array: Opt extends { array: true } ? true : false },\n FieldOutput<InferFieldsOutput<F>, Opt>\n >;\n}\n\n/**\n * Creates a new TailorDBType instance.\n * @param name - Type name\n * @param fields - Field definitions\n * @param options - Type options\n * @param options.pluralForm - Optional plural form\n * @param options.description - Optional description\n * @returns A new TailorDBType\n */\nfunction createTailorDBType<\n // oxlint-disable-next-line no-explicit-any\n const Fields extends Record<string, TailorAnyDBField> = any,\n User extends object = InferredAttributeMap,\n>(\n name: string,\n fields: Fields,\n options: { pluralForm?: string; description?: string },\n): TailorDBType<Fields, User> {\n let _description = options.description;\n let _settings: TypeFeatures = {};\n let _indexes: IndexDef<TailorDBType<Fields, User>>[] = [];\n const _permissions: RawPermissions = {};\n let _files: Record<string, string> = {};\n const _plugins: PluginAttachment[] = [];\n\n if (options.pluralForm) {\n if (name === options.pluralForm) {\n throw new Error(`The name and the plural form must be different. name=${name}`);\n }\n _settings.pluralForm = options.pluralForm;\n }\n\n const dbType: TailorDBType<Fields, User> = {\n name,\n fields: { ...fields },\n _output: null as unknown as InferFieldsOutput<Fields>,\n _description,\n\n get metadata(): TailorDBTypeMetadata {\n // Convert indexes to the format expected by the manifest\n const indexes: Record<string, { fields: string[]; unique?: boolean }> = {};\n if (_indexes && _indexes.length > 0) {\n _indexes.forEach((index) => {\n const fieldNames = index.fields.map((field) => String(field));\n const key = index.name || `idx_${fieldNames.join(\"_\")}`;\n indexes[key] = {\n fields: fieldNames,\n unique: index.unique,\n };\n });\n }\n\n return {\n name: this.name,\n description: _description,\n settings: _settings,\n permissions: _permissions,\n files: _files,\n ...(Object.keys(indexes).length > 0 && { indexes }),\n };\n },\n\n hooks(hooks: Hooks<Fields>) {\n // `Hooks<Fields>` is strongly typed, but `Object.entries()` loses that information.\n // oxlint-disable-next-line no-explicit-any\n Object.entries(hooks).forEach(([fieldName, fieldHooks]: [string, any]) => {\n (this.fields as Record<string, TailorAnyDBField>)[fieldName] =\n this.fields[fieldName].hooks(fieldHooks);\n });\n return this;\n },\n\n validate(validators: Validators<Fields>) {\n Object.entries(validators).forEach(([fieldName, fieldValidators]) => {\n const field = this.fields[fieldName] as TailorAnyDBField;\n\n const validators = fieldValidators as\n | FieldValidateInput<unknown>\n | FieldValidateInput<unknown>[];\n\n const isValidateConfig = (v: unknown): v is ValidateConfig<unknown> => {\n return Array.isArray(v) && v.length === 2 && typeof v[1] === \"string\";\n };\n\n let updatedField: TailorAnyDBField;\n if (Array.isArray(validators)) {\n if (isValidateConfig(validators)) {\n updatedField = field.validate(validators);\n } else {\n updatedField = field.validate(...validators);\n }\n } else {\n updatedField = field.validate(validators);\n }\n (this.fields as Record<string, TailorAnyDBField>)[fieldName] = updatedField;\n });\n return this;\n },\n\n features(features: Omit<TypeFeatures, \"pluralForm\">) {\n _settings = {\n ..._settings,\n ...features,\n };\n return this;\n },\n\n indexes(...indexes: IndexDef<TailorDBType<Fields, User>>[]) {\n _indexes = indexes;\n return this;\n },\n\n files<const F extends string>(\n files: Record<F, string> & Partial<Record<keyof output<TailorDBType<Fields, User>>, never>>,\n ) {\n _files = files;\n return this;\n },\n\n permission<\n U extends object = User,\n P extends TailorTypePermission<U, output<TailorDBType<Fields, User>>> = TailorTypePermission<\n U,\n output<TailorDBType<Fields, User>>\n >,\n >(permission: P) {\n const ret = this as TailorDBType<Fields, U>;\n _permissions.record = permission as RawPermissions[\"record\"];\n return ret;\n },\n\n gqlPermission<\n U extends object = User,\n P extends TailorTypeGqlPermission<U> = TailorTypeGqlPermission<U>,\n >(permission: P) {\n const ret = this as TailorDBType<Fields, U>;\n _permissions.gql = permission as RawPermissions[\"gql\"];\n return ret;\n },\n\n description(description: string) {\n _description = description;\n this._description = description;\n return this;\n },\n\n pickFields<K extends keyof Fields, const Opt extends FieldOptions>(keys: K[], options?: Opt) {\n const result = {} as Record<K, TailorAnyDBField>;\n for (const key of keys) {\n if (options) {\n result[key] = this.fields[key].clone(options);\n } else {\n result[key] = this.fields[key];\n }\n }\n // oxlint-disable-next-line no-explicit-any\n return result as any;\n },\n\n omitFields<K extends keyof Fields>(keys: K[]): Omit<Fields, K> {\n const keysSet = new Set(keys);\n const result = {} as Record<string, TailorAnyDBField>;\n for (const key in this.fields) {\n if (Object.hasOwn(this.fields, key) && !keysSet.has(key as unknown as K)) {\n result[key] = this.fields[key];\n }\n }\n return result as Omit<Fields, K>;\n },\n\n get plugins(): PluginAttachment[] {\n return _plugins;\n },\n\n plugin<P extends keyof PluginConfigs<keyof Fields & string>>(config: {\n [K in P]: PluginConfigs<keyof Fields & string>[K];\n }): TailorDBType<Fields, User> {\n for (const [pluginId, pluginConfig] of Object.entries(config)) {\n _plugins.push({ pluginId, config: pluginConfig });\n }\n return this;\n },\n };\n\n return brandValue(dbType, \"tailordb-type\");\n}\n\nconst idField = uuid();\ntype idField = typeof idField;\ntype DBType<F extends { id?: never } & Record<string, TailorAnyDBField>> = TailorDBInstance<\n { id: idField } & F\n>;\n\n/**\n * Creates a new database type with the specified fields.\n * An `id` field (UUID) is automatically added to every type.\n * @param name - The name of the type, or a tuple of [name, pluralForm]\n * @param fields - The field definitions for the type\n * @returns A new TailorDBType instance\n * @example\n * export const user = db.type(\"User\", {\n * name: db.string(),\n * email: db.string(),\n * age: db.int({ optional: true }),\n * role: db.enum([\"admin\", \"member\"]),\n * ...db.fields.timestamps(),\n * });\n * // Always export both the value and type:\n * export type user = typeof user;\n */\nfunction dbType<const F extends { id?: never } & Record<string, TailorAnyDBField>>(\n name: string | [string, string],\n fields: F,\n): DBType<F>;\n/**\n * Creates a new database type with the specified fields and description.\n * An `id` field (UUID) is automatically added to every type.\n * @param name - The name of the type, or a tuple of [name, pluralForm]\n * @param description - A description of the type\n * @param fields - The field definitions for the type\n * @returns A new TailorDBType instance\n */\nfunction dbType<const F extends { id?: never } & Record<string, TailorAnyDBField>>(\n name: string | [string, string],\n description: string,\n fields: F,\n): DBType<F>;\nfunction dbType<const F extends { id?: never } & Record<string, TailorAnyDBField>>(\n name: string | [string, string],\n fieldsOrDescription: string | F,\n fields?: F,\n): DBType<F> {\n const typeName = Array.isArray(name) ? name[0] : name;\n const pluralForm = Array.isArray(name) ? name[1] : undefined;\n\n let description: string | undefined;\n let fieldDef: F;\n if (typeof fieldsOrDescription === \"string\") {\n description = fieldsOrDescription;\n fieldDef = fields as F;\n } else {\n fieldDef = fieldsOrDescription;\n }\n return createTailorDBType<{ id: idField } & F>(\n typeName,\n {\n id: idField,\n ...fieldDef,\n },\n { pluralForm, description },\n ) as DBType<F>;\n}\n\n/** TailorDB schema builder utilities for defining types and fields. */\nexport const db = {\n type: dbType,\n uuid,\n string,\n bool,\n int,\n float,\n decimal,\n date,\n datetime,\n time,\n enum: _enum,\n object,\n fields: {\n /**\n * Creates standard timestamp fields (createdAt, updatedAt) with auto-hooks.\n * createdAt is set on create, updatedAt is set on update.\n * @returns An object with createdAt and updatedAt fields\n * @example\n * const model = db.type(\"Model\", {\n * name: db.string(),\n * ...db.fields.timestamps(),\n * });\n */\n timestamps: () => ({\n createdAt: datetime()\n .hooks({ create: () => new Date() })\n .description(\"Record creation timestamp\"),\n updatedAt: datetime({ optional: true })\n .hooks({ update: () => new Date() })\n .description(\"Record last update timestamp\"),\n }),\n },\n};\n","import type { InferredAttributeMap } from \"@/types/user\";\n\n// --- Permission types (UX-focused, for configure layer) ---\n\n/**\n * Record-level permission configuration for a TailorDB type.\n * Defines create, read, update, and delete permissions.\n *\n * Prefer object format with explicit `conditions` and `permit` for readability.\n * Shorthand array format is supported for compatibility, but less readable.\n *\n * For update operations, use `newRecord`/`oldRecord` operands instead of `record`.\n * @example\n * const permission: TailorTypePermission = {\n * create: [{ conditions: [[{ user: \"_loggedIn\" }, \"=\", true]], permit: true }],\n * read: [{ conditions: [[{ record: \"isPublic\" }, \"=\", true]], permit: true }],\n * update: [{ conditions: [[{ newRecord: \"ownerId\" }, \"=\", { user: \"id\" }]], permit: true }],\n * delete: [{ conditions: [[{ record: \"ownerId\" }, \"=\", { user: \"id\" }]], permit: true }],\n * };\n */\nexport type TailorTypePermission<\n User extends object = InferredAttributeMap,\n Type extends object = object,\n> = {\n create: readonly ActionPermission<\"record\", User, Type, false>[];\n read: readonly ActionPermission<\"record\", User, Type, false>[];\n update: readonly ActionPermission<\"record\", User, Type, true>[];\n delete: readonly ActionPermission<\"record\", User, Type, false>[];\n};\n\ntype ActionPermission<\n Level extends \"record\" | \"gql\" = \"record\" | \"gql\",\n User extends object = InferredAttributeMap,\n Type extends object = object,\n Update extends boolean = boolean,\n> =\n | {\n conditions:\n | PermissionCondition<Level, User, Update, Type>\n | readonly PermissionCondition<Level, User, Update, Type>[];\n description?: string | undefined;\n permit?: boolean;\n }\n | readonly [...PermissionCondition<Level, User, Update, Type>, ...([] | [boolean])] // single array condition\n | readonly [...PermissionCondition<Level, User, Update, Type>[], ...([] | [boolean])]; // multiple array condition\n\nexport type TailorTypeGqlPermission<\n User extends object = InferredAttributeMap,\n Type extends object = object,\n> = readonly GqlPermissionPolicy<User, Type>[];\n\ntype GqlPermissionPolicy<\n User extends object = InferredAttributeMap,\n Type extends object = object,\n> = {\n conditions: readonly PermissionCondition<\"gql\", User, boolean, Type>[];\n actions: \"all\" | readonly GqlPermissionAction[];\n permit?: boolean;\n description?: string;\n};\n\ntype GqlPermissionAction = \"read\" | \"create\" | \"update\" | \"delete\" | \"aggregate\" | \"bulkUpsert\";\n\ntype EqualityOperator = \"=\" | \"!=\";\ntype ContainsOperator = \"in\" | \"not in\";\ntype HasAnyOperator = \"hasAny\" | \"not hasAny\";\n\n// Helper types for User field extraction\ntype StringFieldKeys<User extends object> = {\n [K in keyof User]: User[K] extends string ? K : never;\n}[keyof User];\n\ntype StringArrayFieldKeys<User extends object> = {\n [K in keyof User]: User[K] extends string[] ? K : never;\n}[keyof User];\n\ntype BooleanFieldKeys<User extends object> = {\n [K in keyof User]: User[K] extends boolean ? K : never;\n}[keyof User];\n\ntype BooleanArrayFieldKeys<User extends object> = {\n [K in keyof User]: User[K] extends boolean[] ? K : never;\n}[keyof User];\n\ntype UserStringOperand<User extends object = InferredAttributeMap> = {\n user: StringFieldKeys<User> | \"id\";\n};\n\ntype UserStringArrayOperand<User extends object = InferredAttributeMap> = {\n user: StringArrayFieldKeys<User>;\n};\n\ntype UserBooleanOperand<User extends object = InferredAttributeMap> = {\n user: BooleanFieldKeys<User> | \"_loggedIn\";\n};\n\ntype UserBooleanArrayOperand<User extends object = InferredAttributeMap> = {\n user: BooleanArrayFieldKeys<User>;\n};\n\ntype RecordOperand<Type extends object, Update extends boolean = false> = Update extends true\n ? { oldRecord: (keyof Type & string) | \"id\" } | { newRecord: (keyof Type & string) | \"id\" }\n : { record: (keyof Type & string) | \"id\" };\n\ntype StringEqualityCondition<\n Level extends \"record\" | \"gql\",\n User extends object,\n Update extends boolean,\n Type extends object,\n> =\n | (Level extends \"gql\" ? readonly [string, EqualityOperator, boolean] : never)\n | readonly [string, EqualityOperator, string]\n | readonly [UserStringOperand<User>, EqualityOperator, string]\n | readonly [string, EqualityOperator, UserStringOperand<User>]\n | (Level extends \"record\"\n ?\n | readonly [\n RecordOperand<Type, Update>,\n EqualityOperator,\n string | UserStringOperand<User>,\n ]\n | readonly [\n string | UserStringOperand<User>,\n EqualityOperator,\n RecordOperand<Type, Update>,\n ]\n : never);\n\ntype BooleanEqualityCondition<\n Level extends \"record\" | \"gql\",\n User extends object,\n Update extends boolean,\n Type extends object,\n> =\n | readonly [boolean, EqualityOperator, boolean]\n | readonly [UserBooleanOperand<User>, EqualityOperator, boolean]\n | readonly [boolean, EqualityOperator, UserBooleanOperand<User>]\n | (Level extends \"record\"\n ?\n | readonly [\n RecordOperand<Type, Update>,\n EqualityOperator,\n boolean | UserBooleanOperand<User>,\n ]\n | readonly [\n boolean | UserBooleanOperand<User>,\n EqualityOperator,\n RecordOperand<Type, Update>,\n ]\n : never);\n\ntype EqualityCondition<\n Level extends \"record\" | \"gql\" = \"record\",\n User extends object = InferredAttributeMap,\n Update extends boolean = boolean,\n Type extends object = object,\n> =\n | StringEqualityCondition<Level, User, Update, Type>\n | BooleanEqualityCondition<Level, User, Update, Type>;\n\ntype StringContainsCondition<\n Level extends \"record\" | \"gql\",\n User extends object,\n Update extends boolean,\n Type extends object,\n> =\n | readonly [string, ContainsOperator, string[]]\n | readonly [UserStringOperand<User>, ContainsOperator, string[]]\n | readonly [string, ContainsOperator, UserStringArrayOperand<User>]\n | (Level extends \"record\"\n ?\n | readonly [\n RecordOperand<Type, Update>,\n ContainsOperator,\n string[] | UserStringArrayOperand<User>,\n ]\n | readonly [\n string | UserStringOperand<User>,\n ContainsOperator,\n RecordOperand<Type, Update>,\n ]\n : never);\n\ntype BooleanContainsCondition<\n Level extends \"record\" | \"gql\",\n User extends object,\n Update extends boolean,\n Type extends object,\n> =\n | (Level extends \"gql\" ? readonly [string, ContainsOperator, boolean[]] : never)\n | readonly [boolean, ContainsOperator, boolean[]]\n | readonly [UserBooleanOperand<User>, ContainsOperator, boolean[]]\n | readonly [boolean, ContainsOperator, UserBooleanArrayOperand<User>]\n | (Level extends \"record\"\n ?\n | readonly [\n RecordOperand<Type, Update>,\n ContainsOperator,\n boolean[] | UserBooleanArrayOperand<User>,\n ]\n | readonly [\n boolean | UserBooleanOperand<User>,\n ContainsOperator,\n RecordOperand<Type, Update>,\n ]\n : never);\n\ntype ContainsCondition<\n Level extends \"record\" | \"gql\" = \"record\",\n User extends object = InferredAttributeMap,\n Update extends boolean = boolean,\n Type extends object = object,\n> =\n | StringContainsCondition<Level, User, Update, Type>\n | BooleanContainsCondition<Level, User, Update, Type>;\n\ntype HasAnyCondition<\n Level extends \"record\" | \"gql\",\n User extends object,\n Update extends boolean,\n Type extends object,\n> =\n | readonly [\n string[] | UserStringArrayOperand<User>,\n HasAnyOperator,\n string[] | UserStringArrayOperand<User>,\n ]\n | (Level extends \"record\"\n ?\n | readonly [\n RecordOperand<Type, Update>,\n HasAnyOperator,\n string[] | UserStringArrayOperand<User>,\n ]\n | readonly [\n string[] | UserStringArrayOperand<User>,\n HasAnyOperator,\n RecordOperand<Type, Update>,\n ]\n : never);\n\n/**\n * Type representing a permission condition that combines user attributes, record fields, and literal values using comparison operators.\n *\n * The User type is extended by `tailor.d.ts`, which is automatically generated when running `tailor-sdk generate`.\n * Attributes enabled in the config file's `auth.userProfile.attributes` (or\n * `auth.machineUserAttributes` when userProfile is omitted) become available as types.\n * @example\n * ```ts\n * // tailor.config.ts\n * export const auth = defineAuth(\"my-auth\", {\n * userProfile: {\n * type: user,\n * attributes: {\n * isAdmin: true,\n * roles: true,\n * }\n * }\n * });\n * ```\n */\nexport type PermissionCondition<\n Level extends \"record\" | \"gql\" = \"record\",\n User extends object = InferredAttributeMap,\n Update extends boolean = boolean,\n Type extends object = object,\n> =\n | EqualityCondition<Level, User, Update, Type>\n | ContainsCondition<Level, User, Update, Type>\n | HasAnyCondition<Level, User, Update, Type>;\n\n// --- Runtime constants ---\n\n/**\n * Grants full record-level access without any conditions.\n *\n * Unsafe and intended only for local development, prototyping, or tests.\n * Do not use this in production environments, as it effectively disables\n * authorization checks.\n */\nexport const unsafeAllowAllTypePermission: TailorTypePermission = {\n create: [{ conditions: [], permit: true }],\n read: [{ conditions: [], permit: true }],\n update: [{ conditions: [], permit: true }],\n delete: [{ conditions: [], permit: true }],\n};\n\n/**\n * Grants full GraphQL access (all actions) without any conditions.\n *\n * Unsafe and intended only for local development, prototyping, or tests.\n * Do not use this in production environments, as it effectively disables\n * authorization checks.\n */\nexport const unsafeAllowAllGqlPermission: TailorTypeGqlPermission = [\n { conditions: [], actions: \"all\", permit: true },\n];\n"],"mappings":";;;;;;AAoSA,SAAS,qBACP,QAC8B;CAC9B,OAAO,OAAO,OAAO,SAAS;;AAGhC,MAAM,QAAQ;CACZ,MAAM;CACN,MAAM;CACN,MAAM;CACN,UACE;CACF,SAAS;CACV;;;;;;;;;AAgCD,SAAS,oBAKP,MACA,SACA,QACA,QAIA;CAMA,MAAM,YAA6B,EAAE,UAAU,MAAM;CACrD,IAAI;CAEJ,IAAI,SAAS;EACX,IAAI,QAAQ,aAAa,MACvB,UAAU,WAAW;EAEvB,IAAI,QAAQ,UAAU,MACpB,UAAU,QAAQ;;CAGtB,IAAI,QACF,UAAU,gBAAgB,iBAAiB,OAAO;;;;;;;CASpD,SAAS,cAAc,MAA2D;EAChF,MAAM,EAAE,OAAO,MAAM,MAAM,cAAc;EACzC,MAAM,SAAmC,EAAE;EAG3C,QAAQ,MAAR;GACE,KAAK;IACH,IAAI,OAAO,UAAU,UACnB,OAAO,KAAK;KACV,SAAS,+BAA+B,OAAO,MAAM;KACrD,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GAEF,KAAK;IACH,IAAI,OAAO,UAAU,YAAY,CAAC,OAAO,UAAU,MAAM,EACvD,OAAO,KAAK;KACV,SAAS,iCAAiC,OAAO,MAAM;KACvD,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GAEF,KAAK;IACH,IAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,MAAM,EACtD,OAAO,KAAK;KACV,SAAS,+BAA+B,OAAO,MAAM;KACrD,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GAEF,KAAK;IACH,IAAI,OAAO,UAAU,WACnB,OAAO,KAAK;KACV,SAAS,gCAAgC,OAAO,MAAM;KACtD,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GAEF,KAAK;IACH,IAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,KAAK,MAAM,EACtD,OAAO,KAAK;KACV,SAAS,mCAAmC,OAAO,MAAM;KACzD,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GACF,KAAK;IACH,IAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,KAAK,MAAM,EACtD,OAAO,KAAK;KACV,SAAS,mDAAmD,OAAO,MAAM;KACzE,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GACF,KAAK;IACH,IAAI,OAAO,UAAU,YAAY,CAAC,MAAM,SAAS,KAAK,MAAM,EAC1D,OAAO,KAAK;KACV,SAAS,0CAA0C,OAAO,MAAM;KAChE,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GACF,KAAK;IACH,IAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,KAAK,MAAM,EACtD,OAAO,KAAK;KACV,SAAS,8CAA8C,OAAO,MAAM;KACpE,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GACF,KAAK;IACH,IAAI,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,MAAM,EACzD,OAAO,KAAK;KACV,SAAS,uCAAuC,OAAO,MAAM;KAC7D,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GAEF,KAAK;IACH,IAAI,MAAM,UAAU,eAAe;KACjC,MAAM,gBAAgB,MAAM,UAAU,cAAc,KAAK,MAAM,EAAE,MAAM;KACvE,IAAI,OAAO,UAAU,YAAY,CAAC,cAAc,SAAS,MAAM,EAC7D,OAAO,KAAK;MACV,SAAS,mBAAmB,cAAc,KAAK,KAAK,CAAC,cAAc,OAAO,MAAM;MAChF,MAAM,UAAU,SAAS,IAAI,YAAY;MAC1C,CAAC;;IAGN;GAEF,KAAK;IAEH,IACE,OAAO,UAAU,YACjB,UAAU,QACV,MAAM,QAAQ,MAAM,IACpB,iBAAiB,MAEjB,OAAO,KAAK;KACV,SAAS,gCAAgC,OAAO,MAAM;KACtD,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;SACG,IAAI,MAAM,UAAU,OAAO,KAAK,MAAM,OAAO,CAAC,SAAS,GAC5D,KAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,MAAM,OAAO,EAAE;KACnE,MAAM,aAAa,QAAQ;KAC3B,MAAM,SAAS,YAAY,eAAe;MACxC,OAAO;MACP;MACA;MACA,WAAW,UAAU,OAAO,UAAU;MACvC,CAAC;KACF,IAAI,OAAO,QACT,OAAO,KAAK,GAAG,OAAO,OAAO;;IAInC;;EAIJ,MAAM,cAAc,MAAM,UAAU;EACpC,IAAI,eAAe,YAAY,SAAS,GACtC,KAAK,MAAM,iBAAiB,aAAa;GACvC,MAAM,EAAE,IAAI,YACV,OAAO,kBAAkB,aACrB;IAAE,IAAI;IAAe,SAAS;IAAqB,GACnD;IAAE,IAAI,cAAc;IAAI,SAAS,cAAc;IAAI;GAEzD,IAAI,CAAC,GAAG;IAAE;IAAO;IAAM;IAAM,CAAC,EAC5B,OAAO,KAAK;IACV;IACA,MAAM,UAAU,SAAS,IAAI,YAAY;IAC1C,CAAC;;EAKR,OAAO;;;;;;;CAQT,SAAS,cACP,MAC4D;EAC5D,MAAM,EAAE,OAAO,MAAM,MAAM,cAAc;EACzC,MAAM,SAAmC,EAAE;EAG3C,MAAM,oBAAoB,UAAU,QAAQ,UAAU;EACtD,IAAI,MAAM,UAAU,YAAY,mBAAmB;GACjD,OAAO,KAAK;IACV,SAAS;IACT,MAAM,UAAU,SAAS,IAAI,YAAY;IAC1C,CAAC;GACF,OAAO,EAAE,QAAQ;;EAInB,IAAI,CAAC,MAAM,UAAU,YAAY,mBAC/B,OAAO,EAAE,OAAO,SAAS,MAAM;EAIjC,IAAI,MAAM,UAAU,OAAO;GACzB,IAAI,CAAC,MAAM,QAAQ,MAAM,EAAE;IACzB,OAAO,KAAK;KACV,SAAS;KACT,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IACF,OAAO,EAAE,QAAQ;;GAInB,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;IACrC,MAAM,eAAe,MAAM;IAI3B,MAAM,gBAAgB,cAAc;KAClC,OAAO;KACP;KACA;KACA,WAPkB,UAAU,OAAO,IAAI,EAAE,GAOnB;KACvB,CAAC;IACF,IAAI,cAAc,SAAS,GACzB,OAAO,KAAK,GAAG,cAAc;;GAIjC,IAAI,OAAO,SAAS,GAClB,OAAO,EAAE,QAAQ;GAEnB,OAAO,EAAS,OAA4C;;EAI9D,MAAM,cAAc,cAAc;GAAE;GAAO;GAAM;GAAM;GAAW,CAAC;EACnE,OAAO,KAAK,GAAG,YAAY;EAE3B,IAAI,OAAO,SAAS,GAClB,OAAO,EAAE,QAAQ;EAGnB,OAAO,EAAE,OAAO;;CAGlB,SAAS,UAAU,iBAA2C;EAC5D,MAAM,SAAS,MAAM,OAAO;EAC5B,OAAO,OAAO,OAAO,WAAW,gBAAgB;EAChD,OAAO;;CAGT,MAAM,QAAmB;EACvB;EACA,QAAS,UAAU,EAAE;EACrB,UAAU;EAIV,SAAS;EACT;EAEA,IAAI,WAAW;GACb,OAAO,EAAE,GAAG,KAAK,WAAW;;EAG9B,IAAI,cAAuD;GACzD,OAAO,eAAe;IAAE,GAAG;IAAc,QAAQ,EAAE,GAAG,aAAa,QAAQ;IAAE,GAAG;;EAGlF,YAAY,aAAqB;GAE/B,OAAO,UAAU,EAAE,aAAa,CAAC;;EAInC,YAAY,aAAqB,UAAU,EAAE,UAAU,CAAC;EAExD,SAAS,GAAG,gBAAyE;GAEnF,OAAO,UAAU,EAAE,UAAU,gBAAgB,CAAC;;EAGhD,MAAM,MAAkF;GACtF,OAAO,cAAc;IACnB,OAAO,KAAK;IACZ,MAAM,KAAK;IACX,MAAM,KAAK;IACX,WAAW,EAAE;IACd,CAAC;;EAGJ,gBAAgB;EAGhB,SAAS,QAAyE;GAChF,MAAM,SAAS,MAAM,OAAO;GAC5B,MAAM,aAAa,qBAAqB,OAAO,GAAG,SAAS,OAAO,OAAO,KAAK;GAE9E,AAAC,OAAe,gBAAgB;IAC9B,MAAM,OAAO;IACb,QAAQ;KACN,MAAM;KACN,IAAI,OAAO,OAAO;KAClB,KAAK,OAAO,OAAO;KACpB;IACD,UAAU,OAAO;IAClB,CAAC;GAEF,OAAO;;EAGT,QAAQ;GAEN,OAAO,UAAU,EAAE,OAAO,MAAM,CAAC;;EAGnC,SAAS;GAEP,OAAO,UAAU;IAAE,QAAQ;IAAM,OAAO;IAAM,CAAC;;EAGjD,SAAS;GAEP,OAAO,UAAU,EAAE,QAAQ,MAAM,CAAC;;EAGpC,MAAM,OAAyD;GAE7D,OAAO,UAAU,EAAE,OAAO,CAAC;;EAG7B,OAAO,QAAsB;GAE3B,OAAO,UAAU,EAAE,QAAQ,QAAQ,CAAC;;EAGtC,MAAM,cAA6B;GAEjC,IAAI,eAAe;GACnB,IAAI,QAAQ;IACV,MAAM,SAA2C,EAAE;IACnD,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,OAAO,EAC/C,OAAO,OAAO,MAAM,OAAO;IAE7B,eAAe;;GAIjB,MAAM,cAAc,oBAAoB,MAAM,SAAS,cAAc,OAAO;GAG5E,OAAO,OAAO,YAAY,WAAW,UAAU,KAAK,UAAU,CAAC;GAG/D,IAAI,cAAc;IAChB,IAAI,aAAa,aAAa,QAC5B,YAAY,UAAU,WAAW,CAAC,aAAa;IAEjD,IAAI,aAAa,UAAU,QACzB,YAAY,UAAU,QAAQ,aAAa;;GAK/C,IAAI,cAAc;IAChB,MAAM,oBAAoB,UAAU,aAAa;IAEjD,AAAC,YAAoB,gBAAgB,kBAAkB;;GAIzD,OAAO;;EAKT,gBAAgB,UAA6B;GAC3C,eAAe;;EAElB;CAED,OAAO;;AAGT,MAAM,cAAc;;;;;;;;AASpB,SAAS,KAAqC,SAAe;CAC3D,OAAO,YAAY,QAAQ,QAAQ;;;;;;;;;AAUrC,SAAS,OAAuC,SAAe;CAC7D,OAAO,YAAY,UAAU,QAAQ;;;;;;;;;;AAWvC,SAAS,KAAqC,SAAe;CAC3D,OAAO,YAAY,WAAW,QAAQ;;;;;;;;;AAUxC,SAAS,IAAoC,SAAe;CAC1D,OAAO,YAAY,WAAW,QAAQ;;;;;;;;;AAUxC,SAAS,MAAsC,SAAe;CAC5D,OAAO,YAAY,SAAS,QAAQ;;;;;;;;;;AAetC,SAAS,QAA+C,SAAe;CACrE,IAAI,SAAS,UAAU,QACrB;MAAI,CAAC,OAAO,UAAU,QAAQ,MAAM,IAAI,QAAQ,QAAQ,KAAK,QAAQ,QAAQ,IAC3E,MAAM,IAAI,MAAM,4CAA4C;;CAGhE,MAAM,QAAQ,YAAY,WAAW,QAAQ;CAC7C,IAAI,SAAS,UAAU,QACrB,MAAM,UAAU,QAAQ,QAAQ;CAElC,OAAO;;;;;;;;;AAUT,SAAS,KAAqC,SAAe;CAC3D,OAAO,YAAY,QAAQ,QAAQ;;;;;;;;;AAUrC,SAAS,SAAyC,SAAe;CAC/D,OAAO,YAAY,YAAY,QAAQ;;;;;;;;;AAUzC,SAAS,KAAqC,SAAe;CAC3D,OAAO,YAAY,QAAQ,QAAQ;;;;;;;;;;AAWrC,SAAS,MACP,QACA,SAIA;CACA,OAAO,YAAiD,QAAQ,SAAS,QAAW,OAAO;;;;;;;;;;AAW7F,SAAS,OAGP,QAAW,SAAe;CAC1B,OAAO,YAAY,UAAU,SAAS,OAAO;;;;;;;;;;;AAe/C,SAAS,mBAKP,MACA,QACA,SAC4B;CAC5B,IAAI,eAAe,QAAQ;CAC3B,IAAI,YAA0B,EAAE;CAChC,IAAI,WAAmD,EAAE;CACzD,MAAM,eAA+B,EAAE;CACvC,IAAI,SAAiC,EAAE;CACvC,MAAM,WAA+B,EAAE;CAEvC,IAAI,QAAQ,YAAY;EACtB,IAAI,SAAS,QAAQ,YACnB,MAAM,IAAI,MAAM,wDAAwD,OAAO;EAEjF,UAAU,aAAa,QAAQ;;CA2JjC,OAAO,WAAW;EAvJhB;EACA,QAAQ,EAAE,GAAG,QAAQ;EACrB,SAAS;EACT;EAEA,IAAI,WAAiC;GAEnC,MAAM,UAAkE,EAAE;GAC1E,IAAI,YAAY,SAAS,SAAS,GAChC,SAAS,SAAS,UAAU;IAC1B,MAAM,aAAa,MAAM,OAAO,KAAK,UAAU,OAAO,MAAM,CAAC;IAC7D,MAAM,MAAM,MAAM,QAAQ,OAAO,WAAW,KAAK,IAAI;IACrD,QAAQ,OAAO;KACb,QAAQ;KACR,QAAQ,MAAM;KACf;KACD;GAGJ,OAAO;IACL,MAAM,KAAK;IACX,aAAa;IACb,UAAU;IACV,aAAa;IACb,OAAO;IACP,GAAI,OAAO,KAAK,QAAQ,CAAC,SAAS,KAAK,EAAE,SAAS;IACnD;;EAGH,MAAM,OAAsB;GAG1B,OAAO,QAAQ,MAAM,CAAC,SAAS,CAAC,WAAW,gBAA+B;IACxE,AAAC,KAAK,OAA4C,aAChD,KAAK,OAAO,WAAW,MAAM,WAAW;KAC1C;GACF,OAAO;;EAGT,SAAS,YAAgC;GACvC,OAAO,QAAQ,WAAW,CAAC,SAAS,CAAC,WAAW,qBAAqB;IACnE,MAAM,QAAQ,KAAK,OAAO;IAE1B,MAAM,aAAa;IAInB,MAAM,oBAAoB,MAA6C;KACrE,OAAO,MAAM,QAAQ,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,EAAE,OAAO;;IAG/D,IAAI;IACJ,IAAI,MAAM,QAAQ,WAAW,EAC3B,IAAI,iBAAiB,WAAW,EAC9B,eAAe,MAAM,SAAS,WAAW;SAEzC,eAAe,MAAM,SAAS,GAAG,WAAW;SAG9C,eAAe,MAAM,SAAS,WAAW;IAE3C,AAAC,KAAK,OAA4C,aAAa;KAC/D;GACF,OAAO;;EAGT,SAAS,UAA4C;GACnD,YAAY;IACV,GAAG;IACH,GAAG;IACJ;GACD,OAAO;;EAGT,QAAQ,GAAG,SAAiD;GAC1D,WAAW;GACX,OAAO;;EAGT,MACE,OACA;GACA,SAAS;GACT,OAAO;;EAGT,WAME,YAAe;GACf,MAAM,MAAM;GACZ,aAAa,SAAS;GACtB,OAAO;;EAGT,cAGE,YAAe;GACf,MAAM,MAAM;GACZ,aAAa,MAAM;GACnB,OAAO;;EAGT,YAAY,aAAqB;GAC/B,eAAe;GACf,KAAK,eAAe;GACpB,OAAO;;EAGT,WAAmE,MAAW,SAAe;GAC3F,MAAM,SAAS,EAAE;GACjB,KAAK,MAAM,OAAO,MAChB,IAAI,SACF,OAAO,OAAO,KAAK,OAAO,KAAK,MAAM,QAAQ;QAE7C,OAAO,OAAO,KAAK,OAAO;GAI9B,OAAO;;EAGT,WAAmC,MAA4B;GAC7D,MAAM,UAAU,IAAI,IAAI,KAAK;GAC7B,MAAM,SAAS,EAAE;GACjB,KAAK,MAAM,OAAO,KAAK,QACrB,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAoB,EACtE,OAAO,OAAO,KAAK,OAAO;GAG9B,OAAO;;EAGT,IAAI,UAA8B;GAChC,OAAO;;EAGT,OAA6D,QAE9B;GAC7B,KAAK,MAAM,CAAC,UAAU,iBAAiB,OAAO,QAAQ,OAAO,EAC3D,SAAS,KAAK;IAAE;IAAU,QAAQ;IAAc,CAAC;GAEnD,OAAO;;EAIa,EAAE,gBAAgB;;AAG5C,MAAM,UAAU,MAAM;AAwCtB,SAAS,OACP,MACA,qBACA,QACW;CACX,MAAM,WAAW,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK;CACjD,MAAM,aAAa,MAAM,QAAQ,KAAK,GAAG,KAAK,KAAK;CAEnD,IAAI;CACJ,IAAI;CACJ,IAAI,OAAO,wBAAwB,UAAU;EAC3C,cAAc;EACd,WAAW;QAEX,WAAW;CAEb,OAAO,mBACL,UACA;EACE,IAAI;EACJ,GAAG;EACJ,EACD;EAAE;EAAY;EAAa,CAC5B;;;AAIH,MAAa,KAAK;CAChB,MAAM;CACN;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,MAAM;CACN;CACA,QAAQ;;;;;;;;;;;AAWN,mBAAmB;EACjB,WAAW,UAAU,CAClB,MAAM,EAAE,8BAAc,IAAI,MAAM,EAAE,CAAC,CACnC,YAAY,4BAA4B;EAC3C,WAAW,SAAS,EAAE,UAAU,MAAM,CAAC,CACpC,MAAM,EAAE,8BAAc,IAAI,MAAM,EAAE,CAAC,CACnC,YAAY,+BAA+B;EAC/C,GACF;CACF;;;;;;;;;;;ACz3BD,MAAa,+BAAqD;CAChE,QAAQ,CAAC;EAAE,YAAY,EAAE;EAAE,QAAQ;EAAM,CAAC;CAC1C,MAAM,CAAC;EAAE,YAAY,EAAE;EAAE,QAAQ;EAAM,CAAC;CACxC,QAAQ,CAAC;EAAE,YAAY,EAAE;EAAE,QAAQ;EAAM,CAAC;CAC1C,QAAQ,CAAC;EAAE,YAAY,EAAE;EAAE,QAAQ;EAAM,CAAC;CAC3C;;;;;;;;AASD,MAAa,8BAAuD,CAClE;CAAE,YAAY,EAAE;CAAE,SAAS;CAAO,QAAQ;CAAM,CACjD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"telemetry-DcL8Fsm_.mjs","names":[],"sources":["../src/cli/telemetry/config.ts","../src/cli/telemetry/index.ts"],"sourcesContent":["/**\n * Telemetry configuration parsed from standard OpenTelemetry environment variables.\n * Tracing is enabled when OTEL_EXPORTER_OTLP_ENDPOINT is set.\n */\nexport interface TelemetryConfig {\n readonly enabled: boolean;\n readonly endpoint: string;\n}\n\n/**\n * Parse telemetry configuration from standard OpenTelemetry environment variables.\n * Tracing is enabled when OTEL_EXPORTER_OTLP_ENDPOINT is set.\n * @returns Telemetry configuration\n */\nexport function parseTelemetryConfig(): TelemetryConfig {\n const endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? \"\";\n const enabled = endpoint.length > 0;\n\n return {\n enabled,\n endpoint,\n };\n}\n","import { trace, SpanStatusCode, type Span } from \"@opentelemetry/api\";\nimport { parseTelemetryConfig, type TelemetryConfig } from \"./config\";\n\nlet _config: TelemetryConfig | undefined;\nlet _initialized = false;\nlet _provider: { register: () => void; shutdown: () => Promise<void> } | undefined;\n\n/**\n * Check whether telemetry is currently enabled.\n * @returns true if telemetry has been initialized and is enabled\n */\nexport function isTelemetryEnabled(): boolean {\n return _config?.enabled ?? false;\n}\n\n/**\n * Initialize telemetry if OTEL_EXPORTER_OTLP_ENDPOINT is set.\n * When disabled, this is a no-op with zero overhead beyond reading env vars.\n * @returns Promise that resolves when initialization completes\n */\nexport async function initTelemetry(): Promise<void> {\n if (_initialized) return;\n _initialized = true;\n\n _config = parseTelemetryConfig();\n if (!_config.enabled) return;\n\n // Dynamic imports - only loaded when tracing is enabled\n const [\n { NodeTracerProvider, BatchSpanProcessor },\n { OTLPTraceExporter },\n { resourceFromAttributes },\n { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION },\n { readPackageJson },\n ] = await Promise.all([\n import(\"@opentelemetry/sdk-trace-node\"),\n import(\"@opentelemetry/exporter-trace-otlp-proto\"),\n import(\"@opentelemetry/resources\"),\n import(\"@opentelemetry/semantic-conventions\"),\n import(\"@/cli/shared/package-json\"),\n ]);\n\n const packageJson = await readPackageJson();\n const version = packageJson.version ?? \"unknown\";\n\n const resource = resourceFromAttributes({\n [ATTR_SERVICE_NAME]: \"tailor-sdk\",\n [ATTR_SERVICE_VERSION]: version,\n });\n\n const exporter = new OTLPTraceExporter({\n url: `${_config.endpoint}/v1/traces`,\n });\n\n _provider = new NodeTracerProvider({\n resource,\n spanProcessors: [new BatchSpanProcessor(exporter)],\n });\n\n _provider.register();\n}\n\n/**\n * Shutdown the telemetry provider, flushing all pending spans.\n * Must be called before process exit to ensure traces are exported.\n * @returns Promise that resolves when shutdown completes\n */\nexport async function shutdownTelemetry(): Promise<void> {\n if (!_provider) return;\n await _provider.shutdown();\n}\n\n/**\n * Execute a function within a new span. Records exceptions and sets span status.\n * When no TracerProvider is registered, the OTel API automatically provides\n * noop spans with zero overhead.\n * @param name - Span name\n * @param fn - Function to execute within the span\n * @returns Result of fn\n */\nexport async function withSpan<T>(name: string, fn: (span: Span) => Promise<T>): Promise<T> {\n const tracer = trace.getTracer(\"tailor-sdk\");\n\n return tracer.startActiveSpan(name, async (span) => {\n try {\n const result = await fn(span);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({ code: SpanStatusCode.ERROR });\n if (error instanceof Error) {\n span.recordException(error);\n }\n throw error;\n } finally {\n span.end();\n }\n });\n}\n"],"mappings":";;;;;;;;;AAcA,SAAgB,uBAAwC;CACtD,MAAM,WAAW,QAAQ,IAAI,+BAA+B;
|
|
1
|
+
{"version":3,"file":"telemetry-DcL8Fsm_.mjs","names":[],"sources":["../src/cli/telemetry/config.ts","../src/cli/telemetry/index.ts"],"sourcesContent":["/**\n * Telemetry configuration parsed from standard OpenTelemetry environment variables.\n * Tracing is enabled when OTEL_EXPORTER_OTLP_ENDPOINT is set.\n */\nexport interface TelemetryConfig {\n readonly enabled: boolean;\n readonly endpoint: string;\n}\n\n/**\n * Parse telemetry configuration from standard OpenTelemetry environment variables.\n * Tracing is enabled when OTEL_EXPORTER_OTLP_ENDPOINT is set.\n * @returns Telemetry configuration\n */\nexport function parseTelemetryConfig(): TelemetryConfig {\n const endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? \"\";\n const enabled = endpoint.length > 0;\n\n return {\n enabled,\n endpoint,\n };\n}\n","import { trace, SpanStatusCode, type Span } from \"@opentelemetry/api\";\nimport { parseTelemetryConfig, type TelemetryConfig } from \"./config\";\n\nlet _config: TelemetryConfig | undefined;\nlet _initialized = false;\nlet _provider: { register: () => void; shutdown: () => Promise<void> } | undefined;\n\n/**\n * Check whether telemetry is currently enabled.\n * @returns true if telemetry has been initialized and is enabled\n */\nexport function isTelemetryEnabled(): boolean {\n return _config?.enabled ?? false;\n}\n\n/**\n * Initialize telemetry if OTEL_EXPORTER_OTLP_ENDPOINT is set.\n * When disabled, this is a no-op with zero overhead beyond reading env vars.\n * @returns Promise that resolves when initialization completes\n */\nexport async function initTelemetry(): Promise<void> {\n if (_initialized) return;\n _initialized = true;\n\n _config = parseTelemetryConfig();\n if (!_config.enabled) return;\n\n // Dynamic imports - only loaded when tracing is enabled\n const [\n { NodeTracerProvider, BatchSpanProcessor },\n { OTLPTraceExporter },\n { resourceFromAttributes },\n { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION },\n { readPackageJson },\n ] = await Promise.all([\n import(\"@opentelemetry/sdk-trace-node\"),\n import(\"@opentelemetry/exporter-trace-otlp-proto\"),\n import(\"@opentelemetry/resources\"),\n import(\"@opentelemetry/semantic-conventions\"),\n import(\"@/cli/shared/package-json\"),\n ]);\n\n const packageJson = await readPackageJson();\n const version = packageJson.version ?? \"unknown\";\n\n const resource = resourceFromAttributes({\n [ATTR_SERVICE_NAME]: \"tailor-sdk\",\n [ATTR_SERVICE_VERSION]: version,\n });\n\n const exporter = new OTLPTraceExporter({\n url: `${_config.endpoint}/v1/traces`,\n });\n\n _provider = new NodeTracerProvider({\n resource,\n spanProcessors: [new BatchSpanProcessor(exporter)],\n });\n\n _provider.register();\n}\n\n/**\n * Shutdown the telemetry provider, flushing all pending spans.\n * Must be called before process exit to ensure traces are exported.\n * @returns Promise that resolves when shutdown completes\n */\nexport async function shutdownTelemetry(): Promise<void> {\n if (!_provider) return;\n await _provider.shutdown();\n}\n\n/**\n * Execute a function within a new span. Records exceptions and sets span status.\n * When no TracerProvider is registered, the OTel API automatically provides\n * noop spans with zero overhead.\n * @param name - Span name\n * @param fn - Function to execute within the span\n * @returns Result of fn\n */\nexport async function withSpan<T>(name: string, fn: (span: Span) => Promise<T>): Promise<T> {\n const tracer = trace.getTracer(\"tailor-sdk\");\n\n return tracer.startActiveSpan(name, async (span) => {\n try {\n const result = await fn(span);\n span.setStatus({ code: SpanStatusCode.OK });\n return result;\n } catch (error) {\n span.setStatus({ code: SpanStatusCode.ERROR });\n if (error instanceof Error) {\n span.recordException(error);\n }\n throw error;\n } finally {\n span.end();\n }\n });\n}\n"],"mappings":";;;;;;;;;AAcA,SAAgB,uBAAwC;CACtD,MAAM,WAAW,QAAQ,IAAI,+BAA+B;CAG5D,OAAO;EACL,SAHc,SAAS,SAAS;EAIhC;EACD;;;;;AClBH,IAAI;AACJ,IAAI,eAAe;AACnB,IAAI;;;;;;AAeJ,eAAsB,gBAA+B;CACnD,IAAI,cAAc;CAClB,eAAe;CAEf,UAAU,sBAAsB;CAChC,IAAI,CAAC,QAAQ,SAAS;CAGtB,MAAM,CACJ,EAAE,oBAAoB,sBACtB,EAAE,qBACF,EAAE,0BACF,EAAE,mBAAmB,wBACrB,EAAE,qBACA,MAAM,QAAQ,IAAI;EACpB,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACP,OAAO;EACR,CAAC;CAGF,MAAM,WAAU,MADU,iBAAiB,EACf,WAAW;CAWvC,YAAY,IAAI,mBAAmB;EACjC,UAVe,uBAAuB;IACrC,oBAAoB;IACpB,uBAAuB;GACzB,CAOS;EACR,gBAAgB,CAAC,IAAI,mBAAmB,IANrB,kBAAkB,EACrC,KAAK,GAAG,QAAQ,SAAS,aAC1B,CAIiD,CAAC,CAAC;EACnD,CAAC;CAEF,UAAU,UAAU;;;;;;;AAQtB,eAAsB,oBAAmC;CACvD,IAAI,CAAC,WAAW;CAChB,MAAM,UAAU,UAAU;;;;;;;;;;AAW5B,eAAsB,SAAY,MAAc,IAA4C;CAG1F,OAFe,MAAM,UAAU,aAElB,CAAC,gBAAgB,MAAM,OAAO,SAAS;EAClD,IAAI;GACF,MAAM,SAAS,MAAM,GAAG,KAAK;GAC7B,KAAK,UAAU,EAAE,MAAM,eAAe,IAAI,CAAC;GAC3C,OAAO;WACA,OAAO;GACd,KAAK,UAAU,EAAE,MAAM,eAAe,OAAO,CAAC;GAC9C,IAAI,iBAAiB,OACnB,KAAK,gBAAgB,MAAM;GAE7B,MAAM;YACE;GACR,KAAK,KAAK;;GAEZ"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { t as mapAllowedValues } from "./field-
|
|
2
|
+
import { t as mapAllowedValues } from "./field-DLSIuMTu.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/configure/types/type.ts
|
|
5
5
|
const regex = {
|
|
@@ -340,4 +340,4 @@ const t = {
|
|
|
340
340
|
|
|
341
341
|
//#endregion
|
|
342
342
|
export { t };
|
|
343
|
-
//# sourceMappingURL=types-
|
|
343
|
+
//# sourceMappingURL=types-sir9UPht.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types-Duhhsx3R.mjs","names":[],"sources":["../src/configure/types/type.ts"],"sourcesContent":["import { type AllowedValues, type AllowedValuesOutput, mapAllowedValues } from \"./field\";\nimport type {\n DefinedFieldMetadata,\n TailorFieldType,\n TailorToTs,\n FieldMetadata,\n FieldOptions,\n FieldOutput,\n} from \"@/types/field-types\";\nimport type { InferFieldsOutput, Prettify } from \"@/types/helpers\";\nimport type { TailorField as TailorFieldBase } from \"@/types/tailor-field\";\nimport type { TailorUser } from \"@/types/user\";\nimport type { FieldValidateInput } from \"@/types/validation\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n// This helper type intentionally uses `any` as a placeholder for unknown field output.\n// oxlint-disable-next-line no-explicit-any\nexport type TailorAnyField = TailorField<any>;\n\n/**\n * Full TailorField interface with builder methods.\n * Extends the minimal structural interface from types/ with fluent API methods.\n */\nexport interface TailorField<\n Defined extends DefinedFieldMetadata = DefinedFieldMetadata,\n // Generic default output type (kept loose on purpose for library ergonomics).\n // oxlint-disable-next-line no-explicit-any\n Output = any,\n M extends FieldMetadata = FieldMetadata,\n T extends TailorFieldType = TailorFieldType,\n> extends TailorFieldBase<Defined, Output, M, T> {\n readonly fields: Record<string, TailorAnyField>;\n _metadata: M;\n\n /**\n * Set a description for the field\n * @param description - The description text\n * @returns The field with updated metadata\n */\n description<CurrentDefined extends Defined>(\n this: CurrentDefined extends { description: unknown }\n ? never\n : TailorField<CurrentDefined, Output>,\n description: string,\n ): TailorField<Prettify<CurrentDefined & { description: true }>, Output>;\n\n /**\n * Set a custom type name for enum or nested types\n * @param typeName - The custom type name\n * @returns The field with updated metadata\n */\n typeName<CurrentDefined extends Defined>(\n this: CurrentDefined extends { typeName: unknown }\n ? never\n : CurrentDefined extends { type: \"enum\" | \"nested\" }\n ? TailorField<CurrentDefined, Output>\n : never,\n typeName: string,\n ): TailorField<Prettify<CurrentDefined & { typeName: true }>, Output>;\n\n /**\n * Add validation functions to the field\n * @param validate - One or more validation functions\n * @returns The field with updated metadata\n */\n validate<CurrentDefined extends Defined>(\n this: CurrentDefined extends { validate: unknown }\n ? never\n : TailorField<CurrentDefined, Output>,\n ...validate: FieldValidateInput<Output>[]\n ): TailorField<Prettify<CurrentDefined & { validate: true }>, Output>;\n\n /**\n * Parse and validate a value against this field's validation rules\n * Returns StandardSchema Result type with success or failure\n * @param args - Value, context data, and user\n * @returns Validation result\n */\n parse(args: FieldParseArgs): StandardSchemaV1.Result<Output>;\n\n /**\n * Internal parse method that tracks field path for nested validation\n * @private\n * @param args - Parse arguments\n * @returns Validation result\n */\n _parseInternal(args: FieldParseInternalArgs): StandardSchemaV1.Result<Output>;\n}\n\nconst regex = {\n uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n date: /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})$/,\n time: /^(?<hour>\\d{2}):(?<minute>\\d{2})$/,\n datetime:\n /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})T(?<hour>\\d{2}):(?<minute>\\d{2}):(?<second>\\d{2})(.(?<millisec>\\d{3}))?Z$/,\n decimal: /^-?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/,\n} as const;\n\ntype FieldParseArgs = {\n value: unknown;\n data: unknown;\n user: TailorUser;\n};\n\ntype FieldValidateValueArgs<T extends TailorFieldType> = {\n value: TailorToTs[T];\n data: unknown;\n user: TailorUser;\n pathArray: string[];\n};\n\ntype FieldParseInternalArgs = {\n // Runtime input is unknown/untyped; we validate and narrow it inside the parser.\n // oxlint-disable-next-line no-explicit-any\n value: any;\n data: unknown;\n user: TailorUser;\n pathArray: string[];\n};\n\n/**\n * Creates a new TailorField instance.\n * @param type - Field type\n * @param options - Field options\n * @param fields - Nested fields for object-like types\n * @param values - Allowed values for enum-like fields\n * @returns A new TailorField\n */\nfunction createTailorField<\n const T extends TailorFieldType,\n const TOptions extends FieldOptions,\n const OutputBase = TailorToTs[T],\n>(\n type: T,\n options?: TOptions,\n fields?: Record<string, TailorAnyField>,\n values?: AllowedValues,\n): TailorField<\n { type: T; array: TOptions extends { array: true } ? true : false },\n FieldOutput<OutputBase, TOptions>\n> {\n const _metadata: FieldMetadata = { required: true };\n\n if (options) {\n if (options.optional === true) {\n _metadata.required = false;\n }\n if (options.array === true) {\n _metadata.array = true;\n }\n }\n if (values) {\n _metadata.allowedValues = mapAllowedValues(values);\n }\n\n /**\n * Validate a single value (not an array element)\n * Used internally for array element validation\n * @param args - Value, context data, and user\n * @returns Array of validation issues\n */\n function validateValue(args: FieldValidateValueArgs<T>): StandardSchemaV1.Issue[] {\n const { value, data, user, pathArray } = args;\n const issues: StandardSchemaV1.Issue[] = [];\n\n // Type-specific validation\n switch (type) {\n case \"string\":\n if (typeof value !== \"string\") {\n issues.push({\n message: `Expected a string: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"integer\":\n if (typeof value !== \"number\" || !Number.isInteger(value)) {\n issues.push({\n message: `Expected an integer: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"float\":\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n issues.push({\n message: `Expected a number: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n issues.push({\n message: `Expected a boolean: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"uuid\":\n if (typeof value !== \"string\" || !regex.uuid.test(value)) {\n issues.push({\n message: `Expected a valid UUID: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"date\":\n if (typeof value !== \"string\" || !regex.date.test(value)) {\n issues.push({\n message: `Expected to match \"yyyy-MM-dd\" format: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"datetime\":\n if (typeof value !== \"string\" || !regex.datetime.test(value)) {\n issues.push({\n message: `Expected to match ISO format: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"time\":\n if (typeof value !== \"string\" || !regex.time.test(value)) {\n issues.push({\n message: `Expected to match \"HH:mm\" format: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"decimal\":\n if (typeof value !== \"string\" || !regex.decimal.test(value)) {\n issues.push({\n message: `Expected a decimal string: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"enum\":\n if (field._metadata.allowedValues) {\n const allowedValues = field._metadata.allowedValues.map((v) => v.value);\n if (typeof value !== \"string\" || !allowedValues.includes(value)) {\n issues.push({\n message: `Must be one of [${allowedValues.join(\", \")}]: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n }\n break;\n\n case \"nested\":\n // Validate nested object fields\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value) ||\n value instanceof Date\n ) {\n issues.push({\n message: `Expected an object: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n } else if (field.fields && Object.keys(field.fields).length > 0) {\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n const fieldValue = value?.[fieldName];\n const result = nestedField._parseInternal({\n value: fieldValue,\n data,\n user,\n pathArray: pathArray.concat(fieldName),\n });\n if (result.issues) {\n issues.push(...result.issues);\n }\n }\n }\n break;\n }\n\n // Custom validation functions\n const validateFns = field._metadata.validate;\n if (validateFns && validateFns.length > 0) {\n for (const validateInput of validateFns) {\n const { fn, message } =\n typeof validateInput === \"function\"\n ? { fn: validateInput, message: \"Validation failed\" }\n : { fn: validateInput[0], message: validateInput[1] };\n\n if (!fn({ value, data, user })) {\n issues.push({\n message,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n }\n }\n\n return issues;\n }\n\n /**\n * Internal parse method that tracks field path for nested validation\n * @param args - Parse arguments\n * @returns Parse result with value or issues\n */\n function parseInternal(\n args: FieldParseInternalArgs,\n ): StandardSchemaV1.Result<FieldOutput<OutputBase, TOptions>> {\n const { value, data, user, pathArray } = args;\n const issues: StandardSchemaV1.Issue[] = [];\n\n // 1. Check required/optional\n const isNullOrUndefined = value === null || value === undefined;\n if (field._metadata.required && isNullOrUndefined) {\n issues.push({\n message: \"Required field is missing\",\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n return { issues };\n }\n\n // If optional and null/undefined, skip further validation and normalize to null\n if (!field._metadata.required && isNullOrUndefined) {\n return { value: value ?? null };\n }\n\n // 2. Check array type\n if (field._metadata.array) {\n if (!Array.isArray(value)) {\n issues.push({\n message: \"Expected an array\",\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n return { issues };\n }\n\n // Validate each array element (without array flag)\n for (let i = 0; i < value.length; i++) {\n const elementValue = value[i];\n const elementPath = pathArray.concat(`[${i}]`);\n\n // Validate element with same type but without array flag\n const elementIssues = validateValue({\n value: elementValue,\n data,\n user,\n pathArray: elementPath,\n });\n if (elementIssues.length > 0) {\n issues.push(...elementIssues);\n }\n }\n\n if (issues.length > 0) {\n return { issues };\n }\n return { value: value as FieldOutput<OutputBase, TOptions> };\n }\n\n // 3. Type-specific validation and custom validation\n const valueIssues = validateValue({ value, data, user, pathArray });\n issues.push(...valueIssues);\n\n if (issues.length > 0) {\n return { issues };\n }\n\n return { value };\n }\n\n const field: TailorField<\n { type: T; array: TOptions extends { array: true } ? true : false },\n FieldOutput<OutputBase, TOptions>\n > = {\n type,\n fields: fields ?? {},\n _defined: undefined as unknown as {\n type: T;\n array: TOptions extends { array: true } ? true : false;\n },\n _output: undefined as FieldOutput<OutputBase, TOptions>,\n _metadata,\n\n get metadata() {\n return { ...this._metadata };\n },\n\n description(description: string) {\n this._metadata.description = description;\n // Fluent API returns this with updated type\n // oxlint-disable-next-line no-explicit-any\n return this as any;\n },\n\n typeName(typeName: string) {\n this._metadata.typeName = typeName;\n // Fluent API returns this with updated type\n // oxlint-disable-next-line no-explicit-any\n return this as any;\n },\n\n validate(...validateInputs: FieldValidateInput<FieldOutput<OutputBase, TOptions>>[]) {\n this._metadata.validate = validateInputs;\n // Fluent API returns this with updated type\n // oxlint-disable-next-line no-explicit-any\n return this as any;\n },\n\n parse(args: FieldParseArgs): StandardSchemaV1.Result<FieldOutput<OutputBase, TOptions>> {\n return parseInternal({\n value: args.value,\n data: args.data,\n user: args.user,\n pathArray: [],\n });\n },\n\n _parseInternal: parseInternal,\n };\n\n return field;\n}\n\n/**\n * Create a UUID field for resolver input/output.\n * @param options - Field configuration options\n * @returns A UUID field\n * @example t.uuid()\n */\nfunction uuid<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"uuid\", options);\n}\n\n/**\n * Create a string field for resolver input/output.\n * @param options - Field configuration options\n * @returns A string field\n * @example t.string()\n * @example t.string({ optional: true })\n * @example t.string({ array: true })\n */\nfunction string<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"string\", options);\n}\n\n/**\n * Create a boolean field for resolver input/output.\n * @param options - Field configuration options\n * @returns A boolean field\n * @example t.bool()\n */\nfunction bool<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"boolean\", options);\n}\n\n/**\n * Create an integer field for resolver input/output.\n * @param options - Field configuration options\n * @returns An integer field\n * @example t.int()\n */\nfunction int<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"integer\", options);\n}\n\n/**\n * Create a float field for resolver input/output.\n * @param options - Field configuration options\n * @returns A float field\n * @example t.float()\n */\nfunction float<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"float\", options);\n}\n\n/**\n * Create a decimal field for resolver input/output (stored as string for precision).\n * @param options - Field configuration options\n * @returns A decimal field\n * @example t.decimal()\n * @example t.decimal({ optional: true })\n */\nfunction decimal<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"decimal\", options);\n}\n\n/**\n * Create a date field for resolver input/output.\n * @param options - Field configuration options\n * @returns A date field\n * @example t.date()\n */\nfunction date<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"date\", options);\n}\n\n/**\n * Create a datetime field for resolver input/output.\n * @param options - Field configuration options\n * @returns A datetime field\n * @example t.datetime()\n */\nfunction datetime<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"datetime\", options);\n}\n\n/**\n * Create a time field for resolver input/output.\n * @param options - Field configuration options\n * @returns A time field\n * @example t.time()\n */\nfunction time<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"time\", options);\n}\n\n/**\n * Create an enum field for resolver input/output.\n * @param values - Array of allowed string values\n * @param options - Field configuration options\n * @returns An enum field\n * @example t.enum([\"active\", \"inactive\"])\n */\nfunction _enum<const V extends AllowedValues, const Opt extends FieldOptions>(\n values: V,\n options?: Opt,\n): TailorField<\n { type: \"enum\"; array: Opt extends { array: true } ? true : false },\n FieldOutput<AllowedValuesOutput<V>, Opt>\n> {\n return createTailorField<\"enum\", Opt, AllowedValuesOutput<V>>(\"enum\", options, undefined, values);\n}\n\n/**\n * Create a nested object field for resolver input/output.\n * @param fields - Record of field definitions\n * @param options - Field options (optional, array)\n * @returns A nested object field\n * @example\n * // Single object:\n * output: t.object({ name: t.string(), email: t.string() })\n * @example\n * // Array of objects:\n * items: t.object({ name: t.string() }, { array: true })\n */\nfunction object<const F extends Record<string, TailorAnyField>, const Opt extends FieldOptions>(\n fields: F,\n options?: Opt,\n) {\n const objectField = createTailorField(\"nested\", options, fields) as TailorField<\n { type: \"nested\"; array: Opt extends { array: true } ? true : false },\n FieldOutput<InferFieldsOutput<F>, Opt>\n >;\n return objectField;\n}\n\nexport const t = {\n uuid,\n string,\n bool,\n int,\n float,\n decimal,\n date,\n datetime,\n time,\n enum: _enum,\n object,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types-sir9UPht.mjs","names":[],"sources":["../src/configure/types/type.ts"],"sourcesContent":["import { type AllowedValues, type AllowedValuesOutput, mapAllowedValues } from \"./field\";\nimport type {\n DefinedFieldMetadata,\n TailorFieldType,\n TailorToTs,\n FieldMetadata,\n FieldOptions,\n FieldOutput,\n} from \"@/types/field-types\";\nimport type { InferFieldsOutput, Prettify } from \"@/types/helpers\";\nimport type { TailorField as TailorFieldBase } from \"@/types/tailor-field\";\nimport type { TailorUser } from \"@/types/user\";\nimport type { FieldValidateInput } from \"@/types/validation\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n// This helper type intentionally uses `any` as a placeholder for unknown field output.\n// oxlint-disable-next-line no-explicit-any\nexport type TailorAnyField = TailorField<any>;\n\n/**\n * Full TailorField interface with builder methods.\n * Extends the minimal structural interface from types/ with fluent API methods.\n */\nexport interface TailorField<\n Defined extends DefinedFieldMetadata = DefinedFieldMetadata,\n // Generic default output type (kept loose on purpose for library ergonomics).\n // oxlint-disable-next-line no-explicit-any\n Output = any,\n M extends FieldMetadata = FieldMetadata,\n T extends TailorFieldType = TailorFieldType,\n> extends TailorFieldBase<Defined, Output, M, T> {\n readonly fields: Record<string, TailorAnyField>;\n _metadata: M;\n\n /**\n * Set a description for the field\n * @param description - The description text\n * @returns The field with updated metadata\n */\n description<CurrentDefined extends Defined>(\n this: CurrentDefined extends { description: unknown }\n ? never\n : TailorField<CurrentDefined, Output>,\n description: string,\n ): TailorField<Prettify<CurrentDefined & { description: true }>, Output>;\n\n /**\n * Set a custom type name for enum or nested types\n * @param typeName - The custom type name\n * @returns The field with updated metadata\n */\n typeName<CurrentDefined extends Defined>(\n this: CurrentDefined extends { typeName: unknown }\n ? never\n : CurrentDefined extends { type: \"enum\" | \"nested\" }\n ? TailorField<CurrentDefined, Output>\n : never,\n typeName: string,\n ): TailorField<Prettify<CurrentDefined & { typeName: true }>, Output>;\n\n /**\n * Add validation functions to the field\n * @param validate - One or more validation functions\n * @returns The field with updated metadata\n */\n validate<CurrentDefined extends Defined>(\n this: CurrentDefined extends { validate: unknown }\n ? never\n : TailorField<CurrentDefined, Output>,\n ...validate: FieldValidateInput<Output>[]\n ): TailorField<Prettify<CurrentDefined & { validate: true }>, Output>;\n\n /**\n * Parse and validate a value against this field's validation rules\n * Returns StandardSchema Result type with success or failure\n * @param args - Value, context data, and user\n * @returns Validation result\n */\n parse(args: FieldParseArgs): StandardSchemaV1.Result<Output>;\n\n /**\n * Internal parse method that tracks field path for nested validation\n * @private\n * @param args - Parse arguments\n * @returns Validation result\n */\n _parseInternal(args: FieldParseInternalArgs): StandardSchemaV1.Result<Output>;\n}\n\nconst regex = {\n uuid: /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,\n date: /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})$/,\n time: /^(?<hour>\\d{2}):(?<minute>\\d{2})$/,\n datetime:\n /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})T(?<hour>\\d{2}):(?<minute>\\d{2}):(?<second>\\d{2})(.(?<millisec>\\d{3}))?Z$/,\n decimal: /^-?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/,\n} as const;\n\ntype FieldParseArgs = {\n value: unknown;\n data: unknown;\n user: TailorUser;\n};\n\ntype FieldValidateValueArgs<T extends TailorFieldType> = {\n value: TailorToTs[T];\n data: unknown;\n user: TailorUser;\n pathArray: string[];\n};\n\ntype FieldParseInternalArgs = {\n // Runtime input is unknown/untyped; we validate and narrow it inside the parser.\n // oxlint-disable-next-line no-explicit-any\n value: any;\n data: unknown;\n user: TailorUser;\n pathArray: string[];\n};\n\n/**\n * Creates a new TailorField instance.\n * @param type - Field type\n * @param options - Field options\n * @param fields - Nested fields for object-like types\n * @param values - Allowed values for enum-like fields\n * @returns A new TailorField\n */\nfunction createTailorField<\n const T extends TailorFieldType,\n const TOptions extends FieldOptions,\n const OutputBase = TailorToTs[T],\n>(\n type: T,\n options?: TOptions,\n fields?: Record<string, TailorAnyField>,\n values?: AllowedValues,\n): TailorField<\n { type: T; array: TOptions extends { array: true } ? true : false },\n FieldOutput<OutputBase, TOptions>\n> {\n const _metadata: FieldMetadata = { required: true };\n\n if (options) {\n if (options.optional === true) {\n _metadata.required = false;\n }\n if (options.array === true) {\n _metadata.array = true;\n }\n }\n if (values) {\n _metadata.allowedValues = mapAllowedValues(values);\n }\n\n /**\n * Validate a single value (not an array element)\n * Used internally for array element validation\n * @param args - Value, context data, and user\n * @returns Array of validation issues\n */\n function validateValue(args: FieldValidateValueArgs<T>): StandardSchemaV1.Issue[] {\n const { value, data, user, pathArray } = args;\n const issues: StandardSchemaV1.Issue[] = [];\n\n // Type-specific validation\n switch (type) {\n case \"string\":\n if (typeof value !== \"string\") {\n issues.push({\n message: `Expected a string: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"integer\":\n if (typeof value !== \"number\" || !Number.isInteger(value)) {\n issues.push({\n message: `Expected an integer: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"float\":\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n issues.push({\n message: `Expected a number: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"boolean\":\n if (typeof value !== \"boolean\") {\n issues.push({\n message: `Expected a boolean: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"uuid\":\n if (typeof value !== \"string\" || !regex.uuid.test(value)) {\n issues.push({\n message: `Expected a valid UUID: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"date\":\n if (typeof value !== \"string\" || !regex.date.test(value)) {\n issues.push({\n message: `Expected to match \"yyyy-MM-dd\" format: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"datetime\":\n if (typeof value !== \"string\" || !regex.datetime.test(value)) {\n issues.push({\n message: `Expected to match ISO format: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"time\":\n if (typeof value !== \"string\" || !regex.time.test(value)) {\n issues.push({\n message: `Expected to match \"HH:mm\" format: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n case \"decimal\":\n if (typeof value !== \"string\" || !regex.decimal.test(value)) {\n issues.push({\n message: `Expected a decimal string: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n break;\n\n case \"enum\":\n if (field._metadata.allowedValues) {\n const allowedValues = field._metadata.allowedValues.map((v) => v.value);\n if (typeof value !== \"string\" || !allowedValues.includes(value)) {\n issues.push({\n message: `Must be one of [${allowedValues.join(\", \")}]: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n }\n break;\n\n case \"nested\":\n // Validate nested object fields\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value) ||\n value instanceof Date\n ) {\n issues.push({\n message: `Expected an object: received ${String(value)}`,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n } else if (field.fields && Object.keys(field.fields).length > 0) {\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n const fieldValue = value?.[fieldName];\n const result = nestedField._parseInternal({\n value: fieldValue,\n data,\n user,\n pathArray: pathArray.concat(fieldName),\n });\n if (result.issues) {\n issues.push(...result.issues);\n }\n }\n }\n break;\n }\n\n // Custom validation functions\n const validateFns = field._metadata.validate;\n if (validateFns && validateFns.length > 0) {\n for (const validateInput of validateFns) {\n const { fn, message } =\n typeof validateInput === \"function\"\n ? { fn: validateInput, message: \"Validation failed\" }\n : { fn: validateInput[0], message: validateInput[1] };\n\n if (!fn({ value, data, user })) {\n issues.push({\n message,\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n }\n }\n }\n\n return issues;\n }\n\n /**\n * Internal parse method that tracks field path for nested validation\n * @param args - Parse arguments\n * @returns Parse result with value or issues\n */\n function parseInternal(\n args: FieldParseInternalArgs,\n ): StandardSchemaV1.Result<FieldOutput<OutputBase, TOptions>> {\n const { value, data, user, pathArray } = args;\n const issues: StandardSchemaV1.Issue[] = [];\n\n // 1. Check required/optional\n const isNullOrUndefined = value === null || value === undefined;\n if (field._metadata.required && isNullOrUndefined) {\n issues.push({\n message: \"Required field is missing\",\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n return { issues };\n }\n\n // If optional and null/undefined, skip further validation and normalize to null\n if (!field._metadata.required && isNullOrUndefined) {\n return { value: value ?? null };\n }\n\n // 2. Check array type\n if (field._metadata.array) {\n if (!Array.isArray(value)) {\n issues.push({\n message: \"Expected an array\",\n path: pathArray.length > 0 ? pathArray : undefined,\n });\n return { issues };\n }\n\n // Validate each array element (without array flag)\n for (let i = 0; i < value.length; i++) {\n const elementValue = value[i];\n const elementPath = pathArray.concat(`[${i}]`);\n\n // Validate element with same type but without array flag\n const elementIssues = validateValue({\n value: elementValue,\n data,\n user,\n pathArray: elementPath,\n });\n if (elementIssues.length > 0) {\n issues.push(...elementIssues);\n }\n }\n\n if (issues.length > 0) {\n return { issues };\n }\n return { value: value as FieldOutput<OutputBase, TOptions> };\n }\n\n // 3. Type-specific validation and custom validation\n const valueIssues = validateValue({ value, data, user, pathArray });\n issues.push(...valueIssues);\n\n if (issues.length > 0) {\n return { issues };\n }\n\n return { value };\n }\n\n const field: TailorField<\n { type: T; array: TOptions extends { array: true } ? true : false },\n FieldOutput<OutputBase, TOptions>\n > = {\n type,\n fields: fields ?? {},\n _defined: undefined as unknown as {\n type: T;\n array: TOptions extends { array: true } ? true : false;\n },\n _output: undefined as FieldOutput<OutputBase, TOptions>,\n _metadata,\n\n get metadata() {\n return { ...this._metadata };\n },\n\n description(description: string) {\n this._metadata.description = description;\n // Fluent API returns this with updated type\n // oxlint-disable-next-line no-explicit-any\n return this as any;\n },\n\n typeName(typeName: string) {\n this._metadata.typeName = typeName;\n // Fluent API returns this with updated type\n // oxlint-disable-next-line no-explicit-any\n return this as any;\n },\n\n validate(...validateInputs: FieldValidateInput<FieldOutput<OutputBase, TOptions>>[]) {\n this._metadata.validate = validateInputs;\n // Fluent API returns this with updated type\n // oxlint-disable-next-line no-explicit-any\n return this as any;\n },\n\n parse(args: FieldParseArgs): StandardSchemaV1.Result<FieldOutput<OutputBase, TOptions>> {\n return parseInternal({\n value: args.value,\n data: args.data,\n user: args.user,\n pathArray: [],\n });\n },\n\n _parseInternal: parseInternal,\n };\n\n return field;\n}\n\n/**\n * Create a UUID field for resolver input/output.\n * @param options - Field configuration options\n * @returns A UUID field\n * @example t.uuid()\n */\nfunction uuid<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"uuid\", options);\n}\n\n/**\n * Create a string field for resolver input/output.\n * @param options - Field configuration options\n * @returns A string field\n * @example t.string()\n * @example t.string({ optional: true })\n * @example t.string({ array: true })\n */\nfunction string<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"string\", options);\n}\n\n/**\n * Create a boolean field for resolver input/output.\n * @param options - Field configuration options\n * @returns A boolean field\n * @example t.bool()\n */\nfunction bool<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"boolean\", options);\n}\n\n/**\n * Create an integer field for resolver input/output.\n * @param options - Field configuration options\n * @returns An integer field\n * @example t.int()\n */\nfunction int<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"integer\", options);\n}\n\n/**\n * Create a float field for resolver input/output.\n * @param options - Field configuration options\n * @returns A float field\n * @example t.float()\n */\nfunction float<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"float\", options);\n}\n\n/**\n * Create a decimal field for resolver input/output (stored as string for precision).\n * @param options - Field configuration options\n * @returns A decimal field\n * @example t.decimal()\n * @example t.decimal({ optional: true })\n */\nfunction decimal<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"decimal\", options);\n}\n\n/**\n * Create a date field for resolver input/output.\n * @param options - Field configuration options\n * @returns A date field\n * @example t.date()\n */\nfunction date<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"date\", options);\n}\n\n/**\n * Create a datetime field for resolver input/output.\n * @param options - Field configuration options\n * @returns A datetime field\n * @example t.datetime()\n */\nfunction datetime<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"datetime\", options);\n}\n\n/**\n * Create a time field for resolver input/output.\n * @param options - Field configuration options\n * @returns A time field\n * @example t.time()\n */\nfunction time<const Opt extends FieldOptions>(options?: Opt) {\n return createTailorField(\"time\", options);\n}\n\n/**\n * Create an enum field for resolver input/output.\n * @param values - Array of allowed string values\n * @param options - Field configuration options\n * @returns An enum field\n * @example t.enum([\"active\", \"inactive\"])\n */\nfunction _enum<const V extends AllowedValues, const Opt extends FieldOptions>(\n values: V,\n options?: Opt,\n): TailorField<\n { type: \"enum\"; array: Opt extends { array: true } ? true : false },\n FieldOutput<AllowedValuesOutput<V>, Opt>\n> {\n return createTailorField<\"enum\", Opt, AllowedValuesOutput<V>>(\"enum\", options, undefined, values);\n}\n\n/**\n * Create a nested object field for resolver input/output.\n * @param fields - Record of field definitions\n * @param options - Field options (optional, array)\n * @returns A nested object field\n * @example\n * // Single object:\n * output: t.object({ name: t.string(), email: t.string() })\n * @example\n * // Array of objects:\n * items: t.object({ name: t.string() }, { array: true })\n */\nfunction object<const F extends Record<string, TailorAnyField>, const Opt extends FieldOptions>(\n fields: F,\n options?: Opt,\n) {\n const objectField = createTailorField(\"nested\", options, fields) as TailorField<\n { type: \"nested\"; array: Opt extends { array: true } ? true : false },\n FieldOutput<InferFieldsOutput<F>, Opt>\n >;\n return objectField;\n}\n\nexport const t = {\n uuid,\n string,\n bool,\n int,\n float,\n decimal,\n date,\n datetime,\n time,\n enum: _enum,\n object,\n};\n"],"mappings":";;;;AAyFA,MAAM,QAAQ;CACZ,MAAM;CACN,MAAM;CACN,MAAM;CACN,UACE;CACF,SAAS;CACV;;;;;;;;;AAgCD,SAAS,kBAKP,MACA,SACA,QACA,QAIA;CACA,MAAM,YAA2B,EAAE,UAAU,MAAM;CAEnD,IAAI,SAAS;EACX,IAAI,QAAQ,aAAa,MACvB,UAAU,WAAW;EAEvB,IAAI,QAAQ,UAAU,MACpB,UAAU,QAAQ;;CAGtB,IAAI,QACF,UAAU,gBAAgB,iBAAiB,OAAO;;;;;;;CASpD,SAAS,cAAc,MAA2D;EAChF,MAAM,EAAE,OAAO,MAAM,MAAM,cAAc;EACzC,MAAM,SAAmC,EAAE;EAG3C,QAAQ,MAAR;GACE,KAAK;IACH,IAAI,OAAO,UAAU,UACnB,OAAO,KAAK;KACV,SAAS,+BAA+B,OAAO,MAAM;KACrD,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GAEF,KAAK;IACH,IAAI,OAAO,UAAU,YAAY,CAAC,OAAO,UAAU,MAAM,EACvD,OAAO,KAAK;KACV,SAAS,iCAAiC,OAAO,MAAM;KACvD,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GAEF,KAAK;IACH,IAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,MAAM,EACtD,OAAO,KAAK;KACV,SAAS,+BAA+B,OAAO,MAAM;KACrD,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GAEF,KAAK;IACH,IAAI,OAAO,UAAU,WACnB,OAAO,KAAK;KACV,SAAS,gCAAgC,OAAO,MAAM;KACtD,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GAEF,KAAK;IACH,IAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,KAAK,MAAM,EACtD,OAAO,KAAK;KACV,SAAS,mCAAmC,OAAO,MAAM;KACzD,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GACF,KAAK;IACH,IAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,KAAK,MAAM,EACtD,OAAO,KAAK;KACV,SAAS,mDAAmD,OAAO,MAAM;KACzE,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GACF,KAAK;IACH,IAAI,OAAO,UAAU,YAAY,CAAC,MAAM,SAAS,KAAK,MAAM,EAC1D,OAAO,KAAK;KACV,SAAS,0CAA0C,OAAO,MAAM;KAChE,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GACF,KAAK;IACH,IAAI,OAAO,UAAU,YAAY,CAAC,MAAM,KAAK,KAAK,MAAM,EACtD,OAAO,KAAK;KACV,SAAS,8CAA8C,OAAO,MAAM;KACpE,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GACF,KAAK;IACH,IAAI,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,MAAM,EACzD,OAAO,KAAK;KACV,SAAS,uCAAuC,OAAO,MAAM;KAC7D,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IAEJ;GAEF,KAAK;IACH,IAAI,MAAM,UAAU,eAAe;KACjC,MAAM,gBAAgB,MAAM,UAAU,cAAc,KAAK,MAAM,EAAE,MAAM;KACvE,IAAI,OAAO,UAAU,YAAY,CAAC,cAAc,SAAS,MAAM,EAC7D,OAAO,KAAK;MACV,SAAS,mBAAmB,cAAc,KAAK,KAAK,CAAC,cAAc,OAAO,MAAM;MAChF,MAAM,UAAU,SAAS,IAAI,YAAY;MAC1C,CAAC;;IAGN;GAEF,KAAK;IAEH,IACE,OAAO,UAAU,YACjB,UAAU,QACV,MAAM,QAAQ,MAAM,IACpB,iBAAiB,MAEjB,OAAO,KAAK;KACV,SAAS,gCAAgC,OAAO,MAAM;KACtD,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;SACG,IAAI,MAAM,UAAU,OAAO,KAAK,MAAM,OAAO,CAAC,SAAS,GAC5D,KAAK,MAAM,CAAC,WAAW,gBAAgB,OAAO,QAAQ,MAAM,OAAO,EAAE;KACnE,MAAM,aAAa,QAAQ;KAC3B,MAAM,SAAS,YAAY,eAAe;MACxC,OAAO;MACP;MACA;MACA,WAAW,UAAU,OAAO,UAAU;MACvC,CAAC;KACF,IAAI,OAAO,QACT,OAAO,KAAK,GAAG,OAAO,OAAO;;IAInC;;EAIJ,MAAM,cAAc,MAAM,UAAU;EACpC,IAAI,eAAe,YAAY,SAAS,GACtC,KAAK,MAAM,iBAAiB,aAAa;GACvC,MAAM,EAAE,IAAI,YACV,OAAO,kBAAkB,aACrB;IAAE,IAAI;IAAe,SAAS;IAAqB,GACnD;IAAE,IAAI,cAAc;IAAI,SAAS,cAAc;IAAI;GAEzD,IAAI,CAAC,GAAG;IAAE;IAAO;IAAM;IAAM,CAAC,EAC5B,OAAO,KAAK;IACV;IACA,MAAM,UAAU,SAAS,IAAI,YAAY;IAC1C,CAAC;;EAKR,OAAO;;;;;;;CAQT,SAAS,cACP,MAC4D;EAC5D,MAAM,EAAE,OAAO,MAAM,MAAM,cAAc;EACzC,MAAM,SAAmC,EAAE;EAG3C,MAAM,oBAAoB,UAAU,QAAQ,UAAU;EACtD,IAAI,MAAM,UAAU,YAAY,mBAAmB;GACjD,OAAO,KAAK;IACV,SAAS;IACT,MAAM,UAAU,SAAS,IAAI,YAAY;IAC1C,CAAC;GACF,OAAO,EAAE,QAAQ;;EAInB,IAAI,CAAC,MAAM,UAAU,YAAY,mBAC/B,OAAO,EAAE,OAAO,SAAS,MAAM;EAIjC,IAAI,MAAM,UAAU,OAAO;GACzB,IAAI,CAAC,MAAM,QAAQ,MAAM,EAAE;IACzB,OAAO,KAAK;KACV,SAAS;KACT,MAAM,UAAU,SAAS,IAAI,YAAY;KAC1C,CAAC;IACF,OAAO,EAAE,QAAQ;;GAInB,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;IACrC,MAAM,eAAe,MAAM;IAI3B,MAAM,gBAAgB,cAAc;KAClC,OAAO;KACP;KACA;KACA,WAPkB,UAAU,OAAO,IAAI,EAAE,GAOnB;KACvB,CAAC;IACF,IAAI,cAAc,SAAS,GACzB,OAAO,KAAK,GAAG,cAAc;;GAIjC,IAAI,OAAO,SAAS,GAClB,OAAO,EAAE,QAAQ;GAEnB,OAAO,EAAS,OAA4C;;EAI9D,MAAM,cAAc,cAAc;GAAE;GAAO;GAAM;GAAM;GAAW,CAAC;EACnE,OAAO,KAAK,GAAG,YAAY;EAE3B,IAAI,OAAO,SAAS,GAClB,OAAO,EAAE,QAAQ;EAGnB,OAAO,EAAE,OAAO;;CAGlB,MAAM,QAGF;EACF;EACA,QAAQ,UAAU,EAAE;EACpB,UAAU;EAIV,SAAS;EACT;EAEA,IAAI,WAAW;GACb,OAAO,EAAE,GAAG,KAAK,WAAW;;EAG9B,YAAY,aAAqB;GAC/B,KAAK,UAAU,cAAc;GAG7B,OAAO;;EAGT,SAAS,UAAkB;GACzB,KAAK,UAAU,WAAW;GAG1B,OAAO;;EAGT,SAAS,GAAG,gBAAyE;GACnF,KAAK,UAAU,WAAW;GAG1B,OAAO;;EAGT,MAAM,MAAkF;GACtF,OAAO,cAAc;IACnB,OAAO,KAAK;IACZ,MAAM,KAAK;IACX,MAAM,KAAK;IACX,WAAW,EAAE;IACd,CAAC;;EAGJ,gBAAgB;EACjB;CAED,OAAO;;;;;;;;AAST,SAAS,KAAqC,SAAe;CAC3D,OAAO,kBAAkB,QAAQ,QAAQ;;;;;;;;;;AAW3C,SAAS,OAAuC,SAAe;CAC7D,OAAO,kBAAkB,UAAU,QAAQ;;;;;;;;AAS7C,SAAS,KAAqC,SAAe;CAC3D,OAAO,kBAAkB,WAAW,QAAQ;;;;;;;;AAS9C,SAAS,IAAoC,SAAe;CAC1D,OAAO,kBAAkB,WAAW,QAAQ;;;;;;;;AAS9C,SAAS,MAAsC,SAAe;CAC5D,OAAO,kBAAkB,SAAS,QAAQ;;;;;;;;;AAU5C,SAAS,QAAwC,SAAe;CAC9D,OAAO,kBAAkB,WAAW,QAAQ;;;;;;;;AAS9C,SAAS,KAAqC,SAAe;CAC3D,OAAO,kBAAkB,QAAQ,QAAQ;;;;;;;;AAS3C,SAAS,SAAyC,SAAe;CAC/D,OAAO,kBAAkB,YAAY,QAAQ;;;;;;;;AAS/C,SAAS,KAAqC,SAAe;CAC3D,OAAO,kBAAkB,QAAQ,QAAQ;;;;;;;;;AAU3C,SAAS,MACP,QACA,SAIA;CACA,OAAO,kBAAuD,QAAQ,SAAS,QAAW,OAAO;;;;;;;;;;;;;;AAenG,SAAS,OACP,QACA,SACA;CAKA,OAJoB,kBAAkB,UAAU,SAAS,OAIvC;;AAGpB,MAAa,IAAI;CACf;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,MAAM;CACN;CACD"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/// <reference types="@tailor-platform/function-types" />
|
|
2
2
|
import { Vt as TailorInvoker } from "../../tailor-db-field-Bn8ZC5lK.mjs";
|
|
3
3
|
import { O as TailorDBType } from "../../workflow.generated-i7PK4fg-.mjs";
|
|
4
|
-
import { dt as WORKFLOW_TEST_ENV_KEY, n as output, xt as TailorField } from "../../index-
|
|
4
|
+
import { dt as WORKFLOW_TEST_ENV_KEY, n as output, xt as TailorField } from "../../index-DB8EapT-.mjs";
|
|
5
5
|
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
6
6
|
|
|
7
7
|
//#region src/utils/test/mock.d.ts
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/utils/test/mock.ts","../../../src/utils/test/index.ts"],"sourcesContent":["import * as path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { TailorInvoker } from \"@/types/user\";\n\ntype MainFunction = (args: Record<string, unknown>) => unknown | Promise<unknown>;\ntype QueryResolver = (query: string, params: unknown[]) => unknown[];\ntype JobHandler = (jobName: string, args: unknown) => unknown;\ntype WaitHandler = (key: string, payload: unknown) => unknown;\ntype ResolveHandler = (\n executionId: string,\n key: string,\n callback: (payload: unknown) => unknown,\n) => Promise<void> | void;\n\ninterface TailordbGlobal {\n tailordb?: {\n Client: new (config: { namespace?: string }) => {\n connect(): Promise<void> | void;\n end(): Promise<void> | void;\n queryObject(\n query: string,\n params?: unknown[],\n ): Promise<{ rows: unknown[] }> | { rows: unknown[] };\n };\n };\n tailor?: {\n workflow: {\n triggerJobFunction: (jobName: string, args: unknown) => unknown;\n wait?: (key: string, payload?: unknown) => unknown;\n resolve?: (\n executionId: string,\n key: string,\n callback: (payload: unknown) => unknown,\n ) => Promise<void>;\n };\n context: {\n getInvoker: () => tailor.context.Invoker | null;\n };\n };\n}\n\ninterface TailorErrorItem {\n message: string;\n path: (string | number)[];\n}\n\ninterface TailorErrorsGlobal {\n TailorErrors?: new (errors: TailorErrorItem[]) => Error;\n}\n\nconst GlobalThis = globalThis as TailordbGlobal & TailorErrorsGlobal;\n\n/**\n * Sets up a mock for `globalThis.tailordb.Client` used in bundled resolver/executor tests.\n * @deprecated Use `tailordbMock` from `@tailor-platform/sdk/vitest` with the `tailor-runtime` environment instead.\n * @param resolver - Optional function to resolve query results. Defaults to returning empty arrays.\n * @returns Object containing arrays of executed queries and created clients for assertions.\n */\nexport function setupTailordbMock(resolver: QueryResolver = () => []): {\n executedQueries: { query: string; params: unknown[] }[];\n createdClients: { namespace?: string; ended: boolean }[];\n} {\n const executedQueries: { query: string; params: unknown[] }[] = [];\n const createdClients: { namespace?: string; ended: boolean }[] = [];\n\n class MockTailordbClient {\n private record: { namespace?: string; ended: boolean };\n\n constructor({ namespace }: { namespace?: string }) {\n this.record = { namespace, ended: false };\n createdClients.push(this.record);\n }\n\n async connect(): Promise<void> {\n /* noop */\n }\n\n async end(): Promise<void> {\n this.record.ended = true;\n }\n\n async queryObject(query: string, params: unknown[] = []): Promise<{ rows: unknown[] }> {\n executedQueries.push({ query, params });\n return { rows: resolver(query, params) ?? [] };\n }\n }\n\n GlobalThis.tailordb = {\n Client: MockTailordbClient,\n } as typeof GlobalThis.tailordb;\n\n return { executedQueries, createdClients };\n}\n\n/**\n * Sets up a mock for `globalThis.tailor.workflow.triggerJobFunction` used in bundled workflow tests.\n * `wait`/`resolve` are stubbed to throw a helpful error directing to `workflowMock`,\n * so mistakenly calling wait without wait-point mocks produces a clear message instead of a TypeError.\n * @deprecated Use `workflowMock` from `@tailor-platform/sdk/vitest` with the `tailor-runtime` environment instead.\n * @param handler - Function that handles triggered job calls and returns results.\n * @returns Object containing an array of triggered jobs for assertions.\n */\nexport function setupWorkflowMock(handler: JobHandler): {\n triggeredJobs: { jobName: string; args: unknown }[];\n} {\n const triggeredJobs: { jobName: string; args: unknown }[] = [];\n\n GlobalThis.tailor = {\n ...GlobalThis.tailor,\n workflow: {\n wait: () => {\n throw new Error(\n \"tailor.workflow.wait is not mocked. Use workflowMock from @tailor-platform/sdk/vitest in tests.\",\n );\n },\n resolve: async () => {\n throw new Error(\n \"tailor.workflow.resolve is not mocked. Use workflowMock from @tailor-platform/sdk/vitest in tests.\",\n );\n },\n ...GlobalThis.tailor?.workflow,\n triggerJobFunction: (jobName: string, args: unknown) => {\n triggeredJobs.push({ jobName, args });\n return handler(jobName, args);\n },\n },\n } as typeof GlobalThis.tailor;\n\n return { triggeredJobs };\n}\n\n/**\n * Sets up a mock for `globalThis.tailor.context.getInvoker` used in bundled\n * resolver/executor/workflow tests.\n * @deprecated With the `tailor-runtime` environment from `@tailor-platform/sdk/vitest`, drive the invoker via `vi.spyOn(globalThis.tailor.context, \"getInvoker\").mockReturnValue(...)` for bundled tests, or pass `invoker` directly to `.body()` when unit-testing resolvers/executors/workflow jobs against the TypeScript source.\n * @param invoker - The `TailorInvoker` value to return, or `null` for anonymous.\n */\nexport function setupInvokerMock(invoker: TailorInvoker): void {\n const raw: tailor.context.Invoker | null = invoker\n ? {\n id: invoker.id,\n type: invoker.type,\n workspaceId: invoker.workspaceId,\n attributes: invoker.attributeList as string[],\n attributeMap: invoker.attributes as Record<string, unknown>,\n }\n : null;\n\n GlobalThis.tailor = {\n ...GlobalThis.tailor,\n context: {\n getInvoker: () => raw,\n },\n } as typeof GlobalThis.tailor;\n}\n\n/**\n * Sets up a mock for `globalThis.TailorErrors` used in bundled resolver tests.\n * Mimics the PF runtime's TailorErrors class that serializes errors with the `TailorErrors: ` prefix.\n * @deprecated Use the `tailor-runtime` environment from `@tailor-platform/sdk/vitest` which auto-injects TailorErrors.\n */\nexport function setupTailorErrorsMock(): void {\n GlobalThis.TailorErrors = class TailorErrors extends Error {\n errors: TailorErrorItem[];\n\n constructor(errors: TailorErrorItem[]) {\n super(`TailorErrors: ${JSON.stringify({ errors })}`);\n this.name = \"TailorErrors\";\n this.errors = errors;\n }\n };\n}\n\n/**\n * Sets up mocks for `globalThis.tailor.workflow.wait` and `.resolve` used in bundled workflow tests.\n * `triggerJobFunction` is stubbed to throw a helpful error directing to `setupWorkflowMock()`,\n * so mistakenly triggering a job without job mocks produces a clear message instead of silently returning undefined.\n * @deprecated Use `workflowMock` from `@tailor-platform/sdk/vitest` with the `tailor-runtime` environment instead.\n * `setWaitHandler` / `setResolveHandler` cover wait/resolve, and `waitCalls` / `resolveCalls` give the same assertion shape.\n * @param config - Optional handlers for wait and resolve calls.\n * @param config.onWait - Handler called when wait is invoked.\n * @param config.onResolve - Handler called when resolve is invoked.\n * @returns Object containing arrays of wait and resolve calls for assertions.\n */\nexport function setupWaitPointMock(config?: { onWait?: WaitHandler; onResolve?: ResolveHandler }): {\n waitCalls: { key: string; payload: unknown }[];\n resolveCalls: { executionId: string; key: string }[];\n} {\n const waitCalls: { key: string; payload: unknown }[] = [];\n const resolveCalls: { executionId: string; key: string }[] = [];\n\n GlobalThis.tailor = {\n ...GlobalThis.tailor,\n workflow: {\n triggerJobFunction: () => {\n throw new Error(\n \"tailor.workflow.triggerJobFunction is not mocked. Use setupWorkflowMock() in tests.\",\n );\n },\n ...GlobalThis.tailor?.workflow,\n wait: (key: string, payload?: unknown) => {\n waitCalls.push({ key, payload });\n return config?.onWait?.(key, payload);\n },\n resolve: async (\n executionId: string,\n key: string,\n callback: (payload: unknown) => unknown,\n ) => {\n resolveCalls.push({ executionId, key });\n await config?.onResolve?.(executionId, key, callback);\n },\n },\n } as typeof GlobalThis.tailor;\n\n return { waitCalls, resolveCalls };\n}\n\n/**\n * Creates a function that imports a bundled JS file and returns its `main` export.\n * Used to test bundled output from `apply --buildOnly`.\n * @param baseDir - Base directory where bundled files are located.\n * @returns An async function that takes a relative path and returns the `main` function.\n * @deprecated This is an SDK-internal testing helper. Bundling integrity is the SDK's responsibility,\n * not the application's — verify your code through unit tests against the TypeScript source and\n * E2E tests against a deployed application instead. This export will be removed in a future release.\n */\nexport function createImportMain(baseDir: string): (relativePath: string) => Promise<MainFunction> {\n return async (relativePath: string): Promise<MainFunction> => {\n const fileUrl = pathToFileURL(path.join(baseDir, relativePath));\n fileUrl.searchParams.set(\"v\", `${Date.now()}-${Math.random()}`);\n const module = await import(fileUrl.href);\n const main = module.main;\n if (typeof main !== \"function\") {\n throw new Error(`Expected \"main\" to be a function in ${relativePath}, got ${typeof main}`);\n }\n return main;\n };\n}\n","import type { output, TailorUser } from \"@/configure\";\nimport type { TailorDBType } from \"@/configure/services/tailordb/schema\";\nimport type { TailorField } from \"@/configure/types/type\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nexport { WORKFLOW_TEST_ENV_KEY } from \"@/configure/services/workflow/job\";\nexport {\n setupTailordbMock,\n setupTailorErrorsMock,\n setupWorkflowMock,\n setupInvokerMock,\n setupWaitPointMock,\n createImportMain,\n} from \"./mock\";\n\n/** Represents an unauthenticated user in the Tailor platform. */\nexport const unauthenticatedTailorUser = {\n id: \"00000000-0000-0000-0000-000000000000\",\n type: \"\",\n workspaceId: \"00000000-0000-0000-0000-000000000000\",\n attributes: null,\n attributeList: [],\n} as const satisfies TailorUser;\n\n/**\n * Creates a hook function that processes TailorDB type fields\n * - Uses existing id from data if provided, otherwise generates UUID for id fields\n * - Recursively processes nested types\n * - Executes hooks.create for fields with create hooks\n * @template T - The output type of the hook function\n * @param type - TailorDB type definition\n * @returns A function that transforms input data according to field hooks\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function createTailorDBHook<T extends TailorDBType<any, any>>(type: T) {\n return (data: unknown) => {\n return Object.entries(type.fields).reduce(\n (hooked, [key, value]) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const field = value as TailorField<any, any, any>;\n if (key === \"id\") {\n // Use existing id from data if provided, otherwise generate new UUID\n const existingId =\n data && typeof data === \"object\" ? (data as Record<string, unknown>)[key] : undefined;\n hooked[key] = existingId ?? crypto.randomUUID();\n } else if (field.type === \"nested\") {\n const nestedValue =\n data && typeof data === \"object\" ? (data as Record<string, unknown>)[key] : undefined;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const nestedHook = createTailorDBHook({ fields: field.fields } as any);\n if (field.metadata.array) {\n // For nested array fields, recurse per element and pass through non-array values\n // (e.g. null/undefined for optional fields) so validation sees the original value.\n hooked[key] = Array.isArray(nestedValue)\n ? nestedValue.map((item) => nestedHook(item))\n : nestedValue;\n } else {\n hooked[key] = nestedHook(nestedValue);\n }\n } else if (field.metadata.hooks?.create) {\n hooked[key] = field.metadata.hooks.create({\n value: (data as Record<string, unknown>)[key],\n data: data,\n user: unauthenticatedTailorUser,\n });\n if (hooked[key] instanceof Date) {\n hooked[key] = hooked[key].toISOString();\n }\n } else if (data && typeof data === \"object\") {\n hooked[key] = (data as Record<string, unknown>)[key];\n }\n return hooked;\n },\n {} as Record<string, unknown>,\n ) as Partial<output<T>>;\n };\n}\n\n/**\n * Creates the standard schema definition for lines-db\n * This returns the first argument for defineSchema with the ~standard section\n * @template T - The output type after validation\n * @param schemaType - TailorDB field schema for validation\n * @param hook - Hook function to transform data before validation\n * @returns Schema object with ~standard section for defineSchema\n */\nexport function createStandardSchema<T = Record<string, unknown>>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schemaType: TailorField<any, T>,\n hook: (data: unknown) => Partial<T>,\n) {\n return {\n \"~standard\": {\n version: 1,\n vendor: \"@tailor-platform/sdk\",\n validate: (value: unknown) => {\n const hooked = hook(value);\n const result = schemaType.parse({\n value: hooked,\n data: hooked,\n user: unauthenticatedTailorUser,\n });\n if (result.issues) {\n return result;\n }\n return { value: hooked as T };\n },\n },\n } as const satisfies StandardSchemaV1<T>;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../../src/utils/test/mock.ts","../../../src/utils/test/index.ts"],"sourcesContent":["import * as path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { TailorInvoker } from \"@/types/user\";\n\ntype MainFunction = (args: Record<string, unknown>) => unknown | Promise<unknown>;\ntype QueryResolver = (query: string, params: unknown[]) => unknown[];\ntype JobHandler = (jobName: string, args: unknown) => unknown;\ntype WaitHandler = (key: string, payload: unknown) => unknown;\ntype ResolveHandler = (\n executionId: string,\n key: string,\n callback: (payload: unknown) => unknown,\n) => Promise<void> | void;\n\ninterface TailordbGlobal {\n tailordb?: {\n Client: new (config: { namespace?: string }) => {\n connect(): Promise<void> | void;\n end(): Promise<void> | void;\n queryObject(\n query: string,\n params?: unknown[],\n ): Promise<{ rows: unknown[] }> | { rows: unknown[] };\n };\n };\n tailor?: {\n workflow: {\n triggerJobFunction: (jobName: string, args: unknown) => unknown;\n wait?: (key: string, payload?: unknown) => unknown;\n resolve?: (\n executionId: string,\n key: string,\n callback: (payload: unknown) => unknown,\n ) => Promise<void>;\n };\n context: {\n getInvoker: () => tailor.context.Invoker | null;\n };\n };\n}\n\ninterface TailorErrorItem {\n message: string;\n path: (string | number)[];\n}\n\ninterface TailorErrorsGlobal {\n TailorErrors?: new (errors: TailorErrorItem[]) => Error;\n}\n\nconst GlobalThis = globalThis as TailordbGlobal & TailorErrorsGlobal;\n\n/**\n * Sets up a mock for `globalThis.tailordb.Client` used in bundled resolver/executor tests.\n * @deprecated Use `tailordbMock` from `@tailor-platform/sdk/vitest` with the `tailor-runtime` environment instead.\n * @param resolver - Optional function to resolve query results. Defaults to returning empty arrays.\n * @returns Object containing arrays of executed queries and created clients for assertions.\n */\nexport function setupTailordbMock(resolver: QueryResolver = () => []): {\n executedQueries: { query: string; params: unknown[] }[];\n createdClients: { namespace?: string; ended: boolean }[];\n} {\n const executedQueries: { query: string; params: unknown[] }[] = [];\n const createdClients: { namespace?: string; ended: boolean }[] = [];\n\n class MockTailordbClient {\n private record: { namespace?: string; ended: boolean };\n\n constructor({ namespace }: { namespace?: string }) {\n this.record = { namespace, ended: false };\n createdClients.push(this.record);\n }\n\n async connect(): Promise<void> {\n /* noop */\n }\n\n async end(): Promise<void> {\n this.record.ended = true;\n }\n\n async queryObject(query: string, params: unknown[] = []): Promise<{ rows: unknown[] }> {\n executedQueries.push({ query, params });\n return { rows: resolver(query, params) ?? [] };\n }\n }\n\n GlobalThis.tailordb = {\n Client: MockTailordbClient,\n } as typeof GlobalThis.tailordb;\n\n return { executedQueries, createdClients };\n}\n\n/**\n * Sets up a mock for `globalThis.tailor.workflow.triggerJobFunction` used in bundled workflow tests.\n * `wait`/`resolve` are stubbed to throw a helpful error directing to `workflowMock`,\n * so mistakenly calling wait without wait-point mocks produces a clear message instead of a TypeError.\n * @deprecated Use `workflowMock` from `@tailor-platform/sdk/vitest` with the `tailor-runtime` environment instead.\n * @param handler - Function that handles triggered job calls and returns results.\n * @returns Object containing an array of triggered jobs for assertions.\n */\nexport function setupWorkflowMock(handler: JobHandler): {\n triggeredJobs: { jobName: string; args: unknown }[];\n} {\n const triggeredJobs: { jobName: string; args: unknown }[] = [];\n\n GlobalThis.tailor = {\n ...GlobalThis.tailor,\n workflow: {\n wait: () => {\n throw new Error(\n \"tailor.workflow.wait is not mocked. Use workflowMock from @tailor-platform/sdk/vitest in tests.\",\n );\n },\n resolve: async () => {\n throw new Error(\n \"tailor.workflow.resolve is not mocked. Use workflowMock from @tailor-platform/sdk/vitest in tests.\",\n );\n },\n ...GlobalThis.tailor?.workflow,\n triggerJobFunction: (jobName: string, args: unknown) => {\n triggeredJobs.push({ jobName, args });\n return handler(jobName, args);\n },\n },\n } as typeof GlobalThis.tailor;\n\n return { triggeredJobs };\n}\n\n/**\n * Sets up a mock for `globalThis.tailor.context.getInvoker` used in bundled\n * resolver/executor/workflow tests.\n * @deprecated With the `tailor-runtime` environment from `@tailor-platform/sdk/vitest`, drive the invoker via `vi.spyOn(globalThis.tailor.context, \"getInvoker\").mockReturnValue(...)` for bundled tests, or pass `invoker` directly to `.body()` when unit-testing resolvers/executors/workflow jobs against the TypeScript source.\n * @param invoker - The `TailorInvoker` value to return, or `null` for anonymous.\n */\nexport function setupInvokerMock(invoker: TailorInvoker): void {\n const raw: tailor.context.Invoker | null = invoker\n ? {\n id: invoker.id,\n type: invoker.type,\n workspaceId: invoker.workspaceId,\n attributes: invoker.attributeList as string[],\n attributeMap: invoker.attributes as Record<string, unknown>,\n }\n : null;\n\n GlobalThis.tailor = {\n ...GlobalThis.tailor,\n context: {\n getInvoker: () => raw,\n },\n } as typeof GlobalThis.tailor;\n}\n\n/**\n * Sets up a mock for `globalThis.TailorErrors` used in bundled resolver tests.\n * Mimics the PF runtime's TailorErrors class that serializes errors with the `TailorErrors: ` prefix.\n * @deprecated Use the `tailor-runtime` environment from `@tailor-platform/sdk/vitest` which auto-injects TailorErrors.\n */\nexport function setupTailorErrorsMock(): void {\n GlobalThis.TailorErrors = class TailorErrors extends Error {\n errors: TailorErrorItem[];\n\n constructor(errors: TailorErrorItem[]) {\n super(`TailorErrors: ${JSON.stringify({ errors })}`);\n this.name = \"TailorErrors\";\n this.errors = errors;\n }\n };\n}\n\n/**\n * Sets up mocks for `globalThis.tailor.workflow.wait` and `.resolve` used in bundled workflow tests.\n * `triggerJobFunction` is stubbed to throw a helpful error directing to `setupWorkflowMock()`,\n * so mistakenly triggering a job without job mocks produces a clear message instead of silently returning undefined.\n * @deprecated Use `workflowMock` from `@tailor-platform/sdk/vitest` with the `tailor-runtime` environment instead.\n * `setWaitHandler` / `setResolveHandler` cover wait/resolve, and `waitCalls` / `resolveCalls` give the same assertion shape.\n * @param config - Optional handlers for wait and resolve calls.\n * @param config.onWait - Handler called when wait is invoked.\n * @param config.onResolve - Handler called when resolve is invoked.\n * @returns Object containing arrays of wait and resolve calls for assertions.\n */\nexport function setupWaitPointMock(config?: { onWait?: WaitHandler; onResolve?: ResolveHandler }): {\n waitCalls: { key: string; payload: unknown }[];\n resolveCalls: { executionId: string; key: string }[];\n} {\n const waitCalls: { key: string; payload: unknown }[] = [];\n const resolveCalls: { executionId: string; key: string }[] = [];\n\n GlobalThis.tailor = {\n ...GlobalThis.tailor,\n workflow: {\n triggerJobFunction: () => {\n throw new Error(\n \"tailor.workflow.triggerJobFunction is not mocked. Use setupWorkflowMock() in tests.\",\n );\n },\n ...GlobalThis.tailor?.workflow,\n wait: (key: string, payload?: unknown) => {\n waitCalls.push({ key, payload });\n return config?.onWait?.(key, payload);\n },\n resolve: async (\n executionId: string,\n key: string,\n callback: (payload: unknown) => unknown,\n ) => {\n resolveCalls.push({ executionId, key });\n await config?.onResolve?.(executionId, key, callback);\n },\n },\n } as typeof GlobalThis.tailor;\n\n return { waitCalls, resolveCalls };\n}\n\n/**\n * Creates a function that imports a bundled JS file and returns its `main` export.\n * Used to test bundled output from `apply --buildOnly`.\n * @param baseDir - Base directory where bundled files are located.\n * @returns An async function that takes a relative path and returns the `main` function.\n * @deprecated This is an SDK-internal testing helper. Bundling integrity is the SDK's responsibility,\n * not the application's — verify your code through unit tests against the TypeScript source and\n * E2E tests against a deployed application instead. This export will be removed in a future release.\n */\nexport function createImportMain(baseDir: string): (relativePath: string) => Promise<MainFunction> {\n return async (relativePath: string): Promise<MainFunction> => {\n const fileUrl = pathToFileURL(path.join(baseDir, relativePath));\n fileUrl.searchParams.set(\"v\", `${Date.now()}-${Math.random()}`);\n const module = await import(fileUrl.href);\n const main = module.main;\n if (typeof main !== \"function\") {\n throw new Error(`Expected \"main\" to be a function in ${relativePath}, got ${typeof main}`);\n }\n return main;\n };\n}\n","import type { output, TailorUser } from \"@/configure\";\nimport type { TailorDBType } from \"@/configure/services/tailordb/schema\";\nimport type { TailorField } from \"@/configure/types/type\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\nexport { WORKFLOW_TEST_ENV_KEY } from \"@/configure/services/workflow/job\";\nexport {\n setupTailordbMock,\n setupTailorErrorsMock,\n setupWorkflowMock,\n setupInvokerMock,\n setupWaitPointMock,\n createImportMain,\n} from \"./mock\";\n\n/** Represents an unauthenticated user in the Tailor platform. */\nexport const unauthenticatedTailorUser = {\n id: \"00000000-0000-0000-0000-000000000000\",\n type: \"\",\n workspaceId: \"00000000-0000-0000-0000-000000000000\",\n attributes: null,\n attributeList: [],\n} as const satisfies TailorUser;\n\n/**\n * Creates a hook function that processes TailorDB type fields\n * - Uses existing id from data if provided, otherwise generates UUID for id fields\n * - Recursively processes nested types\n * - Executes hooks.create for fields with create hooks\n * @template T - The output type of the hook function\n * @param type - TailorDB type definition\n * @returns A function that transforms input data according to field hooks\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function createTailorDBHook<T extends TailorDBType<any, any>>(type: T) {\n return (data: unknown) => {\n return Object.entries(type.fields).reduce(\n (hooked, [key, value]) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const field = value as TailorField<any, any, any>;\n if (key === \"id\") {\n // Use existing id from data if provided, otherwise generate new UUID\n const existingId =\n data && typeof data === \"object\" ? (data as Record<string, unknown>)[key] : undefined;\n hooked[key] = existingId ?? crypto.randomUUID();\n } else if (field.type === \"nested\") {\n const nestedValue =\n data && typeof data === \"object\" ? (data as Record<string, unknown>)[key] : undefined;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const nestedHook = createTailorDBHook({ fields: field.fields } as any);\n if (field.metadata.array) {\n // For nested array fields, recurse per element and pass through non-array values\n // (e.g. null/undefined for optional fields) so validation sees the original value.\n hooked[key] = Array.isArray(nestedValue)\n ? nestedValue.map((item) => nestedHook(item))\n : nestedValue;\n } else {\n hooked[key] = nestedHook(nestedValue);\n }\n } else if (field.metadata.hooks?.create) {\n hooked[key] = field.metadata.hooks.create({\n value: (data as Record<string, unknown>)[key],\n data: data,\n user: unauthenticatedTailorUser,\n });\n if (hooked[key] instanceof Date) {\n hooked[key] = hooked[key].toISOString();\n }\n } else if (data && typeof data === \"object\") {\n hooked[key] = (data as Record<string, unknown>)[key];\n }\n return hooked;\n },\n {} as Record<string, unknown>,\n ) as Partial<output<T>>;\n };\n}\n\n/**\n * Creates the standard schema definition for lines-db\n * This returns the first argument for defineSchema with the ~standard section\n * @template T - The output type after validation\n * @param schemaType - TailorDB field schema for validation\n * @param hook - Hook function to transform data before validation\n * @returns Schema object with ~standard section for defineSchema\n */\nexport function createStandardSchema<T = Record<string, unknown>>(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schemaType: TailorField<any, T>,\n hook: (data: unknown) => Partial<T>,\n) {\n return {\n \"~standard\": {\n version: 1,\n vendor: \"@tailor-platform/sdk\",\n validate: (value: unknown) => {\n const hooked = hook(value);\n const result = schemaType.parse({\n value: hooked,\n data: hooked,\n user: unauthenticatedTailorUser,\n });\n if (result.issues) {\n return result;\n }\n return { value: hooked as T };\n },\n },\n } as const satisfies StandardSchemaV1<T>;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.mjs","names":[],"sources":["../../src/vitest/environment.ts"],"sourcesContent":["import * as globals from \"globals\";\nimport { STATE_KEY, RUNTIME_FLAG_KEY, injectMocks, cleanupMocks } from \"./mock\";\n\n// Normalize the `globals` module shape across CJS/ESM interop so the\n// whitelist build doesn't crash if the default export is unavailable or\n// the keyed sets are missing. Mirrors src/cli/services/tailordb/es-builtins.ts.\ntype GlobalsShape = {\n builtin?: Record<string, boolean>;\n \"shared-node-browser\"?: Record<string, boolean>;\n};\nconst globalsMap: GlobalsShape =\n (globals as unknown as { default?: GlobalsShape }).default ??\n (globals as unknown as GlobalsShape);\n\n// Globals allowed in the Tailor Platform runtime.\n// Mirrors ES_BUILTINS in src/cli/services/tailordb/es-builtins.ts so the\n// emulated runtime exposes exactly the same identifiers as the production\n// platform's free-variable allowlist (ECMAScript builtins + shared\n// Node/browser runtime globals like console, fetch, setTimeout).\n// Platform API mocks (tailor, tailordb, etc.) are not listed here — they are\n// injected by injectMocks() after the whitelist cleanup, so they are never removed.\nconst ALLOWED_GLOBALS = new Set([\n ...Object.keys(globalsMap.builtin ?? {}),\n ...Object.keys(globalsMap[\"shared-node-browser\"] ?? {}),\n\n // Mock state key (lazily populated by mock helpers) and the\n // environment-active flag (set in injectMocks, used by setup.ts to detect\n // the tailor-runtime environment).\n STATE_KEY,\n RUNTIME_FLAG_KEY,\n\n // Used by Vitest internally — not in the platform runtime, but removing breaks the test runner\n \"process\",\n \"require\",\n \"module\",\n \"exports\",\n \"__vitest_worker__\",\n \"__vitest_mocker__\",\n \"VITEST_POOL_ID\",\n]);\n\nexport default {\n name: \"tailor-runtime\",\n viteEnvironment: \"ssr\",\n\n async setup(global: typeof globalThis) {\n const g = global as Record<string, unknown>;\n\n // Save and remove all non-whitelisted globals\n const saved: Record<string, PropertyDescriptor> = {};\n for (const key of Object.getOwnPropertyNames(g)) {\n if (!ALLOWED_GLOBALS.has(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(g, key);\n if (descriptor?.configurable) {\n saved[key] = descriptor;\n delete g[key];\n }\n }\n }\n\n // Inject platform API mocks after whitelist cleanup\n injectMocks(global);\n\n return {\n teardown(global: typeof globalThis) {\n cleanupMocks(global);\n\n // Restore removed globals\n const g = global as Record<string, unknown>;\n for (const [key, descriptor] of Object.entries(saved)) {\n Object.defineProperty(g, key, descriptor);\n }\n },\n };\n },\n};\n"],"mappings":";;;;;AAUA,MAAM,aACH,QAAkD,WAClD;AASH,MAAM,kBAAkB,IAAI,IAAI;CAC9B,GAAG,OAAO,KAAK,WAAW,WAAW,EAAE,CAAC;CACxC,GAAG,OAAO,KAAK,WAAW,0BAA0B,EAAE,CAAC;CAKvD;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,0BAAe;CACb,MAAM;CACN,iBAAiB;CAEjB,MAAM,MAAM,QAA2B;EACrC,MAAM,IAAI;EAGV,MAAM,QAA4C,EAAE;
|
|
1
|
+
{"version":3,"file":"environment.mjs","names":[],"sources":["../../src/vitest/environment.ts"],"sourcesContent":["import * as globals from \"globals\";\nimport { STATE_KEY, RUNTIME_FLAG_KEY, injectMocks, cleanupMocks } from \"./mock\";\n\n// Normalize the `globals` module shape across CJS/ESM interop so the\n// whitelist build doesn't crash if the default export is unavailable or\n// the keyed sets are missing. Mirrors src/cli/services/tailordb/es-builtins.ts.\ntype GlobalsShape = {\n builtin?: Record<string, boolean>;\n \"shared-node-browser\"?: Record<string, boolean>;\n};\nconst globalsMap: GlobalsShape =\n (globals as unknown as { default?: GlobalsShape }).default ??\n (globals as unknown as GlobalsShape);\n\n// Globals allowed in the Tailor Platform runtime.\n// Mirrors ES_BUILTINS in src/cli/services/tailordb/es-builtins.ts so the\n// emulated runtime exposes exactly the same identifiers as the production\n// platform's free-variable allowlist (ECMAScript builtins + shared\n// Node/browser runtime globals like console, fetch, setTimeout).\n// Platform API mocks (tailor, tailordb, etc.) are not listed here — they are\n// injected by injectMocks() after the whitelist cleanup, so they are never removed.\nconst ALLOWED_GLOBALS = new Set([\n ...Object.keys(globalsMap.builtin ?? {}),\n ...Object.keys(globalsMap[\"shared-node-browser\"] ?? {}),\n\n // Mock state key (lazily populated by mock helpers) and the\n // environment-active flag (set in injectMocks, used by setup.ts to detect\n // the tailor-runtime environment).\n STATE_KEY,\n RUNTIME_FLAG_KEY,\n\n // Used by Vitest internally — not in the platform runtime, but removing breaks the test runner\n \"process\",\n \"require\",\n \"module\",\n \"exports\",\n \"__vitest_worker__\",\n \"__vitest_mocker__\",\n \"VITEST_POOL_ID\",\n]);\n\nexport default {\n name: \"tailor-runtime\",\n viteEnvironment: \"ssr\",\n\n async setup(global: typeof globalThis) {\n const g = global as Record<string, unknown>;\n\n // Save and remove all non-whitelisted globals\n const saved: Record<string, PropertyDescriptor> = {};\n for (const key of Object.getOwnPropertyNames(g)) {\n if (!ALLOWED_GLOBALS.has(key)) {\n const descriptor = Object.getOwnPropertyDescriptor(g, key);\n if (descriptor?.configurable) {\n saved[key] = descriptor;\n delete g[key];\n }\n }\n }\n\n // Inject platform API mocks after whitelist cleanup\n injectMocks(global);\n\n return {\n teardown(global: typeof globalThis) {\n cleanupMocks(global);\n\n // Restore removed globals\n const g = global as Record<string, unknown>;\n for (const [key, descriptor] of Object.entries(saved)) {\n Object.defineProperty(g, key, descriptor);\n }\n },\n };\n },\n};\n"],"mappings":";;;;;AAUA,MAAM,aACH,QAAkD,WAClD;AASH,MAAM,kBAAkB,IAAI,IAAI;CAC9B,GAAG,OAAO,KAAK,WAAW,WAAW,EAAE,CAAC;CACxC,GAAG,OAAO,KAAK,WAAW,0BAA0B,EAAE,CAAC;CAKvD;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,0BAAe;CACb,MAAM;CACN,iBAAiB;CAEjB,MAAM,MAAM,QAA2B;EACrC,MAAM,IAAI;EAGV,MAAM,QAA4C,EAAE;EACpD,KAAK,MAAM,OAAO,OAAO,oBAAoB,EAAE,EAC7C,IAAI,CAAC,gBAAgB,IAAI,IAAI,EAAE;GAC7B,MAAM,aAAa,OAAO,yBAAyB,GAAG,IAAI;GAC1D,IAAI,YAAY,cAAc;IAC5B,MAAM,OAAO;IACb,OAAO,EAAE;;;EAMf,YAAY,OAAO;EAEnB,OAAO,EACL,SAAS,QAA2B;GAClC,aAAa,OAAO;GAGpB,MAAM,IAAI;GACV,KAAK,MAAM,CAAC,KAAK,eAAe,OAAO,QAAQ,MAAM,EACnD,OAAO,eAAe,GAAG,KAAK,WAAW;KAG9C;;CAEJ"}
|