@tailor-platform/sdk 1.46.0 → 1.47.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +48 -0
- package/dist/{actor-BmxQeMFP.d.mts → actor-jk4-f0yp.d.mts} +3 -3
- package/dist/{application-B4zVVNRS.mjs → application-C7H7y0hS.mjs} +66 -103
- package/dist/application-C7H7y0hS.mjs.map +1 -0
- package/dist/application-Csq5jxYP.mjs +4 -0
- package/dist/{brand-Ll48SMXe.mjs → brand-D-d15jx3.mjs} +1 -1
- package/dist/{brand-Ll48SMXe.mjs.map → brand-D-d15jx3.mjs.map} +1 -1
- package/dist/cli/index.mjs +36 -18
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lib.d.mts +6 -6
- package/dist/cli/lib.mjs +3 -3
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/skills.mjs.map +1 -1
- package/dist/{client-DTaArWQr.mjs → client-DCqdtFte.mjs} +1 -1
- package/dist/client-DbyKSN1F.mjs +1061 -0
- package/dist/client-DbyKSN1F.mjs.map +1 -0
- package/dist/configure/index.d.mts +4 -4
- package/dist/configure/index.mjs +8 -47
- package/dist/configure/index.mjs.map +1 -1
- package/dist/{crashreport-DGeGj9BF.mjs → crashreport-CNSw_BrJ.mjs} +2 -2
- package/dist/{crashreport-DGeGj9BF.mjs.map → crashreport-CNSw_BrJ.mjs.map} +1 -1
- package/dist/{crashreport-6mcMyWu4.mjs → crashreport-DXGFd16F.mjs} +1 -1
- package/dist/enum-constants-C3KSpsYj.mjs.map +1 -1
- package/dist/errors-wNQxQQBH.mjs.map +1 -1
- package/dist/{field-BY2vbJ8f.mjs → field-DLSIuMTu.mjs} +1 -1
- package/dist/{field-BY2vbJ8f.mjs.map → field-DLSIuMTu.mjs.map} +1 -1
- package/dist/file-utils-DjNi_3U_.mjs.map +1 -1
- package/dist/{index-DV-5OIEv.d.mts → index-BRvNi5q9.d.mts} +2 -2
- package/dist/{index-BBvPd9Uv.d.mts → index-BXyS7xKC.d.mts} +2 -2
- package/dist/{index-Dxe6alSZ.d.mts → index-BbOTbZFf.d.mts} +2 -2
- package/dist/{index-PB0otrDj.d.mts → index-DB8EapT-.d.mts} +7 -15
- package/dist/{index-B5_4Tzm2.d.mts → index-iy-hNfGp.d.mts} +2 -2
- package/dist/{interceptor-CrcDfLPq.mjs → interceptor-CBsqEWDK.mjs} +1 -1
- package/dist/{interceptor-CrcDfLPq.mjs.map → interceptor-CBsqEWDK.mjs.map} +1 -1
- package/dist/{job-BOvKyNdT.mjs → job-R5C2Hfcc.mjs} +2 -3
- package/dist/job-R5C2Hfcc.mjs.map +1 -0
- package/dist/kysely/index.mjs.map +1 -1
- package/dist/kysely-type-B8aRz_oC.mjs.map +1 -1
- package/dist/logger-DTNAMYGy.mjs.map +1 -1
- package/dist/mock-BP-9O5On.mjs +796 -0
- package/dist/mock-BP-9O5On.mjs.map +1 -0
- package/dist/multiline-e3IpANmS.mjs.map +1 -1
- package/dist/package-json-6Px8bDpG.mjs.map +1 -1
- package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
- package/dist/plugin/builtin/file-utils/index.d.mts +1 -1
- package/dist/plugin/builtin/kysely-type/index.d.mts +1 -1
- package/dist/plugin/builtin/seed/index.d.mts +1 -1
- package/dist/plugin/index.d.mts +2 -2
- package/dist/plugin/index.mjs.map +1 -1
- package/dist/{repl-editor-BlT2dFtm.mjs → repl-editor-CZpLlOBj.mjs} +1 -1
- package/dist/{repl-editor-BlT2dFtm.mjs.map → repl-editor-CZpLlOBj.mjs.map} +1 -1
- package/dist/{runtime-B67skpW-.mjs → runtime-XjP6JMmP.mjs} +91 -10
- package/dist/runtime-XjP6JMmP.mjs.map +1 -0
- package/dist/seed/index.mjs.map +1 -1
- package/dist/seed-DrKY5yIF.mjs.map +1 -1
- package/dist/{service-CCgw66c6.mjs → service-obEU5gSM.mjs} +1 -1
- package/dist/{service-CCgw66c6.mjs.map → service-obEU5gSM.mjs.map} +1 -1
- package/dist/{tailor-db-field-Hx9OqPWY.d.mts → tailor-db-field-Bn8ZC5lK.d.mts} +1 -1
- package/dist/{schema-DBq6hr6h.mjs → tailordb-DjlNUV6u.mjs} +44 -4
- package/dist/tailordb-DjlNUV6u.mjs.map +1 -0
- package/dist/telemetry-DcL8Fsm_.mjs.map +1 -1
- package/dist/types-DoIG6Nij.mjs +5 -0
- package/dist/{types-Duhhsx3R.mjs → types-sir9UPht.mjs} +2 -2
- package/dist/{types-Duhhsx3R.mjs.map → types-sir9UPht.mjs.map} +1 -1
- package/dist/utils/test/index.d.mts +13 -4
- package/dist/utils/test/index.mjs +13 -4
- package/dist/utils/test/index.mjs.map +1 -1
- package/dist/vitest/environment.d.mts +12 -0
- package/dist/vitest/environment.mjs +44 -0
- package/dist/vitest/environment.mjs.map +1 -0
- package/dist/vitest/index.d.mts +345 -0
- package/dist/vitest/index.mjs +350 -0
- package/dist/vitest/index.mjs.map +1 -0
- package/dist/vitest/setup.d.mts +64 -0
- package/dist/vitest/setup.mjs +141 -0
- package/dist/vitest/setup.mjs.map +1 -0
- package/dist/{workflow.generated-DFljpJh7.d.mts → workflow.generated-i7PK4fg-.d.mts} +2 -2
- package/docs/cli/setup.md +1 -0
- package/docs/services/tailordb.md +43 -12
- package/docs/services/workflow.md +1 -6
- package/docs/testing.md +530 -243
- package/package.json +37 -10
- package/dist/application-B4zVVNRS.mjs.map +0 -1
- package/dist/application-Boa_11Nv.mjs +0 -4
- package/dist/client-BwXkoiMq.mjs +0 -16536
- package/dist/client-BwXkoiMq.mjs.map +0 -1
- package/dist/job-BOvKyNdT.mjs.map +0 -1
- package/dist/runtime-B67skpW-.mjs.map +0 -1
- package/dist/schema-DBq6hr6h.mjs.map +0 -1
- package/dist/types-BnphjkIJ.mjs +0 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-BP-9O5On.mjs","names":["#record","#namespace","#fromEncoding","#toEncoding"],"sources":["../src/vitest/mock.ts"],"sourcesContent":["/**\n * Mock implementations for Tailor Platform APIs.\n *\n * Provides singleton mock objects that are automatically injected into\n * globalThis by the tailor-runtime Vitest environment. Tests can configure\n * responses and assert on recorded calls via the exported mock objects.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ntype QueryResolver = (query: string, params: unknown[]) => unknown[];\ntype JobHandler = (jobName: string, args: unknown) => unknown;\ntype IdpResolver = (method: string, args: unknown[], namespace: string) => unknown;\ntype FileResolver = (method: string, call: FileCall) => unknown;\ntype IconvResolver = (method: string, args: unknown[]) => unknown;\n\ntype TriggerWorkflowOptions = {\n authInvoker?: { namespace: string; machineUserName: string };\n};\ntype TriggerHandlerFn = (\n workflowName: string,\n args: unknown,\n options?: TriggerWorkflowOptions,\n) => string;\ntype WaitHandlerFn = (key: string, payload: unknown) => unknown;\ntype ResolveHandler = (\n executionId: string,\n key: string,\n callback: (payload: unknown) => unknown,\n) => unknown | Promise<unknown>;\n\n// Overloaded so TypeScript narrows to WaitHandlerFn first (giving inferred\n// `(key: string, payload: unknown) => …` for callers) before falling back\n// to the static-value form. A union type would let `unknown` swallow the\n// function variant and break inference.\ntype SetWaitHandler = {\n (handler: WaitHandlerFn): void;\n (handler: unknown): void;\n};\n\ninterface ExecutedQuery {\n query: string;\n params: unknown[];\n}\n\ninterface CreatedClient {\n namespace: string | undefined;\n ended: boolean;\n}\n\ninterface TriggeredJob {\n jobName: string;\n args: unknown;\n}\n\ninterface SecretCall {\n method: \"getSecret\" | \"getSecrets\";\n vault: string;\n name?: string;\n names?: readonly string[];\n}\n\ninterface AuthConnectionCall {\n connectionName: string;\n}\n\ninterface IdpCall {\n method: string;\n args: unknown[];\n namespace: string;\n}\n\ninterface FileCall {\n method: string;\n namespace: string;\n typeName: string;\n fieldName: string;\n recordId: string;\n}\n\ninterface IconvCall {\n method: string;\n args: unknown[];\n}\n\ninterface WorkflowCall {\n method: \"triggerWorkflow\" | \"wait\" | \"resolve\";\n args: unknown[];\n}\n\ninterface MockState {\n // TailorDB\n queryResolver: QueryResolver;\n queryResultQueue: unknown[][];\n executedQueries: ExecutedQuery[];\n createdClients: CreatedClient[];\n // Workflow\n jobHandler: JobHandler;\n jobResultQueue: unknown[];\n triggeredJobs: TriggeredJob[];\n triggerHandler: string | TriggerHandlerFn;\n waitHandler: unknown | WaitHandlerFn;\n resolveHandler: ResolveHandler | null;\n workflowCalls: WorkflowCall[];\n // SecretManager\n secretStore: Record<string, Record<string, string>>;\n secretCalls: SecretCall[];\n // AuthConnection\n authTokens: Record<string, unknown>;\n authCalls: AuthConnectionCall[];\n // IDP\n idpResolver: IdpResolver;\n idpResultQueue: unknown[];\n idpCalls: IdpCall[];\n // File\n fileResolver: FileResolver;\n fileResultQueue: unknown[];\n fileCalls: FileCall[];\n // Iconv\n iconvResolver: IconvResolver | null;\n iconvCalls: IconvCall[];\n}\n\n// ---------------------------------------------------------------------------\n// State management (shared via globalThis for environment/test interop)\n// ---------------------------------------------------------------------------\n\nexport const STATE_KEY = \"__tailorMockState\";\n\n// Sentinel set by the tailor-runtime environment in injectMocks() and cleared\n// in cleanupMocks(). Distinct from STATE_KEY, which is created lazily by\n// getState() whenever a mock helper runs (even from a non-tailor-runtime\n// project that happens to import the mocks). Use this flag to detect whether\n// the environment itself is active.\nexport const RUNTIME_FLAG_KEY = \"__tailorRuntimeActive\";\n\nfunction getState(): MockState {\n const g = globalThis as Record<string, unknown>;\n if (!g[STATE_KEY]) {\n g[STATE_KEY] = createDefaultState();\n }\n return g[STATE_KEY] as MockState;\n}\n\nfunction createDefaultState(): MockState {\n return {\n queryResolver: () => [],\n queryResultQueue: [],\n executedQueries: [],\n createdClients: [],\n jobHandler: () => null,\n jobResultQueue: [],\n triggeredJobs: [],\n triggerHandler: \"mock-execution-id\",\n waitHandler: null,\n resolveHandler: null,\n workflowCalls: [],\n secretStore: {},\n secretCalls: [],\n authTokens: {},\n authCalls: [],\n idpResolver: () => null,\n idpResultQueue: [],\n idpCalls: [],\n fileResolver: () => null,\n fileResultQueue: [],\n fileCalls: [],\n iconvResolver: null,\n iconvCalls: [],\n };\n}\n\n// ---------------------------------------------------------------------------\n// TailorDB Mock\n// ---------------------------------------------------------------------------\n\n/**\n * Mock control object for TailorDB operations.\n *\n * Automatically injected into `globalThis.tailordb` by the tailor-runtime environment.\n * Use this object to configure query responses and assert on executed queries.\n * @example\n * ```typescript\n * import { tailordbMock } from \"@tailor-platform/sdk/vitest\";\n *\n * beforeEach(() => tailordbMock.reset());\n *\n * test(\"content-based\", () => {\n * tailordbMock.setQueryResolver((query) => {\n * if (query.includes(\"SELECT\")) return [{ id: \"1\" }];\n * return [];\n * });\n * });\n *\n * test(\"order-based\", () => {\n * tailordbMock.enqueueResults(\n * [], // BEGIN (empty result)\n * [{ age: 30 }], // SELECT (one row)\n * [], // COMMIT (empty result)\n * );\n * });\n * ```\n */\nexport const tailordbMock = {\n /**\n * Set a fallback query resolver. Called when the result queue is empty.\n * @param resolver - Function that returns rows for a given query and params\n */\n setQueryResolver(resolver: QueryResolver): void {\n getState().queryResolver = resolver;\n },\n\n /**\n * Enqueue rows for the next `queryObject` call. Arguments are the row objects returned\n * by that single query. Call with no arguments for an empty result. Consumed in FIFO\n * order; when the queue is exhausted, subsequent calls fall back to `setQueryResolver`\n * (default: empty rows). Use `enqueueResults` to stage rows for multiple queries in one\n * call.\n * @param rows - Row objects to return from the next `queryObject` call\n */\n enqueueResult(...rows: unknown[]): void {\n getState().queryResultQueue.push(rows);\n },\n\n /**\n * Enqueue rows for multiple subsequent `queryObject` calls. Each argument is a rows\n * array for one query, consumed in FIFO order.\n * @param rowsList - Rows arrays, one per upcoming query\n */\n enqueueResults(...rowsList: unknown[][]): void {\n getState().queryResultQueue.push(...rowsList);\n },\n\n /**\n * All queries executed via `queryObject`, in order.\n * @returns Executed queries array\n */\n get executedQueries(): ExecutedQuery[] {\n return getState().executedQueries;\n },\n\n /**\n * All TailorDB clients created, with their namespace and end state.\n * @returns Created clients array\n */\n get createdClients(): CreatedClient[] {\n return getState().createdClients;\n },\n\n /** Reset all TailorDB mock state. Call in `beforeEach`. */\n reset(): void {\n const state = getState();\n state.queryResolver = () => [];\n state.queryResultQueue.length = 0;\n state.executedQueries.length = 0;\n state.createdClients.length = 0;\n },\n};\n\n// ---------------------------------------------------------------------------\n// Workflow Mock\n// ---------------------------------------------------------------------------\n\n/**\n * Mock control object for workflow operations.\n *\n * Automatically injected into `globalThis.tailor.workflow` by the tailor-runtime environment.\n * @example\n * ```typescript\n * import { workflowMock } from \"@tailor-platform/sdk/vitest\";\n *\n * beforeEach(() => workflowMock.reset());\n *\n * test(\"job handler\", () => {\n * workflowMock.setJobHandler((jobName, args) => {\n * if (jobName === \"validate\") return { valid: true };\n * return null;\n * });\n * });\n *\n * test(\"wait point\", () => {\n * workflowMock.setWaitHandler(() => ({ approved: true }));\n * // …\n * expect(workflowMock.waitCalls).toEqual([{ key: \"approval\", payload: undefined }]);\n * });\n *\n * test(\"resolve point\", () => {\n * workflowMock.setResolveHandler((_executionId, _key, callback) =>\n * callback({ approved: true }),\n * );\n * // …\n * expect(workflowMock.resolveCalls).toEqual([\n * { executionId: \"mock-execution-id\", key: \"approval\" },\n * ]);\n * });\n * ```\n */\nexport const workflowMock = {\n /**\n * Set a fallback job handler. Called when the result queue is empty.\n * @param handler - Function that returns a result for a given job name and args\n */\n setJobHandler(handler: JobHandler): void {\n getState().jobHandler = handler;\n },\n\n /**\n * Enqueue a single result for the next `triggerJobFunction` call. Consumed in FIFO\n * order; when the queue is exhausted, subsequent calls fall back to `setJobHandler`\n * (default: null). Use `enqueueResults` to stage multiple results in one call.\n * @param result - Result to return from the next `triggerJobFunction` call\n */\n enqueueResult(result: unknown): void {\n getState().jobResultQueue.push(result);\n },\n\n /**\n * Enqueue results for multiple subsequent `triggerJobFunction` calls.\n * @param results - Results to enqueue, one per upcoming call\n */\n enqueueResults(...results: unknown[]): void {\n const queue = getState().jobResultQueue;\n for (const result of results) {\n queue.push(result);\n }\n },\n\n /**\n * All jobs triggered via `triggerJobFunction`, in order.\n * @returns Triggered jobs array\n */\n get triggeredJobs(): TriggeredJob[] {\n return getState().triggeredJobs;\n },\n\n /**\n * Configure what `tailor.workflow.triggerWorkflow` returns. Pass a string to return\n * the same execution ID for every call, or a function `(name, args, options) => string`\n * to compute one per call. Default: `\"mock-execution-id\"`.\n * @param handler - Static execution ID or a function that returns one\n */\n setTriggerHandler(handler: string | TriggerHandlerFn): void {\n getState().triggerHandler = handler;\n },\n\n /**\n * Configure what `tailor.workflow.wait` returns. Pass a function `(key, payload) => unknown`\n * to compute one per call, or any other value to return it for every call. Default: `null`.\n * @param handler - Static value or a function that returns one\n */\n setWaitHandler: ((handler: unknown) => {\n getState().waitHandler = handler;\n }) as SetWaitHandler,\n\n /**\n * Configure how `tailor.workflow.resolve` runs the user-supplied callback. The handler\n * receives `(executionId, key, callback)` — invoke `callback(payload)` to drive\n * resolve→wait wiring in tests. Default: callback is not invoked (records the call only).\n * @param handler - Function invoked per `resolve` call\n */\n setResolveHandler(handler: ResolveHandler): void {\n getState().resolveHandler = handler;\n },\n\n /**\n * Calls to triggerWorkflow, wait, resolve (not triggerJobFunction — use triggeredJobs).\n * @returns Workflow calls array\n */\n get calls(): WorkflowCall[] {\n return getState().workflowCalls;\n },\n\n /**\n * `tailor.workflow.wait` calls reshaped as `{ key, payload }` for assertions.\n * @returns Wait call records\n */\n get waitCalls(): { key: string; payload: unknown }[] {\n return getState()\n .workflowCalls.filter((c) => c.method === \"wait\")\n .map((c) => ({ key: c.args[0] as string, payload: c.args[1] }));\n },\n\n /**\n * `tailor.workflow.resolve` calls reshaped as `{ executionId, key }` for assertions.\n * @returns Resolve call records\n */\n get resolveCalls(): { executionId: string; key: string }[] {\n return getState()\n .workflowCalls.filter((c) => c.method === \"resolve\")\n .map((c) => ({ executionId: c.args[0] as string, key: c.args[1] as string }));\n },\n\n /** Reset all workflow mock state. Call in `beforeEach`. */\n reset(): void {\n const state = getState();\n state.jobHandler = () => null;\n state.jobResultQueue.length = 0;\n state.triggeredJobs.length = 0;\n state.triggerHandler = \"mock-execution-id\";\n state.waitHandler = null;\n state.resolveHandler = null;\n state.workflowCalls.length = 0;\n },\n};\n\n// ---------------------------------------------------------------------------\n// SecretManager Mock\n// ---------------------------------------------------------------------------\n\n/** Mock control for `tailor.secretmanager` — secret store and call recording. */\nexport const secretmanagerMock = {\n setSecrets(secrets: Record<string, Record<string, string>>): void {\n getState().secretStore = secrets;\n },\n\n get calls(): SecretCall[] {\n return getState().secretCalls;\n },\n\n reset(): void {\n const state = getState();\n state.secretStore = {};\n state.secretCalls.length = 0;\n },\n};\n\n// ---------------------------------------------------------------------------\n// AuthConnection Mock\n// ---------------------------------------------------------------------------\n\n/** Mock control for `tailor.authconnection` — token store and call recording. */\nexport const authconnectionMock = {\n setTokens(tokens: Record<string, unknown>): void {\n getState().authTokens = tokens;\n },\n\n get calls(): AuthConnectionCall[] {\n return getState().authCalls;\n },\n\n reset(): void {\n const state = getState();\n state.authTokens = {};\n state.authCalls.length = 0;\n },\n};\n\n// ---------------------------------------------------------------------------\n// IDP Mock\n// ---------------------------------------------------------------------------\n\n/** Mock control for `tailor.idp` — IDP client responses and call recording. */\nexport const idpMock = {\n setResolver(resolver: IdpResolver): void {\n getState().idpResolver = resolver;\n },\n\n /**\n * Enqueue a single result for the next IDP call. Consumed in FIFO order; falls back\n * to `setResolver` when exhausted. Use `enqueueResults` to stage multiple in one call.\n * @param result - Result to return from the next IDP call\n */\n enqueueResult(result: unknown): void {\n getState().idpResultQueue.push(result);\n },\n\n /**\n * Enqueue results for multiple subsequent IDP calls.\n * @param results - Results to enqueue, one per upcoming call\n */\n enqueueResults(...results: unknown[]): void {\n const queue = getState().idpResultQueue;\n for (const result of results) {\n queue.push(result);\n }\n },\n\n get calls(): IdpCall[] {\n return getState().idpCalls;\n },\n\n reset(): void {\n const state = getState();\n state.idpResolver = () => null;\n state.idpResultQueue.length = 0;\n state.idpCalls.length = 0;\n },\n};\n\n// ---------------------------------------------------------------------------\n// File Mock\n// ---------------------------------------------------------------------------\n\n/** Mock control for `tailordb.file` — file operation responses and call recording. */\nexport const fileMock = {\n setResolver(resolver: FileResolver): void {\n getState().fileResolver = resolver;\n },\n\n /**\n * Enqueue a single result for the next `tailordb.file` call. Consumed in FIFO order;\n * falls back to `setResolver` when exhausted. Use `enqueueResults` to stage multiple\n * in one call.\n * @param result - Result to return from the next file call\n */\n enqueueResult(result: unknown): void {\n getState().fileResultQueue.push(result);\n },\n\n /**\n * Enqueue results for multiple subsequent `tailordb.file` calls.\n * @param results - Results to enqueue, one per upcoming call\n */\n enqueueResults(...results: unknown[]): void {\n const queue = getState().fileResultQueue;\n for (const result of results) {\n queue.push(result);\n }\n },\n\n get calls(): FileCall[] {\n return getState().fileCalls;\n },\n\n reset(): void {\n const state = getState();\n state.fileResolver = () => null;\n state.fileResultQueue.length = 0;\n state.fileCalls.length = 0;\n },\n};\n\n// ---------------------------------------------------------------------------\n// Iconv Mock\n// ---------------------------------------------------------------------------\n\n/** Mock control for `tailor.iconv` — encoding call recording. */\nexport const iconvMock = {\n setResolver(resolver: IconvResolver): void {\n getState().iconvResolver = resolver;\n },\n\n get calls(): IconvCall[] {\n return getState().iconvCalls;\n },\n\n reset(): void {\n const state = getState();\n state.iconvResolver = null;\n state.iconvCalls.length = 0;\n },\n};\n\n// ---------------------------------------------------------------------------\n// Mock Client implementation (injected as globalThis.tailordb.Client)\n// ---------------------------------------------------------------------------\n\nclass MockQueryResult {\n command: string;\n rowCount: number;\n rows: unknown[];\n\n constructor(rows: unknown[]) {\n this.command = \"\";\n this.rowCount = rows.length;\n this.rows = rows;\n }\n}\n\nclass MockTransaction {\n async begin(): Promise<void> {\n /* noop */\n }\n async commit(): Promise<void> {\n /* noop */\n }\n async rollback(): Promise<void> {\n /* noop */\n }\n\n async queryObject(query: string, params: unknown[] = []): Promise<MockQueryResult> {\n return resolveQuery(query, params);\n }\n}\n\nclass MockTailordbClient {\n #record: CreatedClient;\n\n constructor(config?: { namespace?: string }) {\n this.#record = { namespace: config?.namespace, ended: false };\n getState().createdClients.push(this.#record);\n }\n\n async connect(): Promise<void> {\n /* noop */\n }\n\n async end(): Promise<void> {\n this.#record.ended = true;\n }\n\n async queryObject(query: string, params: unknown[] = []): Promise<MockQueryResult> {\n return resolveQuery(query, params);\n }\n\n createTransaction(name: string): MockTransaction {\n if (!name) {\n throw new Error(\"Transaction name must be a non-empty string\");\n }\n return new MockTransaction();\n }\n}\n\nfunction resolveQuery(query: string, params: unknown[]): MockQueryResult {\n const state = getState();\n state.executedQueries.push({ query, params });\n\n // 1. Queue takes priority (order-based)\n if (state.queryResultQueue.length > 0) {\n return new MockQueryResult(state.queryResultQueue.shift()!);\n }\n\n // 2. Fallback to query resolver (content-based)\n const rows = state.queryResolver(query, params) ?? [];\n return new MockQueryResult(rows);\n}\n\n// ---------------------------------------------------------------------------\n// Mock: tailor.workflow\n// ---------------------------------------------------------------------------\n\nfunction mockTriggerJobFunction(jobName: string, args?: unknown): unknown {\n const state = getState();\n state.triggeredJobs.push({ jobName, args });\n if (state.jobResultQueue.length > 0) return state.jobResultQueue.shift();\n return state.jobHandler(jobName, args);\n}\n\nasync function mockTriggerWorkflow(\n workflowName: string,\n args?: unknown,\n options?: TriggerWorkflowOptions,\n): Promise<string> {\n const state = getState();\n state.workflowCalls.push({ method: \"triggerWorkflow\", args: [workflowName, args, options] });\n const handler = state.triggerHandler;\n return typeof handler === \"function\" ? handler(workflowName, args, options) : handler;\n}\n\nfunction mockWait(key: string, payload?: unknown): unknown {\n const state = getState();\n state.workflowCalls.push({ method: \"wait\", args: [key, payload] });\n const handler = state.waitHandler;\n return typeof handler === \"function\" ? (handler as WaitHandlerFn)(key, payload) : handler;\n}\n\n// Records the resolve call. By default the callback is not invoked, mirroring\n// platform semantics where tailor.workflow.resolve enqueues the callback\n// against the wait point and returns immediately. Tests that need\n// resolve→wait wiring can register a handler via workflowMock.setResolveHandler\n// — the handler receives `(executionId, key, callback)` and decides whether to\n// invoke the callback (typically with a synthesized payload).\nasync function mockResolve(\n executionId: string,\n key: string,\n callback: (payload: unknown) => unknown | Promise<unknown>,\n): Promise<void> {\n const state = getState();\n state.workflowCalls.push({ method: \"resolve\", args: [executionId, key, callback] });\n if (state.resolveHandler) {\n await state.resolveHandler(executionId, key, callback);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Mock: tailor.context\n// ---------------------------------------------------------------------------\n\nfunction mockGetInvoker(): tailor.context.Invoker | null {\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Mock: tailor.secretmanager\n// ---------------------------------------------------------------------------\n\nasync function mockGetSecrets<const T extends readonly string[]>(\n vault: string,\n names: T,\n): Promise<Partial<Record<T[number], string>>> {\n const state = getState();\n state.secretCalls.push({ method: \"getSecrets\", vault, names });\n const vaultData = state.secretStore[vault] ?? {};\n const result: Record<string, string> = {};\n for (const name of names) {\n if (name in vaultData) {\n result[name] = vaultData[name];\n }\n }\n return result as Partial<Record<T[number], string>>;\n}\n\nasync function mockGetSecret(vault: string, name: string): Promise<string | undefined> {\n const state = getState();\n state.secretCalls.push({ method: \"getSecret\", vault, name });\n return state.secretStore[vault]?.[name];\n}\n\n// ---------------------------------------------------------------------------\n// Mock: tailor.authconnection\n// ---------------------------------------------------------------------------\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nasync function mockGetConnectionToken(connectionName: string): Promise<any> {\n const state = getState();\n state.authCalls.push({ connectionName });\n return state.authTokens[connectionName] ?? { access_token: \"mock-token\" };\n}\n\n// ---------------------------------------------------------------------------\n// Mock: tailor.idp\n// ---------------------------------------------------------------------------\n\nconst IDP_DEFAULTS: Record<string, unknown> = {\n users: { users: [], nextPageToken: null, totalCount: 0 },\n user: { id: \"mock-id\", name: \"mock-user\", disabled: false },\n userByName: { id: \"mock-id\", name: \"mock-user\", disabled: false },\n createUser: { id: \"mock-id\", name: \"mock-user\", disabled: false },\n updateUser: { id: \"mock-id\", name: \"mock-user\", disabled: false },\n deleteUser: true,\n sendPasswordResetEmail: true,\n};\n\nfunction resolveIdpCall(method: string, args: unknown[], namespace: string): unknown {\n const state = getState();\n state.idpCalls.push({ method, args, namespace });\n if (state.idpResultQueue.length > 0) return state.idpResultQueue.shift();\n const resolved = state.idpResolver(method, args, namespace);\n // Treat null and undefined alike as \"no override\" — resolvers commonly\n // `return null` for unmatched methods.\n if (resolved != null) return resolved;\n // Clone the default so a test mutating the returned value (e.g.\n // `result.users.push(x)`) cannot corrupt the shared module-level object\n // for subsequent tests in the same worker.\n const fallback = IDP_DEFAULTS[method];\n return fallback === undefined ? undefined : structuredClone(fallback);\n}\n\nclass MockIdpClient {\n #namespace: string;\n constructor(config: { namespace: string }) {\n this.#namespace = config.namespace;\n }\n async users(options?: {\n first?: number;\n after?: string;\n query?: { ids?: string[]; names?: string[] };\n }): Promise<{ users: tailor.idp.User[]; nextPageToken: string | null; totalCount: number }> {\n return resolveIdpCall(\"users\", [options], this.#namespace) as Awaited<\n ReturnType<typeof this.users>\n >;\n }\n async user(userId: string): Promise<tailor.idp.User> {\n return resolveIdpCall(\"user\", [userId], this.#namespace) as tailor.idp.User;\n }\n async userByName(name: string): Promise<tailor.idp.User> {\n return resolveIdpCall(\"userByName\", [name], this.#namespace) as tailor.idp.User;\n }\n async createUser(input: {\n name: string;\n password?: string;\n disabled?: boolean;\n }): Promise<tailor.idp.User> {\n return resolveIdpCall(\"createUser\", [input], this.#namespace) as tailor.idp.User;\n }\n async updateUser(input: {\n id: string;\n name?: string;\n password?: string;\n clearPassword?: boolean;\n disabled?: boolean;\n }): Promise<tailor.idp.User> {\n return resolveIdpCall(\"updateUser\", [input], this.#namespace) as tailor.idp.User;\n }\n async deleteUser(userId: string): Promise<boolean> {\n return resolveIdpCall(\"deleteUser\", [userId], this.#namespace) as boolean;\n }\n async sendPasswordResetEmail(input: { userId: string; redirectUri: string }): Promise<boolean> {\n return resolveIdpCall(\"sendPasswordResetEmail\", [input], this.#namespace) as boolean;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Mock: tailor.iconv\n// ---------------------------------------------------------------------------\n\n// Iconv methods return `string` for UTF-8 target encodings and `Uint8Array`\n// for any other byte-producing encoding (the platform API mirrors this).\n// Default returns must respect that contract so tests that don't configure a\n// resolver still get type-consistent values.\nfunction isUtf8(encoding: unknown): boolean {\n return encoding === \"UTF8\" || encoding === \"UTF-8\";\n}\n\nfunction defaultIconvResult(method: string, args: unknown[]): unknown {\n switch (method) {\n case \"convert\":\n case \"convertBuffer\":\n return isUtf8(args[2]) ? \"\" : new Uint8Array();\n case \"decode\":\n return \"\";\n case \"encode\":\n return isUtf8(args[1]) ? \"\" : new Uint8Array();\n case \"encodings\":\n return [];\n default:\n return undefined;\n }\n}\n\nfunction resolveIconvCall(method: string, args: unknown[]): unknown {\n const state = getState();\n state.iconvCalls.push({ method, args: [...args] });\n if (state.iconvResolver) {\n const result = state.iconvResolver(method, args);\n // Treat both null and undefined as \"no override\" so resolvers using\n // implicit returns (e.g. early `return;` for unhandled methods) still\n // fall through to the type-consistent default.\n if (result != null) return result;\n }\n return defaultIconvResult(method, args);\n}\n\nfunction mockConvert<T extends string>(\n str: string | Uint8Array | ArrayBuffer,\n fromEncoding: string,\n toEncoding: T,\n): T extends \"UTF8\" | \"UTF-8\" ? string : Uint8Array {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return resolveIconvCall(\"convert\", [str, fromEncoding, toEncoding]) as any;\n}\n\nfunction mockConvertBuffer<T extends string>(\n buffer: Uint8Array | ArrayBuffer,\n fromEncoding: string,\n toEncoding: T,\n): T extends \"UTF8\" | \"UTF-8\" ? string : Uint8Array {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return resolveIconvCall(\"convertBuffer\", [buffer, fromEncoding, toEncoding]) as any;\n}\n\nfunction mockDecode(buffer: Uint8Array | ArrayBuffer, encoding: string): string {\n return resolveIconvCall(\"decode\", [buffer, encoding]) as string;\n}\n\nfunction mockEncode<T extends string>(\n str: string,\n encoding: T,\n): T extends \"UTF8\" | \"UTF-8\" ? string : Uint8Array {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return resolveIconvCall(\"encode\", [str, encoding]) as any;\n}\n\nfunction mockEncodings(): string[] {\n return resolveIconvCall(\"encodings\", []) as string[];\n}\n\nclass MockIconv {\n #fromEncoding: string;\n #toEncoding: string;\n\n constructor(fromEncoding: string, toEncoding: string) {\n this.#fromEncoding = fromEncoding;\n this.#toEncoding = toEncoding;\n }\n\n convert(input: string | Uint8Array | ArrayBuffer): string | Uint8Array {\n return resolveIconvCall(\"convert\", [input, this.#fromEncoding, this.#toEncoding]) as\n | string\n | Uint8Array;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Mock: tailordb.file\n// ---------------------------------------------------------------------------\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst FILE_DEFAULTS: Record<string, any> = {\n upload: { metadata: { fileSize: 0, sha256sum: \"\" } },\n download: {\n data: new Uint8Array(),\n metadata: { contentType: \"\", fileSize: 0, sha256sum: \"\", lastUploadedAt: \"\" },\n },\n downloadAsBase64: {\n data: \"\",\n metadata: { contentType: \"\", fileSize: 0, sha256sum: \"\", lastUploadedAt: \"\" },\n },\n delete: undefined,\n getMetadata: { contentType: \"\", fileSize: 0, sha256sum: \"\", urlPath: \"\" },\n};\n\nfunction resolveFileCall(\n method: string,\n namespace: string,\n typeName: string,\n fieldName: string,\n recordId: string,\n): unknown {\n const state = getState();\n const call: FileCall = { method, namespace, typeName, fieldName, recordId };\n state.fileCalls.push(call);\n if (state.fileResultQueue.length > 0) return state.fileResultQueue.shift();\n const resolved = state.fileResolver(method, call);\n // Treat null and undefined alike as \"no override\" — resolvers commonly\n // `return null` for unmatched methods.\n if (resolved != null) return resolved;\n // Clone the default so a test mutating the returned value (e.g. the\n // `data: Uint8Array` payload from `download`) cannot corrupt the shared\n // module-level object for subsequent tests in the same worker.\n const fallback = FILE_DEFAULTS[method];\n return fallback === undefined ? undefined : structuredClone(fallback);\n}\n\nconst mockTailordbFile = {\n async upload(\n namespace: string,\n typeName: string,\n fieldName: string,\n recordId: string,\n _data: string | ArrayBuffer | Uint8Array | number[],\n _options?: { contentType?: string },\n ): Promise<{ metadata: { fileSize: number; sha256sum: string } }> {\n return resolveFileCall(\"upload\", namespace, typeName, fieldName, recordId) as Awaited<\n ReturnType<typeof this.upload>\n >;\n },\n async download(\n namespace: string,\n typeName: string,\n fieldName: string,\n recordId: string,\n ): Promise<{\n data: Uint8Array;\n metadata: { contentType: string; fileSize: number; sha256sum: string; lastUploadedAt: string };\n }> {\n return resolveFileCall(\"download\", namespace, typeName, fieldName, recordId) as Awaited<\n ReturnType<typeof this.download>\n >;\n },\n async downloadAsBase64(\n namespace: string,\n typeName: string,\n fieldName: string,\n recordId: string,\n ): Promise<{\n data: string;\n metadata: { contentType: string; fileSize: number; sha256sum: string; lastUploadedAt: string };\n }> {\n return resolveFileCall(\"downloadAsBase64\", namespace, typeName, fieldName, recordId) as Awaited<\n ReturnType<typeof this.downloadAsBase64>\n >;\n },\n async delete(\n namespace: string,\n typeName: string,\n fieldName: string,\n recordId: string,\n ): Promise<void> {\n resolveFileCall(\"delete\", namespace, typeName, fieldName, recordId);\n },\n async getMetadata(\n namespace: string,\n typeName: string,\n fieldName: string,\n recordId: string,\n ): Promise<{\n contentType: string;\n fileSize: number;\n sha256sum: string;\n urlPath: string;\n lastUploadedAt?: string;\n }> {\n return resolveFileCall(\"getMetadata\", namespace, typeName, fieldName, recordId) as Awaited<\n ReturnType<typeof this.getMetadata>\n >;\n },\n openDownloadStream(\n namespace: string,\n typeName: string,\n fieldName: string,\n recordId: string,\n ): Promise<AsyncIterableIterator<unknown> & { close(): Promise<void> }> {\n const resolved = resolveFileCall(\n \"openDownloadStream\",\n namespace,\n typeName,\n fieldName,\n recordId,\n );\n return Promise.resolve(toFileStream(resolved));\n },\n};\n\ntype FileStream = AsyncIterableIterator<unknown> & { close(): Promise<void> };\n\nfunction toFileStream(value: unknown): FileStream {\n // Already a complete stream-like object: pass through.\n if (\n value !== null &&\n typeof value === \"object\" &&\n Symbol.asyncIterator in value &&\n typeof (value as { close?: unknown }).close === \"function\"\n ) {\n return value as FileStream;\n }\n // Binary chunk shorthand: a single ArrayBuffer / TypedArray (e.g. Uint8Array)\n // should be delivered as one chunk, not iterated as a sequence of numbers.\n // Tests passing `[chunk1, chunk2]` continue to work via the iterable branch\n // below.\n if (value instanceof ArrayBuffer || ArrayBuffer.isView(value)) {\n return toFileStream([value]);\n }\n // Iterable (array, sync iterator, etc.): wrap as a chunked async iterator\n // so `fileMock.enqueueResult([chunk1, chunk2])` controls stream contents.\n if (\n value !== null &&\n typeof value === \"object\" &&\n (Symbol.iterator in value || Symbol.asyncIterator in value)\n ) {\n const source = value as Iterable<unknown> | AsyncIterable<unknown>;\n const inner =\n Symbol.asyncIterator in source\n ? (source as AsyncIterable<unknown>)[Symbol.asyncIterator]()\n : (source as Iterable<unknown>)[Symbol.iterator]();\n const stream: FileStream = {\n async next() {\n const r = await inner.next();\n return r.done ? { done: true as const, value: undefined } : r;\n },\n async close() {},\n [Symbol.asyncIterator]() {\n return stream;\n },\n };\n return stream;\n }\n const empty: FileStream = {\n async next() {\n return { done: true as const, value: undefined };\n },\n async close() {},\n [Symbol.asyncIterator]() {\n return empty;\n },\n };\n return empty;\n}\n\n// ---------------------------------------------------------------------------\n// Error class mocks\n// ---------------------------------------------------------------------------\n\ninterface TailorErrorItem {\n message: string;\n path: (string | number)[];\n}\n\nclass TailorErrorsMock extends Error {\n errors: TailorErrorItem[];\n\n constructor(errors: TailorErrorItem[]) {\n if (!Array.isArray(errors)) {\n throw new TypeError(\"TailorErrors: errors must be an array\");\n }\n const validated = errors.map((e, i) => {\n if (typeof e.message !== \"string\") {\n throw new TypeError(`TailorErrors: errors[${i}].message must be a string`);\n }\n if (!Array.isArray(e.path)) {\n throw new TypeError(`TailorErrors: errors[${i}].path must be an array`);\n }\n return { message: e.message, path: e.path };\n });\n // Match the PF runtime's TailorErrors serialization, which prefixes the\n // JSON payload with \"TailorErrors: \". Other SDK code (e.g. apply\n // integration fixtures) strips this prefix before JSON.parse.\n super(`TailorErrors: ${JSON.stringify({ errors: validated })}`);\n this.name = \"TailorErrors\";\n this.errors = validated;\n }\n}\n\nclass TailorErrorMessageMock extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"TailorErrorMessage\";\n }\n}\n\nclass TailorDBFileErrorMock extends Error {\n code?: string;\n override cause: unknown;\n\n constructor(message: string, code?: string, cause?: unknown) {\n super(message);\n this.name = \"TailorDBFileError\";\n this.code = code;\n this.cause = cause;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Injection / Cleanup (called by environment.ts)\n// ---------------------------------------------------------------------------\n\n/**\n * Inject all platform API mocks into globalThis.\n * Called by the tailor-runtime Vitest environment during setup.\n * @param global - The global object to inject mocks into\n */\nexport function injectMocks(global: typeof globalThis): void {\n const g = global as Record<string, unknown>;\n\n // Ensure fresh state and mark the environment as active so setup.ts can\n // distinguish \"tailor-runtime is selected\" from \"some test code happened\n // to read a mock helper and lazily created STATE_KEY\".\n g[STATE_KEY] = createDefaultState();\n g[RUNTIME_FLAG_KEY] = true;\n\n g.tailordb = {\n Client: MockTailordbClient,\n file: mockTailordbFile,\n };\n\n g.tailor = {\n secretmanager: {\n getSecrets: mockGetSecrets,\n getSecret: mockGetSecret,\n },\n authconnection: {\n getConnectionToken: mockGetConnectionToken,\n },\n workflow: {\n triggerJobFunction: mockTriggerJobFunction,\n triggerWorkflow: mockTriggerWorkflow,\n wait: mockWait,\n resolve: mockResolve,\n },\n context: {\n getInvoker: mockGetInvoker,\n },\n idp: { Client: MockIdpClient },\n iconv: {\n convert: mockConvert,\n convertBuffer: mockConvertBuffer,\n decode: mockDecode,\n encode: mockEncode,\n encodings: mockEncodings,\n Iconv: MockIconv,\n },\n };\n\n g.TailorErrors = TailorErrorsMock;\n g.TailorErrorMessage = TailorErrorMessageMock;\n g.TailorDBFileError = TailorDBFileErrorMock;\n}\n\n/**\n * Remove all injected mocks from globalThis.\n * Called by the tailor-runtime Vitest environment during teardown.\n * @param global - The global object to clean up mocks from\n */\nexport function cleanupMocks(global: typeof globalThis): void {\n const g = global as Record<string, unknown>;\n delete g.tailordb;\n delete g.tailor;\n delete g.TailorErrors;\n delete g.TailorErrorMessage;\n delete g.TailorDBFileError;\n delete g[STATE_KEY];\n delete g[RUNTIME_FLAG_KEY];\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"multiline-e3IpANmS.mjs","names":[],"sources":["../src/utils/multiline.ts"],"sourcesContent":["/**\n * Tag function which strips the common leading indent from a multi-line\n * template literal and trims surrounding blank lines, while indenting each\n * line of interpolated values to match the placeholder's indent.\n *\n * Mirrors the behaviour of the `multiline-ts` package, which we used to\n * depend on. We replaced it with this in-tree implementation because the\n * upstream package ships a `preinstall: npx only-allow pnpm` hook that\n * makes `npx create-tailor-sdk@latest` (and any other npm-based install\n * path that resolves a fresh copy) abort with `ECOMPROMISED`.\n * @param value - Template strings array, or a plain string for non-tagged usage\n * @param inputs - Interpolated values\n * @returns The dedented and trimmed string\n */\nexport default function multiline(\n value: TemplateStringsArray | string,\n ...inputs: string[]\n): string {\n const strings = typeof value === \"string\" ? value.split(/(?=\\r\\n|\\r|\\n)/) : Array.from(value);\n\n let currentIndent = \"\";\n const joined = strings\n .map((segment, i) => {\n if (/\\r\\n|\\r|\\n/.test(segment)) {\n currentIndent = getFinalIndent(segment) || currentIndent;\n }\n const input = inputs[i] ?? \"\";\n return segment + input.replace(/\\r\\n|\\r|\\n/g, `\\n${currentIndent}`);\n })\n .join(\"\");\n\n const lines = joined.split(/\\r\\n|\\r|\\n/);\n const indents = lines.filter((line) => /[^ \\t]/.test(line)).map((line) => getIndent(line).length);\n const minIndent = indents.length === 0 ? 0 : Math.min(...indents);\n return lines\n .map((line) => line.slice(minIndent))\n .join(\"\\n\")\n .replace(/^\\n|\\n[ \\t]*$/g, \"\");\n}\n\nfunction getIndent(line: string): string {\n const match = line.match(/^[ \\t]+/);\n return match ? match[0] : \"\";\n}\n\nfunction getFinalIndent(value: string): string {\n const match = value.match(/(?<=(\\r\\n|\\r|\\n))[ \\t]+$/);\n return match ? match[0] : \"\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAcA,SAAwB,UACtB,OACA,GAAG,QACK;CACR,MAAM,UAAU,OAAO,UAAU,WAAW,MAAM,MAAM,iBAAiB,GAAG,MAAM,KAAK,MAAM;CAE7F,IAAI,gBAAgB;CAWpB,MAAM,QAVS,QACZ,KAAK,SAAS,MAAM;
|
|
1
|
+
{"version":3,"file":"multiline-e3IpANmS.mjs","names":[],"sources":["../src/utils/multiline.ts"],"sourcesContent":["/**\n * Tag function which strips the common leading indent from a multi-line\n * template literal and trims surrounding blank lines, while indenting each\n * line of interpolated values to match the placeholder's indent.\n *\n * Mirrors the behaviour of the `multiline-ts` package, which we used to\n * depend on. We replaced it with this in-tree implementation because the\n * upstream package ships a `preinstall: npx only-allow pnpm` hook that\n * makes `npx create-tailor-sdk@latest` (and any other npm-based install\n * path that resolves a fresh copy) abort with `ECOMPROMISED`.\n * @param value - Template strings array, or a plain string for non-tagged usage\n * @param inputs - Interpolated values\n * @returns The dedented and trimmed string\n */\nexport default function multiline(\n value: TemplateStringsArray | string,\n ...inputs: string[]\n): string {\n const strings = typeof value === \"string\" ? value.split(/(?=\\r\\n|\\r|\\n)/) : Array.from(value);\n\n let currentIndent = \"\";\n const joined = strings\n .map((segment, i) => {\n if (/\\r\\n|\\r|\\n/.test(segment)) {\n currentIndent = getFinalIndent(segment) || currentIndent;\n }\n const input = inputs[i] ?? \"\";\n return segment + input.replace(/\\r\\n|\\r|\\n/g, `\\n${currentIndent}`);\n })\n .join(\"\");\n\n const lines = joined.split(/\\r\\n|\\r|\\n/);\n const indents = lines.filter((line) => /[^ \\t]/.test(line)).map((line) => getIndent(line).length);\n const minIndent = indents.length === 0 ? 0 : Math.min(...indents);\n return lines\n .map((line) => line.slice(minIndent))\n .join(\"\\n\")\n .replace(/^\\n|\\n[ \\t]*$/g, \"\");\n}\n\nfunction getIndent(line: string): string {\n const match = line.match(/^[ \\t]+/);\n return match ? match[0] : \"\";\n}\n\nfunction getFinalIndent(value: string): string {\n const match = value.match(/(?<=(\\r\\n|\\r|\\n))[ \\t]+$/);\n return match ? match[0] : \"\";\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAcA,SAAwB,UACtB,OACA,GAAG,QACK;CACR,MAAM,UAAU,OAAO,UAAU,WAAW,MAAM,MAAM,iBAAiB,GAAG,MAAM,KAAK,MAAM;CAE7F,IAAI,gBAAgB;CAWpB,MAAM,QAVS,QACZ,KAAK,SAAS,MAAM;EACnB,IAAI,aAAa,KAAK,QAAQ,EAC5B,gBAAgB,eAAe,QAAQ,IAAI;EAG7C,OAAO,WADO,OAAO,MAAM,IACJ,QAAQ,eAAe,KAAK,gBAAgB;GACnE,CACD,KAAK,GAEY,CAAC,MAAM,aAAa;CACxC,MAAM,UAAU,MAAM,QAAQ,SAAS,SAAS,KAAK,KAAK,CAAC,CAAC,KAAK,SAAS,UAAU,KAAK,CAAC,OAAO;CACjG,MAAM,YAAY,QAAQ,WAAW,IAAI,IAAI,KAAK,IAAI,GAAG,QAAQ;CACjE,OAAO,MACJ,KAAK,SAAS,KAAK,MAAM,UAAU,CAAC,CACpC,KAAK,KAAK,CACV,QAAQ,kBAAkB,GAAG;;AAGlC,SAAS,UAAU,MAAsB;CACvC,MAAM,QAAQ,KAAK,MAAM,UAAU;CACnC,OAAO,QAAQ,MAAM,KAAK;;AAG5B,SAAS,eAAe,OAAuB;CAC7C,MAAM,QAAQ,MAAM,MAAM,2BAA2B;CACrD,OAAO,QAAQ,MAAM,KAAK"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package-json-6Px8bDpG.mjs","names":[],"sources":["../src/cli/shared/package-json.ts"],"sourcesContent":["import { readPackageJSON, type PackageJson } from \"pkg-types\";\n\nlet packageJson: PackageJson | null = null;\n\n/**\n * Read and cache the package.json of the SDK package.\n * @returns Parsed package.json contents\n */\nexport async function readPackageJson() {\n if (packageJson) {\n return packageJson;\n }\n packageJson = await readPackageJSON(import.meta.url);\n return packageJson;\n}\n"],"mappings":";;;;AAEA,IAAI,cAAkC;;;;;AAMtC,eAAsB,kBAAkB;
|
|
1
|
+
{"version":3,"file":"package-json-6Px8bDpG.mjs","names":[],"sources":["../src/cli/shared/package-json.ts"],"sourcesContent":["import { readPackageJSON, type PackageJson } from \"pkg-types\";\n\nlet packageJson: PackageJson | null = null;\n\n/**\n * Read and cache the package.json of the SDK package.\n * @returns Parsed package.json contents\n */\nexport async function readPackageJson() {\n if (packageJson) {\n return packageJson;\n }\n packageJson = await readPackageJSON(import.meta.url);\n return packageJson;\n}\n"],"mappings":";;;;AAEA,IAAI,cAAkC;;;;;AAMtC,eAAsB,kBAAkB;CACtC,IAAI,aACF,OAAO;CAET,cAAc,MAAM,gBAAgB,OAAO,KAAK,IAAI;CACpD,OAAO"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/// <reference types="@tailor-platform/function-types" />
|
|
2
|
-
import { n as enumConstantsPlugin, t as EnumConstantsGeneratorID } from "../../../index-
|
|
2
|
+
import { n as enumConstantsPlugin, t as EnumConstantsGeneratorID } from "../../../index-BbOTbZFf.mjs";
|
|
3
3
|
export { EnumConstantsGeneratorID, enumConstantsPlugin };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/// <reference types="@tailor-platform/function-types" />
|
|
2
|
-
import { n as fileUtilsPlugin, t as FileUtilsGeneratorID } from "../../../index-
|
|
2
|
+
import { n as fileUtilsPlugin, t as FileUtilsGeneratorID } from "../../../index-iy-hNfGp.mjs";
|
|
3
3
|
export { FileUtilsGeneratorID, fileUtilsPlugin };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/// <reference types="@tailor-platform/function-types" />
|
|
2
|
-
import { n as kyselyTypePlugin, t as KyselyGeneratorID } from "../../../index-
|
|
2
|
+
import { n as kyselyTypePlugin, t as KyselyGeneratorID } from "../../../index-BRvNi5q9.mjs";
|
|
3
3
|
export { KyselyGeneratorID, kyselyTypePlugin };
|
package/dist/plugin/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="@tailor-platform/function-types" />
|
|
2
|
-
import { n as TailorAnyDBType } from "../tailor-db-field-
|
|
3
|
-
import { r as TailorEnv, t as TailorActor } from "../actor-
|
|
2
|
+
import { n as TailorAnyDBType } from "../tailor-db-field-Bn8ZC5lK.mjs";
|
|
3
|
+
import { r as TailorEnv, t as TailorActor } from "../actor-jk4-f0yp.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/plugin/with-context.d.ts
|
|
6
6
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/plugin/with-context.ts","../../src/plugin/get-generated-type.ts"],"sourcesContent":["/**\n * Plugin executor context support for defining plugin executors in separate files.\n * This module provides utilities for creating type-safe plugin executors that receive\n * context (like type references and namespace) at runtime.\n */\n\nimport type { TailorActor, TailorEnv } from \"@/types/runtime\";\n\n/**\n * Plugin executor factory function type.\n * Takes context and returns an executor configuration.\n * Returns unknown since the exact return type depends on createExecutor's generic params.\n */\nexport type PluginExecutorFactory<Ctx> = (ctx: Ctx) => unknown;\n\n// ============================================================================\n// Plugin Executor Args Types\n// ============================================================================\n\n/**\n * Base args for plugin executor function operations.\n * Provides typed access to runtime context without requiring specific record types.\n */\nexport interface PluginFunctionArgs {\n /** Workspace ID where the executor runs */\n workspaceId: string;\n /** Application namespace */\n appNamespace: string;\n /** Environment variables */\n env: TailorEnv;\n /** Actor (user) who triggered the event, null for system events */\n actor: TailorActor | null;\n /** Name of the TailorDB type */\n typeName: string;\n /** TailorDB connections by namespace */\n tailordb: Record<string, unknown>;\n}\n\n/**\n * Args for plugin executors triggered on record creation.\n */\nexport interface PluginRecordCreatedArgs extends PluginFunctionArgs {\n /** The newly created record */\n newRecord: Record<string, unknown>;\n}\n\n/**\n * Args for plugin executors triggered on record update.\n */\nexport interface PluginRecordUpdatedArgs extends PluginFunctionArgs {\n /** The record after update */\n newRecord: Record<string, unknown>;\n /** The record before update */\n oldRecord: Record<string, unknown>;\n}\n\n/**\n * Args for plugin executors triggered on record deletion.\n */\nexport interface PluginRecordDeletedArgs extends PluginFunctionArgs {\n /** The deleted record */\n oldRecord: Record<string, unknown>;\n}\n\n/**\n * Database schema type for plugins.\n * Since plugins work with dynamic types, the schema uses Record types.\n */\nexport type PluginDBSchema = Record<string, Record<string, unknown>>;\n\n/**\n * Base record type for TailorDB records.\n * All records have an id field.\n */\nexport type PluginRecord = { id: string } & Record<string, unknown>;\n\n/**\n * Define a plugin executor that receives context at runtime.\n * This allows executor definitions to be in separate files while\n * still receiving dynamic values like typeName, generated types, and namespace.\n * @param factory - Function that takes context and returns executor configuration\n * @returns The same factory function (for type inference)\n * @example\n * ```typescript\n * // executors/on-create.ts\n * import { withPluginContext } from \"@tailor-platform/sdk/plugin\";\n * import { createExecutor, recordCreatedTrigger } from \"@tailor-platform/sdk\";\n * import { getDB } from \"@tailor-platform/function-kysely-tailordb\";\n *\n * interface MyContext {\n * sourceType: TailorAnyDBType;\n * historyType: TailorAnyDBType;\n * namespace: string;\n * }\n *\n * export default withPluginContext<MyContext>((ctx) =>\n * createExecutor({\n * name: `${ctx.sourceType.name.toLowerCase()}-on-create`,\n * trigger: recordCreatedTrigger({ type: ctx.sourceType }),\n * operation: {\n * kind: \"function\",\n * body: async (args) => {\n * const db = getDB(ctx.namespace);\n * await db.insertInto(ctx.historyType.name).values({\n * recordId: args.newRecord.id,\n * // ...\n * }).execute();\n * },\n * },\n * })\n * );\n * ```\n */\nexport function withPluginContext<Ctx>(\n factory: PluginExecutorFactory<Ctx>,\n): PluginExecutorFactory<Ctx> {\n return factory;\n}\n","import * as fs from \"node:fs\";\nimport { pathToFileURL } from \"node:url\";\nimport * as path from \"pathe\";\nimport type { Plugin, PluginOutput, TypePluginOutput } from \"@/types/plugin\";\nimport type { TailorAnyDBType } from \"@/types/tailordb\";\n\n// ========================================\n// Config loading and caching\n// ========================================\n\ninterface PluginEntry {\n plugin: Plugin;\n pluginConfig: unknown;\n}\n\ninterface ConfigCache {\n config: { db?: Record<string, unknown> };\n plugins: Map<string, PluginEntry>;\n configDir: string;\n}\n\n/** Cache: resolved config path -> loaded config data */\nconst configCacheMap = new Map<string, ConfigCache>();\n\n/**\n * Check if a value is a Plugin instance.\n * @param value - Value to check\n * @returns True if value has the shape of Plugin\n */\nfunction isPlugin(value: unknown): value is Plugin {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as Record<string, unknown>).id === \"string\" &&\n typeof (value as Record<string, unknown>).description === \"string\"\n );\n}\n\n/**\n * Load and cache config module from the given path.\n * Extracts plugins from all array exports using definePlugins() format.\n * Returns null if the config file does not exist (e.g., in bundled executor on platform server).\n * @param configPath - Absolute or relative path to tailor.config.ts\n * @returns Cached config data with plugins map, or null if config file is not available\n */\nasync function loadAndCacheConfig(configPath: string): Promise<ConfigCache | null> {\n const resolvedPath = path.resolve(configPath);\n\n const cached = configCacheMap.get(resolvedPath);\n if (cached) return cached;\n\n // Config file may not exist in bundled environments (e.g., platform server)\n if (!fs.existsSync(resolvedPath)) {\n return null;\n }\n\n const configModule = await import(pathToFileURL(resolvedPath).href);\n if (!configModule?.default) {\n throw new Error(`Invalid config module at \"${resolvedPath}\": default export not found`);\n }\n\n const config = configModule.default as { db?: Record<string, unknown> };\n const configDir = path.dirname(resolvedPath);\n const plugins = new Map<string, PluginEntry>();\n\n // Find plugin arrays from exports (definePlugins returns PluginConfig[])\n for (const value of Object.values(configModule)) {\n if (!Array.isArray(value)) continue;\n\n for (const item of value) {\n if (isPlugin(item)) {\n plugins.set(item.id, { plugin: item, pluginConfig: item.pluginConfig });\n }\n }\n }\n\n const result: ConfigCache = { config, plugins, configDir };\n configCacheMap.set(resolvedPath, result);\n return result;\n}\n\n// ========================================\n// Namespace resolution\n// ========================================\n\ninterface DbNamespaceConfig {\n files?: string[];\n external?: boolean;\n}\n\n/**\n * Resolve the namespace for a type-attached sourceType by checking config.db file patterns.\n * Uses ESM module cache identity: same file path yields same object references.\n * @param config - App config with db namespace definitions\n * @param config.db - DB namespace definitions\n * @param configDir - Directory containing the config file\n * @param sourceType - The TailorDB type to look up\n * @returns The namespace name\n */\nasync function resolveNamespaceForType(\n config: { db?: Record<string, unknown> },\n configDir: string,\n sourceType: TailorAnyDBType,\n): Promise<string> {\n if (!config.db) {\n throw new Error(`No db configuration found in config`);\n }\n\n for (const [namespace, nsConfig] of Object.entries(config.db)) {\n const dbConfig = nsConfig as DbNamespaceConfig;\n // Skip external namespaces (no files to resolve)\n if (dbConfig.external || !dbConfig.files) continue;\n\n for (const pattern of dbConfig.files) {\n const absolutePattern = path.resolve(configDir, pattern);\n let matchedFiles: string[];\n try {\n matchedFiles = fs.globSync(absolutePattern);\n } catch {\n continue;\n }\n\n for (const file of matchedFiles) {\n const mod = await import(pathToFileURL(file).href);\n for (const exported of Object.values(mod)) {\n if (exported === sourceType) {\n return namespace;\n }\n }\n }\n }\n }\n\n throw new Error(\n `Could not resolve namespace for type \"${sourceType.name}\". ` +\n `Ensure the type file is included in a db namespace's files pattern.`,\n );\n}\n\n/**\n * Resolve the namespace for a namespace plugin by trying each namespace.\n * Calls onNamespaceLoaded() for each and returns the first whose output contains the requested kind.\n * @param config - App config with db namespace definitions\n * @param config.db - DB namespace definitions\n * @param plugin - Plugin instance\n * @param kind - The generated type kind to look for\n * @param pluginConfig - Plugin-level configuration\n * @returns The namespace name\n */\nasync function resolveNamespaceForNamespacePlugin(\n config: { db?: Record<string, unknown> },\n plugin: Plugin,\n kind: string,\n pluginConfig: unknown,\n): Promise<{ namespace: string; output: PluginOutput }> {\n if (!config.db) {\n throw new Error(`No db configuration found in config`);\n }\n\n if (!plugin.onNamespaceLoaded) {\n throw new Error(`Plugin \"${plugin.id}\" does not have a onNamespaceLoaded() method`);\n }\n\n for (const namespace of Object.keys(config.db)) {\n const dbConfig = config.db[namespace] as DbNamespaceConfig;\n if (dbConfig.external) continue;\n\n const output = await plugin.onNamespaceLoaded({\n pluginConfig,\n namespace,\n });\n\n if (output.types?.[kind]) {\n return { namespace, output };\n }\n }\n\n throw new Error(\n `Could not resolve namespace for plugin \"${plugin.id}\" with kind \"${kind}\". ` +\n `No namespace produced a type with that kind.`,\n );\n}\n\n// ========================================\n// Process caching\n// ========================================\n\n// Cache: plugin -> cacheKey -> TypePluginOutput\nconst processCache = new WeakMap<Plugin, Map<string, TypePluginOutput>>();\n\n// Cache for namespace plugins: plugin -> cacheKey -> PluginOutput\nconst namespaceProcessCache = new WeakMap<Plugin, Map<string, PluginOutput>>();\n\n/**\n * Generate a cache key that includes pluginConfig.\n * @param baseKey - Base key for the cache\n * @param pluginConfig - Plugin configuration to include in the key\n * @returns Cache key string\n */\nfunction getCacheKey(baseKey: string, pluginConfig: unknown): string {\n if (pluginConfig === undefined) {\n return baseKey;\n }\n try {\n return `${baseKey}:${JSON.stringify(pluginConfig)}`;\n } catch {\n throw new Error(\n `pluginConfig must be JSON-serializable for caching. Received non-serializable value.`,\n );\n }\n}\n\n// ========================================\n// Main API\n// ========================================\n\n/**\n * Get a generated type from a plugin by loading the config and resolving everything automatically.\n * For type-attached plugins, calls onTypeLoaded() with the sourceType.\n * For namespace plugins, calls onNamespaceLoaded() with auto-resolved namespace.\n * Results are cached per config path, plugin, namespace, and pluginConfig to avoid redundant processing.\n * @param configPath - Path to tailor.config.ts (absolute or relative to cwd)\n * @param pluginId - The plugin's unique identifier\n * @param sourceType - The source TailorDB type (null for namespace plugins)\n * @param kind - The generated type kind (e.g., \"request\", \"step\")\n * @returns The generated TailorDB type\n */\nexport async function getGeneratedType(\n configPath: string,\n pluginId: string,\n sourceType: TailorAnyDBType | null,\n kind: string,\n): Promise<TailorAnyDBType> {\n const cache = await loadAndCacheConfig(configPath);\n\n if (!cache) {\n // Config not available (e.g., running in bundled executor on platform server).\n // Return a placeholder. The actual type is resolved at generate/apply time.\n return { name: `__placeholder_${kind}__`, fields: {} } as TailorAnyDBType;\n }\n\n const { config, configDir, plugins } = cache;\n\n const pluginEntry = plugins.get(pluginId);\n if (!pluginEntry) {\n throw new Error(\n `Plugin \"${pluginId}\" not found in config at \"${configPath}\". ` +\n `Ensure the plugin is registered via definePlugins().`,\n );\n }\n\n const { plugin, pluginConfig } = pluginEntry;\n\n if (sourceType === null) {\n return getGeneratedTypeForNamespacePlugin(config, plugin, kind, pluginConfig);\n }\n\n const namespace = await resolveNamespaceForType(config, configDir, sourceType);\n return getGeneratedTypeForTypeAttachedPlugin(plugin, sourceType, kind, pluginConfig, namespace);\n}\n\n/**\n * Get a generated type from a type-attached plugin.\n * @param plugin - The plugin instance (must have onTypeLoaded() method)\n * @param sourceType - The source TailorDB type\n * @param kind - The generated type kind\n * @param pluginConfig - Plugin-level configuration\n * @param namespace - Resolved namespace\n * @returns The generated TailorDB type\n */\nasync function getGeneratedTypeForTypeAttachedPlugin(\n plugin: Plugin,\n sourceType: TailorAnyDBType,\n kind: string,\n pluginConfig: unknown,\n namespace: string,\n): Promise<TailorAnyDBType> {\n if (!plugin.onTypeLoaded) {\n throw new Error(`Plugin \"${plugin.id}\" does not have a onTypeLoaded() method`);\n }\n\n // Check cache first\n let pluginCache = processCache.get(plugin);\n if (!pluginCache) {\n pluginCache = new Map();\n processCache.set(plugin, pluginCache);\n }\n\n const cacheKey = getCacheKey(`${sourceType.name}:ns=${namespace}`, pluginConfig);\n let output = pluginCache.get(cacheKey);\n\n if (!output) {\n const typeConfig = sourceType.plugins?.find((p) => p.pluginId === plugin.id)?.config;\n output = await plugin.onTypeLoaded({\n type: sourceType,\n typeConfig: typeConfig ?? {},\n pluginConfig,\n namespace,\n });\n pluginCache.set(cacheKey, output);\n }\n\n const generatedType = output.types?.[kind];\n if (!generatedType) {\n throw new Error(\n `Generated type not found: plugin=${plugin.id}, sourceType=${sourceType.name}, kind=${kind}`,\n );\n }\n\n return generatedType as TailorAnyDBType;\n}\n\n/**\n * Get a generated type from a namespace plugin.\n * Auto-resolves the namespace by trying each one.\n * @param config - App config with db namespace definitions\n * @param config.db - DB namespace definitions\n * @param plugin - The plugin instance (must have onNamespaceLoaded() method)\n * @param kind - The generated type kind\n * @param pluginConfig - Plugin-level configuration\n * @returns The generated TailorDB type\n */\nasync function getGeneratedTypeForNamespacePlugin(\n config: { db?: Record<string, unknown> },\n plugin: Plugin,\n kind: string,\n pluginConfig: unknown,\n): Promise<TailorAnyDBType> {\n if (!plugin.onNamespaceLoaded) {\n throw new Error(`Plugin \"${plugin.id}\" does not have a onNamespaceLoaded() method`);\n }\n\n // Check cache first - try all namespaces\n let pluginCache = namespaceProcessCache.get(plugin);\n if (!pluginCache) {\n pluginCache = new Map();\n namespaceProcessCache.set(plugin, pluginCache);\n }\n\n // Try cached results first\n if (config.db) {\n for (const namespace of Object.keys(config.db)) {\n const dbConfig = config.db[namespace] as DbNamespaceConfig;\n if (dbConfig.external) continue;\n\n const cacheKey = getCacheKey(`namespace:ns=${namespace}`, pluginConfig);\n const cached = pluginCache.get(cacheKey);\n if (cached?.types?.[kind]) {\n return cached.types[kind] as TailorAnyDBType;\n }\n }\n }\n\n // Not in cache - resolve namespace and process\n const { namespace, output } = await resolveNamespaceForNamespacePlugin(\n config,\n plugin,\n kind,\n pluginConfig,\n );\n\n const cacheKey = getCacheKey(`namespace:ns=${namespace}`, pluginConfig);\n pluginCache.set(cacheKey, output);\n\n const generatedType = output.types?.[kind];\n if (!generatedType) {\n throw new Error(`Generated type not found: plugin=${plugin.id}, kind=${kind}`);\n }\n\n return generatedType as TailorAnyDBType;\n}\n\n/**\n * Clear all internal caches. For testing only.\n */\nexport function _clearCacheForTesting(): void {\n configCacheMap.clear();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/plugin/with-context.ts","../../src/plugin/get-generated-type.ts"],"sourcesContent":["/**\n * Plugin executor context support for defining plugin executors in separate files.\n * This module provides utilities for creating type-safe plugin executors that receive\n * context (like type references and namespace) at runtime.\n */\n\nimport type { TailorActor, TailorEnv } from \"@/types/runtime\";\n\n/**\n * Plugin executor factory function type.\n * Takes context and returns an executor configuration.\n * Returns unknown since the exact return type depends on createExecutor's generic params.\n */\nexport type PluginExecutorFactory<Ctx> = (ctx: Ctx) => unknown;\n\n// ============================================================================\n// Plugin Executor Args Types\n// ============================================================================\n\n/**\n * Base args for plugin executor function operations.\n * Provides typed access to runtime context without requiring specific record types.\n */\nexport interface PluginFunctionArgs {\n /** Workspace ID where the executor runs */\n workspaceId: string;\n /** Application namespace */\n appNamespace: string;\n /** Environment variables */\n env: TailorEnv;\n /** Actor (user) who triggered the event, null for system events */\n actor: TailorActor | null;\n /** Name of the TailorDB type */\n typeName: string;\n /** TailorDB connections by namespace */\n tailordb: Record<string, unknown>;\n}\n\n/**\n * Args for plugin executors triggered on record creation.\n */\nexport interface PluginRecordCreatedArgs extends PluginFunctionArgs {\n /** The newly created record */\n newRecord: Record<string, unknown>;\n}\n\n/**\n * Args for plugin executors triggered on record update.\n */\nexport interface PluginRecordUpdatedArgs extends PluginFunctionArgs {\n /** The record after update */\n newRecord: Record<string, unknown>;\n /** The record before update */\n oldRecord: Record<string, unknown>;\n}\n\n/**\n * Args for plugin executors triggered on record deletion.\n */\nexport interface PluginRecordDeletedArgs extends PluginFunctionArgs {\n /** The deleted record */\n oldRecord: Record<string, unknown>;\n}\n\n/**\n * Database schema type for plugins.\n * Since plugins work with dynamic types, the schema uses Record types.\n */\nexport type PluginDBSchema = Record<string, Record<string, unknown>>;\n\n/**\n * Base record type for TailorDB records.\n * All records have an id field.\n */\nexport type PluginRecord = { id: string } & Record<string, unknown>;\n\n/**\n * Define a plugin executor that receives context at runtime.\n * This allows executor definitions to be in separate files while\n * still receiving dynamic values like typeName, generated types, and namespace.\n * @param factory - Function that takes context and returns executor configuration\n * @returns The same factory function (for type inference)\n * @example\n * ```typescript\n * // executors/on-create.ts\n * import { withPluginContext } from \"@tailor-platform/sdk/plugin\";\n * import { createExecutor, recordCreatedTrigger } from \"@tailor-platform/sdk\";\n * import { getDB } from \"@tailor-platform/function-kysely-tailordb\";\n *\n * interface MyContext {\n * sourceType: TailorAnyDBType;\n * historyType: TailorAnyDBType;\n * namespace: string;\n * }\n *\n * export default withPluginContext<MyContext>((ctx) =>\n * createExecutor({\n * name: `${ctx.sourceType.name.toLowerCase()}-on-create`,\n * trigger: recordCreatedTrigger({ type: ctx.sourceType }),\n * operation: {\n * kind: \"function\",\n * body: async (args) => {\n * const db = getDB(ctx.namespace);\n * await db.insertInto(ctx.historyType.name).values({\n * recordId: args.newRecord.id,\n * // ...\n * }).execute();\n * },\n * },\n * })\n * );\n * ```\n */\nexport function withPluginContext<Ctx>(\n factory: PluginExecutorFactory<Ctx>,\n): PluginExecutorFactory<Ctx> {\n return factory;\n}\n","import * as fs from \"node:fs\";\nimport { pathToFileURL } from \"node:url\";\nimport * as path from \"pathe\";\nimport type { Plugin, PluginOutput, TypePluginOutput } from \"@/types/plugin\";\nimport type { TailorAnyDBType } from \"@/types/tailordb\";\n\n// ========================================\n// Config loading and caching\n// ========================================\n\ninterface PluginEntry {\n plugin: Plugin;\n pluginConfig: unknown;\n}\n\ninterface ConfigCache {\n config: { db?: Record<string, unknown> };\n plugins: Map<string, PluginEntry>;\n configDir: string;\n}\n\n/** Cache: resolved config path -> loaded config data */\nconst configCacheMap = new Map<string, ConfigCache>();\n\n/**\n * Check if a value is a Plugin instance.\n * @param value - Value to check\n * @returns True if value has the shape of Plugin\n */\nfunction isPlugin(value: unknown): value is Plugin {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as Record<string, unknown>).id === \"string\" &&\n typeof (value as Record<string, unknown>).description === \"string\"\n );\n}\n\n/**\n * Load and cache config module from the given path.\n * Extracts plugins from all array exports using definePlugins() format.\n * Returns null if the config file does not exist (e.g., in bundled executor on platform server).\n * @param configPath - Absolute or relative path to tailor.config.ts\n * @returns Cached config data with plugins map, or null if config file is not available\n */\nasync function loadAndCacheConfig(configPath: string): Promise<ConfigCache | null> {\n const resolvedPath = path.resolve(configPath);\n\n const cached = configCacheMap.get(resolvedPath);\n if (cached) return cached;\n\n // Config file may not exist in bundled environments (e.g., platform server)\n if (!fs.existsSync(resolvedPath)) {\n return null;\n }\n\n const configModule = await import(pathToFileURL(resolvedPath).href);\n if (!configModule?.default) {\n throw new Error(`Invalid config module at \"${resolvedPath}\": default export not found`);\n }\n\n const config = configModule.default as { db?: Record<string, unknown> };\n const configDir = path.dirname(resolvedPath);\n const plugins = new Map<string, PluginEntry>();\n\n // Find plugin arrays from exports (definePlugins returns PluginConfig[])\n for (const value of Object.values(configModule)) {\n if (!Array.isArray(value)) continue;\n\n for (const item of value) {\n if (isPlugin(item)) {\n plugins.set(item.id, { plugin: item, pluginConfig: item.pluginConfig });\n }\n }\n }\n\n const result: ConfigCache = { config, plugins, configDir };\n configCacheMap.set(resolvedPath, result);\n return result;\n}\n\n// ========================================\n// Namespace resolution\n// ========================================\n\ninterface DbNamespaceConfig {\n files?: string[];\n external?: boolean;\n}\n\n/**\n * Resolve the namespace for a type-attached sourceType by checking config.db file patterns.\n * Uses ESM module cache identity: same file path yields same object references.\n * @param config - App config with db namespace definitions\n * @param config.db - DB namespace definitions\n * @param configDir - Directory containing the config file\n * @param sourceType - The TailorDB type to look up\n * @returns The namespace name\n */\nasync function resolveNamespaceForType(\n config: { db?: Record<string, unknown> },\n configDir: string,\n sourceType: TailorAnyDBType,\n): Promise<string> {\n if (!config.db) {\n throw new Error(`No db configuration found in config`);\n }\n\n for (const [namespace, nsConfig] of Object.entries(config.db)) {\n const dbConfig = nsConfig as DbNamespaceConfig;\n // Skip external namespaces (no files to resolve)\n if (dbConfig.external || !dbConfig.files) continue;\n\n for (const pattern of dbConfig.files) {\n const absolutePattern = path.resolve(configDir, pattern);\n let matchedFiles: string[];\n try {\n matchedFiles = fs.globSync(absolutePattern);\n } catch {\n continue;\n }\n\n for (const file of matchedFiles) {\n const mod = await import(pathToFileURL(file).href);\n for (const exported of Object.values(mod)) {\n if (exported === sourceType) {\n return namespace;\n }\n }\n }\n }\n }\n\n throw new Error(\n `Could not resolve namespace for type \"${sourceType.name}\". ` +\n `Ensure the type file is included in a db namespace's files pattern.`,\n );\n}\n\n/**\n * Resolve the namespace for a namespace plugin by trying each namespace.\n * Calls onNamespaceLoaded() for each and returns the first whose output contains the requested kind.\n * @param config - App config with db namespace definitions\n * @param config.db - DB namespace definitions\n * @param plugin - Plugin instance\n * @param kind - The generated type kind to look for\n * @param pluginConfig - Plugin-level configuration\n * @returns The namespace name\n */\nasync function resolveNamespaceForNamespacePlugin(\n config: { db?: Record<string, unknown> },\n plugin: Plugin,\n kind: string,\n pluginConfig: unknown,\n): Promise<{ namespace: string; output: PluginOutput }> {\n if (!config.db) {\n throw new Error(`No db configuration found in config`);\n }\n\n if (!plugin.onNamespaceLoaded) {\n throw new Error(`Plugin \"${plugin.id}\" does not have a onNamespaceLoaded() method`);\n }\n\n for (const namespace of Object.keys(config.db)) {\n const dbConfig = config.db[namespace] as DbNamespaceConfig;\n if (dbConfig.external) continue;\n\n const output = await plugin.onNamespaceLoaded({\n pluginConfig,\n namespace,\n });\n\n if (output.types?.[kind]) {\n return { namespace, output };\n }\n }\n\n throw new Error(\n `Could not resolve namespace for plugin \"${plugin.id}\" with kind \"${kind}\". ` +\n `No namespace produced a type with that kind.`,\n );\n}\n\n// ========================================\n// Process caching\n// ========================================\n\n// Cache: plugin -> cacheKey -> TypePluginOutput\nconst processCache = new WeakMap<Plugin, Map<string, TypePluginOutput>>();\n\n// Cache for namespace plugins: plugin -> cacheKey -> PluginOutput\nconst namespaceProcessCache = new WeakMap<Plugin, Map<string, PluginOutput>>();\n\n/**\n * Generate a cache key that includes pluginConfig.\n * @param baseKey - Base key for the cache\n * @param pluginConfig - Plugin configuration to include in the key\n * @returns Cache key string\n */\nfunction getCacheKey(baseKey: string, pluginConfig: unknown): string {\n if (pluginConfig === undefined) {\n return baseKey;\n }\n try {\n return `${baseKey}:${JSON.stringify(pluginConfig)}`;\n } catch {\n throw new Error(\n `pluginConfig must be JSON-serializable for caching. Received non-serializable value.`,\n );\n }\n}\n\n// ========================================\n// Main API\n// ========================================\n\n/**\n * Get a generated type from a plugin by loading the config and resolving everything automatically.\n * For type-attached plugins, calls onTypeLoaded() with the sourceType.\n * For namespace plugins, calls onNamespaceLoaded() with auto-resolved namespace.\n * Results are cached per config path, plugin, namespace, and pluginConfig to avoid redundant processing.\n * @param configPath - Path to tailor.config.ts (absolute or relative to cwd)\n * @param pluginId - The plugin's unique identifier\n * @param sourceType - The source TailorDB type (null for namespace plugins)\n * @param kind - The generated type kind (e.g., \"request\", \"step\")\n * @returns The generated TailorDB type\n */\nexport async function getGeneratedType(\n configPath: string,\n pluginId: string,\n sourceType: TailorAnyDBType | null,\n kind: string,\n): Promise<TailorAnyDBType> {\n const cache = await loadAndCacheConfig(configPath);\n\n if (!cache) {\n // Config not available (e.g., running in bundled executor on platform server).\n // Return a placeholder. The actual type is resolved at generate/apply time.\n return { name: `__placeholder_${kind}__`, fields: {} } as TailorAnyDBType;\n }\n\n const { config, configDir, plugins } = cache;\n\n const pluginEntry = plugins.get(pluginId);\n if (!pluginEntry) {\n throw new Error(\n `Plugin \"${pluginId}\" not found in config at \"${configPath}\". ` +\n `Ensure the plugin is registered via definePlugins().`,\n );\n }\n\n const { plugin, pluginConfig } = pluginEntry;\n\n if (sourceType === null) {\n return getGeneratedTypeForNamespacePlugin(config, plugin, kind, pluginConfig);\n }\n\n const namespace = await resolveNamespaceForType(config, configDir, sourceType);\n return getGeneratedTypeForTypeAttachedPlugin(plugin, sourceType, kind, pluginConfig, namespace);\n}\n\n/**\n * Get a generated type from a type-attached plugin.\n * @param plugin - The plugin instance (must have onTypeLoaded() method)\n * @param sourceType - The source TailorDB type\n * @param kind - The generated type kind\n * @param pluginConfig - Plugin-level configuration\n * @param namespace - Resolved namespace\n * @returns The generated TailorDB type\n */\nasync function getGeneratedTypeForTypeAttachedPlugin(\n plugin: Plugin,\n sourceType: TailorAnyDBType,\n kind: string,\n pluginConfig: unknown,\n namespace: string,\n): Promise<TailorAnyDBType> {\n if (!plugin.onTypeLoaded) {\n throw new Error(`Plugin \"${plugin.id}\" does not have a onTypeLoaded() method`);\n }\n\n // Check cache first\n let pluginCache = processCache.get(plugin);\n if (!pluginCache) {\n pluginCache = new Map();\n processCache.set(plugin, pluginCache);\n }\n\n const cacheKey = getCacheKey(`${sourceType.name}:ns=${namespace}`, pluginConfig);\n let output = pluginCache.get(cacheKey);\n\n if (!output) {\n const typeConfig = sourceType.plugins?.find((p) => p.pluginId === plugin.id)?.config;\n output = await plugin.onTypeLoaded({\n type: sourceType,\n typeConfig: typeConfig ?? {},\n pluginConfig,\n namespace,\n });\n pluginCache.set(cacheKey, output);\n }\n\n const generatedType = output.types?.[kind];\n if (!generatedType) {\n throw new Error(\n `Generated type not found: plugin=${plugin.id}, sourceType=${sourceType.name}, kind=${kind}`,\n );\n }\n\n return generatedType as TailorAnyDBType;\n}\n\n/**\n * Get a generated type from a namespace plugin.\n * Auto-resolves the namespace by trying each one.\n * @param config - App config with db namespace definitions\n * @param config.db - DB namespace definitions\n * @param plugin - The plugin instance (must have onNamespaceLoaded() method)\n * @param kind - The generated type kind\n * @param pluginConfig - Plugin-level configuration\n * @returns The generated TailorDB type\n */\nasync function getGeneratedTypeForNamespacePlugin(\n config: { db?: Record<string, unknown> },\n plugin: Plugin,\n kind: string,\n pluginConfig: unknown,\n): Promise<TailorAnyDBType> {\n if (!plugin.onNamespaceLoaded) {\n throw new Error(`Plugin \"${plugin.id}\" does not have a onNamespaceLoaded() method`);\n }\n\n // Check cache first - try all namespaces\n let pluginCache = namespaceProcessCache.get(plugin);\n if (!pluginCache) {\n pluginCache = new Map();\n namespaceProcessCache.set(plugin, pluginCache);\n }\n\n // Try cached results first\n if (config.db) {\n for (const namespace of Object.keys(config.db)) {\n const dbConfig = config.db[namespace] as DbNamespaceConfig;\n if (dbConfig.external) continue;\n\n const cacheKey = getCacheKey(`namespace:ns=${namespace}`, pluginConfig);\n const cached = pluginCache.get(cacheKey);\n if (cached?.types?.[kind]) {\n return cached.types[kind] as TailorAnyDBType;\n }\n }\n }\n\n // Not in cache - resolve namespace and process\n const { namespace, output } = await resolveNamespaceForNamespacePlugin(\n config,\n plugin,\n kind,\n pluginConfig,\n );\n\n const cacheKey = getCacheKey(`namespace:ns=${namespace}`, pluginConfig);\n pluginCache.set(cacheKey, output);\n\n const generatedType = output.types?.[kind];\n if (!generatedType) {\n throw new Error(`Generated type not found: plugin=${plugin.id}, kind=${kind}`);\n }\n\n return generatedType as TailorAnyDBType;\n}\n\n/**\n * Clear all internal caches. For testing only.\n */\nexport function _clearCacheForTesting(): void {\n configCacheMap.clear();\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"repl-editor-BlT2dFtm.mjs","names":[],"sources":["../src/cli/query/repl-editor.ts"],"sourcesContent":["import { GraphQLError, Lexer, Source, TokenKind } from \"graphql\";\nimport { getSegments } from \"sql-highlight\";\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 = lines[row];\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 = lines[row];\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 = lines[row];\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 = lines[row - 1];\n const baseIndent = prevLine.match(/^(\\s*)/)?.[1] ?? \"\";\n const endsWithOpen = /[{([]$/.test(prevLine.trimEnd());\n const startsWithClose = /^[}\\])]/.test(lines[row].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 newLines[row] = innerIndent;\n newLines.splice(row + 1, 0, baseIndent + lines[row].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 newLines[row] = indent + lines[row];\n newLines.splice(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 + lines[row]), row, col: baseIndent.length };\n }\n }\n\n return undefined;\n}\n"],"mappings":";;;;;AAOA,MAAM,QAAQ;AACd,MAAM,OAAO;AACb,MAAM,UAAU;AAChB,MAAM,SAAS;AACf,MAAM,eAAe;AACrB,MAAM,OAAO;AACb,MAAM,cAAc;AACpB,MAAM,YAAY;AAClB,MAAM,eAAe;AACrB,MAAM,gBAAgB;AACtB,MAAM,QAAQ;AACd,MAAM,MAAM;AACZ,MAAM,aAAa;AAEnB,MAAM,gBAAwC;CAC5C,SAAS;CACT,UAAU;CACV,YAAY;CACZ,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,SAAS;CACV;;;;;;AAOD,SAAgB,iBAAiB,MAAsB;CACrD,MAAM,WAAW,YAAY,KAAK;CAClC,IAAI,SAAS;AACb,MAAK,MAAM,OAAO,UAAU;EAC1B,MAAM,QAAQ,cAAc,IAAI;AAChC,YAAU,QAAQ,QAAQ,IAAI,UAAU,QAAQ,IAAI;;AAEtD,QAAO;;AAGT,MAAM,eAAe,IAAI,IAAI;CAC3B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,CAAC;AAGF,MAAM,mBAAmB,IAAI,IAAI;CAAC;CAAS;CAAY;CAAgB;CAAW,CAAC;AAEnF,MAAM,eAAe,IAAI,IAAI;CAAC;CAAQ;CAAS;CAAO,CAAC;;;;;;;;AASvD,SAAgB,qBAAqB,MAAsB;AACzD,KAAI,KAAK,WAAW,CAAC,WAAW,IAAI,CAClC,QAAO,GAAG,MAAM,OAAO;AAGzB,KAAI;EAEF,MAAM,QAAQ,IAAI,MAAM,IADL,OAAO,KACI,CAAC;EAC/B,IAAI,SAAS;EACb,IAAI,MAAM;EAEV,IAAI,aAAa;EACjB,IAAI,WAAmB;EACvB,IAAI,WAAW;EACf,IAAI,aAAa;EAEjB,IAAI,QAAQ,MAAM,SAAS;AAC3B,SAAO,MAAM,SAAS,UAAU,KAAK;AACnC,OAAI,MAAM,QAAQ,IAChB,WAAU,KAAK,MAAM,KAAK,MAAM,MAAM;GAGxC,MAAM,OAAO,KAAK,MAAM,MAAM,OAAO,MAAM,IAAI;AAC/C,WAAQ,MAAM,MAAd;IACE,KAAK,UAAU;AACb,SAAI,aAAa,UAAU,OACzB,WAAU,GAAG,UAAU,OAAO;cACrB,aAAa,UAAU,GAChC,WAAU,GAAG,eAAe,OAAO;cAC1B,aAAa,IAAI,KAAK,IAAI,aAAa,IAAI,KAAK,CACzD,WAAU,GAAG,OAAO,OAAO;cAClB,iBAAiB,IAAI,SAAS,CACvC,WAAU,GAAG,YAAY,OAAO;cACvB,WACT,WAAU,GAAG,OAAO,OAAO;cAClB,aAAa,EACtB,WAAU,GAAG,gBAAgB,OAAO;SAEpC,WAAU,GAAG,cAAc,OAAO;AAEpC,kBAAa;AACb;IAEF,KAAK,UAAU;IACf,KAAK,UAAU;AACb,eAAU,GAAG,OAAO,OAAO;AAC3B,kBAAa;AACb;IACF,KAAK,UAAU;IACf,KAAK,UAAU;AACb,eAAU,GAAG,QAAQ,OAAO;AAC5B,kBAAa;AACb;IACF,KAAK,UAAU;AACb,eAAU,GAAG,UAAU,OAAO;AAC9B,kBAAa;AACb;IACF,KAAK,UAAU;AACb,eAAU,GAAG,eAAe,OAAO;AACnC,kBAAa;AACb;IACF,KAAK,UAAU;IACf,KAAK,UAAU;AACb,eAAU,GAAG,SAAS,OAAO;AAC7B,kBAAa;AACb;IACF,KAAK,UAAU;AACb,mBAAc;AACd,eAAU,GAAG,aAAa,OAAO;AACjC,kBAAa;AACb;IACF,KAAK,UAAU;AACb,kBAAa,KAAK,IAAI,GAAG,aAAa,EAAE;AACxC,eAAU,GAAG,aAAa,OAAO;AACjC,kBAAa;AACb;IACF,KAAK,UAAU;IACf,KAAK,UAAU;AACb,eAAU,GAAG,aAAa,OAAO;AACjC,kBAAa;AACb;IACF,KAAK,UAAU;AACb,eAAU,GAAG,MAAM,OAAO;AAC1B,kBAAa;AACb;IACF,KAAK,UAAU;IACf,KAAK,UAAU;IACf,KAAK,UAAU;IACf,KAAK,UAAU;IACf,KAAK,UAAU;AACb,eAAU,GAAG,MAAM,OAAO;AAC1B,kBAAa;AACb;IACF;AACE,eAAU;AACV,kBAAa;;AAGjB,cAAW,MAAM;AACjB,cAAW;AACX,SAAM,MAAM;AACZ,WAAQ,MAAM,SAAS;;AAGzB,MAAI,MAAM,KAAK,OACb,WAAU,KAAK,MAAM,IAAI;AAE3B,SAAO;UACA,OAAO;AAKd,MAAI,iBAAiB,aACnB,QAAO;AAET,QAAM;;;AAIV,MAAM,gBAAwC;CAAE,KAAK;CAAK,KAAK;CAAK,KAAK;CAAK;AAC9E,MAAM,iBAAiB,IAAI,IAAI,OAAO,OAAO,cAAc,CAAC;;;;;;;;AAS5D,SAAgB,cACd,OACA,OAC4B;CAC5B,MAAM,EAAE,OAAO,KAAK,QAAQ;AAE5B,KAAI,MAAM,SAAS,YAAY,MAAM,QAAQ,eAAe;EAC1D,MAAM,QAAQ,cAAc,MAAM;EAClC,MAAM,OAAO,MAAM;EACnB,MAAM,UAAU,KAAK,MAAM,GAAG,IAAI,GAAG,QAAQ,KAAK,MAAM,IAAI;AAC5D,SAAO;GAAE,OAAO,MAAM,KAAK,KAAK,QAAQ;GAAE;GAAK;GAAK;;AAGtD,KAAI,MAAM,SAAS,YAAY,eAAe,IAAI,MAAM,KAAK,EAAE;EAC7D,MAAM,OAAO,MAAM;AACnB,MAAI,KAAK,SAAS,MAAM,MAAM;GAC5B,MAAM,UAAU,KAAK,MAAM,GAAG,IAAI,GAAG,KAAK,MAAM,MAAM,EAAE;AACxD,UAAO;IAAE,OAAO,MAAM,KAAK,KAAK,QAAQ;IAAE;IAAK;IAAK;;;AAIxD,KAAI,MAAM,SAAS,aAAa;EAC9B,MAAM,OAAO,MAAM;EACnB,MAAM,eAAe,KAAK,MAAM,GAAG,IAAI;AACvC,MAAI,aAAa,UAAU,KAAK,OAAO,KAAK,aAAa,EAAE;GACzD,MAAM,YAAY,aAAa,MAAM,GAAG,GAAG;GAC3C,MAAM,UAAU,YAAY,KAAK,MAAM,IAAI;AAC3C,UAAO;IAAE,OAAO,MAAM,KAAK,KAAK,QAAQ;IAAE;IAAK,KAAK,UAAU;IAAQ;;;AAI1E,KAAI,MAAM,SAAS,aAAa,MAAM,GAAG;EACvC,MAAM,WAAW,MAAM,MAAM;EAC7B,MAAM,aAAa,SAAS,MAAM,SAAS,GAAG,MAAM;EACpD,MAAM,eAAe,SAAS,KAAK,SAAS,SAAS,CAAC;EACtD,MAAM,kBAAkB,UAAU,KAAK,MAAM,KAAK,WAAW,CAAC;AAE9D,MAAI,gBAAgB,iBAAiB;GAInC,MAAM,cAAc,aAAa;GACjC,MAAM,WAAW,CAAC,GAAG,MAAM;AAC3B,YAAS,OAAO;AAChB,YAAS,OAAO,MAAM,GAAG,GAAG,aAAa,MAAM,KAAK,WAAW,CAAC;AAChE,UAAO;IAAE,OAAO;IAAU;IAAK,KAAK,YAAY;IAAQ;;AAE1D,MAAI,cAAc;GAIhB,MAAM,YAAY,cADD,SAAS,SAAS,CAAC,MAAM,GACF,KAAK;GAC7C,MAAM,SAAS,aAAa;GAC5B,MAAM,WAAW,CAAC,GAAG,MAAM;AAC3B,YAAS,OAAO,SAAS,MAAM;AAC/B,YAAS,OAAO,MAAM,GAAG,GAAG,aAAa,UAAU;AACnD,UAAO;IAAE,OAAO;IAAU;IAAK,KAAK,OAAO;IAAQ;;AAErD,MAAI,cAAc,QAAQ,EACxB,QAAO;GAAE,OAAO,MAAM,KAAK,KAAK,aAAa,MAAM,KAAK;GAAE;GAAK,KAAK,WAAW;GAAQ"}
|
|
1
|
+
{"version":3,"file":"repl-editor-CZpLlOBj.mjs","names":[],"sources":["../src/cli/query/repl-editor.ts"],"sourcesContent":["import { GraphQLError, Lexer, Source, TokenKind } from \"graphql\";\nimport { getSegments } from \"sql-highlight\";\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 = lines[row];\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 = lines[row];\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 = lines[row];\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 = lines[row - 1];\n const baseIndent = prevLine.match(/^(\\s*)/)?.[1] ?? \"\";\n const endsWithOpen = /[{([]$/.test(prevLine.trimEnd());\n const startsWithClose = /^[}\\])]/.test(lines[row].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 newLines[row] = innerIndent;\n newLines.splice(row + 1, 0, baseIndent + lines[row].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 newLines[row] = indent + lines[row];\n newLines.splice(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 + lines[row]), row, col: baseIndent.length };\n }\n }\n\n return undefined;\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { r as db } from "./tailordb-DjlNUV6u.mjs";
|
|
3
|
+
import { $ as FilterSchema, A as FunctionExecution_Status, B as AuthOAuth2Client_GrantType, C as TailorDBType_Permission_Operator, D as IdPLang, E as PipelineResolver_OperationType, F as AuthConnection_Type, H as AuthSCIMAttribute_Type, I as AuthHookPoint, J as GetApplicationSchemaHealthResponse_ApplicationSchemaHealthStatus, K as TenantProviderConfig_TenantProviderType, L as AuthIDPConfig_AuthType, M as ExecutorJobStatus, N as ExecutorTargetType, O as IdPPermissionOperator, P as ExecutorTriggerType, Q as Condition_Operator, R as AuthInvokerSchema, S as TailorDBGQLPermission_Permit, T as TailorDBType_PermitAction, U as AuthSCIMAttribute_Uniqueness, V as AuthSCIMAttribute_Mutability, W as AuthSCIMConfig_AuthorizationType, X as Subgraph_ServiceType, Y as ApplicationSchemaUpdateAttemptStatus, Z as ConditionSchema, _ as WorkspacePlatformUserRole, a as fetchMachineUserToken, b as TailorDBGQLPermission_Action, d as initOperatorClient, et as PageDirection, g as OperatorService, h as userAgent, i as fetchAll, k as IdPPermissionPermit, m as resolveStaticWebsiteUrls, o as fetchPaged, p as platformBaseUrl, q as UserProfileProviderConfig_UserProfileProviderType, v as WorkflowExecution_Status, w as TailorDBType_Permission_Permit, x as TailorDBGQLPermission_Operator, y as WorkflowJobExecution_Status, z as AuthOAuth2Client_ClientType } from "./client-DbyKSN1F.mjs";
|
|
4
4
|
import { a as parseBoolean, i as symbols, n as logger, r as styles, t as CIPromptError } from "./logger-DTNAMYGy.mjs";
|
|
5
|
-
import { C as loadWorkspaceId, D as writePlatformConfig, S as loadAccessToken, _ as getDistDir, d as buildResolverOperationHookExpr, f as OAuth2ClientSchema, g as createBundleCache, h as loadFilesWithIgnores, m as stringifyFunction, n as generatePluginFilesIfNeeded, p as TailorDBTypeSchema, r as loadApplication, s as createExecutorService, t as defineApplication, u as buildExecutorArgsExpr, v as hashFile, w as readPlatformConfig, y as loadConfig } from "./application-
|
|
5
|
+
import { C as loadWorkspaceId, D as writePlatformConfig, S as loadAccessToken, _ as getDistDir, d as buildResolverOperationHookExpr, f as OAuth2ClientSchema, g as createBundleCache, h as loadFilesWithIgnores, m as stringifyFunction, n as generatePluginFilesIfNeeded, p as TailorDBTypeSchema, r as loadApplication, s as createExecutorService, t as defineApplication, u as buildExecutorArgsExpr, v as hashFile, w as readPlatformConfig, y as loadConfig } from "./application-C7H7y0hS.mjs";
|
|
6
6
|
import { t as multiline } from "./multiline-e3IpANmS.mjs";
|
|
7
7
|
import { t as readPackageJson } from "./package-json-6Px8bDpG.mjs";
|
|
8
8
|
import { n as isCLIError, t as createCLIError } from "./errors-wNQxQQBH.mjs";
|
|
@@ -21,10 +21,10 @@ import { tmpdir } from "node:os";
|
|
|
21
21
|
import { findUpSync } from "find-up-simple";
|
|
22
22
|
import { xdgConfig } from "xdg-basedir";
|
|
23
23
|
import { Code, ConnectError } from "@connectrpc/connect";
|
|
24
|
-
import * as crypto from "node:crypto";
|
|
25
|
-
import { createHash } from "node:crypto";
|
|
26
24
|
import { resolveTSConfig } from "pkg-types";
|
|
27
25
|
import { ScalarType, create, fromJson, toJson } from "@bufbuild/protobuf";
|
|
26
|
+
import * as crypto from "node:crypto";
|
|
27
|
+
import { createHash } from "node:crypto";
|
|
28
28
|
import { ExitPromptError } from "@inquirer/core";
|
|
29
29
|
import { confirm, input, password } from "@inquirer/prompts";
|
|
30
30
|
import { isCI } from "std-env";
|
|
@@ -1122,6 +1122,66 @@ var PluginManager = class {
|
|
|
1122
1122
|
return results;
|
|
1123
1123
|
}
|
|
1124
1124
|
/**
|
|
1125
|
+
* Run every plugin attachment for a single TailorDB type in order, threading the
|
|
1126
|
+
* extended type through the chain. Returns plain data (no logging, no shared state)
|
|
1127
|
+
* so the caller decides how to apply updates and render progress.
|
|
1128
|
+
* @param params - The raw type, its attachments, and the target namespace
|
|
1129
|
+
* @returns Final extended type (if any), generated types, and render events
|
|
1130
|
+
*/
|
|
1131
|
+
async processAttachmentsForType(params) {
|
|
1132
|
+
const { rawType, attachments, namespace } = params;
|
|
1133
|
+
let currentType = rawType;
|
|
1134
|
+
let extendedType;
|
|
1135
|
+
const generatedTypes = [];
|
|
1136
|
+
const events = [];
|
|
1137
|
+
for (const attachment of attachments) {
|
|
1138
|
+
const result = await this.processAttachment({
|
|
1139
|
+
type: currentType,
|
|
1140
|
+
typeConfig: attachment.config,
|
|
1141
|
+
namespace,
|
|
1142
|
+
pluginId: attachment.pluginId
|
|
1143
|
+
});
|
|
1144
|
+
if (!result.success) throw new Error(result.error);
|
|
1145
|
+
const output = result.output;
|
|
1146
|
+
const extendFields = output.extends?.fields;
|
|
1147
|
+
if (extendFields && Object.keys(extendFields).length > 0) {
|
|
1148
|
+
currentType = this.extendType({
|
|
1149
|
+
originalType: currentType,
|
|
1150
|
+
extendFields,
|
|
1151
|
+
pluginId: attachment.pluginId
|
|
1152
|
+
});
|
|
1153
|
+
extendedType = currentType;
|
|
1154
|
+
events.push({
|
|
1155
|
+
kind: "extended",
|
|
1156
|
+
typeName: currentType.name,
|
|
1157
|
+
fieldCount: Object.keys(extendFields).length,
|
|
1158
|
+
pluginId: attachment.pluginId
|
|
1159
|
+
});
|
|
1160
|
+
}
|
|
1161
|
+
const plugin = this.getPlugin(attachment.pluginId);
|
|
1162
|
+
for (const [kind, gen] of Object.entries(output.types ?? {})) {
|
|
1163
|
+
generatedTypes.push({
|
|
1164
|
+
typeName: gen.name,
|
|
1165
|
+
type: gen,
|
|
1166
|
+
kind,
|
|
1167
|
+
pluginId: attachment.pluginId,
|
|
1168
|
+
pluginImportPath: this.getPluginImportPath(attachment.pluginId) ?? "",
|
|
1169
|
+
pluginConfig: plugin?.pluginConfig
|
|
1170
|
+
});
|
|
1171
|
+
events.push({
|
|
1172
|
+
kind: "generated",
|
|
1173
|
+
typeName: gen.name,
|
|
1174
|
+
pluginId: attachment.pluginId
|
|
1175
|
+
});
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
return {
|
|
1179
|
+
extendedType,
|
|
1180
|
+
generatedTypes,
|
|
1181
|
+
events
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
/**
|
|
1125
1185
|
* Get plugins that have onNamespaceLoaded method
|
|
1126
1186
|
* @returns Array of plugin IDs that support namespace processing
|
|
1127
1187
|
*/
|
|
@@ -5521,6 +5581,22 @@ const DB_TYPES_FILE_NAME = "db.ts";
|
|
|
5521
5581
|
*/
|
|
5522
5582
|
const MIGRATION_NUMBER_PATTERN = /^\d{4}$/;
|
|
5523
5583
|
/**
|
|
5584
|
+
* Platform default scale for decimal fields when scale is not explicitly specified.
|
|
5585
|
+
* Must stay in sync with the platform's default decimal scale.
|
|
5586
|
+
*/
|
|
5587
|
+
const DEFAULT_DECIMAL_SCALE = 6;
|
|
5588
|
+
/**
|
|
5589
|
+
* Resolve the effective scale of a field for comparison purposes.
|
|
5590
|
+
* Decimal fields without an explicit scale are stored on the platform with the
|
|
5591
|
+
* default scale, so we normalize unset values to the default to avoid false drift.
|
|
5592
|
+
* @param {SnapshotFieldConfig} field - Field configuration
|
|
5593
|
+
* @returns {number | undefined} Effective scale, or undefined for non-decimal fields without scale
|
|
5594
|
+
*/
|
|
5595
|
+
function getEffectiveScale(field) {
|
|
5596
|
+
if (field.scale !== void 0) return field.scale;
|
|
5597
|
+
if (field.type === "decimal") return 6;
|
|
5598
|
+
}
|
|
5599
|
+
/**
|
|
5524
5600
|
* Validate that a migration number follows the expected format (4-digit number)
|
|
5525
5601
|
* @param {string} numberStr - Migration number string to validate
|
|
5526
5602
|
* @returns {boolean} True if number matches expected format
|
|
@@ -6037,7 +6113,7 @@ function areFieldsDifferent(oldField, newField) {
|
|
|
6037
6113
|
if (oldSerial.maxValue !== newSerial.maxValue) return true;
|
|
6038
6114
|
if ((oldSerial.format ?? "") !== (newSerial.format ?? "")) return true;
|
|
6039
6115
|
}
|
|
6040
|
-
if (oldField
|
|
6116
|
+
if (getEffectiveScale(oldField) !== getEffectiveScale(newField)) return true;
|
|
6041
6117
|
const oldFields = oldField.fields ?? {};
|
|
6042
6118
|
const newFields = newField.fields ?? {};
|
|
6043
6119
|
const oldFieldNames = Object.keys(oldFields);
|
|
@@ -6505,7 +6581,9 @@ function compareFields(typeName, fieldName, remoteField, snapshotField) {
|
|
|
6505
6581
|
const remoteVector = remoteField.vector ?? false;
|
|
6506
6582
|
const snapshotVector = snapshotField.vector ?? false;
|
|
6507
6583
|
if (remoteVector !== snapshotVector) differences.push(`vector: remote=${remoteVector}, expected=${snapshotVector}`);
|
|
6508
|
-
|
|
6584
|
+
const remoteScale = getEffectiveScale(remoteField);
|
|
6585
|
+
const snapshotScale = getEffectiveScale(snapshotField);
|
|
6586
|
+
if (remoteScale !== snapshotScale) differences.push(`scale: remote=${remoteScale}, expected=${snapshotScale}`);
|
|
6509
6587
|
if (differences.length > 0) return {
|
|
6510
6588
|
typeName,
|
|
6511
6589
|
kind: "field_mismatch",
|
|
@@ -10935,6 +11013,9 @@ const WatcherErrorCode = {
|
|
|
10935
11013
|
* Watcher-specific error.
|
|
10936
11014
|
*/
|
|
10937
11015
|
var WatcherError = class extends Error {
|
|
11016
|
+
code;
|
|
11017
|
+
filePath;
|
|
11018
|
+
originalError;
|
|
10938
11019
|
constructor(message, code, filePath, originalError) {
|
|
10939
11020
|
super(message);
|
|
10940
11021
|
this.code = code;
|
|
@@ -13291,7 +13372,7 @@ async function generate(options) {
|
|
|
13291
13372
|
if (options.init) await handleInitOption(namespacesWithMigrations, options.yes);
|
|
13292
13373
|
let pluginManager;
|
|
13293
13374
|
if (plugins.length > 0) pluginManager = new PluginManager(plugins);
|
|
13294
|
-
const { defineApplication } = await import("./application-
|
|
13375
|
+
const { defineApplication } = await import("./application-Csq5jxYP.mjs");
|
|
13295
13376
|
const application = defineApplication({
|
|
13296
13377
|
config,
|
|
13297
13378
|
pluginManager
|
|
@@ -15106,7 +15187,7 @@ async function runRepl(options) {
|
|
|
15106
15187
|
const execute = await prepareQueryExecutor(options);
|
|
15107
15188
|
const historyPath = getReplHistoryPath(options.engine, options.profile, options.workspaceId);
|
|
15108
15189
|
const validate = createReplValidator(options.engine);
|
|
15109
|
-
const { highlightSqlLine, highlightGraphqlLine, replTransform } = await import("./repl-editor-
|
|
15190
|
+
const { highlightSqlLine, highlightGraphqlLine, replTransform } = await import("./repl-editor-CZpLlOBj.mjs");
|
|
15110
15191
|
const highlight = options.engine === "sql" ? highlightSqlLine : highlightGraphqlLine;
|
|
15111
15192
|
const prompt = createPrompt({
|
|
15112
15193
|
prefix: "",
|
|
@@ -15440,4 +15521,4 @@ function isDeno() {
|
|
|
15440
15521
|
|
|
15441
15522
|
//#endregion
|
|
15442
15523
|
export { deleteCommand$1 as $, getMigrationDirPath as $t, truncate as A, executionsCommand as At, updateOrganization as B, MIGRATION_LABEL_KEY as Bt, listCommand$2 as C, toPageDirection as Cn, jobsCommand as Ct, resumeWorkflow as D, startWorkflow as Dt, resumeCommand as E, startCommand as Et, showCommand as F, getCommand$6 as Ft, getCommand$1 as G, INITIAL_SCHEMA_NUMBER as Gt, treeCommand as H, bundleMigrationScript as Ht, logBetaWarning as I, getExecutor as It, updateFolder as J, compareLocalTypesWithSnapshot as Jt, getOrganization as K, MIGRATE_FILE_NAME as Kt, remove as L, deploy as Lt, generate as M, listWorkflowExecutions as Mt, generateCommand as N, functionExecutionStatusToString as Nt, listCommand$3 as O, getCommand$5 as Ot, show as P, formatKeyValueTable as Pt, getFolder as Q, getLatestMigrationNumber as Qt, removeCommand$1 as R, executeScript as Rt, listApps as S, paginationArgs as Sn, getExecutorJob as St, healthCommand as T, watchExecutorJob as Tt, listCommand$4 as U, DB_TYPES_FILE_NAME as Ut, organizationTree as V, parseMigrationLabelNumber as Vt, listOrganizations as W, DIFF_FILE_NAME as Wt, listFolders as X, createSnapshotFromLocalTypes as Xt, listCommand$5 as Y, compareSnapshots as Yt, getCommand$2 as Z, formatMigrationNumber as Zt, getWorkspace as _, commonArgs as _n, webhookCommand as _t, updateUser as a, reconstructSnapshotFromMigrations as an, getCommand$3 as at, createCommand as b, isVerbose as bn, listCommand$9 as bt, listCommand as c, hasChanges as cn, tokenCommand as ct, inviteUser as d, trnPrefix as dn, generate$1 as dt, getMigrationFilePath as en, deleteFolder as et, restoreCommand as f, generateUserTypes as fn, listCommand$8 as ft, getCommand as g, defineAppCommand as gn, listWebhookExecutors as gt, listWorkspaces as h, apiCall as hn, getFunctionRegistry as ht, updateCommand as i, loadDiff as in, listOAuth2Clients as it, truncateCommand as j, getWorkflowExecution as jt, listWorkflows as k, getWorkflow as kt, listUsers as l, getNamespacesWithMigrations as ln, listCommand$7 as lt, listCommand$1 as m, apiCommand as mn, getCommand$4 as mt, query as n, getNextMigrationNumber as nn, createFolder as nt, removeCommand as o, formatDiffSummary as on, getOAuth2Client as ot, restoreWorkspace as p, prompt as pn, listFunctionRegistries as pt, updateCommand$2 as q, SCHEMA_FILE_NAME as qt, queryCommand as r, isValidMigrationNumber as rn, listCommand$6 as rt, removeUser as s, formatMigrationDiff as sn, getMachineUserToken as st, isNativeTypeScriptRuntime as t, getMigrationFiles as tn, createCommand$1 as tt, inviteCommand as u, sdkNameLabelKey as un, listMachineUsers as ut, deleteCommand as v, confirmationArgs as vn, triggerCommand as vt, getAppHealth as w, workspaceArgs as wn, listExecutorJobs as wt, createWorkspace as x, pagedLogArgs as xn, listExecutors as xt, deleteWorkspace as y, deploymentArgs as yn, triggerExecutor as yt, updateCommand$1 as z, waitForExecution$1 as zt };
|
|
15443
|
-
//# sourceMappingURL=runtime-
|
|
15524
|
+
//# sourceMappingURL=runtime-XjP6JMmP.mjs.map
|