@tailor-platform/sdk 2.4.0 → 2.6.0
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 +131 -0
- package/bin/tailor.mjs +3 -2
- package/dist/aigateway-DsWDjzk4.mjs +2 -0
- package/dist/{aigateway-DR4Kwuik.mjs.map → aigateway-DsWDjzk4.mjs.map} +1 -1
- package/dist/application-CNeOcaLc.mjs +1 -0
- package/dist/application-CmXOqTaK.mjs +192 -0
- package/dist/application-CmXOqTaK.mjs.map +1 -0
- package/dist/assert-WeXvmG4j.mjs +2 -0
- package/dist/{assert-DBxo8jPo.mjs.map → assert-WeXvmG4j.mjs.map} +1 -1
- package/dist/authconnection-CynFBIv8.mjs +2 -0
- package/dist/{authconnection-CZvi9ANm.mjs.map → authconnection-CynFBIv8.mjs.map} +1 -1
- package/dist/brand-C8nMKhJC.mjs +2 -0
- package/dist/{brand-Eo4pLXPJ.mjs.map → brand-C8nMKhJC.mjs.map} +1 -1
- package/dist/cli/commands/api/index.d.mts +1 -1
- package/dist/cli/commands/deploy/deploy.d.mts +2 -2
- package/dist/cli/commands/deploy/deployment-target.d.mts +2 -0
- package/dist/cli/commands/deploy/event-subscriptions.d.mts +3 -0
- package/dist/cli/commands/deploy/tailordb/apply.d.mts +3 -0
- package/dist/cli/commands/deploy/tailordb/index.d.mts +3 -10
- package/dist/cli/commands/deploy/tailordb/migration-validation.d.mts +5 -0
- package/dist/cli/commands/deploy/tailordb/plan.d.mts +8 -0
- package/dist/cli/commands/executor/jobs.d.mts +1 -1
- package/dist/cli/commands/executor/trigger.d.mts +1 -1
- package/dist/cli/commands/generate/seed/bundler.d.mts +2 -2
- package/dist/cli/commands/show.d.mts +1 -1
- package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +11 -11
- package/dist/cli/commands/tailordb/migrate/generate.d.mts +4 -0
- package/dist/cli/commands/tailordb/migrate/rename-detection.d.mts +1 -1
- package/dist/cli/commands/tailordb/migrate/snapshot-comparison.d.mts +43 -0
- package/dist/cli/commands/tailordb/migrate/snapshot-files.d.mts +62 -0
- package/dist/cli/commands/tailordb/migrate/snapshot-local.d.mts +12 -0
- package/dist/cli/commands/tailordb/migrate/snapshot-migrations.d.mts +12 -0
- package/dist/cli/commands/tailordb/migrate/snapshot-remote.d.mts +1 -0
- package/dist/cli/commands/tailordb/migrate/snapshot-types.d.mts +3 -1
- package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +5 -117
- package/dist/cli/commands/workflow/start.d.mts +1 -1
- package/dist/cli/commands/workspace/list.d.mts +1 -1
- package/dist/cli/lib.d.mts +12 -4
- package/dist/cli/lib.mjs +1 -9
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/main.d.mts +2 -0
- package/dist/cli/main.mjs +1170 -7754
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/shared/args.d.mts +65 -1
- package/dist/cli/shared/command.d.mts +11 -0
- package/dist/cli/shared/context.d.mts +1 -1
- package/dist/cli/shared/logger.d.mts +64 -0
- package/dist/cli/shared/script-executor.d.mts +1 -1
- package/dist/cli/shared/seed-chunker.d.mts +5 -5
- package/dist/completion/zsh-worker.zsh +82 -9
- package/dist/configure/config/index.d.mts +1 -1
- package/dist/configure/config/types.d.mts +2 -2
- package/dist/configure/index.d.mts +48 -12
- package/dist/configure/index.mjs +1 -1267
- package/dist/configure/index.mjs.map +1 -1
- package/dist/configure/services/auth/types.d.mts +1 -1
- package/dist/configure/services/idp/types.d.mts +1 -1
- package/dist/configure/services/tailordb/schema.d.mts +22 -8
- package/dist/configure/services/tailordb/types.d.mts +2 -2
- package/dist/configure/services/workflow/execution-policy.d.mts +3 -3
- package/dist/configure/services/workflow/job.d.mts +12 -2
- package/dist/configure/types/field.types.d.mts +1 -1
- package/dist/configure/types/permission-operand.types.d.mts +1 -1
- package/dist/context-D0QjfxzD.mjs +2 -0
- package/dist/{context-DYQVYWqZ.mjs.map → context-D0QjfxzD.mjs.map} +1 -1
- package/dist/crashreport-BN28xp5B.mjs +42 -0
- package/dist/{crashreport-Q0pDAlrj.mjs.map → crashreport-BN28xp5B.mjs.map} +1 -1
- package/dist/crashreport-By23O2k-.mjs +1 -0
- package/dist/errors-DLsQ_-ol.mjs +2 -0
- package/dist/errors-DLsQ_-ol.mjs.map +1 -0
- package/dist/es-builtins-n3wBv4Sv.mjs +2 -0
- package/dist/es-builtins-n3wBv4Sv.mjs.map +1 -0
- package/dist/file-COPYfju_.mjs +2 -0
- package/dist/file-COPYfju_.mjs.map +1 -0
- package/dist/globals-CMHSnj4w.mjs +2 -0
- package/dist/{globals-B2nlxBrz.mjs.map → globals-CMHSnj4w.mjs.map} +1 -1
- package/dist/iconv-DlFMt2gW.mjs +2 -0
- package/dist/{iconv-QWaZh0TT.mjs.map → iconv-DlFMt2gW.mjs.map} +1 -1
- package/dist/idp-G_ojPBB5.mjs +2 -0
- package/dist/{idp-RA_swu-h.mjs.map → idp-G_ojPBB5.mjs.map} +1 -1
- package/dist/interceptor-DQg3cR_9.mjs +2 -0
- package/dist/{interceptor-e33JtsC-.mjs.map → interceptor-DQg3cR_9.mjs.map} +1 -1
- package/dist/kysely/index.mjs +1 -32
- package/dist/kysely/index.mjs.map +1 -1
- package/dist/kysely-type-BTi3BMtL.mjs +43 -0
- package/dist/kysely-type-BTi3BMtL.mjs.map +1 -0
- package/dist/logger-CCjs1DuH.mjs +9 -0
- package/dist/logger-CCjs1DuH.mjs.map +1 -0
- package/dist/logger-DP2BjQ93.mjs +2 -0
- package/dist/{logger-BtX0suGY.mjs.map → logger-DP2BjQ93.mjs.map} +1 -1
- package/dist/multiline-EyzjEwn9.mjs +3 -0
- package/dist/{multiline-sfHpTZZK.mjs.map → multiline-EyzjEwn9.mjs.map} +1 -1
- package/dist/node-builtins-oBl7EbyV.mjs +2 -0
- package/dist/{node-builtins-CmaL2Cbq.mjs.map → node-builtins-oBl7EbyV.mjs.map} +1 -1
- package/dist/package-json-C690ceex.mjs +2 -0
- package/dist/{package-json-8b0O9TlX.mjs.map → package-json-C690ceex.mjs.map} +1 -1
- package/dist/package-json-CmqhDJ__.mjs +1 -0
- package/dist/parser/service/tailordb/type-source.d.mts +5 -5
- package/dist/parser/service/tailordb/types.d.mts +4 -4
- package/dist/platform-serialize-DkiTdHOt.mjs +2 -0
- package/dist/{platform-serialize-RoRtBS0v.mjs.map → platform-serialize-DkiTdHOt.mjs.map} +1 -1
- package/dist/plugin/builtin/enum-constants/index.mjs +5 -114
- package/dist/plugin/builtin/enum-constants/index.mjs.map +1 -1
- package/dist/plugin/builtin/file-utils/index.mjs +22 -104
- package/dist/plugin/builtin/file-utils/index.mjs.map +1 -1
- package/dist/plugin/builtin/kysely-type/index.d.mts +8 -1
- package/dist/plugin/builtin/kysely-type/index.mjs +1 -275
- package/dist/plugin/builtin/seed/index.d.mts +5 -0
- package/dist/plugin/builtin/seed/index.mjs +1 -3
- package/dist/plugin/builtin/seed/seed-type-processor.d.mts +0 -2
- package/dist/plugin/{get-generated-type.d.mts → get-generated-table.d.mts} +5 -5
- package/dist/plugin/index.d.mts +3 -2
- package/dist/plugin/index.mjs +1 -251
- package/dist/plugin/index.mjs.map +1 -1
- package/dist/plugin/types.d.mts +30 -23
- package/dist/plugin/with-context.d.mts +3 -3
- package/dist/register-ts-hook-oDA2JLp2.mjs +640 -0
- package/dist/register-ts-hook-oDA2JLp2.mjs.map +1 -0
- package/dist/registry-HlEaGvl5.mjs +2 -0
- package/dist/{registry-BIGVUrMB.mjs.map → registry-HlEaGvl5.mjs.map} +1 -1
- package/dist/repl-editor-BG1aDOfH.mjs +2 -0
- package/dist/{repl-editor-F9LotMNx.mjs.map → repl-editor-BG1aDOfH.mjs.map} +1 -1
- package/dist/runtime/aigateway.mjs +1 -3
- package/dist/runtime/authconnection.mjs +1 -3
- package/dist/runtime/context.mjs +1 -3
- package/dist/runtime/file.d.mts +21 -21
- package/dist/runtime/file.mjs +1 -3
- package/dist/runtime/globals.mjs +1 -1
- package/dist/runtime/iconv.mjs +1 -3
- package/dist/runtime/idp.mjs +1 -3
- package/dist/runtime/index.mjs +1 -11
- package/dist/runtime/logger.mjs +1 -3
- package/dist/runtime/secretmanager.mjs +1 -3
- package/dist/runtime/types.d.mts +1 -1
- package/dist/runtime/workflow.mjs +1 -3
- package/dist/schema-AYG4OhXY.mjs +2 -0
- package/dist/schema-AYG4OhXY.mjs.map +1 -0
- package/dist/secret-file-C9wp_FCX.mjs +2 -0
- package/dist/{secret-file-C3J4Gy8r.mjs.map → secret-file-C9wp_FCX.mjs.map} +1 -1
- package/dist/secretmanager-5olfnI1b.mjs +2 -0
- package/dist/{secretmanager-IY4UvinW.mjs.map → secretmanager-5olfnI1b.mjs.map} +1 -1
- package/dist/secretmanager-vHQoXdQz.mjs +2 -0
- package/dist/{secretmanager-CYlpffsz.mjs.map → secretmanager-vHQoXdQz.mjs.map} +1 -1
- package/dist/seed/index.mjs +8 -244
- package/dist/seed/index.mjs.map +1 -1
- package/dist/seed-DwqRFdqP.mjs +207 -0
- package/dist/seed-DwqRFdqP.mjs.map +1 -0
- package/dist/service-CLPMoj9n.mjs +2 -0
- package/dist/{service-LTfp03ZZ.mjs.map → service-CLPMoj9n.mjs.map} +1 -1
- package/dist/service-D7iXk0BT.mjs +1 -0
- package/dist/service-YqDsHmlK.mjs +7 -0
- package/dist/service-YqDsHmlK.mjs.map +1 -0
- package/dist/service_pb-DGKCLuAs.mjs +2 -0
- package/dist/{service_pb-BEWj1pOV.mjs.map → service_pb-DGKCLuAs.mjs.map} +1 -1
- package/dist/service_pb-_aeFE-Nv.mjs +1 -0
- package/dist/shared/src/color.d.mts +5 -0
- package/dist/tailor-proto/src/tailor/v1/workspace_pb.d.mts +1 -1
- package/dist/telemetry-Bklv9kQY.mjs +2 -0
- package/dist/{telemetry-BRVdwh14.mjs.map → telemetry-Bklv9kQY.mjs.map} +1 -1
- package/dist/telemetry-DXHP3VVi.mjs +1 -0
- package/dist/type-source--ZNcV8RJ.mjs +2 -0
- package/dist/type-source--ZNcV8RJ.mjs.map +1 -0
- package/dist/types/executor.generated.d.mts +1 -1
- package/dist/user-agent-vdHYF3QL.mjs +2 -0
- package/dist/{user-agent-Bgsszb5I.mjs.map → user-agent-vdHYF3QL.mjs.map} +1 -1
- package/dist/utils/test/index.mjs +1 -109
- package/dist/utils/test/index.mjs.map +1 -1
- package/dist/vitest/environment.mjs +1 -41
- package/dist/vitest/environment.mjs.map +1 -1
- package/dist/vitest/index.mjs +1 -1986
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/vitest/mocks/file.d.mts +8 -8
- package/dist/vitest/setup.mjs +1 -140
- package/dist/vitest/setup.mjs.map +1 -1
- package/dist/wait-point-invoker-eiP-IIux.mjs +2 -0
- package/dist/wait-point-invoker-eiP-IIux.mjs.map +1 -0
- package/dist/wait-point-registry-B-ESkTZX.mjs +2 -0
- package/dist/wait-point-registry-B-ESkTZX.mjs.map +1 -0
- package/dist/workflow-Cs9ISw6j.mjs +2 -0
- package/dist/{workflow-Bamae_Yc.mjs.map → workflow-Cs9ISw6j.mjs.map} +1 -1
- package/dist/workspace_resource_pb--GeYQPXu.mjs +2 -0
- package/dist/{workspace_resource_pb-HNIL_Vfj.mjs.map → workspace_resource_pb--GeYQPXu.mjs.map} +1 -1
- package/docs/cli/function.md +66 -6
- package/docs/cli/setup.md +24 -14
- package/docs/cli/tailordb.md +2 -0
- package/docs/cli-reference.md +9 -8
- package/docs/github-actions.md +14 -12
- package/docs/migration/v2.md +18 -2
- package/docs/migration/v3.md +121 -0
- package/docs/plugin/custom.md +130 -85
- package/docs/plugin/index.md +3 -3
- package/docs/services/tailordb-migration.md +21 -7
- package/docs/services/tailordb.md +9 -7
- package/docs/services/workflow.md +10 -9
- package/package.json +14 -13
- package/postinstall.mjs +1 -1
- package/dist/aigateway-DR4Kwuik.mjs +0 -9
- package/dist/application-C8a0UJ-z.mjs +0 -6071
- package/dist/application-C8a0UJ-z.mjs.map +0 -1
- package/dist/application-D4zOiLLa.mjs +0 -3
- package/dist/assert-DBxo8jPo.mjs +0 -9
- package/dist/authconnection-CZvi9ANm.mjs +0 -9
- package/dist/brand-Eo4pLXPJ.mjs +0 -36
- package/dist/context-DYQVYWqZ.mjs +0 -23
- package/dist/crashreport-Cd4TqfZq.mjs +0 -3
- package/dist/crashreport-Q0pDAlrj.mjs +0 -427
- package/dist/errors-Bxut5_Sy.mjs +0 -89
- package/dist/errors-Bxut5_Sy.mjs.map +0 -1
- package/dist/file-BUcmVIH2.mjs +0 -58
- package/dist/file-BUcmVIH2.mjs.map +0 -1
- package/dist/globals-B2nlxBrz.mjs +0 -126
- package/dist/iconv-QWaZh0TT.mjs +0 -38
- package/dist/idp-RA_swu-h.mjs +0 -82
- package/dist/interceptor-e33JtsC-.mjs +0 -33
- package/dist/logger-BtX0suGY.mjs +0 -48
- package/dist/logger-D0bEznPv.mjs +0 -362
- package/dist/logger-D0bEznPv.mjs.map +0 -1
- package/dist/multiline-sfHpTZZK.mjs +0 -38
- package/dist/node-builtins-CmaL2Cbq.mjs +0 -36
- package/dist/package-json-8b0O9TlX.mjs +0 -17
- package/dist/package-json-Cv2Z-TqQ.mjs +0 -3
- package/dist/platform-serialize-RoRtBS0v.mjs +0 -46
- package/dist/plugin/builtin/kysely-type/index.mjs.map +0 -1
- package/dist/plugin/builtin/seed/types.d.mts +0 -2
- package/dist/register-ts-hook-Vqjza10T.mjs +0 -25679
- package/dist/register-ts-hook-Vqjza10T.mjs.map +0 -1
- package/dist/registry-BIGVUrMB.mjs +0 -54
- package/dist/repl-editor-F9LotMNx.mjs +0 -252
- package/dist/schema-D4TC4BC3.mjs +0 -640
- package/dist/schema-D4TC4BC3.mjs.map +0 -1
- package/dist/secret-file-C3J4Gy8r.mjs +0 -64
- package/dist/secretmanager-CYlpffsz.mjs +0 -13
- package/dist/secretmanager-IY4UvinW.mjs +0 -131
- package/dist/seed-Cibjmtry.mjs +0 -489
- package/dist/seed-Cibjmtry.mjs.map +0 -1
- package/dist/service-2grcAOCJ.mjs +0 -898
- package/dist/service-2grcAOCJ.mjs.map +0 -1
- package/dist/service-CaBPNDIZ.mjs +0 -3
- package/dist/service-LTfp03ZZ.mjs +0 -133
- package/dist/service_pb-BEWj1pOV.mjs +0 -167
- package/dist/service_pb-BjlhvK9E.mjs +0 -3
- package/dist/telemetry-BRVdwh14.mjs +0 -84
- package/dist/telemetry-CkbkeJxl.mjs +0 -3
- package/dist/type-source-DH_LH20p.mjs +0 -13
- package/dist/type-source-DH_LH20p.mjs.map +0 -1
- package/dist/user-agent-Bgsszb5I.mjs +0 -28
- package/dist/wait-point-invoker-__oE88_P.mjs +0 -148
- package/dist/wait-point-invoker-__oE88_P.mjs.map +0 -1
- package/dist/wait-point-registry-TL99zotw.mjs +0 -47
- package/dist/wait-point-registry-TL99zotw.mjs.map +0 -1
- package/dist/workflow-Bamae_Yc.mjs +0 -34
- package/dist/workspace_resource_pb-HNIL_Vfj.mjs +0 -860
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=Symbol.for(`tailor-platform/sdk:job-registry`);function jobs(){let t=globalThis,n=t[e];return n||(n=new Map,t[e]=n),n}function registerJob(e,t){jobs().set(e,t)}function getRegisteredJob(e){return jobs().get(e)}function currentPlatformWorkflow(){return globalThis.tailor?.workflow}function requirePlatformWorkflow(){let e=currentPlatformWorkflow();if(!e)throw Error("tailor.workflow is not available. Run tests in the `tailor-runtime` Vitest environment and use mockWorkflow(), or use runWorkflowLocally() from @tailor-platform/sdk/vitest for local workflow execution.");return e}const t=`00000000-0000-4000-8000-000000000000`;function dispatchStartJob(e,t,n){let r=requirePlatformWorkflow();return arguments.length>=3?r.execJobFunction(e,t,n):r.execJobFunction(e,t)}function dispatchStartWorkflow(e,t,n){let r=requirePlatformWorkflow();return arguments.length<3?r.startWorkflow(e,t):r.startWorkflow(e,t,n?.invoker===void 0?n:{authInvoker:n.invoker})}export{registerJob as a,getRegisteredJob as i,dispatchStartJob as n,dispatchStartWorkflow as r,t};
|
|
2
|
+
//# sourceMappingURL=registry-HlEaGvl5.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry-
|
|
1
|
+
{"version":3,"file":"registry-HlEaGvl5.mjs","names":[],"sources":["../src/configure/services/workflow/registry.ts"],"sourcesContent":["import type { TailorEnv, TailorPrincipal } from \"#/runtime/types\";\nimport type { ExecJobFunctionOptions, StartWorkflowOptions } from \"#/runtime/workflow\";\n\n/**\n * Body signature shared by workflow jobs at registry-write time.\n * The user's `createWorkflowJob`/`createWorkflow` body uses concrete types,\n * but the registry erases them for storage.\n */\nexport type RegisteredJobBody = (\n args: unknown,\n context: { env: TailorEnv; invoker: TailorPrincipal | null },\n) => unknown | Promise<unknown>;\n\nconst JOB_REGISTRY_KEY: unique symbol = Symbol.for(\"tailor-platform/sdk:job-registry\");\n\ntype PlatformWorkflow = {\n startWorkflow: (name: string, args?: unknown, options?: StartWorkflowOptions) => Promise<string>;\n execJobFunction: (name: string, args?: unknown, options?: ExecJobFunctionOptions) => unknown;\n};\n\ntype GlobalWithRegistry = typeof globalThis & {\n [JOB_REGISTRY_KEY]?: Map<string, RegisteredJobBody>;\n tailor?: { workflow?: PlatformWorkflow };\n};\n\nfunction jobs(): Map<string, RegisteredJobBody> {\n const g = globalThis as GlobalWithRegistry;\n let map = g[JOB_REGISTRY_KEY];\n if (!map) {\n map = new Map();\n g[JOB_REGISTRY_KEY] = map;\n }\n return map;\n}\n\n/**\n * Register a job body keyed by job name. Called as a side effect by\n * `createWorkflowJob` so `runWorkflowLocally()` can execute dependent job\n * bodies when `globalThis.tailor.workflow.execJobFunction(name, args)` is invoked.\n *\n * In production builds the bundler rewrites `.start()` calls so this registry\n * is never read; the gated write is dropped as dead code.\n * @param name - Job name\n * @param body - Job body function\n */\nexport function registerJob(name: string, body: RegisteredJobBody): void {\n jobs().set(name, body);\n}\n\n/**\n * Look up a registered job body by name.\n * @param name - Job name\n * @returns The registered body, or undefined when no job is registered\n */\nexport function getRegisteredJob(name: string): RegisteredJobBody | undefined {\n return jobs().get(name);\n}\n\nfunction currentPlatformWorkflow(): PlatformWorkflow | undefined {\n // globalThis may not have the tailor property at runtime\n // oxlint-disable-next-line typescript/no-unnecessary-condition\n return (globalThis as GlobalWithRegistry).tailor?.workflow;\n}\n\nfunction requirePlatformWorkflow(): PlatformWorkflow {\n const workflow = currentPlatformWorkflow();\n if (!workflow) {\n throw new Error(\n \"tailor.workflow is not available. Run tests in the `tailor-runtime` Vitest environment and use mockWorkflow(), or use runWorkflowLocally() from @tailor-platform/sdk/vitest for local workflow execution.\",\n );\n }\n return workflow;\n}\n\n// A valid placeholder UUID, so callers that validate the execution id behave the\n// same locally as against the platform.\nexport const START_DEFAULT = \"00000000-0000-4000-8000-000000000000\";\n\n// `.start()` routes through the installed `tailor.workflow` shim. Local body\n// execution is intentionally available only through `runWorkflowLocally()`.\n// Preserve arity: the shim sees a 2-argument call when the caller supplied no\n// options, and a 3-argument call otherwise, mirroring the bundler rewrite so\n// mocks observe the same shape in local execution and in bundled workflows.\nexport function dispatchStartJob(\n name: string,\n args?: unknown,\n options?: ExecJobFunctionOptions,\n): unknown {\n const workflow = requirePlatformWorkflow();\n // oxlint-disable-next-line prefer-rest-params\n return arguments.length >= 3\n ? workflow.execJobFunction(name, args, options)\n : workflow.execJobFunction(name, args);\n}\n\n// Accepts `unknown` because the SDK-side `.start()` accepts a wider options\n// shape than the platform surface (e.g. `authInvoker` may be a machine-user\n// name string that the bundler normalizes at build time). Local execution\n// forwards the value verbatim; only the bundled path enforces the platform\n// contract.\nexport function dispatchStartWorkflow(\n name: string,\n args?: unknown,\n options?: { invoker?: unknown },\n): Promise<string> {\n const workflow = requirePlatformWorkflow();\n // oxlint-disable-next-line prefer-rest-params\n if (arguments.length < 3) {\n return workflow.startWorkflow(name, args);\n }\n return workflow.startWorkflow(\n name,\n args,\n options?.invoker === undefined\n ? (options as StartWorkflowOptions | undefined)\n : ({ authInvoker: options.invoker } as StartWorkflowOptions),\n );\n}\n"],"mappings":"AAaA,MAAM,EAAkC,OAAO,IAAI,kCAAkC,EAYrF,SAAS,MAAuC,CAC9C,IAAM,EAAI,WACN,EAAM,EAAE,GAKZ,OAJK,IACH,EAAM,IAAI,IACV,EAAE,GAAoB,GAEjB,CACT,CAYA,SAAgB,YAAY,EAAc,EAA+B,CACvE,KAAK,CAAC,CAAC,IAAI,EAAM,CAAI,CACvB,CAOA,SAAgB,iBAAiB,EAA6C,CAC5E,OAAO,KAAK,CAAC,CAAC,IAAI,CAAI,CACxB,CAEA,SAAS,yBAAwD,CAG/D,OAAQ,WAAkC,QAAQ,QACpD,CAEA,SAAS,yBAA4C,CACnD,IAAM,EAAW,wBAAwB,EACzC,GAAI,CAAC,EACH,MAAU,MACR,2MACF,EAEF,OAAO,CACT,CAIA,MAAa,EAAgB,uCAO7B,SAAgB,iBACd,EACA,EACA,EACS,CACT,IAAM,EAAW,wBAAwB,EAEzC,OAAO,UAAU,QAAU,EACvB,EAAS,gBAAgB,EAAM,EAAM,CAAO,EAC5C,EAAS,gBAAgB,EAAM,CAAI,CACzC,CAOA,SAAgB,sBACd,EACA,EACA,EACiB,CACjB,IAAM,EAAW,wBAAwB,EAKzC,OAHI,UAAU,OAAS,EACd,EAAS,cAAc,EAAM,CAAI,EAEnC,EAAS,cACd,EACA,EACA,GAAS,UAAY,IAAA,GAChB,EACA,CAAE,YAAa,EAAQ,OAAQ,CACtC,CACF"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{t as e}from"./assert-WeXvmG4j.mjs";import{GraphQLError as t,Lexer as n,Source as r,TokenKind as i}from"graphql";import{getSegments as a}from"sql-highlight";const o=`\x1B[0m`,s=`\x1B[34m`,c=`\x1B[35m`,l=`\x1B[33m`,u=`\x1B[36m`,d=`\x1B[1;35m`,f=`\x1B[90m`,p=`\x1B[2;33m`,m={keyword:s,function:c,identifier:l,string:`\x1B[92m`,number:u,bracket:p,special:f};function highlightSqlLine(e){let t=a(e),n=``;for(let e of t){let t=m[e.name];n+=t?t+e.content+o:e.content}return n}const h=new Set([`query`,`mutation`,`subscription`,`fragment`,`on`,`type`,`input`,`enum`,`interface`,`union`,`scalar`,`extend`,`schema`,`directive`,`implements`]),g=new Set([`query`,`mutation`,`subscription`,`fragment`]),_=new Set([`true`,`false`,`null`]);function highlightGraphqlLine(e){if(e.trimStart().startsWith(`#`))return`${f}${e}${o}`;try{let t=new r(e),a=new n(t),m=``,v=0,y=0,b=``,x=``,S=!1,C=a.advance();for(;C.kind!==i.EOF;){C.start>v&&(m+=e.slice(v,C.start));let t=e.slice(C.start,C.end);switch(C.kind){case i.NAME:b===i.DOLLAR?m+=`${c}${t}${o}`:b===i.AT?m+=`${d}${t}${o}`:_.has(t)||h.has(t)?m+=`${s}${t}${o}`:g.has(x)?m+=`[1;36m${t}${o}`:m+=S?`${u}${t}${o}`:y>0?`[3;33m${t}${o}`:`[94m${t}${o}`,S=!1;break;case i.INT:case i.FLOAT:m+=`${s}${t}${o}`,S=!1;break;case i.STRING:case i.BLOCK_STRING:m+=`[32m${t}${o}`,S=!1;break;case i.DOLLAR:m+=`${c}${t}${o}`,S=!1;break;case i.AT:m+=`${d}${t}${o}`,S=!1;break;case i.BRACE_L:case i.BRACE_R:m+=`${l}${t}${o}`,S=!1;break;case i.PAREN_L:y+=1,m+=`${p}${t}${o}`,S=!1;break;case i.PAREN_R:y=Math.max(0,y-1),m+=`${p}${t}${o}`,S=!1;break;case i.BRACKET_L:case i.BRACKET_R:m+=`${p}${t}${o}`,S=!1;break;case i.COLON:m+=`${f}${t}${o}`,S=!0;break;case i.BANG:case i.EQUALS:case i.PIPE:case i.AMP:case i.SPREAD:m+=`${f}${t}${o}`,S=!1;break;default:m+=t,S=!1}b=C.kind,x=t,v=C.end,C=a.advance()}return v<e.length&&(m+=e.slice(v)),m}catch(n){if(n instanceof t)return e;throw n}}const v={"(":`)`,"[":`]`,"{":`}`},y=new Set(Object.values(v));function replTransform(t,n){let{lines:r,row:i,col:a}=t;if(n.type===`insert`&&n.char in v){let t=v[n.char],o=e(r[i],`line at row ${i} missing`),s=o.slice(0,a)+t+o.slice(a);return{lines:r.with(i,s),row:i,col:a}}if(n.type===`insert`&&y.has(n.char)){let t=e(r[i],`line at row ${i} missing`);if(t[a]===n.char){let e=t.slice(0,a)+t.slice(a+1);return{lines:r.with(i,e),row:i,col:a}}}if(n.type===`backspace`){let t=e(r[i],`line at row ${i} missing`),n=t.slice(0,a);if(n.length>=1&&/^ +$/.test(n)){let e=n.slice(0,-1),o=e+t.slice(a);return{lines:r.with(i,o),row:i,col:e.length}}}if(n.type===`newline`&&i>0){let t=e(r[i-1],`line at row ${i-1} missing`),n=t.match(/^(\s*)/)?.[1]??``,o=/[{([]$/.test(t.trimEnd()),s=e(r[i],`line at row ${i} missing`),c=/^[}\])]/.test(s.trimStart());if(o&&c){let e=n+` `;return{lines:r.with(i,e).toSpliced(i+1,0,n+s.trimStart()),row:i,col:e.length}}if(o){let e=t.trimEnd().slice(-1),a=v[e]??`}`,o=n+` `;return{lines:r.with(i,o+s).toSpliced(i+1,0,n+a),row:i,col:o.length}}if(n&&a===0)return{lines:r.with(i,n+s),row:i,col:n.length}}}export{highlightGraphqlLine,highlightSqlLine,replTransform};
|
|
2
|
+
//# sourceMappingURL=repl-editor-BG1aDOfH.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repl-editor-F9LotMNx.mjs","names":[],"sources":["../src/cli/query/repl-editor.ts"],"sourcesContent":["import { GraphQLError, Lexer, Source, TokenKind } from \"graphql\";\nimport { getSegments } from \"sql-highlight\";\nimport { assertDefined } from \"#/utils/assert\";\nimport type { TransformEvent, TransformState } from \"@toiroakr/read-multiline\";\n\n// ANSI colour sequences. Kept inline (rather than going through `node:util`\n// styleText) so that tests running outside a TTY still produce deterministic\n// escape sequences regardless of detected colour support.\nconst RESET = \"\\x1b[0m\";\nconst BLUE = \"\\x1b[34m\";\nconst MAGENTA = \"\\x1b[35m\";\nconst YELLOW = \"\\x1b[33m\";\nconst BRIGHT_GREEN = \"\\x1b[92m\";\nconst CYAN = \"\\x1b[36m\";\nconst BRIGHT_BLUE = \"\\x1b[94m\";\nconst BOLD_CYAN = \"\\x1b[1;36m\";\nconst BOLD_MAGENTA = \"\\x1b[1;35m\";\nconst ITALIC_YELLOW = \"\\x1b[3;33m\";\nconst GREEN = \"\\x1b[32m\";\nconst DIM = \"\\x1b[90m\";\nconst DIM_YELLOW = \"\\x1b[2;33m\";\n\nconst SQL_STYLE_MAP: Record<string, string> = {\n keyword: BLUE,\n function: MAGENTA,\n identifier: YELLOW,\n string: BRIGHT_GREEN,\n number: CYAN,\n bracket: DIM_YELLOW,\n special: DIM,\n};\n\n/**\n * Highlight a single SQL line using the `sql-highlight` tokenizer.\n * @param line - SQL text for a single editor line\n * @returns ANSI-decorated line safe for terminal output\n */\nexport function highlightSqlLine(line: string): string {\n const segments = getSegments(line);\n let result = \"\";\n for (const seg of segments) {\n const style = SQL_STYLE_MAP[seg.name];\n result += style ? style + seg.content + RESET : seg.content;\n }\n return result;\n}\n\nconst GQL_KEYWORDS = new Set([\n \"query\",\n \"mutation\",\n \"subscription\",\n \"fragment\",\n \"on\",\n \"type\",\n \"input\",\n \"enum\",\n \"interface\",\n \"union\",\n \"scalar\",\n \"extend\",\n \"schema\",\n \"directive\",\n \"implements\",\n]);\n\n// Keywords that introduce a definition name (next NAME token is the def).\nconst GQL_DEF_KEYWORDS = new Set([\"query\", \"mutation\", \"subscription\", \"fragment\"]);\n\nconst GQL_BUILTINS = new Set([\"true\", \"false\", \"null\"]);\n\n/**\n * Highlight a single GraphQL line using the official `graphql` Lexer. Tracks\n * paren depth and the previous token to provide semantic-level colouring\n * (field names vs argument names vs types).\n * @param line - GraphQL text for a single editor line\n * @returns ANSI-decorated line, or the input unchanged when the lexer rejects it\n */\nexport function highlightGraphqlLine(line: string): string {\n if (line.trimStart().startsWith(\"#\")) {\n return `${DIM}${line}${RESET}`;\n }\n\n try {\n const source = new Source(line);\n const lexer = new Lexer(source);\n let result = \"\";\n let pos = 0;\n\n let parenDepth = 0;\n let prevKind: string = \"\";\n let prevText = \"\";\n let afterColon = false;\n\n let token = lexer.advance();\n while (token.kind !== TokenKind.EOF) {\n if (token.start > pos) {\n result += line.slice(pos, token.start);\n }\n\n const text = line.slice(token.start, token.end);\n switch (token.kind) {\n case TokenKind.NAME: {\n if (prevKind === TokenKind.DOLLAR) {\n result += `${MAGENTA}${text}${RESET}`;\n } else if (prevKind === TokenKind.AT) {\n result += `${BOLD_MAGENTA}${text}${RESET}`;\n } else if (GQL_BUILTINS.has(text) || GQL_KEYWORDS.has(text)) {\n result += `${BLUE}${text}${RESET}`;\n } else if (GQL_DEF_KEYWORDS.has(prevText)) {\n result += `${BOLD_CYAN}${text}${RESET}`;\n } else if (afterColon) {\n result += `${CYAN}${text}${RESET}`;\n } else if (parenDepth > 0) {\n result += `${ITALIC_YELLOW}${text}${RESET}`;\n } else {\n result += `${BRIGHT_BLUE}${text}${RESET}`;\n }\n afterColon = false;\n break;\n }\n case TokenKind.INT:\n case TokenKind.FLOAT:\n result += `${BLUE}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.STRING:\n case TokenKind.BLOCK_STRING:\n result += `${GREEN}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.DOLLAR:\n result += `${MAGENTA}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.AT:\n result += `${BOLD_MAGENTA}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.BRACE_L:\n case TokenKind.BRACE_R:\n result += `${YELLOW}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.PAREN_L:\n parenDepth += 1;\n result += `${DIM_YELLOW}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.PAREN_R:\n parenDepth = Math.max(0, parenDepth - 1);\n result += `${DIM_YELLOW}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.BRACKET_L:\n case TokenKind.BRACKET_R:\n result += `${DIM_YELLOW}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.COLON:\n result += `${DIM}${text}${RESET}`;\n afterColon = true;\n break;\n case TokenKind.BANG:\n case TokenKind.EQUALS:\n case TokenKind.PIPE:\n case TokenKind.AMP:\n case TokenKind.SPREAD:\n result += `${DIM}${text}${RESET}`;\n afterColon = false;\n break;\n default:\n result += text;\n afterColon = false;\n }\n\n prevKind = token.kind;\n prevText = text;\n pos = token.end;\n token = lexer.advance();\n }\n\n if (pos < line.length) {\n result += line.slice(pos);\n }\n return result;\n } catch (error) {\n // The lexer throws GraphQLError on partial or invalid input (e.g. an\n // unterminated string while the user is still typing). Fall back to the\n // raw line so the editor keeps rendering without colour until the input\n // is valid. Any other error is a real bug and should surface.\n if (error instanceof GraphQLError) {\n return line;\n }\n throw error;\n }\n}\n\nconst BRACKET_PAIRS: Record<string, string> = { \"(\": \")\", \"[\": \"]\", \"{\": \"}\" };\nconst CLOSE_BRACKETS = new Set(Object.values(BRACKET_PAIRS));\n\n/**\n * Apply auto-close brackets and auto-indent on newline. Works for both SQL\n * and GraphQL because both languages share the `()`, `[]`, `{}` bracket set.\n * @param state - Editor state after the last edit\n * @param event - Event describing the edit that just occurred\n * @returns A new editor state to apply, or `undefined` to leave the state unchanged\n */\nexport function replTransform(\n state: TransformState,\n event: TransformEvent,\n): TransformState | undefined {\n const { lines, row, col } = state;\n\n if (event.type === \"insert\" && event.char in BRACKET_PAIRS) {\n const close = BRACKET_PAIRS[event.char];\n const line = assertDefined(lines[row], `line at row ${row} missing`);\n const newLine = line.slice(0, col) + close + line.slice(col);\n return { lines: lines.with(row, newLine), row, col };\n }\n\n if (event.type === \"insert\" && CLOSE_BRACKETS.has(event.char)) {\n const line = assertDefined(lines[row], `line at row ${row} missing`);\n if (line[col] === event.char) {\n const newLine = line.slice(0, col) + line.slice(col + 1);\n return { lines: lines.with(row, newLine), row, col };\n }\n }\n\n if (event.type === \"backspace\") {\n const line = assertDefined(lines[row], `line at row ${row} missing`);\n const beforeCursor = line.slice(0, col);\n if (beforeCursor.length >= 1 && /^ +$/.test(beforeCursor)) {\n const newIndent = beforeCursor.slice(0, -1);\n const newLine = newIndent + line.slice(col);\n return { lines: lines.with(row, newLine), row, col: newIndent.length };\n }\n }\n\n if (event.type === \"newline\" && row > 0) {\n const prevLine = assertDefined(lines[row - 1], `line at row ${row - 1} missing`);\n const baseIndent = prevLine.match(/^(\\s*)/)?.[1] ?? \"\";\n const endsWithOpen = /[{([]$/.test(prevLine.trimEnd());\n const currentLine = assertDefined(lines[row], `line at row ${row} missing`);\n const startsWithClose = /^[}\\])]/.test(currentLine.trimStart());\n\n if (endsWithOpen && startsWithClose) {\n // Bracket expansion: the cursor sits between a matching open/close\n // pair (e.g. `{|}`). Expand into a three-line block with the cursor\n // on an indented middle line.\n const innerIndent = baseIndent + \" \";\n const newLines = lines\n .with(row, innerIndent)\n .toSpliced(row + 1, 0, baseIndent + currentLine.trimStart());\n return { lines: newLines, row, col: innerIndent.length };\n }\n if (endsWithOpen) {\n // A lone open bracket on the previous line: drop an extra indent for\n // the new line and auto-insert the matching closing bracket below.\n const openChar = prevLine.trimEnd().slice(-1);\n const closeChar = BRACKET_PAIRS[openChar] ?? \"}\";\n const indent = baseIndent + \" \";\n const newLines = lines\n .with(row, indent + currentLine)\n .toSpliced(row + 1, 0, baseIndent + closeChar);\n return { lines: newLines, row, col: indent.length };\n }\n if (baseIndent && col === 0) {\n return { lines: lines.with(row, baseIndent + currentLine), row, col: baseIndent.length };\n }\n }\n\n return undefined;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"repl-editor-BG1aDOfH.mjs","names":[],"sources":["../src/cli/query/repl-editor.ts"],"sourcesContent":["import { GraphQLError, Lexer, Source, TokenKind } from \"graphql\";\nimport { getSegments } from \"sql-highlight\";\nimport { assertDefined } from \"#/utils/assert\";\nimport type { TransformEvent, TransformState } from \"@toiroakr/read-multiline\";\n\n// ANSI colour sequences. Kept inline (rather than going through `node:util`\n// styleText) so that tests running outside a TTY still produce deterministic\n// escape sequences regardless of detected colour support.\nconst RESET = \"\\x1b[0m\";\nconst BLUE = \"\\x1b[34m\";\nconst MAGENTA = \"\\x1b[35m\";\nconst YELLOW = \"\\x1b[33m\";\nconst BRIGHT_GREEN = \"\\x1b[92m\";\nconst CYAN = \"\\x1b[36m\";\nconst BRIGHT_BLUE = \"\\x1b[94m\";\nconst BOLD_CYAN = \"\\x1b[1;36m\";\nconst BOLD_MAGENTA = \"\\x1b[1;35m\";\nconst ITALIC_YELLOW = \"\\x1b[3;33m\";\nconst GREEN = \"\\x1b[32m\";\nconst DIM = \"\\x1b[90m\";\nconst DIM_YELLOW = \"\\x1b[2;33m\";\n\nconst SQL_STYLE_MAP: Record<string, string> = {\n keyword: BLUE,\n function: MAGENTA,\n identifier: YELLOW,\n string: BRIGHT_GREEN,\n number: CYAN,\n bracket: DIM_YELLOW,\n special: DIM,\n};\n\n/**\n * Highlight a single SQL line using the `sql-highlight` tokenizer.\n * @param line - SQL text for a single editor line\n * @returns ANSI-decorated line safe for terminal output\n */\nexport function highlightSqlLine(line: string): string {\n const segments = getSegments(line);\n let result = \"\";\n for (const seg of segments) {\n const style = SQL_STYLE_MAP[seg.name];\n result += style ? style + seg.content + RESET : seg.content;\n }\n return result;\n}\n\nconst GQL_KEYWORDS = new Set([\n \"query\",\n \"mutation\",\n \"subscription\",\n \"fragment\",\n \"on\",\n \"type\",\n \"input\",\n \"enum\",\n \"interface\",\n \"union\",\n \"scalar\",\n \"extend\",\n \"schema\",\n \"directive\",\n \"implements\",\n]);\n\n// Keywords that introduce a definition name (next NAME token is the def).\nconst GQL_DEF_KEYWORDS = new Set([\"query\", \"mutation\", \"subscription\", \"fragment\"]);\n\nconst GQL_BUILTINS = new Set([\"true\", \"false\", \"null\"]);\n\n/**\n * Highlight a single GraphQL line using the official `graphql` Lexer. Tracks\n * paren depth and the previous token to provide semantic-level colouring\n * (field names vs argument names vs types).\n * @param line - GraphQL text for a single editor line\n * @returns ANSI-decorated line, or the input unchanged when the lexer rejects it\n */\nexport function highlightGraphqlLine(line: string): string {\n if (line.trimStart().startsWith(\"#\")) {\n return `${DIM}${line}${RESET}`;\n }\n\n try {\n const source = new Source(line);\n const lexer = new Lexer(source);\n let result = \"\";\n let pos = 0;\n\n let parenDepth = 0;\n let prevKind: string = \"\";\n let prevText = \"\";\n let afterColon = false;\n\n let token = lexer.advance();\n while (token.kind !== TokenKind.EOF) {\n if (token.start > pos) {\n result += line.slice(pos, token.start);\n }\n\n const text = line.slice(token.start, token.end);\n switch (token.kind) {\n case TokenKind.NAME: {\n if (prevKind === TokenKind.DOLLAR) {\n result += `${MAGENTA}${text}${RESET}`;\n } else if (prevKind === TokenKind.AT) {\n result += `${BOLD_MAGENTA}${text}${RESET}`;\n } else if (GQL_BUILTINS.has(text) || GQL_KEYWORDS.has(text)) {\n result += `${BLUE}${text}${RESET}`;\n } else if (GQL_DEF_KEYWORDS.has(prevText)) {\n result += `${BOLD_CYAN}${text}${RESET}`;\n } else if (afterColon) {\n result += `${CYAN}${text}${RESET}`;\n } else if (parenDepth > 0) {\n result += `${ITALIC_YELLOW}${text}${RESET}`;\n } else {\n result += `${BRIGHT_BLUE}${text}${RESET}`;\n }\n afterColon = false;\n break;\n }\n case TokenKind.INT:\n case TokenKind.FLOAT:\n result += `${BLUE}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.STRING:\n case TokenKind.BLOCK_STRING:\n result += `${GREEN}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.DOLLAR:\n result += `${MAGENTA}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.AT:\n result += `${BOLD_MAGENTA}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.BRACE_L:\n case TokenKind.BRACE_R:\n result += `${YELLOW}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.PAREN_L:\n parenDepth += 1;\n result += `${DIM_YELLOW}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.PAREN_R:\n parenDepth = Math.max(0, parenDepth - 1);\n result += `${DIM_YELLOW}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.BRACKET_L:\n case TokenKind.BRACKET_R:\n result += `${DIM_YELLOW}${text}${RESET}`;\n afterColon = false;\n break;\n case TokenKind.COLON:\n result += `${DIM}${text}${RESET}`;\n afterColon = true;\n break;\n case TokenKind.BANG:\n case TokenKind.EQUALS:\n case TokenKind.PIPE:\n case TokenKind.AMP:\n case TokenKind.SPREAD:\n result += `${DIM}${text}${RESET}`;\n afterColon = false;\n break;\n default:\n result += text;\n afterColon = false;\n }\n\n prevKind = token.kind;\n prevText = text;\n pos = token.end;\n token = lexer.advance();\n }\n\n if (pos < line.length) {\n result += line.slice(pos);\n }\n return result;\n } catch (error) {\n // The lexer throws GraphQLError on partial or invalid input (e.g. an\n // unterminated string while the user is still typing). Fall back to the\n // raw line so the editor keeps rendering without colour until the input\n // is valid. Any other error is a real bug and should surface.\n if (error instanceof GraphQLError) {\n return line;\n }\n throw error;\n }\n}\n\nconst BRACKET_PAIRS: Record<string, string> = { \"(\": \")\", \"[\": \"]\", \"{\": \"}\" };\nconst CLOSE_BRACKETS = new Set(Object.values(BRACKET_PAIRS));\n\n/**\n * Apply auto-close brackets and auto-indent on newline. Works for both SQL\n * and GraphQL because both languages share the `()`, `[]`, `{}` bracket set.\n * @param state - Editor state after the last edit\n * @param event - Event describing the edit that just occurred\n * @returns A new editor state to apply, or `undefined` to leave the state unchanged\n */\nexport function replTransform(\n state: TransformState,\n event: TransformEvent,\n): TransformState | undefined {\n const { lines, row, col } = state;\n\n if (event.type === \"insert\" && event.char in BRACKET_PAIRS) {\n const close = BRACKET_PAIRS[event.char];\n const line = assertDefined(lines[row], `line at row ${row} missing`);\n const newLine = line.slice(0, col) + close + line.slice(col);\n return { lines: lines.with(row, newLine), row, col };\n }\n\n if (event.type === \"insert\" && CLOSE_BRACKETS.has(event.char)) {\n const line = assertDefined(lines[row], `line at row ${row} missing`);\n if (line[col] === event.char) {\n const newLine = line.slice(0, col) + line.slice(col + 1);\n return { lines: lines.with(row, newLine), row, col };\n }\n }\n\n if (event.type === \"backspace\") {\n const line = assertDefined(lines[row], `line at row ${row} missing`);\n const beforeCursor = line.slice(0, col);\n if (beforeCursor.length >= 1 && /^ +$/.test(beforeCursor)) {\n const newIndent = beforeCursor.slice(0, -1);\n const newLine = newIndent + line.slice(col);\n return { lines: lines.with(row, newLine), row, col: newIndent.length };\n }\n }\n\n if (event.type === \"newline\" && row > 0) {\n const prevLine = assertDefined(lines[row - 1], `line at row ${row - 1} missing`);\n const baseIndent = prevLine.match(/^(\\s*)/)?.[1] ?? \"\";\n const endsWithOpen = /[{([]$/.test(prevLine.trimEnd());\n const currentLine = assertDefined(lines[row], `line at row ${row} missing`);\n const startsWithClose = /^[}\\])]/.test(currentLine.trimStart());\n\n if (endsWithOpen && startsWithClose) {\n // Bracket expansion: the cursor sits between a matching open/close\n // pair (e.g. `{|}`). Expand into a three-line block with the cursor\n // on an indented middle line.\n const innerIndent = baseIndent + \" \";\n const newLines = lines\n .with(row, innerIndent)\n .toSpliced(row + 1, 0, baseIndent + currentLine.trimStart());\n return { lines: newLines, row, col: innerIndent.length };\n }\n if (endsWithOpen) {\n // A lone open bracket on the previous line: drop an extra indent for\n // the new line and auto-insert the matching closing bracket below.\n const openChar = prevLine.trimEnd().slice(-1);\n const closeChar = BRACKET_PAIRS[openChar] ?? \"}\";\n const indent = baseIndent + \" \";\n const newLines = lines\n .with(row, indent + currentLine)\n .toSpliced(row + 1, 0, baseIndent + closeChar);\n return { lines: newLines, row, col: indent.length };\n }\n if (baseIndent && col === 0) {\n return { lines: lines.with(row, baseIndent + currentLine), row, col: baseIndent.length };\n }\n }\n\n return undefined;\n}\n"],"mappings":"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"}
|
package/dist/runtime/context.mjs
CHANGED
package/dist/runtime/file.d.mts
CHANGED
|
@@ -85,86 +85,86 @@ interface TailorDBFileAPI {
|
|
|
85
85
|
/**
|
|
86
86
|
* Upload a file to TailorDB.
|
|
87
87
|
* @param namespace - TailorDB namespace
|
|
88
|
-
* @param
|
|
88
|
+
* @param tableName - TailorDB table name
|
|
89
89
|
* @param fieldName - File field name on the table
|
|
90
90
|
* @param recordId - Record ID owning the field
|
|
91
91
|
* @param data - File contents
|
|
92
92
|
* @param options - Upload options (e.g. `contentType`)
|
|
93
93
|
* @returns Upload response containing the file metadata
|
|
94
94
|
*/
|
|
95
|
-
upload(namespace: string,
|
|
95
|
+
upload(namespace: string, tableName: string, fieldName: string, recordId: string, data: string | ArrayBuffer | Uint8Array | number[], options?: FileUploadOptions): Promise<FileUploadResponse>;
|
|
96
96
|
/**
|
|
97
97
|
* Download a file from TailorDB.
|
|
98
98
|
*
|
|
99
99
|
* Throws `TailorDBFileError` with code `FILE_TOO_LARGE` when the file
|
|
100
100
|
* exceeds 10MB — use {@link downloadStream} for large files.
|
|
101
101
|
* @param namespace - TailorDB namespace
|
|
102
|
-
* @param
|
|
102
|
+
* @param tableName - TailorDB table name
|
|
103
103
|
* @param fieldName - File field name on the table
|
|
104
104
|
* @param recordId - Record ID owning the field
|
|
105
105
|
* @returns Bytes and metadata for the file
|
|
106
106
|
*/
|
|
107
|
-
download(namespace: string,
|
|
107
|
+
download(namespace: string, tableName: string, fieldName: string, recordId: string): Promise<FileDownloadResponse>;
|
|
108
108
|
/**
|
|
109
109
|
* Download a file from TailorDB as a Base64-encoded string.
|
|
110
110
|
*
|
|
111
111
|
* Throws `TailorDBFileError` with code `FILE_TOO_LARGE` when the file
|
|
112
112
|
* exceeds 10MB — use {@link downloadStream} for large files.
|
|
113
113
|
* @param namespace - TailorDB namespace
|
|
114
|
-
* @param
|
|
114
|
+
* @param tableName - TailorDB table name
|
|
115
115
|
* @param fieldName - File field name on the table
|
|
116
116
|
* @param recordId - Record ID owning the field
|
|
117
117
|
* @returns Base64-encoded contents and metadata for the file
|
|
118
118
|
*/
|
|
119
|
-
downloadAsBase64(namespace: string,
|
|
119
|
+
downloadAsBase64(namespace: string, tableName: string, fieldName: string, recordId: string): Promise<FileDownloadAsBase64Response>;
|
|
120
120
|
/**
|
|
121
121
|
* Delete a file from TailorDB.
|
|
122
122
|
* @param namespace - TailorDB namespace
|
|
123
|
-
* @param
|
|
123
|
+
* @param tableName - TailorDB table name
|
|
124
124
|
* @param fieldName - File field name on the table
|
|
125
125
|
* @param recordId - Record ID owning the field
|
|
126
126
|
* @returns Resolves once the file has been deleted
|
|
127
127
|
*/
|
|
128
|
-
delete(namespace: string,
|
|
128
|
+
delete(namespace: string, tableName: string, fieldName: string, recordId: string): Promise<void>;
|
|
129
129
|
/**
|
|
130
130
|
* Get file metadata from TailorDB.
|
|
131
131
|
* @param namespace - TailorDB namespace
|
|
132
|
-
* @param
|
|
132
|
+
* @param tableName - TailorDB table name
|
|
133
133
|
* @param fieldName - File field name on the table
|
|
134
134
|
* @param recordId - Record ID owning the field
|
|
135
135
|
* @returns Metadata for the stored file
|
|
136
136
|
*/
|
|
137
|
-
getMetadata(namespace: string,
|
|
137
|
+
getMetadata(namespace: string, tableName: string, fieldName: string, recordId: string): Promise<FileMetadata>;
|
|
138
138
|
/**
|
|
139
139
|
* Download a file as a ReadableStream.
|
|
140
140
|
* @param namespace - TailorDB namespace
|
|
141
|
-
* @param
|
|
141
|
+
* @param tableName - TailorDB table name
|
|
142
142
|
* @param fieldName - File field name on the table
|
|
143
143
|
* @param recordId - Record ID owning the field
|
|
144
144
|
* @returns ReadableStream body and metadata for the file
|
|
145
145
|
*/
|
|
146
|
-
downloadStream(namespace: string,
|
|
146
|
+
downloadStream(namespace: string, tableName: string, fieldName: string, recordId: string): Promise<FileDownloadStreamResponse>;
|
|
147
147
|
/**
|
|
148
148
|
* Upload a file using a ReadableStream.
|
|
149
149
|
* @param namespace - TailorDB namespace
|
|
150
|
-
* @param
|
|
150
|
+
* @param tableName - TailorDB table name
|
|
151
151
|
* @param fieldName - File field name on the table
|
|
152
152
|
* @param recordId - Record ID owning the field
|
|
153
153
|
* @param readableStream - ReadableStream providing the file data
|
|
154
154
|
* @param options - Upload stream options (e.g. `contentType`, `fileSize`)
|
|
155
155
|
* @returns Upload response containing the file metadata
|
|
156
156
|
*/
|
|
157
|
-
uploadStream(namespace: string,
|
|
157
|
+
uploadStream(namespace: string, tableName: string, fieldName: string, recordId: string, readableStream: ReadableStream<Uint8Array | ArrayBuffer>, options?: FileUploadStreamOptions): Promise<FileUploadResponse>;
|
|
158
158
|
}
|
|
159
159
|
/** Runtime wrapper namespace for `tailordb.file`. */
|
|
160
160
|
declare const file: {
|
|
161
|
-
readonly upload: (namespace: string,
|
|
162
|
-
readonly download: (namespace: string,
|
|
163
|
-
readonly downloadAsBase64: (namespace: string,
|
|
164
|
-
readonly delete: (namespace: string,
|
|
165
|
-
readonly getMetadata: (namespace: string,
|
|
166
|
-
readonly downloadStream: (namespace: string,
|
|
167
|
-
readonly uploadStream: (namespace: string,
|
|
161
|
+
readonly upload: (namespace: string, tableName: string, fieldName: string, recordId: string, data: string | ArrayBuffer | Uint8Array | number[], options?: FileUploadOptions) => Promise<FileUploadResponse>;
|
|
162
|
+
readonly download: (namespace: string, tableName: string, fieldName: string, recordId: string) => Promise<FileDownloadResponse>;
|
|
163
|
+
readonly downloadAsBase64: (namespace: string, tableName: string, fieldName: string, recordId: string) => Promise<FileDownloadAsBase64Response>;
|
|
164
|
+
readonly delete: (namespace: string, tableName: string, fieldName: string, recordId: string) => Promise<void>;
|
|
165
|
+
readonly getMetadata: (namespace: string, tableName: string, fieldName: string, recordId: string) => Promise<FileMetadata>;
|
|
166
|
+
readonly downloadStream: (namespace: string, tableName: string, fieldName: string, recordId: string) => Promise<FileDownloadStreamResponse>;
|
|
167
|
+
readonly uploadStream: (namespace: string, tableName: string, fieldName: string, recordId: string, readableStream: ReadableStream<Uint8Array | ArrayBuffer>, options?: FileUploadStreamOptions) => Promise<FileUploadResponse>;
|
|
168
168
|
};
|
|
169
169
|
//#endregion
|
|
170
170
|
export { DownloadMetadata, FileDownloadAsBase64Response, FileDownloadResponse, FileDownloadStreamResponse, FileMetadata, FileUploadOptions, FileUploadResponse, FileUploadStreamOptions, TailorDBFileAPI, TailorDBFileError, TailorDBFileErrorCode, UploadMetadata, file };
|
package/dist/runtime/file.mjs
CHANGED
package/dist/runtime/globals.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export{};
|
package/dist/runtime/iconv.mjs
CHANGED
package/dist/runtime/idp.mjs
CHANGED
package/dist/runtime/index.mjs
CHANGED
|
@@ -1,11 +1 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
import { t as secretmanager } from "../secretmanager-CYlpffsz.mjs";
|
|
3
|
-
import { t as authconnection } from "../authconnection-CZvi9ANm.mjs";
|
|
4
|
-
import { t as idp } from "../idp-RA_swu-h.mjs";
|
|
5
|
-
import { t as workflow } from "../workflow-Bamae_Yc.mjs";
|
|
6
|
-
import { t as context } from "../context-DYQVYWqZ.mjs";
|
|
7
|
-
import { t as file } from "../file-BUcmVIH2.mjs";
|
|
8
|
-
import { t as aigateway } from "../aigateway-DR4Kwuik.mjs";
|
|
9
|
-
import { i as logger } from "../logger-BtX0suGY.mjs";
|
|
10
|
-
|
|
11
|
-
export { aigateway, authconnection, context, file, iconv, idp, logger, secretmanager, workflow };
|
|
1
|
+
import{t as e}from"../iconv-DlFMt2gW.mjs";import{t}from"../secretmanager-vHQoXdQz.mjs";import{t as n}from"../authconnection-CynFBIv8.mjs";import{t as r}from"../idp-G_ojPBB5.mjs";import{t as i}from"../workflow-Cs9ISw6j.mjs";import{t as a}from"../context-D0QjfxzD.mjs";import{t as o}from"../file-COPYfju_.mjs";import{t as s}from"../aigateway-DsWDjzk4.mjs";import{i as c}from"../logger-DP2BjQ93.mjs";export{s as aigateway,n as authconnection,a as context,o as file,e as iconv,r as idp,c as logger,t as secretmanager,i as workflow};
|
package/dist/runtime/logger.mjs
CHANGED
|
@@ -1,3 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
export { debug, error, info, logger, setAttributes, warn };
|
|
1
|
+
import{a as e,i as t,n,o as r,r as i,t as a}from"../logger-DP2BjQ93.mjs";export{a as debug,n as error,i as info,t as logger,e as setAttributes,r as warn};
|
package/dist/runtime/types.d.mts
CHANGED
|
@@ -22,4 +22,4 @@ interface Env {}
|
|
|
22
22
|
/** Represents environment variables in the Tailor platform. */
|
|
23
23
|
type TailorEnv = keyof Env extends never ? Record<string, string | number | boolean> : Env;
|
|
24
24
|
//#endregion
|
|
25
|
-
export { AttributeList, Attributes, Env,
|
|
25
|
+
export { AttributeList, Attributes, Env, InferredAttributes, TailorEnv, TailorPrincipal };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{t as e}from"./brand-C8nMKhJC.mjs";import{cloneDeep as t}from"es-toolkit";const n={uuid:/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,date:/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/,time:/^(?<hour>[01]\d|2[0-3]):(?<minute>[0-5]\d)$/,datetime:/^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})[Tt](?<hour>[01]\d|2[0-3]):(?<minute>[0-5]\d):(?<second>[0-5]\d|60)(\.(?<fraction>\d+))?(?<offset>[Zz]|[+-](?:[01]\d|2[0-3]):[0-5]\d)$/,decimal:/^-?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/};function validateBaseValue(e){let{field:t,value:r,pathArray:i,issues:a}=e,o=i.length>0?i:void 0,s=a.length;switch(t.type){case`string`:typeof r!=`string`&&a.push({message:`Expected a string: received ${String(r)}`,path:o});break;case`integer`:(typeof r!=`number`||!Number.isInteger(r))&&a.push({message:`Expected an integer: received ${String(r)}`,path:o});break;case`float`:(typeof r!=`number`||!Number.isFinite(r))&&a.push({message:`Expected a number: received ${String(r)}`,path:o});break;case`boolean`:typeof r!=`boolean`&&a.push({message:`Expected a boolean: received ${String(r)}`,path:o});break;case`uuid`:(typeof r!=`string`||!n.uuid.test(r))&&a.push({message:`Expected a valid UUID: received ${String(r)}`,path:o});break;case`date`:(typeof r!=`string`||!n.date.test(r))&&a.push({message:`Expected to match "yyyy-MM-dd" format: received ${String(r)}`,path:o});break;case`datetime`:(typeof r!=`string`||!n.datetime.test(r))&&a.push({message:`Expected to match ISO format: received ${String(r)}`,path:o});break;case`time`:(typeof r!=`string`||!n.time.test(r))&&a.push({message:`Expected to match "HH:mm" format: received ${String(r)}`,path:o});break;case`decimal`:(typeof r!=`string`||!n.decimal.test(r))&&a.push({message:`Expected a decimal string: received ${String(r)}`,path:o});break;case`enum`:if(t._metadata.allowedValues){let e=t._metadata.allowedValues.map(e=>e.value);(typeof r!=`string`||!e.includes(r))&&a.push({message:`Must be one of [${e.join(`, `)}]: received ${String(r)}`,path:o})}break;case`nested`:{if(typeof r!=`object`||!r||Array.isArray(r)||r instanceof Date)return a.push({message:`Expected an object: received ${String(r)}`,path:o}),!1;let n=!0;for(let[a,o]of Object.entries(t.fields)){let t=r[a];validateBaseField({...e,field:o,value:t,pathArray:i.concat(a)})||(n=!1)}return n}}return a.length===s}function validateCustomValue(e,t){let{value:n,pathArray:r,issues:i}=e,a=r.length>0?r:void 0;for(let e of t){let t=e({value:n});typeof t==`string`&&i.push({message:t,path:a})}}function validateBaseField(e){let{field:t,value:n,pathArray:r,issues:i}=e,a=r.length>0?r:void 0,o=n==null;if(t._metadata.required&&o)return i.push({message:`Required field is missing`,path:a}),!1;if(!t._metadata.required&&o)return!0;let s=!0;if(t._metadata.array){if(!Array.isArray(n))return i.push({message:`Expected an array`,path:a}),!1;for(let t=0;t<n.length;t++)validateBaseValue({...e,value:n[t],pathArray:r.concat(`[${t}]`)})||(s=!1)}else s=validateBaseValue(e);return s}function validateCustomField(e){let{field:t,value:n,pathArray:r}=e;if(n==null)return;if(t.type===`nested`){let i=t._metadata.array?n:[n];for(let n=0;n<i.length;n++){let a=i[n],o=t._metadata.array?r.concat(`[${n}]`):r;for(let[n,r]of Object.entries(t.fields))validateCustomField({...e,field:r,value:a[n],pathArray:o.concat(n)})}}let i=t._metadata.validate;i?.length&&validateCustomValue(e,i)}function parseInternal(e){let{value:t}=e,n=[],r={...e,issues:n};return validateBaseField(r)&&validateCustomField(r),n.length>0?{issues:n}:{value:t??null}}function parseInputFields(e){let{fields:t,...n}=e;return parseInternal({...n,field:{type:`nested`,fields:t,_metadata:{required:!0}},pathArray:[]})}function mapAllowedValues(e){return e.map(e=>typeof e==`string`?{value:e,description:``}:{...e,description:e.description??``})}function createTailorDBField(e,t,n,r){return createTailorDBFieldRuntime(e,t,n,r)}function createTailorDBFieldRuntime(e,n,r,i){let a={required:!0},o;n&&(n.optional===!0&&(a.required=!1),n.array===!0&&(a.array=!0)),i&&(a.allowedValues=mapAllowedValues(i));function parseInternal$1(e){return parseInternal({...e,field:s})}function cloneWith(e){let t=s.clone();return Object.assign(t._metadata,e),t}let s={type:e,fields:r??{},_defined:void 0,_output:void 0,_metadata:a,get metadata(){return{...this._metadata}},get rawRelation(){return o?{...o,toward:{...o.toward}}:void 0},description(e){return cloneWith({description:e})},typeName(e){return cloneWith({typeName:e})},validate(...e){return cloneWith({validate:e})},parse(e){return parseInternal$1({value:e.value,data:e.data,invoker:e.invoker,pathArray:[]})},relation(e){let t=s.clone(),n=e.toward,r=`table`in n?n.table:n.type,i=r===`self`?`self`:r.name;return t._setRawRelation({type:e.type,toward:{table:i,as:e.toward.as,key:e.toward.key},backward:e.backward}),t},index(){return cloneWith({index:!0})},unique(){return cloneWith({unique:!0,index:!0})},vector(){return cloneWith({vector:!0})},default(e){return cloneWith({default:e})},hooks(e){return cloneWith({hooks:e})},serial(e){return cloneWith({serial:e})},clone(a){if(this._metadata.validate?.length&&a?.array!==void 0&&a.array!==(this._metadata.array===!0))throw Error(`Cannot change the array option on a field with custom validation`);let s=r;if(r){let e={};for(let[t,n]of Object.entries(r))e[t]=n.clone();s=e}let c=createTailorDBFieldRuntime(e,n,s,i);return Object.assign(c._metadata,t(this._metadata)),a&&(a.optional!==void 0&&(c._metadata.required=!a.optional),a.array!==void 0&&(c._metadata.array=a.array)),o&&c._setRawRelation(t(o)),c},_setRawRelation(e){o=e}};return s}const r=createTailorDBField;function uuid(e){return r(`uuid`,e)}function string(e){return r(`string`,e)}function bool(e){return r(`boolean`,e)}function int(e){return r(`integer`,e)}function float(e){return r(`float`,e)}function decimal(e){if(e?.scale!==void 0&&(!Number.isInteger(e.scale)||e.scale<0||e.scale>12))throw Error(`scale must be an integer between 0 and 12`);let t=r(`decimal`,e);return e?.scale!==void 0&&(t._metadata.scale=e.scale),t}function date(e){return r(`date`,e)}function datetime(e){return r(`datetime`,e)}function time(e){return r(`time`,e)}function _enum(e,t){return r(`enum`,t,void 0,e)}function object(e,t){return r(`nested`,t,e)}function createTailorDBType(t,n,r){let i=r.description,a={},o=[],s={},c={},l=[],u,d,f=new Set;r.description!==void 0&&f.add(`description`);function runMethodOnce(e,t){if(f.has(e))throw Error(`.${e}() has already been set`);let n=t();return f.add(e),n}if(r.pluralForm){if(t===r.pluralForm)throw Error(`The name and the plural form must be different. name=${t}`);a.pluralForm=r.pluralForm}let p={name:t,fields:{...n},_output:null,_description:i,get metadata(){let e={};return o.length>0&&o.forEach(t=>{let n=t.fields.map(e=>String(e)),r=t.name||`idx_${n.join(`_`)}`;e[r]={fields:n,unique:t.unique}}),{name:this.name,description:i,settings:a,permissions:s,files:c,...Object.keys(e).length>0&&{indexes:e},...u&&{typeHook:u},...d&&{typeValidate:d}}},hooks(e){return runMethodOnce(`hooks`,()=>(u=e,this))},validate(e){return runMethodOnce(`validate`,()=>(d=e,this))},features(e){return runMethodOnce(`features`,()=>(a={...a,...e},this))},indexes(...e){return runMethodOnce(`indexes`,()=>(o=e,this))},files(e){return runMethodOnce(`files`,()=>(c=e,this))},permission(e){return runMethodOnce(`permission`,()=>{let t=this;return s.record=e,t})},gqlPermission(e){return runMethodOnce(`gqlPermission`,()=>{let t=this;return s.gql=e,t})},description(e){return runMethodOnce(`description`,()=>(i=e,this._description=e,this))},pickFields(e,t){let n={};for(let r of e){let e=this.fields[r];n[r]=t?e.clone(t):e}return n},omitFields(e){let t=new Set(e),n={};for(let e in this.fields)Object.hasOwn(this.fields,e)&&!t.has(e)&&(n[e]=this.fields[e]);return n},get plugins(){return l},plugin(e){for(let[t,n]of Object.entries(e))l.push({pluginId:t,config:n});return this}};return e(p,`tailordb-type`)}const i=uuid();function dbTable(e,t,n){let r=Array.isArray(e)?e[0]:e,a=Array.isArray(e)?e[1]:void 0,o,s;return typeof t==`string`?(o=t,s=n):s=t,createTailorDBType(r,{id:i,...s},{pluralForm:a,description:o})}const timestampsUpdatedAtHook=({input:e,now:t})=>e??t,a=Symbol.for(`tailor-platform/sdk:precompiled-script-expr`);timestampsUpdatedAtHook[a]={"hooks.update":`(({ input, now }) => input ?? now)({ input: _value, oldValue: _oldValue, invoker: _principal, now: _now })`};const o={table:dbTable,uuid,string,bool,int,float,decimal,date,datetime,time,enum:_enum,object,fields:{timestamps:()=>({createdAt:datetime().default(`now`).description(`Record creation timestamp`),updatedAt:datetime().default(`now`).hooks({update:timestampsUpdatedAtHook}).description(`Record update timestamp`)})}};export{parseInternal as i,mapAllowedValues as n,parseInputFields as r,o as t};
|
|
2
|
+
//# sourceMappingURL=schema-AYG4OhXY.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-AYG4OhXY.mjs","names":["parseInternal","parseFieldInternal"],"sources":["../src/runtime/field-parse.ts","../src/configure/types/field.ts","../src/configure/services/tailordb/schema.ts"],"sourcesContent":["import type { FieldMetadata, TailorFieldType } from \"#/configure/types/field.types\";\nimport type { TailorPrincipal } from \"#/runtime/types\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\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>[01]\\d|2[0-3]):(?<minute>[0-5]\\d)$/,\n datetime:\n /^(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})[Tt](?<hour>[01]\\d|2[0-3]):(?<minute>[0-5]\\d):(?<second>[0-5]\\d|60)(\\.(?<fraction>\\d+))?(?<offset>[Zz]|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$/,\n decimal: /^-?(\\d+\\.?\\d*|\\.\\d+)([eE][+-]?\\d+)?$/,\n} as const;\n\nexport type FieldParseArgs = {\n value: unknown;\n data: unknown;\n invoker: TailorPrincipal | null;\n};\n\nexport type FieldParseInternalArgs = {\n value: unknown;\n data: unknown;\n invoker: TailorPrincipal | null;\n pathArray: string[];\n};\n\nexport type FieldRuntime<T extends TailorFieldType = TailorFieldType> = {\n readonly type: T;\n readonly fields: Record<string, FieldRuntime>;\n _metadata: FieldMetadata;\n};\n\ntype FieldParseRuntimeArgs<T extends TailorFieldType> = FieldParseInternalArgs & {\n field: FieldRuntime<T>;\n};\n\ntype FieldValidationArgs<T extends TailorFieldType> = FieldParseRuntimeArgs<T> & {\n issues: StandardSchemaV1.Issue[];\n};\n\nfunction validateBaseValue<T extends TailorFieldType>(args: FieldValidationArgs<T>): boolean {\n const { field, value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n const initialIssueCount = issues.length;\n\n switch (field.type) {\n case \"string\":\n if (typeof value !== \"string\") {\n issues.push({\n message: `Expected a string: received ${String(value)}`,\n path,\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,\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,\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,\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,\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,\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,\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,\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,\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,\n });\n }\n }\n break;\n\n case \"nested\": {\n // Runtime input may not match the declared field type.\n // oxlint-disable typescript/no-unnecessary-condition\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value) ||\n value instanceof Date\n ) {\n // oxlint-enable typescript/no-unnecessary-condition\n issues.push({\n message: `Expected an object: received ${String(value)}`,\n path,\n });\n return false;\n }\n\n let nestedBaseValid = true;\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n const fieldValue = (value as Record<string, unknown>)[fieldName];\n if (\n !validateBaseField({\n ...args,\n field: nestedField,\n value: fieldValue,\n pathArray: pathArray.concat(fieldName),\n })\n ) {\n nestedBaseValid = false;\n }\n }\n return nestedBaseValid;\n }\n }\n\n return issues.length === initialIssueCount;\n}\n\nfunction validateCustomValue<T extends TailorFieldType>(\n args: FieldValidationArgs<T>,\n validateFns: NonNullable<FieldMetadata[\"validate\"]>,\n): void {\n const { value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n\n for (const fn of validateFns) {\n const result = fn({ value });\n if (typeof result === \"string\") {\n issues.push({\n message: result,\n path,\n });\n }\n }\n}\n\nfunction validateBaseField<T extends TailorFieldType>(args: FieldValidationArgs<T>): boolean {\n const { field, value, pathArray, issues } = args;\n const path = pathArray.length > 0 ? pathArray : undefined;\n\n const isNullOrUndefined = value === null || value === undefined;\n if (field._metadata.required && isNullOrUndefined) {\n issues.push({\n message: \"Required field is missing\",\n path,\n });\n return false;\n }\n\n if (!field._metadata.required && isNullOrUndefined) {\n return true;\n }\n\n let baseValid = true;\n if (field._metadata.array) {\n if (!Array.isArray(value)) {\n issues.push({\n message: \"Expected an array\",\n path,\n });\n return false;\n }\n\n for (let i = 0; i < value.length; i++) {\n if (\n !validateBaseValue({\n ...args,\n value: value[i],\n pathArray: pathArray.concat(`[${i}]`),\n })\n ) {\n baseValid = false;\n }\n }\n } else {\n baseValid = validateBaseValue(args);\n }\n\n return baseValid;\n}\n\nfunction validateCustomField<T extends TailorFieldType>(args: FieldValidationArgs<T>): void {\n const { field, value, pathArray } = args;\n if (value === null || value === undefined) {\n return;\n }\n\n if (field.type === \"nested\") {\n const records = field._metadata.array\n ? (value as Record<string, unknown>[])\n : [value as Record<string, unknown>];\n\n for (let i = 0; i < records.length; i++) {\n const record = records[i] as Record<string, unknown>;\n const recordPath = field._metadata.array ? pathArray.concat(`[${i}]`) : pathArray;\n for (const [fieldName, nestedField] of Object.entries(field.fields)) {\n validateCustomField({\n ...args,\n field: nestedField,\n value: record[fieldName],\n pathArray: recordPath.concat(fieldName),\n });\n }\n }\n }\n\n const validateFns = field._metadata.validate;\n if (validateFns?.length) {\n validateCustomValue(args, validateFns);\n }\n}\n\nexport function parseInternal<T extends TailorFieldType, Output>(\n args: FieldParseRuntimeArgs<T>,\n): StandardSchemaV1.Result<Output> {\n const { value } = args;\n const issues: StandardSchemaV1.Issue[] = [];\n const validationArgs = { ...args, issues };\n const baseValid = validateBaseField(validationArgs);\n if (baseValid) {\n validateCustomField(validationArgs);\n }\n if (issues.length > 0) {\n return { issues };\n }\n\n return { value: (value ?? null) as Output };\n}\n\ntype ParseInputFieldsArgs = FieldParseArgs & {\n fields: Record<string, FieldRuntime>;\n};\n\n/**\n * Validate a value against a record of input fields, treating the record as a\n * single required object — the same code path deployed functions run via\n * `t.object(fields).parse(...)`, so local validation matches platform behavior.\n * @param args - Input field definitions plus the value, context data, and user\n * @returns Validation result\n */\nexport function parseInputFields(args: ParseInputFieldsArgs): StandardSchemaV1.Result<unknown> {\n const { fields, ...parseArgs } = args;\n return parseInternal({\n ...parseArgs,\n field: { type: \"nested\", fields, _metadata: { required: true } },\n pathArray: [],\n });\n}\n","import type { EnumValue } from \"#/configure/types/field.types\";\n\nexport type AllowedValues = readonly [string | EnumValue, ...(string | EnumValue)[]];\n\n/**\n * Normalize allowed values into EnumValue objects with descriptions.\n * @param values - Allowed values as strings or EnumValue objects\n * @returns Normalized allowed values\n */\nexport function mapAllowedValues(values: AllowedValues): EnumValue[] {\n return values.map((value) => {\n if (typeof value === \"string\") {\n return { value, description: \"\" };\n }\n return { ...value, description: value.description ?? \"\" };\n });\n}\n\nexport type AllowedValuesOutput<V extends AllowedValues> = V[number] extends infer T\n ? T extends string\n ? T\n : T extends { value: infer K }\n ? K\n : never\n : never;\n","import { cloneDeep } from \"es-toolkit\";\nimport {\n type AllowedValues,\n type AllowedValuesOutput,\n mapAllowedValues,\n} from \"#/configure/types/field\";\nimport {\n parseInternal as parseFieldInternal,\n type FieldParseArgs,\n type FieldParseInternalArgs,\n} from \"#/runtime/field-parse\";\nimport { brandValue } from \"#/utils/brand\";\nimport type {\n FieldOptions,\n FieldOutput,\n TailorFieldType,\n TailorToTs,\n FieldValidateInput,\n} from \"#/configure/types/field.types\";\nimport type {\n PrecompiledScriptExprKey,\n PrecompiledScriptExprMap,\n} from \"#/parser/service/tailordb/types\";\nimport type { PluginAttachment, PluginConfigs } from \"#/plugin/types\";\nimport type { InferredAttributes } from \"#/runtime/types\";\nimport type { output, InferFieldsOutput, TypeLevelError } from \"#/types/helpers\";\nimport type { RawPermissions } from \"#/types/tailordb.generated\";\nimport type { TailorTypeGqlPermission, TailorTypePermission } from \"./permission\";\nimport type {\n TailorDBField as TailorDBFieldBase,\n TailorDBType as TailorDBTypeBase,\n DBFieldMetadata,\n DefinedDBFieldMetadata,\n SerialConfig,\n IndexDef,\n TailorDBTypeMetadata,\n RawRelationConfig,\n RelationType,\n Hook,\n TypeHook,\n UpdateHookFn,\n ExcludeNestedDBFields,\n ExcludeHookedDBFields,\n ExcludeDefaultedDBFields,\n TypeFeatures,\n TypeValidateFn,\n} from \"./types\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n// Erased DB fields stay assignable across builder method-state changes.\n// oxlint-disable-next-line no-explicit-any\ntype AnyBuilderMethod = any;\n\nexport type TailorAnyDBField = Omit<\n TailorDBFieldBase<AnyBuilderMethod, AnyBuilderMethod>,\n \"fields\"\n> & {\n readonly fields: Record<string, AnyBuilderMethod>;\n _metadata: DBFieldMetadata;\n parse: AnyBuilderMethod;\n readonly typeName: TypeLevelError<string>;\n description: AnyBuilderMethod;\n relation: AnyBuilderMethod;\n index: AnyBuilderMethod;\n unique: AnyBuilderMethod;\n vector: AnyBuilderMethod;\n default: AnyBuilderMethod;\n hooks: AnyBuilderMethod;\n validate: AnyBuilderMethod;\n serial: AnyBuilderMethod;\n clone: AnyBuilderMethod;\n};\n\n// Helper alias\n// oxlint-disable-next-line no-explicit-any\nexport type TailorAnyDBType = TailorDBType<any, any, any>;\n\ntype IsAny<T> = 0 extends 1 & T ? true : false;\ntype DBFieldTypeNameMethod<Defined extends DefinedDBFieldMetadata> =\n IsAny<Defined> extends true\n ? TypeLevelError<string>\n : TypeLevelError<\"typeName cannot be used on TailorDB fields\">;\n\ntype WithDBFieldDescription<Defined> = Defined & { description: true };\ntype WithDBFieldRelation<Defined, S extends RelationType | RelationSelfConfig> = S extends\n | \"oneToOne\"\n | \"1-1\"\n ? Defined & { unique: true; index: true; relation: true }\n : S extends { type: \"oneToOne\" | \"1-1\" }\n ? Defined & { unique: true; index: true; relation: true }\n : Defined & { index: true; relation: true };\ntype WithDBFieldIndex<Defined> = Defined & { index: true };\ntype WithDBFieldUnique<Defined> = Defined & { unique: true; index: true };\ntype WithDBFieldVector<Defined> = Defined & { vector: true };\ntype WithDBFieldHooks<Defined, H> = Defined & {\n hooks: {\n create: H extends { create: unknown } ? true : false;\n update: H extends { update: unknown } ? true : false;\n };\n serial: false;\n};\ntype WithDBFieldDefault<Defined> = Defined & { default: true };\ntype WithDBFieldValidate<Defined> = Defined & { validate: true };\ntype WithDBFieldSerial<Defined> = Defined & {\n serial: true;\n hooks: { create: false; update: false };\n};\ntype WithDBFieldCloneOptions<Defined extends DefinedDBFieldMetadata, NewOpt extends FieldOptions> =\n IsAny<Defined> extends true\n ? Defined\n : Omit<Defined, \"array\"> & {\n array: NewOpt extends { array: true }\n ? true\n : NewOpt extends { array: false }\n ? false\n : Defined[\"array\"];\n };\ntype NonNullableDBFieldOutput<Output> = Exclude<Output, null>;\ntype DBFieldScalarOutput<Output> =\n NonNullableDBFieldOutput<Output> extends (infer Item)[] ? Item : NonNullableDBFieldOutput<Output>;\ntype DBFieldCloneArrayOutput<Output, NewOpt extends FieldOptions> = NewOpt extends {\n array: true;\n}\n ? DBFieldScalarOutput<Output>[]\n : NewOpt extends { array: false }\n ? DBFieldScalarOutput<Output>\n : NonNullableDBFieldOutput<Output>;\ntype DBFieldCloneOutput<Output, NewOpt extends FieldOptions> = NewOpt extends { optional: true }\n ? DBFieldCloneArrayOutput<Output, NewOpt> | null\n : NewOpt extends { optional: false }\n ? DBFieldCloneArrayOutput<Output, NewOpt>\n : null extends Output\n ? DBFieldCloneArrayOutput<Output, NewOpt> | null\n : DBFieldCloneArrayOutput<Output, NewOpt>;\ntype DBFieldCloneOptions<Defined extends DefinedDBFieldMetadata> = Omit<FieldOptions, \"array\"> & {\n array?: Defined extends { validate: unknown } ? Defined[\"array\"] : boolean;\n};\ntype InvalidValidatedArrayCloneKeys<\n Fields extends Record<string, TailorAnyDBField>,\n K extends keyof Fields,\n Opt extends FieldOptions,\n> = Opt extends { array: infer ArrayOption }\n ? {\n [P in K]: Fields[P] extends TailorDBField<infer Defined, infer _Output>\n ? Defined extends { validate: unknown }\n ? ArrayOption extends Defined[\"array\"]\n ? never\n : P\n : never\n : never;\n }[K]\n : never;\ntype DBFieldsCloneOptionsGuard<\n Fields extends Record<string, TailorAnyDBField>,\n K extends keyof Fields,\n Opt extends FieldOptions,\n> = [InvalidValidatedArrayCloneKeys<Fields, K, Opt>] extends [never]\n ? unknown\n : TypeLevelError<\"array cannot be changed on fields with custom validation\">;\ntype DefinedDBTypeMetadata = {\n hooks?: true;\n validate?: true;\n features?: true;\n indexes?: true;\n files?: true;\n permission?: true;\n gqlPermission?: true;\n description?: true;\n};\ntype WithDBTypeMetadata<\n Defined extends DefinedDBTypeMetadata,\n Key extends keyof DefinedDBTypeMetadata,\n> = Defined & Record<Key, true>;\ntype DBTypeDuplicateInputGuard<\n Defined extends DefinedDBTypeMetadata,\n Key extends keyof DefinedDBTypeMetadata,\n Input,\n Message extends string,\n> =\n IsAny<Defined> extends true\n ? Input\n : Defined extends Record<Key, unknown>\n ? TypeLevelError<Message>\n : Input;\ntype DBTypeDuplicateRestGuard<\n Defined extends DefinedDBTypeMetadata,\n Key extends keyof DefinedDBTypeMetadata,\n Input extends unknown[],\n Message extends string,\n> =\n IsAny<Defined> extends true\n ? Input\n : Defined extends Record<Key, unknown>\n ? [TypeLevelError<Message>, ...TypeLevelError<Message>[]]\n : Input;\ntype FileKeyConflictError<\n Fields extends Record<string, TailorAnyDBField>,\n User extends object,\n> = Partial<\n Record<\n keyof output<TailorDBType<Fields, User>> & string,\n TypeLevelError<\"file keys cannot use existing field names\">\n >\n>;\ntype DBFieldDescriptionFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = (description: string) => TailorDBField<WithDBFieldDescription<Defined>, Output, Nested>;\ntype DBFieldRelationFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = {\n <S extends RelationType, T extends TailorAnyDBType>(\n config: RelationConfig<S, T>,\n ): TailorDBField<WithDBFieldRelation<Defined, S>, Output, Nested>;\n <S extends RelationSelfConfig>(\n config: S,\n ): TailorDBField<WithDBFieldRelation<Defined, S>, Output, Nested>;\n};\ntype DBFieldIndexFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = () => TailorDBField<WithDBFieldIndex<Defined>, Output, Nested>;\ntype DBFieldUniqueFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = () => TailorDBField<WithDBFieldUnique<Defined>, Output, Nested>;\ntype DBFieldVectorFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = () => TailorDBField<WithDBFieldVector<Defined>, Output, Nested>;\ntype DBFieldHooksFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = <\n const H extends Hook<\n Output,\n Defined extends { default: true } ? Output | null | undefined : Output\n >,\n>(\n hooks: H,\n) => TailorDBField<WithDBFieldHooks<Defined, H>, Output, Nested>;\ntype DBFieldValidateFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = (\n ...validate: FieldValidateInput<Output>[]\n) => TailorDBField<WithDBFieldValidate<Defined>, Output, Nested>;\ntype DBFieldSerialFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = (\n config: SerialConfig<Defined[\"type\"] & (\"integer\" | \"string\")>,\n) => TailorDBField<WithDBFieldSerial<Defined>, Output, Nested>;\ntype DBFieldDescriptionMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldDescriptionFn<Defined, Output, Nested>\n : Defined extends { description: unknown }\n ? TypeLevelError<\".description() has already been set\">\n : DBFieldDescriptionFn<Defined, Output, Nested>;\ntype DBFieldRelationMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldRelationFn<Defined, Output, Nested>\n : Defined extends { relation: unknown }\n ? TypeLevelError<\".relation() has already been set\">\n : DBFieldRelationFn<Defined, Output, Nested>;\ntype DBFieldArrayCheck<A extends boolean, Ok, Msg extends string> = A extends true\n ? TypeLevelError<Msg>\n : Ok;\ntype DBFieldIndexMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldIndexFn<Defined, Output, Nested>\n : Defined extends { index: unknown }\n ? TypeLevelError<\".index() has already been set\">\n : DBFieldArrayCheck<\n Defined[\"array\"],\n DBFieldIndexFn<Defined, Output, Nested>,\n \"index cannot be set on array fields\"\n >;\ntype DBFieldUniqueMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldUniqueFn<Defined, Output, Nested>\n : Defined extends { unique: unknown }\n ? TypeLevelError<\".unique() has already been set\">\n : DBFieldArrayCheck<\n Defined[\"array\"],\n DBFieldUniqueFn<Defined, Output, Nested>,\n \"unique cannot be set on array fields\"\n >;\ntype DBFieldVectorMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldVectorFn<Defined, Output, Nested>\n : Defined extends { vector: unknown }\n ? TypeLevelError<\".vector() has already been set\">\n : Defined extends { type: \"string\"; array: false }\n ? DBFieldVectorFn<Defined, Output, Nested>\n : TypeLevelError<\"vector can only be set on non-array string fields\">;\ntype DBFieldHooksMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldHooksFn<Defined, Output, Nested>\n : Defined extends {\n serial: true;\n hooks: { create: false; update: false };\n }\n ? TypeLevelError<\"hooks cannot be set after serial\">\n : Defined extends {\n hooks: unknown;\n }\n ? TypeLevelError<\".hooks() has already been set\">\n : Defined extends { type: \"nested\" }\n ? TypeLevelError<\"hooks cannot be set on nested type fields\">\n : DBFieldHooksFn<Defined, Output, Nested>;\ntype DBFieldValidateMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldValidateFn<Defined, Output, Nested>\n : Defined extends { validate: unknown }\n ? TypeLevelError<\".validate() has already been set\">\n : DBFieldValidateFn<Defined, Output, Nested>;\ntype DBFieldSerialMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldSerialFn<Defined, Output, Nested>\n : Defined extends { serial: true }\n ? TypeLevelError<\".serial() has already been set\">\n : Defined extends { serial: false }\n ? TypeLevelError<\"serial cannot be set after hooks\">\n : IsAny<Output> extends true\n ? Defined extends { type: \"integer\" | \"string\"; array: false }\n ? DBFieldSerialFn<Defined, Output, Nested>\n : TypeLevelError<\"serial can only be set on non-array integer or string fields\">\n : null extends Output\n ? TypeLevelError<\"serial can only be set on non-array integer or string fields\">\n : Defined extends { type: \"integer\" | \"string\"; array: false }\n ? DBFieldSerialFn<Defined, Output, Nested>\n : TypeLevelError<\"serial can only be set on non-array integer or string fields\">;\ntype DBFieldDefaultFn<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> = (\n value: Output extends null ? NonNullable<Output> : Output,\n) => TailorDBField<WithDBFieldDefault<Defined>, Output, Nested>;\ntype DBFieldDefaultMethod<\n Defined extends DefinedDBFieldMetadata,\n Output,\n Nested extends Record<string, TailorAnyDBField>,\n> =\n IsAny<Defined> extends true\n ? DBFieldDefaultFn<Defined, Output, Nested>\n : Defined extends { default: unknown }\n ? TypeLevelError<\".default() has already been set\">\n : Defined extends { type: \"nested\" }\n ? TypeLevelError<\"default cannot be set on nested type fields\">\n : Defined extends { serial: true }\n ? TypeLevelError<\"default cannot be set on serial fields\">\n : null extends Output\n ? TypeLevelError<\"default cannot be set on optional fields\">\n : DBFieldDefaultFn<Defined, Output, Nested>;\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 // Nested object fields, so a `db.object()` field keeps the shape it was declared with.\n // Every builder method passes it through; dropping it here would erase the shape as\n // soon as one is chained.\n Nested extends Record<string, TailorAnyDBField> = Record<string, TailorAnyDBField>,\n> extends Omit<TailorDBFieldBase<Defined, Output, Nested>, \"fields\"> {\n readonly fields: Nested;\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 * typeName is not available on TailorDB fields.\n * Use typeName on pipeline fields (t.enum / t.object) instead.\n */\n typeName: DBFieldTypeNameMethod<Defined>;\n\n /**\n * Set a description for the field\n */\n description: DBFieldDescriptionMethod<Defined, Output, Nested>;\n\n /**\n * Define a relation to another table.\n */\n relation: DBFieldRelationMethod<Defined, Output, Nested>;\n\n /**\n * Add an index to the field\n */\n index: DBFieldIndexMethod<Defined, Output, Nested>;\n\n /**\n * Make the field unique (also adds an index)\n */\n unique: DBFieldUniqueMethod<Defined, Output, Nested>;\n\n /**\n * Enable vector search on the field (string type only)\n */\n vector: DBFieldVectorMethod<Defined, Output, Nested>;\n\n /**\n * Set a default value for the field on create. When the field is required,\n * this makes it optional in the Create input — the default fills in when\n * no value (or a nullish hook result) is provided.\n *\n * For datetime/date/time fields, pass `\"now\"` to use the operation timestamp.\n */\n default: DBFieldDefaultMethod<Defined, Output, Nested>;\n\n /**\n * Add hooks for create/update operations on this field.\n */\n hooks: DBFieldHooksMethod<Defined, Output, Nested>;\n\n /**\n * Add validation functions to the field.\n *\n * Validators receive `{ value, data, user }` and run after hooks and\n * built-in type validation; they are skipped when built-in validation\n * fails. For array fields, `value` is the complete array.\n */\n validate: DBFieldValidateMethod<Defined, Output, Nested>;\n\n /**\n * Configure serial/auto-increment behavior\n */\n serial: DBFieldSerialMethod<Defined, Output, Nested>;\n\n /**\n * Clone the field with optional overrides for field options.\n * The `array` option cannot change on fields with custom validation.\n */\n clone<const NewOpt extends DBFieldCloneOptions<Defined>>(\n options?: NewOpt,\n ): TailorDBField<\n WithDBFieldCloneOptions<Defined, NewOpt>,\n DBFieldCloneOutput<Output, NewOpt>,\n Nested\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 = InferredAttributes,\n // oxlint-disable-next-line no-explicit-any\n Defined extends DefinedDBTypeMetadata = any,\n> extends TailorDBTypeBase<Fields, User> {\n _description?: string;\n\n hooks(\n hook: DBTypeDuplicateInputGuard<\n Defined,\n \"hooks\",\n TypeHook<Fields>,\n \".hooks() has already been set\"\n >,\n ): TailorDBType<Fields, User, WithDBTypeMetadata<Defined, \"hooks\">>;\n validate(\n fn: DBTypeDuplicateInputGuard<\n Defined,\n \"validate\",\n TypeValidateFn<Fields>,\n \".validate() has already been set\"\n >,\n ): TailorDBType<Fields, User, WithDBTypeMetadata<Defined, \"validate\">>;\n features(\n features: DBTypeDuplicateInputGuard<\n Defined,\n \"features\",\n Omit<TypeFeatures, \"pluralForm\">,\n \".features() has already been set\"\n >,\n ): TailorDBType<Fields, User, WithDBTypeMetadata<Defined, \"features\">>;\n indexes(\n ...indexes: DBTypeDuplicateRestGuard<\n Defined,\n \"indexes\",\n IndexDef<TailorDBType<Fields, User, Defined>>[],\n \".indexes() has already been set\"\n >\n ): TailorDBType<Fields, User, WithDBTypeMetadata<Defined, \"indexes\">>;\n files<const F extends string>(\n files: DBTypeDuplicateInputGuard<\n Defined,\n \"files\",\n Record<F, string> & FileKeyConflictError<Fields, User>,\n \".files() has already been set\"\n >,\n ): TailorDBType<Fields, User, WithDBTypeMetadata<Defined, \"files\">>;\n permission<\n U extends object = User,\n P extends TailorTypePermission<U, output<TailorDBType<Fields, User, Defined>>> =\n TailorTypePermission<U, output<TailorDBType<Fields, User, Defined>>>,\n >(\n permission: DBTypeDuplicateInputGuard<\n Defined,\n \"permission\",\n P,\n \".permission() has already been set\"\n >,\n ): TailorDBType<Fields, U, WithDBTypeMetadata<Defined, \"permission\">>;\n gqlPermission<\n U extends object = User,\n P extends TailorTypeGqlPermission<U> = TailorTypeGqlPermission<U>,\n >(\n permission: DBTypeDuplicateInputGuard<\n Defined,\n \"gqlPermission\",\n P,\n \".gqlPermission() has already been set\"\n >,\n ): TailorDBType<Fields, U, WithDBTypeMetadata<Defined, \"gqlPermission\">>;\n description(\n description: DBTypeDuplicateInputGuard<\n Defined,\n \"description\",\n string,\n \".description() has already been set\"\n >,\n ): TailorDBType<Fields, User, WithDBTypeMetadata<Defined, \"description\">>;\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 & DBFieldsCloneOptionsGuard<Fields, K, Opt>,\n ): {\n [P in K]: Fields[P] extends TailorDBField<infer D, infer O>\n ? TailorDBField<WithDBFieldCloneOptions<D, Opt>, DBFieldCloneOutput<O, Opt>>\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, Defined>;\n}\n\nexport type TailorDBInstance<\n // oxlint-disable-next-line no-explicit-any\n Fields extends Record<string, TailorAnyDBField> = any,\n User extends object = InferredAttributes,\n // oxlint-disable-next-line no-explicit-any\n Defined extends DefinedDBTypeMetadata = any,\n> = TailorDBType<Fields, User, Defined>;\n\ninterface RelationConfig<S extends RelationType, T extends TailorDBType> {\n type: S;\n toward:\n | {\n table: T;\n as?: string;\n key?: keyof T[\"fields\"] & string;\n type?: never;\n }\n | {\n /**\n * @deprecated since 2.6.0 — use `table` instead. codemod: v3/relation-toward-table\n */\n type: T;\n as?: string;\n key?: keyof T[\"fields\"] & string;\n table?: never;\n };\n backward?: string;\n}\n\n// Special config variant for self-referencing relations\ntype RelationSelfConfig = {\n type: RelationType;\n toward:\n | {\n table: \"self\";\n as?: string;\n key?: string;\n type?: never;\n }\n | {\n /**\n * @deprecated since 2.6.0 — use `table` instead. codemod: v3/relation-toward-table\n */\n type: \"self\";\n as?: string;\n key?: string;\n table?: never;\n };\n backward?: string;\n};\n\ntype DBFieldDefined<T extends TailorFieldType, Opt extends FieldOptions> = {\n type: T;\n array: Opt extends { array: true } ? true : false;\n};\ntype DBFieldOutput<\n T extends TailorFieldType,\n Opt extends FieldOptions,\n OutputBase = TailorToTs[T],\n> = FieldOutput<OutputBase, Opt>;\ntype TailorDBFieldInstance<\n T extends TailorFieldType,\n Opt extends FieldOptions,\n OutputBase = TailorToTs[T],\n> = TailorDBField<DBFieldDefined<T, Opt>, DBFieldOutput<T, Opt, OutputBase>>;\ntype TailorDBFieldRuntimeInstance<\n T extends TailorFieldType,\n Opt extends FieldOptions,\n OutputBase = TailorToTs[T],\n> = TailorDBFieldRuntime<DBFieldDefined<T, Opt>, DBFieldOutput<T, Opt, OutputBase>>;\ntype TailorDBFieldRuntime<Defined extends DefinedDBFieldMetadata, Output> = Omit<\n TailorDBFieldBase<Defined, Output>,\n \"fields\"\n> & {\n readonly fields: Record<string, TailorAnyDBField>;\n _metadata: DBFieldMetadata;\n description(description: string): object;\n typeName(typeName: string): object;\n validate(...validate: FieldValidateInput<Output>[]): object;\n relation(config: RelationConfig<RelationType, TailorDBType> | RelationSelfConfig): object;\n index(): object;\n unique(): object;\n vector(): object;\n default(value: unknown): object;\n hooks(hooks: Hook<Output>): object;\n serial(config: SerialConfig): object;\n clone(options?: FieldOptions): TailorDBFieldRuntime<DefinedDBFieldMetadata, AnyBuilderMethod>;\n parse(args: FieldParseArgs): StandardSchemaV1.Result<Output>;\n _setRawRelation(relation: RawRelationConfig): void;\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): TailorDBFieldInstance<T, TOptions, OutputBase>;\nfunction createTailorDBField<const T extends TailorFieldType, const TOptions extends FieldOptions>(\n type: T,\n options?: TOptions,\n fields?: Record<string, TailorAnyDBField>,\n values?: AllowedValues,\n): object {\n return createTailorDBFieldRuntime(type, options, fields, values);\n}\n\nfunction createTailorDBFieldRuntime<\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): TailorDBFieldRuntimeInstance<T, TOptions, OutputBase> {\n type FieldValue = DBFieldOutput<T, TOptions, OutputBase>;\n type FieldType = TailorDBFieldRuntimeInstance<T, TOptions, OutputBase>;\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 function parseInternal(args: FieldParseInternalArgs): StandardSchemaV1.Result<FieldValue> {\n return parseFieldInternal<T, FieldValue>({\n ...args,\n field,\n });\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 ?? {},\n _defined: undefined as unknown as DBFieldDefined<T, TOptions>,\n _output: undefined as FieldValue,\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 return cloneWith({ description });\n },\n\n typeName(typeName: string) {\n return cloneWith({ typeName });\n },\n\n validate(...validateInputs: FieldValidateInput<FieldValue>[]) {\n return cloneWith({ validate: validateInputs });\n },\n\n parse(args: FieldParseArgs): StandardSchemaV1.Result<FieldValue> {\n return parseInternal({\n value: args.value,\n data: args.data,\n invoker: args.invoker,\n pathArray: [],\n });\n },\n\n // TailorDBField specific methods\n relation(config: RelationConfig<RelationType, TailorDBType> | RelationSelfConfig) {\n const cloned = field.clone();\n // The public type is a nested union (RelationConfig | RelationSelfConfig,\n // each with a `{ table } | { type }` toward), which TS's \"in\" narrowing\n // can't discriminate across cleanly. Re-view it as the flat two-branch\n // shape it always is at runtime — the `table?: never` / `type?: never`\n // markers above already forbid both keys from being set together.\n const toward = config.toward as\n | { table: TailorDBType | \"self\" }\n | { type: TailorDBType | \"self\" };\n const towardTarget = \"table\" in toward ? toward.table : toward.type;\n const targetTable = towardTarget === \"self\" ? \"self\" : towardTarget.name;\n cloned._setRawRelation({\n type: config.type,\n toward: {\n table: targetTable,\n as: config.toward.as,\n key: config.toward.key,\n },\n backward: config.backward,\n });\n return cloned;\n },\n\n index() {\n return cloneWith({ index: true });\n },\n\n unique() {\n return cloneWith({ unique: true, index: true });\n },\n\n vector() {\n return cloneWith({ vector: true });\n },\n\n // oxlint-disable-next-line no-explicit-any\n default(value: any) {\n // oxlint-disable-next-line no-explicit-any\n return cloneWith({ default: value }) as any;\n },\n\n hooks(hooks: Hook<FieldValue>) {\n return cloneWith({ hooks });\n },\n\n serial(config: SerialConfig) {\n return cloneWith({ serial: config });\n },\n\n clone(cloneOptions?: FieldOptions) {\n if (\n this._metadata.validate?.length &&\n cloneOptions?.array !== undefined &&\n cloneOptions.array !== (this._metadata.array === true)\n ) {\n throw new Error(\"Cannot change the array option on a field with custom validation\");\n }\n\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 = createTailorDBFieldRuntime(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 clonedField._setRawRelation(cloneDeep(_rawRelation));\n }\n\n return clonedField;\n },\n\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, such as \"yyyy-MM-ddTHH:mm:ssZ\" or \"yyyy-MM-ddTHH:mm:ss+09:00\"\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> &\n ExcludeNestedDBFields<F> &\n ExcludeHookedDBFields<F> &\n ExcludeDefaultedDBFields<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 F\n >;\n}\n\n/**\n * Creates a new TailorDBType instance.\n * @param name - Table name\n * @param fields - Field definitions\n * @param options - Table 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 = InferredAttributes,\n>(\n name: string,\n fields: Fields,\n options: { pluralForm?: string; description?: string },\n): TailorDBType<Fields, User, DefinedDBTypeMetadata> {\n let _description = options.description;\n let _settings: TypeFeatures = {};\n let _indexes: IndexDef<TailorDBType<Fields, User, DefinedDBTypeMetadata>>[] = [];\n const _permissions: RawPermissions = {};\n let _files: Record<string, string> = {};\n const _plugins: PluginAttachment[] = [];\n // oxlint-disable-next-line typescript/no-unsafe-function-type\n let _typeHook: { create?: Function; update?: Function } | undefined;\n // oxlint-disable-next-line typescript/no-unsafe-function-type\n let _typeValidate: Function | undefined;\n const _definedMethods = new Set<keyof DefinedDBTypeMetadata>();\n if (options.description !== undefined) {\n _definedMethods.add(\"description\");\n }\n\n function runMethodOnce<T>(method: keyof DefinedDBTypeMetadata, action: () => T): T {\n if (_definedMethods.has(method)) {\n throw new Error(`.${method}() has already been set`);\n }\n const result = action();\n _definedMethods.add(method);\n return result;\n }\n type TypeAfter<Key extends keyof DefinedDBTypeMetadata> = TailorDBType<\n Fields,\n User,\n WithDBTypeMetadata<DefinedDBTypeMetadata, Key>\n >;\n type TypeAfterUser<\n NextUser extends object,\n Key extends keyof DefinedDBTypeMetadata,\n > = TailorDBType<Fields, NextUser, WithDBTypeMetadata<DefinedDBTypeMetadata, Key>>;\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, DefinedDBTypeMetadata> = {\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.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 ...(_typeHook && { typeHook: _typeHook }),\n ...(_typeValidate && { typeValidate: _typeValidate }),\n };\n },\n\n hooks(hook: TypeHook<Fields>): TypeAfter<\"hooks\"> {\n return runMethodOnce(\"hooks\", () => {\n _typeHook = hook;\n return this as TypeAfter<\"hooks\">;\n });\n },\n\n validate(fn: TypeValidateFn<Fields>): TypeAfter<\"validate\"> {\n return runMethodOnce(\"validate\", () => {\n _typeValidate = fn;\n return this as TypeAfter<\"validate\">;\n });\n },\n\n features(features: Omit<TypeFeatures, \"pluralForm\">): TypeAfter<\"features\"> {\n return runMethodOnce(\"features\", () => {\n _settings = {\n ..._settings,\n ...features,\n };\n return this as TypeAfter<\"features\">;\n });\n },\n\n indexes(\n ...indexes: IndexDef<TailorDBType<Fields, User, DefinedDBTypeMetadata>>[]\n ): TypeAfter<\"indexes\"> {\n return runMethodOnce(\"indexes\", () => {\n _indexes = indexes;\n return this as TypeAfter<\"indexes\">;\n });\n },\n\n files<const F extends string>(\n files: Record<F, string> & FileKeyConflictError<Fields, User>,\n ): TypeAfter<\"files\"> {\n return runMethodOnce(\"files\", () => {\n _files = files;\n return this as TypeAfter<\"files\">;\n });\n },\n\n permission<\n U extends object = User,\n P extends TailorTypePermission<U, output<TailorDBType<Fields, User, DefinedDBTypeMetadata>>> =\n TailorTypePermission<U, output<TailorDBType<Fields, User, DefinedDBTypeMetadata>>>,\n >(permission: P): TypeAfterUser<U, \"permission\"> {\n return runMethodOnce(\"permission\", () => {\n const ret = this as unknown as TypeAfterUser<U, \"permission\">;\n _permissions.record = permission as RawPermissions[\"record\"];\n return ret;\n });\n },\n\n gqlPermission<\n U extends object = User,\n P extends TailorTypeGqlPermission<U> = TailorTypeGqlPermission<U>,\n >(permission: P): TypeAfterUser<U, \"gqlPermission\"> {\n return runMethodOnce(\"gqlPermission\", () => {\n const ret = this as unknown as TypeAfterUser<U, \"gqlPermission\">;\n _permissions.gql = permission as RawPermissions[\"gql\"];\n return ret;\n });\n },\n\n description(description: string): TypeAfter<\"description\"> {\n return runMethodOnce(\"description\", () => {\n _description = description;\n this._description = description;\n return this as TypeAfter<\"description\">;\n });\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 const field = this.fields[key] as TailorAnyDBField;\n if (options) {\n result[key] = field.clone(options);\n } else {\n result[key] = field;\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] as TailorAnyDBField;\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, AnyBuilderMethod> {\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 DBTable<\n F extends { id?: never } & Record<string, TailorAnyDBField>,\n Defined extends DefinedDBTypeMetadata = DefinedDBTypeMetadata,\n> = TailorDBInstance<{ id: idField } & F, InferredAttributes, Defined>;\n\n/**\n * Creates a new database table with the specified fields.\n * An `id` field (UUID) is automatically added to every table.\n * @param name - The name of the table, or a tuple of [name, pluralForm]\n * @param fields - The field definitions for the table\n * @returns A new TailorDB table instance\n * @example\n * export const user = db.table(\"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 dbTable<const F extends { id?: never } & Record<string, TailorAnyDBField>>(\n name: string | [string, string],\n fields: F,\n): DBTable<F>;\n/**\n * Creates a new database table with the specified fields and description.\n * An `id` field (UUID) is automatically added to every table.\n * @param name - The name of the table, or a tuple of [name, pluralForm]\n * @param description - A description of the table\n * @param fields - The field definitions for the table\n * @returns A new TailorDB table instance\n */\nfunction dbTable<const F extends { id?: never } & Record<string, TailorAnyDBField>>(\n name: string | [string, string],\n description: string,\n fields: F,\n): DBTable<F, WithDBTypeMetadata<DefinedDBTypeMetadata, \"description\">>;\nfunction dbTable<const F extends { id?: never } & Record<string, TailorAnyDBField>>(\n name: string | [string, string],\n fieldsOrDescription: string | F,\n fields?: F,\n): DBTable<F> | DBTable<F, WithDBTypeMetadata<DefinedDBTypeMetadata, \"description\">> {\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 );\n}\n\n// `Function.prototype.toString()` of this hook is embedded verbatim into deployed\n// schemas and migration diffs (see parser/service/tailordb/hooks-validate-precompiled-expr.ts\n// and field.ts). Its source text depends on how the SDK itself was built (e.g.\n// minification), so a fixed expression is pinned onto it directly here instead -\n// configure cannot import parser's `setPrecompiledScriptExpr` runtime helper across\n// the module boundary, only the symbol registry key and map types. Keep\n// this literal in sync with the \"timestamps() updatedAt hook resolves to the pinned\n// expr\" test in parser/service/tailordb/field.precompiled.test.ts, which fails if it\n// ever drifts from what this hook's own source naturally produces.\ntype TimestampsUpdatedAtHookFn = UpdateHookFn<string | Date | null, string | Date>;\nconst timestampsUpdatedAtHook: TimestampsUpdatedAtHookFn = ({ input, now }) => input ?? now;\nconst PRECOMPILED_EXPR_KEY: PrecompiledScriptExprKey =\n \"tailor-platform/sdk:precompiled-script-expr\";\nconst PRECOMPILED_EXPR_SYMBOL = Symbol.for(PRECOMPILED_EXPR_KEY);\n(timestampsUpdatedAtHook as unknown as Record<symbol, PrecompiledScriptExprMap>)[\n PRECOMPILED_EXPR_SYMBOL\n] = {\n \"hooks.update\":\n \"(({ input, now }) => input ?? now)({ input: _value, oldValue: _oldValue, invoker: _principal, now: _now })\",\n};\n\n/** TailorDB schema builder utilities for defining tables and fields. */\nexport const db = {\n table: dbTable,\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 automatic defaults.\n * Both fields default to the current time on create. updatedAt is also refreshed on update.\n * User-specified values are respected when provided (e.g. seeding historical records).\n * @returns An object with createdAt and updatedAt fields\n * @example\n * const model = db.table(\"Model\", {\n * name: db.string(),\n * ...db.fields.timestamps(),\n * });\n */\n timestamps: () => ({\n createdAt: datetime().default(\"now\").description(\"Record creation timestamp\"),\n updatedAt: datetime()\n .default(\"now\")\n .hooks({ update: timestampsUpdatedAtHook })\n .description(\"Record update timestamp\"),\n }),\n },\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import*as e from"pathe";import*as t from"node:fs";function chmodIfDifferent(e,n){if(process.platform!==`win32`)try{(t.statSync(e).mode&511)!==n&&t.chmodSync(e,n)}catch{}}function writeSecretFile(n,r){ensureSecretDir(e.dirname(n)),t.writeFileSync(n,r,{mode:384}),chmodIfDifferent(n,384)}function ensureSecretDir(e){t.mkdirSync(e,{recursive:!0,mode:448}),chmodIfDifferent(e,448)}function tightenSecretFilePermissions(t){chmodIfDifferent(t,384),chmodIfDifferent(e.dirname(t),448)}export{tightenSecretFilePermissions as n,writeSecretFile as r,ensureSecretDir as t};
|
|
2
|
+
//# sourceMappingURL=secret-file-C9wp_FCX.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-file-
|
|
1
|
+
{"version":3,"file":"secret-file-C9wp_FCX.mjs","names":[],"sources":["../src/cli/shared/secret-file.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"pathe\";\n\nconst DIR_MODE = 0o700;\nconst FILE_MODE = 0o600;\n\n/**\n * Best-effort chmod that only fires when the current mode differs from the\n * target. No-op on Windows (where POSIX mode bits are advisory and ACLs\n * govern access) and on missing paths / permission errors.\n * @param target - Path to chmod\n * @param mode - Desired POSIX mode bits\n */\nfunction chmodIfDifferent(target: string, mode: number): void {\n if (process.platform === \"win32\") return;\n try {\n if ((fs.statSync(target).mode & 0o777) !== mode) {\n fs.chmodSync(target, mode);\n }\n } catch {\n // Missing path or permission error — best-effort.\n }\n}\n\n/**\n * Write a file that may contain secrets with restrictive permissions.\n * Creates the parent directory with 0o700 and the file with 0o600 on POSIX\n * systems so other users on the host cannot read access tokens, refresh\n * tokens, or crash report payloads. On Windows the POSIX mode bits are\n * effectively ignored and ACLs govern access, so the chmod calls are\n * best-effort and silently skipped.\n * @param filePath - Absolute path to write\n * @param content - File content\n */\nexport function writeSecretFile(filePath: string, content: string | Buffer): void {\n ensureSecretDir(path.dirname(filePath));\n fs.writeFileSync(filePath, content, { mode: FILE_MODE });\n chmodIfDifferent(filePath, FILE_MODE);\n}\n\n/**\n * Ensure a directory exists with 0o700 permissions on POSIX systems.\n * `mkdirSync({ recursive: true })` does not chmod existing directories,\n * so this also tightens permissions on directories that were previously\n * created with looser modes.\n * @param dir - Directory path\n */\nexport function ensureSecretDir(dir: string): void {\n fs.mkdirSync(dir, { recursive: true, mode: DIR_MODE });\n chmodIfDifferent(dir, DIR_MODE);\n}\n\n/**\n * Tighten an existing file and its parent directory to secret-file modes\n * (0o600 / 0o700) if they are looser. Used by read paths that may not\n * trigger a subsequent write, so that legacy world-readable files are\n * still secured the next time the CLI runs. Silent no-op on Windows and\n * on missing files / permission errors.\n * @param filePath - Absolute path that should be 0o600 and live under a 0o700 directory\n */\nexport function tightenSecretFilePermissions(filePath: string): void {\n chmodIfDifferent(filePath, FILE_MODE);\n chmodIfDifferent(path.dirname(filePath), DIR_MODE);\n}\n"],"mappings":"kDAaA,SAAS,iBAAiB,EAAgB,EAAoB,CACxD,WAAQ,WAAa,QACzB,GAAI,EACG,EAAG,SAAS,CAAM,CAAC,CAAC,KAAO,OAAW,GACzC,EAAG,UAAU,EAAQ,CAAI,CAE7B,MAAQ,CAER,CACF,CAYA,SAAgB,gBAAgB,EAAkB,EAAgC,CAChF,gBAAgB,EAAK,QAAQ,CAAQ,CAAC,EACtC,EAAG,cAAc,EAAU,EAAS,CAAE,KAAM,GAAU,CAAC,EACvD,iBAAiB,EAAU,GAAS,CACtC,CASA,SAAgB,gBAAgB,EAAmB,CACjD,EAAG,UAAU,EAAK,CAAE,UAAW,GAAM,KAAM,GAAS,CAAC,EACrD,iBAAiB,EAAK,GAAQ,CAChC,CAUA,SAAgB,6BAA6B,EAAwB,CACnE,iBAAiB,EAAU,GAAS,EACpC,iBAAiB,EAAK,QAAQ,CAAQ,EAAG,GAAQ,CACnD"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{t as e}from"./assert-WeXvmG4j.mjs";import{vi as t}from"vitest";function withDispose(e,t){return Object.defineProperty(e,Symbol.dispose,{value:t,enumerable:!1,writable:!0,configurable:!0}),e}function tailorRoot(){let e=globalThis;return e.tailor||={context:{getInvoker:()=>null}},e.tailor}function tailordbRoot(){let e=globalThis;return e.tailordb||={},e.tailordb}const n=Symbol(`tailorSecretStore`);function mockSecretmanager(r={}){let i=tailorRoot(),a=i.secretmanager,o={store:structuredClone(a?.[n]?.store??{})};for(let[e,t]of Object.entries(r.secrets??{}))o.store[e]={...o.store[e],...t};async function defaultGetSecret(e,t){return o.store[e]?.[t]}async function defaultGetSecrets(t,n){let r=o.store[t]??{},i={};for(let t of n)t in r&&(i[t]=e(r[t],`vault entry missing for: ${t}`));return i}let s=t.fn(defaultGetSecret),c=t.fn(defaultGetSecrets);return i.secretmanager={getSecret:s,getSecrets:c,[n]:o},withDispose({getSecret:s,getSecrets:c,setSecrets(e){o.store=e},setSecret(e,t,n){o.store={...o.store,[e]:{...o.store[e],[t]:n}}},mergeSecrets(e,t){o.store={...o.store,[e]:{...o.store[e],...t}}},get calls(){return[...s.mock.calls.map((e,t)=>({order:s.mock.invocationCallOrder[t]??0,call:{method:`getSecret`,vault:e[0],name:e[1]}})),...c.mock.calls.map((e,t)=>({order:c.mock.invocationCallOrder[t]??0,call:{method:`getSecrets`,vault:e[0],names:e[1]}}))].toSorted((e,t)=>e.order-t.order).map(e=>e.call)},clear(){s.mockClear(),c.mockClear()},reset(){o.store={},s.mockReset(),s.mockImplementation(defaultGetSecret),c.mockReset(),c.mockImplementation(defaultGetSecrets)}},()=>{i.secretmanager=a})}export{withDispose as i,tailorRoot as n,tailordbRoot as r,mockSecretmanager as t};
|
|
2
|
+
//# sourceMappingURL=secretmanager-5olfnI1b.mjs.map
|