@tailor-platform/sdk 2.3.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +171 -0
- package/README.md +1 -1
- package/dist/aigateway-DsWDjzk4.mjs +2 -0
- package/dist/{aigateway-DR4Kwuik.mjs.map → aigateway-DsWDjzk4.mjs.map} +1 -1
- package/dist/application-DFOUovmN.mjs +1 -0
- package/dist/application-D_4vg1KR.mjs +192 -0
- package/dist/application-D_4vg1KR.mjs.map +1 -0
- package/dist/assert-WeXvmG4j.mjs +2 -0
- package/dist/{assert-DBxo8jPo.mjs.map → assert-WeXvmG4j.mjs.map} +1 -1
- package/dist/authconnection-CynFBIv8.mjs +2 -0
- package/dist/{authconnection-CZvi9ANm.mjs.map → authconnection-CynFBIv8.mjs.map} +1 -1
- package/dist/brand-C8nMKhJC.mjs +2 -0
- package/dist/{brand-Eo4pLXPJ.mjs.map → brand-C8nMKhJC.mjs.map} +1 -1
- package/dist/cli/commands/deploy/deploy.d.mts +2 -2
- package/dist/cli/commands/deploy/deployment-target.d.mts +2 -0
- package/dist/cli/commands/deploy/event-subscriptions.d.mts +3 -0
- package/dist/cli/commands/deploy/tailordb/apply.d.mts +3 -0
- package/dist/cli/commands/deploy/tailordb/index.d.mts +3 -10
- package/dist/cli/commands/deploy/tailordb/migration-validation.d.mts +5 -0
- package/dist/cli/commands/deploy/tailordb/plan.d.mts +8 -0
- package/dist/cli/commands/executor/jobs.d.mts +1 -1
- package/dist/cli/commands/generate/seed/bundler.d.mts +2 -2
- package/dist/cli/commands/show.d.mts +1 -1
- package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +15 -15
- package/dist/cli/commands/tailordb/migrate/generate.d.mts +7 -3
- package/dist/cli/commands/tailordb/migrate/rename-detection.d.mts +1 -1
- package/dist/cli/commands/tailordb/migrate/snapshot-comparison.d.mts +43 -0
- package/dist/cli/commands/tailordb/migrate/snapshot-files.d.mts +62 -0
- package/dist/cli/commands/tailordb/migrate/snapshot-local.d.mts +12 -0
- package/dist/cli/commands/tailordb/migrate/snapshot-migrations.d.mts +12 -0
- package/dist/cli/commands/tailordb/migrate/snapshot-remote.d.mts +1 -0
- package/dist/cli/commands/tailordb/migrate/snapshot-types.d.mts +3 -1
- package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +5 -117
- package/dist/cli/commands/tailordb/truncate.d.mts +2 -2
- package/dist/cli/lib.d.mts +8 -4
- package/dist/cli/lib.mjs +1 -9
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/main.mjs +1170 -7686
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/shared/seed-chunker.d.mts +5 -5
- package/dist/cli/ts-hook.mjs +3 -1
- package/dist/completion/zsh-worker.zsh +99 -18
- package/dist/configure/config/index.d.mts +2 -2
- package/dist/configure/config/types.d.mts +2 -2
- package/dist/configure/index.d.mts +49 -12
- package/dist/configure/index.mjs +1 -1267
- package/dist/configure/index.mjs.map +1 -1
- package/dist/configure/services/aigateway/index.d.mts +5 -4
- package/dist/configure/services/aigateway/types.d.mts +6 -1
- package/dist/configure/services/auth/types.d.mts +3 -3
- package/dist/configure/services/idp/types.d.mts +1 -1
- package/dist/configure/services/tailordb/permission.d.mts +1 -1
- package/dist/configure/services/tailordb/schema.d.mts +5 -9
- package/dist/configure/services/tailordb/types.d.mts +8 -5
- package/dist/configure/services/workflow/execution-policy.d.mts +3 -3
- package/dist/configure/services/workflow/job.d.mts +12 -2
- package/dist/configure/types/auth-namespace-name.d.mts +18 -0
- package/dist/configure/types/field.types.d.mts +1 -1
- package/dist/configure/types/permission-operand.types.d.mts +1 -1
- package/dist/context-D0QjfxzD.mjs +2 -0
- package/dist/{context-DYQVYWqZ.mjs.map → context-D0QjfxzD.mjs.map} +1 -1
- package/dist/crashreport-B-_HTKLr.mjs +42 -0
- package/dist/{crashreport-CIIfLnoO.mjs.map → crashreport-B-_HTKLr.mjs.map} +1 -1
- package/dist/crashreport-BmsRIdpy.mjs +1 -0
- package/dist/errors-DSEXKRVD.mjs +2 -0
- package/dist/errors-DSEXKRVD.mjs.map +1 -0
- package/dist/file-COPYfju_.mjs +2 -0
- package/dist/file-COPYfju_.mjs.map +1 -0
- package/dist/globals-CMHSnj4w.mjs +2 -0
- package/dist/{globals-B2nlxBrz.mjs.map → globals-CMHSnj4w.mjs.map} +1 -1
- package/dist/iconv-DlFMt2gW.mjs +2 -0
- package/dist/{iconv-QWaZh0TT.mjs.map → iconv-DlFMt2gW.mjs.map} +1 -1
- package/dist/idp-G_ojPBB5.mjs +2 -0
- package/dist/{idp-RA_swu-h.mjs.map → idp-G_ojPBB5.mjs.map} +1 -1
- package/dist/interceptor-DQg3cR_9.mjs +2 -0
- package/dist/{interceptor-e33JtsC-.mjs.map → interceptor-DQg3cR_9.mjs.map} +1 -1
- package/dist/kysely/index.mjs +1 -31
- package/dist/kysely/index.mjs.map +1 -1
- package/dist/kysely-type-BTi3BMtL.mjs +43 -0
- package/dist/kysely-type-BTi3BMtL.mjs.map +1 -0
- package/dist/logger-BcGy-u7G.mjs +9 -0
- package/dist/{logger-DSdExfor.mjs.map → logger-BcGy-u7G.mjs.map} +1 -1
- package/dist/logger-DP2BjQ93.mjs +2 -0
- package/dist/{logger-BtX0suGY.mjs.map → logger-DP2BjQ93.mjs.map} +1 -1
- package/dist/multiline-EyzjEwn9.mjs +3 -0
- package/dist/{multiline-sfHpTZZK.mjs.map → multiline-EyzjEwn9.mjs.map} +1 -1
- package/dist/node-builtins-oBl7EbyV.mjs +2 -0
- package/dist/{node-builtins-CmaL2Cbq.mjs.map → node-builtins-oBl7EbyV.mjs.map} +1 -1
- package/dist/package-json-C690ceex.mjs +2 -0
- package/dist/{package-json-8b0O9TlX.mjs.map → package-json-C690ceex.mjs.map} +1 -1
- package/dist/package-json-CmqhDJ__.mjs +1 -0
- package/dist/parser/service/tailordb/type-source.d.mts +5 -5
- package/dist/parser/service/tailordb/types.d.mts +4 -4
- package/dist/platform-serialize-DkiTdHOt.mjs +2 -0
- package/dist/{platform-serialize-RoRtBS0v.mjs.map → platform-serialize-DkiTdHOt.mjs.map} +1 -1
- package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
- package/dist/plugin/builtin/enum-constants/index.mjs +5 -114
- package/dist/plugin/builtin/enum-constants/index.mjs.map +1 -1
- package/dist/plugin/builtin/file-utils/index.d.mts +1 -1
- package/dist/plugin/builtin/file-utils/index.mjs +22 -101
- package/dist/plugin/builtin/file-utils/index.mjs.map +1 -1
- package/dist/plugin/builtin/kysely-type/index.d.mts +9 -2
- package/dist/plugin/builtin/kysely-type/index.mjs +1 -275
- package/dist/plugin/builtin/seed/index.d.mts +5 -0
- package/dist/plugin/builtin/seed/index.mjs +1 -3
- package/dist/plugin/builtin/seed/seed-type-processor.d.mts +4 -6
- package/dist/plugin/get-generated-table.d.mts +16 -0
- package/dist/plugin/index.d.mts +3 -2
- package/dist/plugin/index.mjs +1 -251
- package/dist/plugin/index.mjs.map +1 -1
- package/dist/plugin/types.d.mts +32 -25
- package/dist/plugin/with-context.d.mts +4 -4
- package/dist/register-ts-hook-Drnaproy.mjs +640 -0
- package/dist/register-ts-hook-Drnaproy.mjs.map +1 -0
- package/dist/registry-HlEaGvl5.mjs +2 -0
- package/dist/{registry-BIGVUrMB.mjs.map → registry-HlEaGvl5.mjs.map} +1 -1
- package/dist/repl-editor-BG1aDOfH.mjs +2 -0
- package/dist/{repl-editor-BCozyiNq.mjs.map → repl-editor-BG1aDOfH.mjs.map} +1 -1
- package/dist/runtime/aigateway.mjs +1 -3
- package/dist/runtime/authconnection.mjs +1 -3
- package/dist/runtime/context.mjs +1 -3
- package/dist/runtime/file.d.mts +28 -28
- package/dist/runtime/file.mjs +1 -3
- package/dist/runtime/globals.mjs +1 -1
- package/dist/runtime/iconv.mjs +1 -3
- package/dist/runtime/idp.mjs +1 -3
- package/dist/runtime/index.mjs +1 -11
- package/dist/runtime/logger.mjs +1 -3
- package/dist/runtime/secretmanager.mjs +1 -3
- package/dist/runtime/types.d.mts +1 -1
- package/dist/runtime/workflow.mjs +1 -3
- package/dist/schema-Ze_dI5VX.mjs +2 -0
- package/dist/schema-Ze_dI5VX.mjs.map +1 -0
- package/dist/secret-file-C9wp_FCX.mjs +2 -0
- package/dist/{secret-file-C3J4Gy8r.mjs.map → secret-file-C9wp_FCX.mjs.map} +1 -1
- package/dist/secretmanager-5olfnI1b.mjs +2 -0
- package/dist/{secretmanager-IY4UvinW.mjs.map → secretmanager-5olfnI1b.mjs.map} +1 -1
- package/dist/secretmanager-vHQoXdQz.mjs +2 -0
- package/dist/{secretmanager-CYlpffsz.mjs.map → secretmanager-vHQoXdQz.mjs.map} +1 -1
- package/dist/seed/index.d.mts +4 -4
- package/dist/seed/index.mjs +8 -244
- package/dist/seed/index.mjs.map +1 -1
- package/dist/seed-DwqRFdqP.mjs +207 -0
- package/dist/seed-DwqRFdqP.mjs.map +1 -0
- package/dist/service-BVe9u2Rt.mjs +7 -0
- package/dist/service-BVe9u2Rt.mjs.map +1 -0
- package/dist/service-CpZELSBa.mjs +1 -0
- package/dist/service-DlgaUO4V.mjs +2 -0
- package/dist/{service-hZskxZmg.mjs.map → service-DlgaUO4V.mjs.map} +1 -1
- package/dist/service_pb-DGKCLuAs.mjs +2 -0
- package/dist/{service_pb-BEWj1pOV.mjs.map → service_pb-DGKCLuAs.mjs.map} +1 -1
- package/dist/service_pb-_aeFE-Nv.mjs +1 -0
- package/dist/telemetry-Bklv9kQY.mjs +2 -0
- package/dist/{telemetry-BRVdwh14.mjs.map → telemetry-Bklv9kQY.mjs.map} +1 -1
- package/dist/telemetry-DXHP3VVi.mjs +1 -0
- package/dist/type-source--ZNcV8RJ.mjs +2 -0
- package/dist/type-source--ZNcV8RJ.mjs.map +1 -0
- package/dist/types/aigateway.generated.d.mts +2 -2
- package/dist/types/auth.generated.d.mts +3 -3
- package/dist/types/executor.generated.d.mts +2 -2
- package/dist/types/tailordb.generated.d.mts +12 -12
- package/dist/user-agent-vdHYF3QL.mjs +2 -0
- package/dist/{user-agent-Bgsszb5I.mjs.map → user-agent-vdHYF3QL.mjs.map} +1 -1
- package/dist/utils/test/index.d.mts +4 -4
- package/dist/utils/test/index.mjs +1 -109
- package/dist/utils/test/index.mjs.map +1 -1
- package/dist/vitest/environment.mjs +1 -41
- package/dist/vitest/environment.mjs.map +1 -1
- package/dist/vitest/index.mjs +1 -1980
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/vitest/mocks/file.d.mts +8 -8
- package/dist/vitest/setup.mjs +1 -140
- package/dist/vitest/setup.mjs.map +1 -1
- package/dist/wait-point-invoker-eiP-IIux.mjs +2 -0
- package/dist/wait-point-invoker-eiP-IIux.mjs.map +1 -0
- package/dist/wait-point-registry-BrkwfyjS.mjs +2 -0
- package/dist/{wait-point-registry-TL99zotw.mjs.map → wait-point-registry-BrkwfyjS.mjs.map} +1 -1
- package/dist/workflow-Cs9ISw6j.mjs +2 -0
- package/dist/{workflow-Bamae_Yc.mjs.map → workflow-Cs9ISw6j.mjs.map} +1 -1
- package/dist/workspace_resource_pb--GeYQPXu.mjs +2 -0
- package/dist/{workspace_resource_pb-HNIL_Vfj.mjs.map → workspace_resource_pb--GeYQPXu.mjs.map} +1 -1
- package/docs/cli/application.md +3 -1
- package/docs/cli/function.md +77 -13
- package/docs/cli/setup.md +24 -14
- package/docs/cli/tailordb.md +32 -30
- package/docs/cli/workspace.md +2 -2
- package/docs/cli-reference.md +23 -22
- package/docs/configuration.md +2 -2
- package/docs/github-actions.md +10 -9
- package/docs/migration/v2.md +16 -4
- package/docs/migration/v3.md +123 -0
- package/docs/plugin/custom.md +130 -85
- package/docs/plugin/index.md +3 -3
- package/docs/quickstart.md +1 -1
- package/docs/services/aigateway.md +33 -9
- package/docs/services/executor.md +5 -1
- package/docs/services/tailordb-migration.md +68 -54
- package/docs/services/tailordb.md +7 -7
- package/docs/services/workflow.md +10 -9
- package/docs/testing.md +1 -1
- package/package.json +16 -16
- package/postinstall.mjs +1 -1
- package/dist/aigateway-DR4Kwuik.mjs +0 -9
- package/dist/application-BZfk4HKm.mjs +0 -3
- package/dist/application-F-nl107y.mjs +0 -6019
- package/dist/application-F-nl107y.mjs.map +0 -1
- package/dist/assert-DBxo8jPo.mjs +0 -9
- package/dist/authconnection-CZvi9ANm.mjs +0 -9
- package/dist/brand-Eo4pLXPJ.mjs +0 -36
- package/dist/context-DYQVYWqZ.mjs +0 -23
- package/dist/crashreport-CIIfLnoO.mjs +0 -423
- package/dist/crashreport-CINZ5dVN.mjs +0 -3
- package/dist/errors-BVb6vYGy.mjs +0 -89
- package/dist/errors-BVb6vYGy.mjs.map +0 -1
- package/dist/file-BUcmVIH2.mjs +0 -58
- package/dist/file-BUcmVIH2.mjs.map +0 -1
- package/dist/globals-B2nlxBrz.mjs +0 -126
- package/dist/iconv-QWaZh0TT.mjs +0 -38
- package/dist/idp-RA_swu-h.mjs +0 -82
- package/dist/interceptor-e33JtsC-.mjs +0 -33
- package/dist/logger-BtX0suGY.mjs +0 -48
- package/dist/logger-DSdExfor.mjs +0 -358
- package/dist/multiline-sfHpTZZK.mjs +0 -38
- package/dist/node-builtins-CmaL2Cbq.mjs +0 -36
- package/dist/package-json-8b0O9TlX.mjs +0 -17
- package/dist/package-json-Cv2Z-TqQ.mjs +0 -3
- package/dist/platform-serialize-RoRtBS0v.mjs +0 -46
- package/dist/plugin/builtin/kysely-type/index.mjs.map +0 -1
- package/dist/plugin/builtin/seed/types.d.mts +0 -2
- package/dist/plugin/get-generated-type.d.mts +0 -16
- package/dist/register-ts-hook-ClI226n2.mjs +0 -25543
- package/dist/register-ts-hook-ClI226n2.mjs.map +0 -1
- package/dist/registry-BIGVUrMB.mjs +0 -54
- package/dist/repl-editor-BCozyiNq.mjs +0 -251
- package/dist/schema--xYWRGfe.mjs +0 -639
- package/dist/schema--xYWRGfe.mjs.map +0 -1
- package/dist/secret-file-C3J4Gy8r.mjs +0 -64
- package/dist/secretmanager-CYlpffsz.mjs +0 -13
- package/dist/secretmanager-IY4UvinW.mjs +0 -131
- package/dist/seed-xqM9WIHP.mjs +0 -483
- package/dist/seed-xqM9WIHP.mjs.map +0 -1
- package/dist/service-C_WpbKHu.mjs +0 -898
- package/dist/service-C_WpbKHu.mjs.map +0 -1
- package/dist/service-D1RCdzIL.mjs +0 -3
- package/dist/service-hZskxZmg.mjs +0 -131
- package/dist/service_pb-BEWj1pOV.mjs +0 -167
- package/dist/service_pb-BjlhvK9E.mjs +0 -3
- package/dist/telemetry-BRVdwh14.mjs +0 -84
- package/dist/telemetry-CkbkeJxl.mjs +0 -3
- package/dist/type-source-DH_LH20p.mjs +0 -13
- package/dist/type-source-DH_LH20p.mjs.map +0 -1
- package/dist/user-agent-Bgsszb5I.mjs +0 -28
- package/dist/wait-point-invoker-__oE88_P.mjs +0 -148
- package/dist/wait-point-invoker-__oE88_P.mjs.map +0 -1
- package/dist/wait-point-registry-TL99zotw.mjs +0 -47
- package/dist/workflow-Bamae_Yc.mjs +0 -34
- package/dist/workspace_resource_pb-HNIL_Vfj.mjs +0 -860
|
@@ -26,9 +26,7 @@ Configure an AI Gateway using `defineAIGateway()`:
|
|
|
26
26
|
```typescript
|
|
27
27
|
import { defineAIGateway, defineConfig } from "@tailor-platform/sdk";
|
|
28
28
|
|
|
29
|
-
const aiGateway = defineAIGateway("my-aigateway", {
|
|
30
|
-
authNamespace: "default",
|
|
31
|
-
});
|
|
29
|
+
const aiGateway = defineAIGateway("my-aigateway", {});
|
|
32
30
|
|
|
33
31
|
export default defineConfig({
|
|
34
32
|
name: "my-app",
|
|
@@ -40,14 +38,42 @@ export default defineConfig({
|
|
|
40
38
|
|
|
41
39
|
### authNamespace
|
|
42
40
|
|
|
43
|
-
The auth namespace used to resolve request tokens against your workspace's auth configuration.
|
|
41
|
+
The auth namespace used to resolve request tokens against your workspace's auth configuration. Optional — when omitted, it defaults to your application's own Auth service (local or external, the name passed to `defineAuth()`), which is what most AI Gateways need. Omitting it without an Auth service configured is rejected by `deploy`/`generate`, asking you to either define one or set `authNamespace` explicitly:
|
|
44
42
|
|
|
45
43
|
```typescript
|
|
46
|
-
defineAIGateway
|
|
47
|
-
|
|
44
|
+
import { defineAIGateway, defineAuth, defineConfig } from "@tailor-platform/sdk";
|
|
45
|
+
|
|
46
|
+
const auth = defineAuth("my-auth", {
|
|
47
|
+
// ...auth configuration...
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const aiGateway = defineAIGateway("my-aigateway", {}); // defaults to "my-auth"
|
|
51
|
+
|
|
52
|
+
export default defineConfig({
|
|
53
|
+
name: "my-app",
|
|
54
|
+
auth,
|
|
55
|
+
aiGateways: [aiGateway],
|
|
48
56
|
});
|
|
49
57
|
```
|
|
50
58
|
|
|
59
|
+
Type-checked and autocompleted against your own Auth service name via the generated `tailor.d.ts` (the `AuthNamespaceNameRegistry` interface). Run `tailor generate` (or `deploy`) after defining an Auth service to refresh it. Before the first generate run, `authNamespace` accepts any string.
|
|
60
|
+
|
|
61
|
+
To authenticate against a **different** application's Auth service, reference it as an [external resource](../configuration.md#external-resources) in your own config — `authNamespace` then defaults to it like any other Auth service:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
import { defineAIGateway, defineConfig } from "@tailor-platform/sdk";
|
|
65
|
+
|
|
66
|
+
const aiGateway = defineAIGateway("my-aigateway", {}); // defaults to "shared-auth"
|
|
67
|
+
|
|
68
|
+
export default defineConfig({
|
|
69
|
+
name: "my-app",
|
|
70
|
+
auth: { name: "shared-auth", external: true },
|
|
71
|
+
aiGateways: [aiGateway],
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
An `authNamespace` that doesn't match any auth namespace in your workspace surfaces only at runtime, as `401 Unauthorized` on every request to the gateway.
|
|
76
|
+
|
|
51
77
|
### cors
|
|
52
78
|
|
|
53
79
|
Optional list of allowed origins for browser-based clients. Each entry is one of:
|
|
@@ -61,7 +87,6 @@ An optional `:port` may be appended in all URL forms. Omitting `cors` (or passin
|
|
|
61
87
|
|
|
62
88
|
```typescript
|
|
63
89
|
defineAIGateway("my-aigateway", {
|
|
64
|
-
authNamespace: "default",
|
|
65
90
|
cors: ["https://app.example.com", "https://*.example.com"],
|
|
66
91
|
});
|
|
67
92
|
```
|
|
@@ -81,8 +106,7 @@ const website = defineStaticWebSite("my-frontend", {
|
|
|
81
106
|
});
|
|
82
107
|
|
|
83
108
|
const aiGateway = defineAIGateway("my-aigateway", {
|
|
84
|
-
//
|
|
85
|
-
authNamespace: "default",
|
|
109
|
+
// authNamespace omitted: defaults to this app's own Auth service, declared below.
|
|
86
110
|
cors: [website.url],
|
|
87
111
|
});
|
|
88
112
|
|
|
@@ -374,7 +374,7 @@ must return the same input type.
|
|
|
374
374
|
|
|
375
375
|
### Authentication for Operations
|
|
376
376
|
|
|
377
|
-
|
|
377
|
+
`graphql`, `function`, `jobFunction`, and `workflow` operations can specify an `invoker` to execute with machine user credentials. Pass the machine user name as a plain string — it is type-narrowed to the names defined in your auth config:
|
|
378
378
|
|
|
379
379
|
```typescript
|
|
380
380
|
import { createExecutor, scheduleTrigger } from "@tailor-platform/sdk";
|
|
@@ -390,6 +390,10 @@ export default createExecutor({
|
|
|
390
390
|
});
|
|
391
391
|
```
|
|
392
392
|
|
|
393
|
+
The machine user is resolved in your application's auth namespace — the name of your Auth service, local or external. `webhook` is the only operation kind that does not accept `invoker`, since it calls an external URL rather than acting inside your workspace.
|
|
394
|
+
|
|
395
|
+
Without an `invoker`, the operation runs as whoever raised the trigger event, or anonymously when there is no such principal — as with a `schedule` trigger. Declare an `invoker` whenever the operation needs an identity of its own.
|
|
396
|
+
|
|
393
397
|
## Event Payloads
|
|
394
398
|
|
|
395
399
|
Each trigger type provides specific context data in the callback functions.
|
|
@@ -59,7 +59,7 @@ If your local tables and remote schema have **diverged**, reconcile them before
|
|
|
59
59
|
|
|
60
60
|
### Resetting
|
|
61
61
|
|
|
62
|
-
`tailor tailordb migration generate --init` deletes the existing `migrations/` directory and creates `0000` from the current local
|
|
62
|
+
`tailor tailordb migration generate --init` deletes the existing `migrations/` directory and creates `0000` from the current local tables. Use it only before the project is deployed. For a deployed migration history, use [`migration rebaseline`](#re-baselining-a-deployed-migration-history), which verifies the history and connected workspace before replacing any files.
|
|
63
63
|
|
|
64
64
|
## Migration Workflow
|
|
65
65
|
|
|
@@ -141,9 +141,9 @@ In an interactive session, `migration generate` offers to record the reason on t
|
|
|
141
141
|
|
|
142
142
|
### Renaming a field
|
|
143
143
|
|
|
144
|
-
Renaming a field in a
|
|
144
|
+
Renaming a field in a table definition looks like a removal plus an addition to the diff engine. Left as-is, that combination silently drops the old field's data: the removal is only a warning, so nothing forces a data copy.
|
|
145
145
|
|
|
146
|
-
To prevent that, when `migration generate` finds a removed field and an added field in the same
|
|
146
|
+
To prevent that, when `migration generate` finds a removed field and an added field in the same table whose stored values can be copied without changing their meaning, it asks whether the change is a rename. Serial fields are never rename candidates, and an enum field only qualifies when it keeps every value of the removed field:
|
|
147
147
|
|
|
148
148
|
```
|
|
149
149
|
? User.fullName was removed and displayName was added with a compatible type. Was it renamed to displayName? (Y/n)
|
|
@@ -166,30 +166,30 @@ If you decline the prompt (or confirm the removal with `--drop`), the change sta
|
|
|
166
166
|
|
|
167
167
|
Renaming a member inside a **nested field** is not detected, and it is quieter: `User.address.zip` → `zipCode` becomes a single `field_modified` on `address` with no breaking change, no warning, and no generated script, so the member's values are not carried over. Copy them with a custom `tailordb migration script` if they must survive.
|
|
168
168
|
|
|
169
|
-
### Renaming a
|
|
169
|
+
### Renaming a table
|
|
170
170
|
|
|
171
|
-
Renaming a whole
|
|
171
|
+
Renaming a whole table is detected the same way: when `migration generate` finds a removed table and an added table with a matching shape, it asks whether the change is a rename:
|
|
172
172
|
|
|
173
173
|
```
|
|
174
174
|
? User was removed and Person was added with a compatible schema. Was it renamed to Person? (Y/n)
|
|
175
175
|
```
|
|
176
176
|
|
|
177
|
-
In non-interactive environments the command fails while a candidate is left unresolved, exactly like field renames. Resolve it with the
|
|
177
|
+
In non-interactive environments the command fails while a candidate is left unresolved, exactly like field renames. Resolve it with the table forms of the same flags (a value without a `.` targets a table):
|
|
178
178
|
|
|
179
179
|
```bash
|
|
180
180
|
tailor tailordb migration generate --rename "User:Person"
|
|
181
181
|
tailor tailordb migration generate --drop "User"
|
|
182
182
|
```
|
|
183
183
|
|
|
184
|
-
Two
|
|
184
|
+
Two tables qualify as a rename pair only when copying every row preserves the data: every field must keep its name, type, array-ness, required/unique constraints, foreign key target, and decimal scale; enum fields may gain values but not lose them; indexes must match. A self-referential foreign key is compared against the new table name and must be optional. Tables with serial fields (their values cannot be written by a script) or file fields (file contents are not copied) are never candidates. Name-derived and data-independent settings — `pluralForm`, description, table settings, permissions, hooks, and validations — may differ.
|
|
185
185
|
|
|
186
|
-
A confirmed rename is recorded as a single `table_renamed` change and treated as **breaking** for two reasons: existing records must be copied by the migration script, and the
|
|
186
|
+
A confirmed rename is recorded as a single `table_renamed` change and treated as **breaking** for two reasons: existing records must be copied by the migration script, and the table's GraphQL API names (derived from the table name and `pluralForm`) change, which breaks API clients. The generated `migrate.ts` copies every row from the old table into the new one in id-ordered batches, preserving ids so stored foreign key references stay valid, and the generated `db.ts` exposes both the old table (readable) and the new table (writable). Self-referential foreign keys are inserted as null and backfilled after every row exists, so a reference to a row in a later batch cannot fail the copy.
|
|
187
187
|
|
|
188
|
-
Two caveats apply to the copy. The old
|
|
188
|
+
Two caveats apply to the copy. The old table is not write-protected: rows written to it after the script's transaction commits — and before post-migration cleanup drops it — are not carried over, so pause writers to the renamed table for the duration of the deploy. And platform-managed record metadata (creation/update timestamps and actors) cannot be written by the script, so the new table's records carry the migration run's metadata instead of the original values.
|
|
189
189
|
|
|
190
|
-
Fields on other
|
|
190
|
+
Fields on other tables that reference the renamed table via `foreignKeyType` must be retargeted at the new name in the same change. That retarget is recognized as part of the rename: it is not flagged as a breaking foreign-key change and needs no reference fixup, because record ids are preserved by the copy.
|
|
191
191
|
|
|
192
|
-
During deploy, the pre-migration phase creates the new
|
|
192
|
+
During deploy, the pre-migration phase creates the new table with its full constraints while the old table stays on the namespace, the script copies the rows, and the old table is dropped in post-migration cleanup after the checkpoint advances — all within a single `tailor deploy`.
|
|
193
193
|
|
|
194
194
|
### Breaking changes without a script
|
|
195
195
|
|
|
@@ -201,6 +201,20 @@ tailor tailordb migration script 0002 --no-script --reason "no data yet, safe to
|
|
|
201
201
|
|
|
202
202
|
This stores the reason in `migrations/0002/diff.json` (commit the change). The next `tailor deploy` applies the schema change as usual, skips only the script step, and logs the recorded reason. The command refuses to record a skip while `migrate.ts` exists — delete the script first. If `migrate.ts` is added back later, `tailor deploy` fails rather than choosing between the script and the acknowledgment; run `tailor tailordb migration script 0002` again to clear the now-stale acknowledgment from `diff.json` (the script then runs on the next deploy), or delete `migrate.ts` to keep the skip.
|
|
203
203
|
|
|
204
|
+
### Data-only migrations
|
|
205
|
+
|
|
206
|
+
Sometimes existing data must be transformed without any schema change — fixing values written by an application bug, or a one-off normalization. Create a migration that carries no schema diff and exists only to run its script:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
tailor tailordb migration generate --data-only --name "normalize legacy phone numbers"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
This writes a numbered migration with an empty `diff.json`, a `migrate.ts` skeleton, and `db.ts` typed against the current schema. Edit `migrate.ts` to implement the transformation; the next `tailor deploy` runs it like any other migration script — in a single transaction, advancing the migration checkpoint (see [Performance and Large Tables](#performance-and-large-tables) for batching patterns). Because the entry is part of the migration history, the fix is versioned, ordered relative to schema changes, and applied once per workspace.
|
|
213
|
+
|
|
214
|
+
The command requires a clean state: if the namespace has schema changes that are not yet in migration files, generate the schema migration first. With multiple namespaces, pass `--namespace` to name the target. `--data-only` cannot be combined with `--init`, `--rename`, `--drop`, or `--expand-contract`.
|
|
215
|
+
|
|
216
|
+
A data-only migration runs in **every** workspace the history is applied to, including freshly created ones. Write the script so it is safe against tables with no matching rows (a set-based `UPDATE` with a `WHERE` clause is naturally a no-op on an empty table). For a fix that should run in a single environment only, or that is too large for one transaction, run it outside the migration history instead.
|
|
217
|
+
|
|
204
218
|
## Configuration
|
|
205
219
|
|
|
206
220
|
```typescript
|
|
@@ -227,13 +241,13 @@ export default defineConfig({
|
|
|
227
241
|
|
|
228
242
|
## Generated Files
|
|
229
243
|
|
|
230
|
-
| File | When generated
|
|
231
|
-
| ---------------------- |
|
|
232
|
-
| `0000/schema.json` | First `migration generate`
|
|
233
|
-
| `XXXX/diff.json` | Every subsequent migration
|
|
234
|
-
| `XXXX/migrate.ts` | Auto-generated for breaking changes; added manually via `tailordb migration script` for warning-tier changes | Data transformation script. The `main` export receives a Kysely `Transaction`. |
|
|
235
|
-
| `XXXX/db.ts` | Generated once when `migrate.ts` is created
|
|
236
|
-
| `XXXX/migrate.test.ts` | Added via `tailordb migration script --with-test`
|
|
244
|
+
| File | When generated | Description |
|
|
245
|
+
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
246
|
+
| `0000/schema.json` | First `migration generate` | Full snapshot of all tables in the namespace. |
|
|
247
|
+
| `XXXX/diff.json` | Every subsequent migration | Field-level diff against the previous snapshot. |
|
|
248
|
+
| `XXXX/migrate.ts` | Auto-generated for breaking changes and `--data-only` migrations; added manually via `tailordb migration script` for warning-tier changes | Data transformation script. The `main` export receives a Kysely `Transaction`. |
|
|
249
|
+
| `XXXX/db.ts` | Generated once when `migrate.ts` is created | Kysely types reflecting the schema **before** this migration. Exports `Database`, `Transaction`, and `MigrationContext`. |
|
|
250
|
+
| `XXXX/migrate.test.ts` | Added via `tailordb migration script --with-test` | Unit-test scaffold for `migrate.ts` (see [Testing Migrations Locally](#testing-migrations-locally)). Never deployed. |
|
|
237
251
|
|
|
238
252
|
`db.ts` reflects the pre-migration schema because the script runs after the pre-migration phase has temporarily relaxed breaking constraints (e.g., a new `required` field is added as `optional` first), so the data being read still matches the previous shape.
|
|
239
253
|
|
|
@@ -320,31 +334,31 @@ The `env` values are injected at bundle time (the same mechanism as resolvers/ex
|
|
|
320
334
|
|
|
321
335
|
## Supported Schema Changes
|
|
322
336
|
|
|
323
|
-
| Change Type | Breaking? | Migration Script? | Notes
|
|
324
|
-
| --------------------------------- | --------- | ----------------- |
|
|
325
|
-
| Add optional field | No | No | Schema change only
|
|
326
|
-
| Add required field | Yes | Yes | Script populates default values
|
|
327
|
-
| Remove field | No | Optional | Warning tier — no script is auto-generated, but you can add one with `tailordb migration script` to preserve or clear data before the field leaves the active schema. The field stays readable from `migrate.ts` during Pre-migration.
|
|
328
|
-
| Rename field | Yes | Yes | Confirmed interactively at generate time or via `--rename "
|
|
329
|
-
| Change optional → required | Yes | Yes | Script sets defaults for null values
|
|
330
|
-
| Change required → optional | No | No | Schema change only
|
|
331
|
-
| Add index (non-unique) | No | No | Schema change only
|
|
332
|
-
| Add unique index | Yes | Yes | Script must resolve duplicate value combinations across the index fields
|
|
333
|
-
| Change unique index fields | Yes | Yes | Treated like adding a new unique constraint over the new field set
|
|
334
|
-
| Remove index | No | No | Schema change only (removing the unique constraint from an index is also non-breaking)
|
|
335
|
-
| Add unique constraint | Yes | Yes | Script must resolve duplicate values
|
|
336
|
-
| Remove unique constraint | No | No | Schema change only
|
|
337
|
-
| Change decimal scale | Yes | Yes | Auto-generated script re-saves existing rows under the new scale. Decreasing scale rounds values half-up and can lose precision. If the same change adds a unique constraint, duplicate handling runs after re-saving.
|
|
338
|
-
| Add enum value | No | No | Schema change only
|
|
339
|
-
| Remove enum value | Yes | Yes | Script migrates records with removed values
|
|
340
|
-
| Add table | No | No | Schema change only
|
|
341
|
-
| Remove table | No | Optional | Warning tier — no script is auto-generated, but you can add one with `tailordb migration script` to preserve data before the table leaves the active schema. The table stays readable from `migrate.ts` during Pre-migration.
|
|
342
|
-
| Rename table | Yes | Yes | Confirmed interactively at generate time or via `--rename "
|
|
343
|
-
| Change foreign key target table | Yes | Yes | Script updates references to the new target
|
|
344
|
-
| Change field type (verified pair) | Yes | Yes | In-place for the pairs listed under [Field type changes](#field-type-changes); review the generated normalization scaffold and customize it only when existing values need transformation
|
|
345
|
-
| Change field type (other pair) | Yes | Yes | Two migrations, generated together after you confirm — see [Converting a field type](#converting-a-field-type). Edit the conversion in the first; the second needs no changes.
|
|
346
|
-
| Change array → single value | - | - | **Not supported** — see [Converting a field type](#converting-a-field-type)
|
|
347
|
-
| Change single value → array | - | - | **Not supported** — see [Converting a field type](#converting-a-field-type)
|
|
337
|
+
| Change Type | Breaking? | Migration Script? | Notes |
|
|
338
|
+
| --------------------------------- | --------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
339
|
+
| Add optional field | No | No | Schema change only |
|
|
340
|
+
| Add required field | Yes | Yes | Script populates default values |
|
|
341
|
+
| Remove field | No | Optional | Warning tier — no script is auto-generated, but you can add one with `tailordb migration script` to preserve or clear data before the field leaves the active schema. The field stays readable from `migrate.ts` during Pre-migration. |
|
|
342
|
+
| Rename field | Yes | Yes | Confirmed interactively at generate time or via `--rename "Table.oldField:newField"` — see [Renaming a field](#renaming-a-field). Auto-generated script copies values from the old field to the new one; both fields coexist during Pre-migration. |
|
|
343
|
+
| Change optional → required | Yes | Yes | Script sets defaults for null values |
|
|
344
|
+
| Change required → optional | No | No | Schema change only |
|
|
345
|
+
| Add index (non-unique) | No | No | Schema change only |
|
|
346
|
+
| Add unique index | Yes | Yes | Script must resolve duplicate value combinations across the index fields |
|
|
347
|
+
| Change unique index fields | Yes | Yes | Treated like adding a new unique constraint over the new field set |
|
|
348
|
+
| Remove index | No | No | Schema change only (removing the unique constraint from an index is also non-breaking) |
|
|
349
|
+
| Add unique constraint | Yes | Yes | Script must resolve duplicate values |
|
|
350
|
+
| Remove unique constraint | No | No | Schema change only |
|
|
351
|
+
| Change decimal scale | Yes | Yes | Auto-generated script re-saves existing rows under the new scale. Decreasing scale rounds values half-up and can lose precision. If the same change adds a unique constraint, duplicate handling runs after re-saving. |
|
|
352
|
+
| Add enum value | No | No | Schema change only |
|
|
353
|
+
| Remove enum value | Yes | Yes | Script migrates records with removed values |
|
|
354
|
+
| Add table | No | No | Schema change only |
|
|
355
|
+
| Remove table | No | Optional | Warning tier — no script is auto-generated, but you can add one with `tailordb migration script` to preserve data before the table leaves the active schema. The table stays readable from `migrate.ts` during Pre-migration. |
|
|
356
|
+
| Rename table | Yes | Yes | Confirmed interactively at generate time or via `--rename "OldTable:NewTable"` — see [Renaming a table](#renaming-a-table). Auto-generated script copies all rows preserving ids; both tables coexist until post-migration cleanup. |
|
|
357
|
+
| Change foreign key target table | Yes | Yes | Script updates references to the new target |
|
|
358
|
+
| Change field type (verified pair) | Yes | Yes | In-place for the pairs listed under [Field type changes](#field-type-changes); review the generated normalization scaffold and customize it only when existing values need transformation |
|
|
359
|
+
| Change field type (other pair) | Yes | Yes | Two migrations, generated together after you confirm — see [Converting a field type](#converting-a-field-type). Edit the conversion in the first; the second needs no changes. |
|
|
360
|
+
| Change array → single value | - | - | **Not supported** — see [Converting a field type](#converting-a-field-type) |
|
|
361
|
+
| Change single value → array | - | - | **Not supported** — see [Converting a field type](#converting-a-field-type) |
|
|
348
362
|
|
|
349
363
|
### Field type changes
|
|
350
364
|
|
|
@@ -449,7 +463,7 @@ Without the flag the command fails rather than converting anything, so a scripte
|
|
|
449
463
|
Some changes are still rejected and need a temporary field you add yourself — add the new field, write a script that fills it and clears the old one, then remove the old field and rename the temporary one in a later migration:
|
|
450
464
|
|
|
451
465
|
- Array-to-scalar and scalar-to-array, since collapsing an array has no answer the generated script could choose for you.
|
|
452
|
-
- A field that is unique, or that an index, relationship, permission, or
|
|
466
|
+
- A field that is unique, or that an index, relationship, permission, or table-level script names. Those keep pointing at the original name, which the conversion removes.
|
|
453
467
|
|
|
454
468
|
## Testing Pending Migrations
|
|
455
469
|
|
|
@@ -465,25 +479,25 @@ The command performs the following sequence:
|
|
|
465
479
|
6. Optionally runs an assertion script against the migrated data.
|
|
466
480
|
7. Deletes an automatically-created workspace after success or failure.
|
|
467
481
|
|
|
468
|
-
Both the pre-migration and final TailorDB schemas come from committed migration snapshots. Ungenerated changes in the current
|
|
482
|
+
Both the pre-migration and final TailorDB schemas come from committed migration snapshots. Ungenerated changes in the current table definitions are not included in the rehearsal.
|
|
469
483
|
|
|
470
484
|
Executors are omitted from the baseline deployment so loading fixture or cloned records cannot trigger current event handlers against the older schema. Auth user profiles are also deferred until the pending migrations finish, while configured machine users remain available to run seed and migration scripts. The final deployment restores the configured executors and user profiles. Static websites are deployed so configuration references to their URLs resolve, but their workspace-bound custom domains are omitted from migration-test deployments.
|
|
471
485
|
|
|
472
486
|
### Seed mode
|
|
473
487
|
|
|
474
|
-
Seed mode is the default and uses the JSONL files produced by the configured `seedPlugin`. Run `tailor generate` after adding the plugin or changing seed
|
|
488
|
+
Seed mode is the default and uses the JSONL files produced by the configured `seedPlugin`. Run `tailor generate` after adding the plugin or changing seed tables, then populate its `data/*.jsonl` files:
|
|
475
489
|
|
|
476
490
|
```bash
|
|
477
491
|
tailor tailordb migration test --data seed
|
|
478
492
|
```
|
|
479
493
|
|
|
480
|
-
Rows are loaded only for
|
|
494
|
+
Rows are loaded only for tables present in the deployed pre-migration snapshots (and current schemas without migrations), in foreign-key dependency order. Fields introduced by pending migrations, including timestamp and nested fields, are removed before insertion so current fixtures can be loaded into the baseline schema. Missing table files are treated as empty. IdP `_User` fixtures are not loaded by this command.
|
|
481
495
|
|
|
482
496
|
Use `--machine-user` to override the seed plugin's `machineUserName`, the namespace migration setting, and the first configured Auth machine user for seed and assertion execution.
|
|
483
497
|
|
|
484
498
|
### Clone mode
|
|
485
499
|
|
|
486
|
-
Clone mode copies TailorDB records from the source workspace after the identical application, namespace names, and pre-migration schemas exist in the target. For namespaces without migration history, the command reproduces the deployed source schema rather than uncommitted local
|
|
500
|
+
Clone mode copies TailorDB records from the source workspace after the identical application, namespace names, and pre-migration schemas exist in the target. For namespaces without migration history, the command reproduces the deployed source schema rather than uncommitted local table changes:
|
|
487
501
|
|
|
488
502
|
```bash
|
|
489
503
|
tailor tailordb migration test --data clone
|
|
@@ -530,10 +544,10 @@ When you run `tailor deploy`, the SDK detects pending migrations (anything past
|
|
|
530
544
|
|
|
531
545
|
For each pending migration:
|
|
532
546
|
|
|
533
|
-
1. **Pre-migration**: Schema changes that would be breaking are applied in a relaxed form first. A verified in-place field type change keeps its complete previous field contract until Post-migration, including field and
|
|
547
|
+
1. **Pre-migration**: Schema changes that would be breaking are applied in a relaxed form first. A verified in-place field type change keeps its complete previous field contract until Post-migration, including field and table-level hooks or validators changed by the same migration. Newly-required fields are added as optional; fields whose `optional → required` transition is breaking are temporarily kept optional. Fields that are being removed in this migration are temporarily kept on the table so that `migrate.ts` can still read them (for example, to `innerJoin` through a foreign key that is about to be dropped). For a renamed field, the old field is kept and the new field is added with its constraints relaxed, so the script can read the old field and write the new one. For a renamed table, the new table is created with its full constraints while the old table stays on the namespace until post-migration cleanup, so the script can copy rows between them. Breaking table-level index changes are relaxed the same way: a newly-added unique index is withheld, and an index gaining a unique constraint (or a unique index changing its field set) keeps its previous definition, so `migrate.ts` can resolve duplicates first. Non-breaking changes that are part of the same migration are also applied here.
|
|
534
548
|
2. **Script execution**: If `migrate.ts` exists on disk for this migration, it is bundled and sent to the platform via the script execution API and runs as the configured machine user inside a transaction. The script is hard-required for breaking changes (`diff.requiresMigrationScript`) — deploy fails if the file is missing, unless a `--no-script` acknowledgment was recorded (see [Breaking changes without a script](#breaking-changes-without-a-script)). It is also executed when present for warning-tier diffs — see [Warnings and optional migration scripts](#warnings-and-optional-migration-scripts).
|
|
535
549
|
3. **Post-migration schema**: Required constraints and the target field definitions are applied. Do not assume that removing a field clears its underlying stored JSON value.
|
|
536
|
-
4. **Checkpoint and cleanup**: The `sdk-migration` label is bumped to this migration's number, then removed GQL permissions and tables — including
|
|
550
|
+
4. **Checkpoint and cleanup**: The `sdk-migration` label is bumped to this migration's number, then removed GQL permissions and tables — including the old table left behind by a rename — are deleted. Advancing the checkpoint first prevents a failed checkpoint write from requiring the SDK to recreate irreversibly deleted records.
|
|
537
551
|
|
|
538
552
|
This split is what allows existing rows to be backfilled before the database starts rejecting nulls, and what lets `migrate.ts` traverse foreign-key fields that the same migration removes.
|
|
539
553
|
|
|
@@ -551,7 +565,7 @@ On drift you'll see something like:
|
|
|
551
565
|
Namespace: tailordb
|
|
552
566
|
Remote migration: 0007
|
|
553
567
|
Differences:
|
|
554
|
-
|
|
568
|
+
Table 'User':
|
|
555
569
|
- Field 'email': required: remote=false, expected=true
|
|
556
570
|
```
|
|
557
571
|
|
|
@@ -565,7 +579,7 @@ tailor tailordb migration validate
|
|
|
565
579
|
|
|
566
580
|
It reports issues per namespace, exits with a non-zero code when any check fails, and supports `--json` for machine-readable output.
|
|
567
581
|
|
|
568
|
-
With `--strict`, validation additionally fails when a migration not yet applied to the remote has data-loss warnings (see [Warnings and optional migration scripts](#warnings-and-optional-migration-scripts)) but neither a `migrate.ts` nor a recorded `--no-script` acknowledgment. The failure names the affected
|
|
582
|
+
With `--strict`, validation additionally fails when a migration not yet applied to the remote has data-loss warnings (see [Warnings and optional migration scripts](#warnings-and-optional-migration-scripts)) but neither a `migrate.ts` nor a recorded `--no-script` acknowledgment. The failure names the affected table and field and prints the exact command to record the acknowledgment.
|
|
569
583
|
|
|
570
584
|
To bypass both checks during deploy (not recommended outside of recovery scenarios):
|
|
571
585
|
|
|
@@ -595,7 +609,7 @@ Before running it:
|
|
|
595
609
|
|
|
596
610
|
1. Apply the latest migration to every environment. The CLI verifies the connected workspace, but it cannot inspect other workspaces.
|
|
597
611
|
2. Commit or otherwise preserve the existing migration history. Files after `0000`, including `migrate.ts` and `db.ts`, disappear from the working tree; Git history retains committed files.
|
|
598
|
-
3. Make sure local
|
|
612
|
+
3. Make sure local table changes have been captured with `tailor tailordb migration generate`.
|
|
599
613
|
|
|
600
614
|
Then re-baseline one namespace:
|
|
601
615
|
|
|
@@ -603,7 +617,7 @@ Then re-baseline one namespace:
|
|
|
603
617
|
tailor tailordb migration rebaseline --namespace tailordb
|
|
604
618
|
```
|
|
605
619
|
|
|
606
|
-
The command validates the migration files, verifies that replaying the latest migration exactly reproduces the local
|
|
620
|
+
The command validates the migration files, verifies that replaying the latest migration exactly reproduces the local table definitions, and checks that the connected workspace is at that latest migration with no schema drift. After confirmation, it replaces the local history with the reconstructed baseline, records a new migration history ID in both `0000/schema.json` and remote metadata, and resets the connected workspace's `sdk-migration` label to `0000`. Use `--yes` only after arranging the same operational preconditions in non-interactive automation.
|
|
607
621
|
|
|
608
622
|
Commit the resulting `migrations/` change before generating any new migrations. For another environment still carrying the exact checkpoint and history ID that the new baseline replaced, the next `tailor deploy` checks whether its remote schema exactly matches the new `0000`. If it does, deploy offers to reset the checkpoint to `0000` and move the environment to the new history ID before applying any later local migrations. A markerless history is eligible only for the first rebaseline, at the exact migration recorded as replaced. Any other checkpoint or history ID is rejected without changing remote metadata, even if its schema happens to match the baseline.
|
|
609
623
|
|
|
@@ -309,11 +309,11 @@ db.string().hooks({
|
|
|
309
309
|
});
|
|
310
310
|
```
|
|
311
311
|
|
|
312
|
-
Field-level hooks operate on a single field and cannot access other fields. Use
|
|
312
|
+
Field-level hooks operate on a single field and cannot access other fields. Use table-level hooks for cross-field logic.
|
|
313
313
|
|
|
314
|
-
####
|
|
314
|
+
#### Table-level Hooks
|
|
315
315
|
|
|
316
|
-
Set hooks across multiple fields using `db.table().hooks()`. The hook returns an object with the fields to override. When both field-level and
|
|
316
|
+
Set hooks across multiple fields using `db.table().hooks()`. The hook returns an object with the fields to override. When both field-level and table-level hooks exist for the same field, table-level hooks take priority.
|
|
317
317
|
|
|
318
318
|
Create hooks receive:
|
|
319
319
|
|
|
@@ -356,7 +356,7 @@ export const order = db
|
|
|
356
356
|
});
|
|
357
357
|
```
|
|
358
358
|
|
|
359
|
-
**Note:** `.hooks()` can only be called once on a table. Duplicate
|
|
359
|
+
**Note:** `.hooks()` can only be called once on a table. Duplicate table-level calls fail at compile time and throw at runtime.
|
|
360
360
|
|
|
361
361
|
### Validation
|
|
362
362
|
|
|
@@ -380,7 +380,7 @@ db.string().validate(
|
|
|
380
380
|
);
|
|
381
381
|
```
|
|
382
382
|
|
|
383
|
-
####
|
|
383
|
+
#### Table-level Validation
|
|
384
384
|
|
|
385
385
|
Set a validator across all fields using `db.table().validate()`. The validator receives `{ newRecord, oldRecord, invoker }` and an `issues()` callback to report errors per field:
|
|
386
386
|
|
|
@@ -415,7 +415,7 @@ For datetime/date/time fields, pass `"now"` to use the operation timestamp:
|
|
|
415
415
|
db.datetime().default("now");
|
|
416
416
|
```
|
|
417
417
|
|
|
418
|
-
**Note:** `.validate()` can only be called once on a table. Duplicate
|
|
418
|
+
**Note:** `.validate()` can only be called once on a table. Duplicate table-level calls fail at compile time and throw at runtime.
|
|
419
419
|
|
|
420
420
|
### Vector Search
|
|
421
421
|
|
|
@@ -450,7 +450,7 @@ export const user = db.table("User", {
|
|
|
450
450
|
|
|
451
451
|
## Table Modifiers
|
|
452
452
|
|
|
453
|
-
Table builder methods that set one
|
|
453
|
+
Table builder methods that set one table-level configuration can be called only once on the same table. Duplicate calls fail at compile time and throw at runtime. This applies to `.description()`, `.hooks()`, `.validate()`, `.features()`, `.indexes()`, `.files()`, `.permission()`, and `.gqlPermission()`.
|
|
454
454
|
|
|
455
455
|
Conditional assignment is still supported when only one branch calls the method:
|
|
456
456
|
|
|
@@ -26,12 +26,15 @@ All workflow components must follow these rules:
|
|
|
26
26
|
- **Job name uniqueness**: Job names must be unique across the entire project (not just within one file)
|
|
27
27
|
- **mainJob required**: Every workflow must specify a `mainJob`
|
|
28
28
|
|
|
29
|
-
| Rule
|
|
30
|
-
|
|
|
31
|
-
| `createWorkflow` result must be default export
|
|
32
|
-
| All jobs must be named exports
|
|
33
|
-
| Job `name` values must be unique
|
|
34
|
-
| `mainJob` is required
|
|
29
|
+
| Rule | Description |
|
|
30
|
+
| ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
31
|
+
| `createWorkflow` result must be default export | Workflow files must export the workflow as default |
|
|
32
|
+
| All jobs must be named exports | Includes `mainJob` and any job started via `.start()` (even if referenced only within the same file) |
|
|
33
|
+
| Job `name` values must be unique | Job names must be unique across the entire project |
|
|
34
|
+
| `mainJob` is required | Every workflow must specify a `mainJob` |
|
|
35
|
+
| `createWorkflowJob`'s `name`/`body` must be written directly in the call | Not as a reference to a variable or the result of another function — the build cannot see through that indirection and fails instead of silently leaving the job out |
|
|
36
|
+
| `.start()` must be called from within the calling job's `body` | A function defined inside `body` may call it too, but not a function defined outside `body` — the build cannot see through that indirection and fails instead of silently leaving the call out |
|
|
37
|
+
| Call `<job>.start()`, not `execJobFunction` directly | Calling `tailor.workflow.execJobFunction(...)` (or the `workflow` value imported from `@tailor-platform/sdk/runtime`) directly is not detected as a dependency and fails the build |
|
|
35
38
|
|
|
36
39
|
## Creating a Workflow Job
|
|
37
40
|
|
|
@@ -481,7 +484,7 @@ An exact-key policy applies to dispatches whose runtime key equals the policy ke
|
|
|
481
484
|
|
|
482
485
|
### Referencing a Policy from a Workflow
|
|
483
486
|
|
|
484
|
-
Pass the runtime key through the `executionPolicyKey` option on `job.start()
|
|
487
|
+
Pass the runtime key through the `executionPolicyKey` option on `job.start()`. For exact-key policies, use `<policy>.key` directly — it's typed so only a value that came from a declared policy can be passed. For wildcard policies (`matchType: "prefix"`), there is no `<policy>.key` — call `<policy>.keyFor(suffix)` to build the concrete key. `keyFor` joins the prefix and suffix with `.` by default; override it with `separator` — the second argument to `defineWorkflowExecutionPolicies` (applies to every policy in the group), or a `def` field on a single `defineWorkflowExecutionPolicy`.
|
|
485
488
|
|
|
486
489
|
```typescript
|
|
487
490
|
import { createWorkflowJob } from "@tailor-platform/sdk";
|
|
@@ -507,8 +510,6 @@ export const mainJob = createWorkflowJob({
|
|
|
507
510
|
});
|
|
508
511
|
```
|
|
509
512
|
|
|
510
|
-
The same `executionPolicyKey` option is available on `tailor.workflow.execJobFunction(name, args, options)` for jobs invoked by name.
|
|
511
|
-
|
|
512
513
|
## Starting a Workflow from a Resolver
|
|
513
514
|
|
|
514
515
|
You can start a workflow execution from a resolver using `workflow.start()`.
|
package/docs/testing.md
CHANGED
|
@@ -661,7 +661,7 @@ describe("retryFailedWorkflow resolver", () => {
|
|
|
661
661
|
|
|
662
662
|
### Testing Executors
|
|
663
663
|
|
|
664
|
-
Function-kind executors expose their handler as `executor.operation.body(args)`. The shape of `args` is determined by the trigger — for example, `recordCreatedTrigger({ type: user })` produces `{ newRecord }` typed against the
|
|
664
|
+
Function-kind executors expose their handler as `executor.operation.body(args)`. The shape of `args` is determined by the trigger — for example, `recordCreatedTrigger({ type: user })` produces `{ newRecord }` typed against the table's output, plus runtime fields such as `env`, `actor`, and `invoker`. GraphQL, webhook, and workflow operation kinds are declarative and don't expose a user-authored body to test.
|
|
665
665
|
|
|
666
666
|
The `executor` template extracts shared DB access into a helper (`shared.ts`) and tests the helper directly against a mocked `tailordb.Client` (same TailorDB-mocking pattern as the resolver section). Executor handlers themselves stay thin and can be tested by spying on the helper:
|
|
667
667
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tailor-platform/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "Tailor Platform SDK - The SDK to work with Tailor Platform",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -151,7 +151,7 @@
|
|
|
151
151
|
"dependencies": {
|
|
152
152
|
"@0no-co/graphql.web": "1.3.3",
|
|
153
153
|
"@badgateway/oauth2-client": "3.3.1",
|
|
154
|
-
"@bufbuild/protobuf": "2.
|
|
154
|
+
"@bufbuild/protobuf": "2.14.0",
|
|
155
155
|
"@bufbuild/protovalidate": "1.2.0",
|
|
156
156
|
"@connectrpc/connect": "2.1.2",
|
|
157
157
|
"@connectrpc/connect-node": "2.1.2",
|
|
@@ -164,34 +164,34 @@
|
|
|
164
164
|
"@opentelemetry/resources": "2.10.0",
|
|
165
165
|
"@opentelemetry/sdk-trace-node": "2.10.0",
|
|
166
166
|
"@opentelemetry/semantic-conventions": "1.43.0",
|
|
167
|
-
"@oxc-project/types": "0.
|
|
167
|
+
"@oxc-project/types": "0.144.0",
|
|
168
168
|
"@secretlint/core": "13.0.4",
|
|
169
169
|
"@secretlint/secretlint-rule-preset-recommend": "13.0.4",
|
|
170
170
|
"@standard-schema/spec": "1.1.0",
|
|
171
171
|
"@tailor-platform/function-kysely-tailordb": "0.1.3",
|
|
172
|
-
"@toiroakr/lines-db": "0.12.
|
|
172
|
+
"@toiroakr/lines-db": "0.12.2",
|
|
173
173
|
"@toiroakr/read-multiline": "0.4.1",
|
|
174
174
|
"@urql/core": "6.0.3",
|
|
175
175
|
"amaro": "1.1.11",
|
|
176
176
|
"confbox": "0.2.4",
|
|
177
177
|
"date-fns": "4.4.0",
|
|
178
|
-
"es-toolkit": "1.
|
|
178
|
+
"es-toolkit": "1.51.0",
|
|
179
179
|
"find-up-simple": "1.0.1",
|
|
180
180
|
"get-east-asian-width": "1.6.0",
|
|
181
|
-
"get-tsconfig": "4.14.
|
|
182
|
-
"globals": "17.
|
|
181
|
+
"get-tsconfig": "4.14.2",
|
|
182
|
+
"globals": "17.11.0",
|
|
183
183
|
"graphql": "17.0.2",
|
|
184
184
|
"inflection": "3.0.2",
|
|
185
|
-
"kysely": "0.29.
|
|
185
|
+
"kysely": "0.29.5",
|
|
186
186
|
"mime-types": "3.0.2",
|
|
187
|
-
"open": "11.0.
|
|
188
|
-
"oxc-parser": "0.
|
|
187
|
+
"open": "11.0.1",
|
|
188
|
+
"oxc-parser": "0.144.0",
|
|
189
189
|
"p-limit": "7.3.1",
|
|
190
190
|
"pathe": "2.0.3",
|
|
191
191
|
"pgsql-ast-parser": "12.0.2",
|
|
192
192
|
"pkg-types": "2.3.1",
|
|
193
193
|
"politty": "0.11.6",
|
|
194
|
-
"rolldown": "1.2.
|
|
194
|
+
"rolldown": "1.2.4",
|
|
195
195
|
"semver": "7.8.5",
|
|
196
196
|
"sql-highlight": "6.1.0",
|
|
197
197
|
"std-env": "4.2.0",
|
|
@@ -207,15 +207,15 @@
|
|
|
207
207
|
"@types/semver": "7.8.0",
|
|
208
208
|
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
209
209
|
"@vitest/coverage-v8": "4.1.10",
|
|
210
|
-
"eslint-plugin-zod": "4.9.
|
|
211
|
-
"oxfmt": "0.
|
|
212
|
-
"oxlint": "1.
|
|
210
|
+
"eslint-plugin-zod": "4.9.1",
|
|
211
|
+
"oxfmt": "0.63.0",
|
|
212
|
+
"oxlint": "1.78.0",
|
|
213
213
|
"oxlint-tsgolint": "7.0.2001",
|
|
214
214
|
"sonda": "0.14.0",
|
|
215
215
|
"tsdown": "0.22.14",
|
|
216
216
|
"typescript": "6.0.3",
|
|
217
217
|
"vitest": "4.1.10",
|
|
218
|
-
"zinfer": "0.2.
|
|
218
|
+
"zinfer": "0.2.8",
|
|
219
219
|
"@tailor-platform/shared": "^0.0.0",
|
|
220
220
|
"@tailor-platform/tailor-proto": "^0.0.1"
|
|
221
221
|
},
|
|
@@ -237,7 +237,7 @@
|
|
|
237
237
|
},
|
|
238
238
|
"engines": {
|
|
239
239
|
"bun": ">=1.2.0",
|
|
240
|
-
"node": ">=22.
|
|
240
|
+
"node": ">=22.18.0"
|
|
241
241
|
},
|
|
242
242
|
"scripts": {
|
|
243
243
|
"test": "vitest",
|
package/postinstall.mjs
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
//#region src/runtime/aigateway.ts
|
|
2
|
-
const api = () => globalThis.tailor.aigateway;
|
|
3
|
-
const get = (...args) => api().get(...args);
|
|
4
|
-
/** Runtime wrapper namespace for `tailor.aigateway`. */
|
|
5
|
-
const aigateway = { get };
|
|
6
|
-
|
|
7
|
-
//#endregion
|
|
8
|
-
export { aigateway as t };
|
|
9
|
-
//# sourceMappingURL=aigateway-DR4Kwuik.mjs.map
|