@tailor-platform/sdk 2.2.0 → 2.4.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 +183 -0
- package/README.md +1 -1
- package/dist/{application-BpLeawBg.mjs → application-C8a0UJ-z.mjs} +312 -166
- package/dist/application-C8a0UJ-z.mjs.map +1 -0
- package/dist/application-D4zOiLLa.mjs +3 -0
- package/dist/cli/commands/tailordb/migrate/diff-calculator.d.mts +47 -24
- package/dist/cli/commands/tailordb/migrate/generate.d.mts +6 -0
- package/dist/cli/commands/tailordb/migrate/rename-detection.d.mts +22 -0
- package/dist/cli/commands/tailordb/migrate/snapshot-types.d.mts +1 -1
- package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +30 -11
- package/dist/cli/commands/tailordb/truncate.d.mts +2 -2
- package/dist/cli/lib.mjs +2 -2
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/main.mjs +366 -137
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/ts-hook.mjs +55 -8
- package/dist/completion/zsh-worker.zsh +38 -10
- package/dist/configure/config/index.d.mts +1 -1
- package/dist/configure/index.d.mts +3 -2
- package/dist/configure/index.mjs +92 -25
- 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 +2 -2
- package/dist/configure/services/index.d.mts +2 -2
- package/dist/configure/services/tailordb/permission.d.mts +1 -1
- package/dist/configure/services/tailordb/schema.d.mts +1 -1
- package/dist/configure/services/tailordb/types.d.mts +7 -4
- package/dist/configure/services/workflow/index.d.mts +2 -2
- package/dist/configure/services/workflow/wait-point.d.mts +72 -13
- package/dist/configure/types/auth-namespace-name.d.mts +18 -0
- package/dist/{crashreport-CINZ5dVN.mjs → crashreport-Cd4TqfZq.mjs} +1 -1
- package/dist/{crashreport-CIIfLnoO.mjs → crashreport-Q0pDAlrj.mjs} +8 -4
- package/dist/{crashreport-CIIfLnoO.mjs.map → crashreport-Q0pDAlrj.mjs.map} +1 -1
- package/dist/{errors-CWj21238.mjs → errors-Bxut5_Sy.mjs} +17 -3
- package/dist/{errors-CWj21238.mjs.map → errors-Bxut5_Sy.mjs.map} +1 -1
- package/dist/file-BUcmVIH2.mjs.map +1 -1
- package/dist/kysely/index.d.mts +2 -1
- package/dist/kysely/index.mjs +2 -1
- package/dist/kysely/index.mjs.map +1 -1
- package/dist/{logger-DSdExfor.mjs → logger-D0bEznPv.mjs} +9 -5
- package/dist/{logger-DSdExfor.mjs.map → logger-D0bEznPv.mjs.map} +1 -1
- package/dist/package-json-8b0O9TlX.mjs.map +1 -1
- package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
- package/dist/plugin/builtin/enum-constants/index.mjs +5 -5
- 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 +14 -11
- package/dist/plugin/builtin/file-utils/index.mjs.map +1 -1
- package/dist/plugin/builtin/kysely-type/index.d.mts +1 -1
- package/dist/plugin/builtin/kysely-type/index.mjs +9 -9
- package/dist/plugin/builtin/kysely-type/index.mjs.map +1 -1
- package/dist/plugin/builtin/seed/index.mjs +1 -1
- package/dist/plugin/builtin/seed/seed-type-processor.d.mts +4 -4
- package/dist/plugin/get-generated-type.d.mts +4 -4
- package/dist/plugin/index.mjs +13 -13
- package/dist/plugin/index.mjs.map +1 -1
- package/dist/plugin/types.d.mts +2 -2
- package/dist/plugin/with-context.d.mts +1 -1
- package/dist/{register-ts-hook-CTth1eqj.mjs → register-ts-hook-Vqjza10T.mjs} +2516 -857
- package/dist/register-ts-hook-Vqjza10T.mjs.map +1 -0
- package/dist/{repl-editor-BCozyiNq.mjs → repl-editor-F9LotMNx.mjs} +3 -2
- package/dist/{repl-editor-BCozyiNq.mjs.map → repl-editor-F9LotMNx.mjs.map} +1 -1
- package/dist/runtime/file.d.mts +14 -14
- package/dist/{schema--xYWRGfe.mjs → schema-D4TC4BC3.mjs} +4 -3
- package/dist/schema-D4TC4BC3.mjs.map +1 -0
- package/dist/seed/index.d.mts +4 -4
- package/dist/seed/index.mjs +3 -3
- package/dist/seed/index.mjs.map +1 -1
- package/dist/{seed-xqM9WIHP.mjs → seed-Cibjmtry.mjs} +46 -40
- package/dist/seed-Cibjmtry.mjs.map +1 -0
- package/dist/{service-goqlJJgA.mjs → service-2grcAOCJ.mjs} +61 -27
- package/dist/service-2grcAOCJ.mjs.map +1 -0
- package/dist/service-CaBPNDIZ.mjs +3 -0
- package/dist/{service-CCwl3Avt.mjs → service-LTfp03ZZ.mjs} +7 -5
- package/dist/{service-CCwl3Avt.mjs.map → service-LTfp03ZZ.mjs.map} +1 -1
- 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 +1 -1
- package/dist/types/tailordb.generated.d.mts +12 -12
- package/dist/utils/test/index.d.mts +4 -4
- package/dist/utils/test/index.mjs +4 -4
- package/dist/utils/test/index.mjs.map +1 -1
- package/dist/vitest/index.mjs +95 -7
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/vitest/mocks/workflow.d.mts +13 -1
- package/dist/wait-point-invoker-__oE88_P.mjs +148 -0
- package/dist/wait-point-invoker-__oE88_P.mjs.map +1 -0
- package/dist/wait-point-registry-TL99zotw.mjs +47 -0
- package/dist/wait-point-registry-TL99zotw.mjs.map +1 -0
- package/docs/cli/application.md +3 -1
- package/docs/cli/function.md +17 -13
- package/docs/cli/setup.md +14 -1
- package/docs/cli/tailordb.md +30 -27
- 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 +73 -28
- package/docs/migration/v2.md +58 -4
- package/docs/migration/v3.md +41 -0
- 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 +146 -44
- package/docs/services/tailordb.md +7 -7
- package/docs/services/workflow.md +52 -2
- package/docs/testing.md +13 -1
- package/package.json +8 -8
- package/dist/application-BpLeawBg.mjs.map +0 -1
- package/dist/application-BxLLiLsr.mjs +0 -3
- package/dist/register-ts-hook-CTth1eqj.mjs.map +0 -1
- package/dist/schema--xYWRGfe.mjs.map +0 -1
- package/dist/seed-xqM9WIHP.mjs.map +0 -1
- package/dist/service-_XmjSEGr.mjs +0 -3
- package/dist/service-goqlJJgA.mjs.map +0 -1
- package/dist/test-env-key-D7UkZp99.mjs +0 -75
- package/dist/test-env-key-D7UkZp99.mjs.map +0 -1
|
@@ -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
|
|
|
@@ -115,7 +115,7 @@ A typical change cycle:
|
|
|
115
115
|
|
|
116
116
|
### Warnings and optional migration scripts
|
|
117
117
|
|
|
118
|
-
Some non-breaking changes can still cause data loss — most notably removing a field (`field_removed`) or removing a table (`
|
|
118
|
+
Some non-breaking changes can still cause data loss — most notably removing a field (`field_removed`) or removing a table (`table_removed`). `migration generate` reports these as **warnings**:
|
|
119
119
|
|
|
120
120
|
```
|
|
121
121
|
Warning: data loss possible:
|
|
@@ -139,6 +139,58 @@ tailor tailordb migration script 0002 --no-script --reason "column no longer nee
|
|
|
139
139
|
|
|
140
140
|
In an interactive session, `migration generate` offers to record the reason on the spot when it detects warnings. The acknowledgment is stored in `diff.json`, so it is reviewable in the PR, and it satisfies `migration validate --strict` — useful for enforcing in CI that destructive changes are explicitly acknowledged before merge (see [Schema verification](#schema-verification)).
|
|
141
141
|
|
|
142
|
+
### Renaming a field
|
|
143
|
+
|
|
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
|
+
|
|
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
|
+
|
|
148
|
+
```
|
|
149
|
+
? User.fullName was removed and displayName was added with a compatible type. Was it renamed to displayName? (Y/n)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
In non-interactive environments (or with `--yes`), no prompt is shown and the command fails while a rename candidate is left unresolved — writing it as remove + add would silently drop the field's data at deploy. Resolve every candidate explicitly: pass the rename, or confirm a genuine removal with `--drop`:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
tailor tailordb migration generate --rename "User.fullName:displayName"
|
|
156
|
+
tailor tailordb migration generate --drop "User.fullName"
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Repeat `--rename` and `--drop` for multiple fields. A `--rename` that does not match a compatible removed + added pair, or a `--drop` that does not match a removed field, fails with an error.
|
|
160
|
+
|
|
161
|
+
A confirmed rename is recorded as a single `field_renamed` change and treated as **breaking**, so a migration script is required. The generated `migrate.ts` copies the old field into the new one with a single set-based update, and the generated `db.ts` exposes both the old field (readable) and the new field (writable). The copy intentionally overwrites every row without checking for existing values: values of removed fields are retained in storage, so a stale value could otherwise resurface under the new name later. If the new field adds a unique constraint, the script also includes a duplicate-resolution block to run before the constraint is enforced.
|
|
162
|
+
|
|
163
|
+
During deploy, the pre-migration phase keeps the old field and adds the new field with its constraints relaxed, the script copies the data, and the post-migration phase drops the old field and enforces the new field's constraints — all within a single `tailor deploy`.
|
|
164
|
+
|
|
165
|
+
If you decline the prompt (or confirm the removal with `--drop`), the change stays a plain removal + addition with the usual data-loss warning.
|
|
166
|
+
|
|
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
|
+
|
|
169
|
+
### Renaming a table
|
|
170
|
+
|
|
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
|
+
|
|
173
|
+
```
|
|
174
|
+
? User was removed and Person was added with a compatible schema. Was it renamed to Person? (Y/n)
|
|
175
|
+
```
|
|
176
|
+
|
|
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
|
+
|
|
179
|
+
```bash
|
|
180
|
+
tailor tailordb migration generate --rename "User:Person"
|
|
181
|
+
tailor tailordb migration generate --drop "User"
|
|
182
|
+
```
|
|
183
|
+
|
|
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
|
+
|
|
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
|
+
|
|
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
|
+
|
|
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
|
+
|
|
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
|
+
|
|
142
194
|
### Breaking changes without a script
|
|
143
195
|
|
|
144
196
|
Breaking changes require `migrate.ts`. If it is missing at deploy time (for example, the generated script was deleted), `tailor deploy` fails before applying the migration or anything after it. When there is genuinely nothing to migrate — say, the affected table holds no data yet — record an explicit acknowledgment instead of keeping an empty script:
|
|
@@ -147,7 +199,7 @@ Breaking changes require `migrate.ts`. If it is missing at deploy time (for exam
|
|
|
147
199
|
tailor tailordb migration script 0002 --no-script --reason "no data yet, safe to skip"
|
|
148
200
|
```
|
|
149
201
|
|
|
150
|
-
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,
|
|
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.
|
|
151
203
|
|
|
152
204
|
## Configuration
|
|
153
205
|
|
|
@@ -187,7 +239,7 @@ export default defineConfig({
|
|
|
187
239
|
|
|
188
240
|
### Migration file format compatibility
|
|
189
241
|
|
|
190
|
-
Migration files are versioned independently of the SDK package. This SDK writes format version `
|
|
242
|
+
Migration files are versioned independently of the SDK package. This SDK writes format version `3` and reads versions `1` through `3`. It normalizes supported older formats in memory; it never rewrites applied migration files on disk.
|
|
191
243
|
|
|
192
244
|
If a future SDK can no longer replay an old migration format, re-baseline while using an SDK version that still supports the complete history, commit the new baseline, deploy it to every environment, and then upgrade the SDK. A file from a newer unsupported format instead requires upgrading the SDK first. The CLI rejects both cases with guidance rather than attempting a best-effort replay.
|
|
193
245
|
|
|
@@ -268,29 +320,56 @@ The `env` values are injected at bundle time (the same mechanism as resolvers/ex
|
|
|
268
320
|
|
|
269
321
|
## Supported Schema Changes
|
|
270
322
|
|
|
271
|
-
| Change Type | Breaking? | Migration Script? | Notes
|
|
272
|
-
| --------------------------------- | --------- | ----------------- |
|
|
273
|
-
| Add optional field | No | No | Schema change only
|
|
274
|
-
| Add required field | Yes | Yes | Script populates default values
|
|
275
|
-
| 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.
|
|
276
|
-
|
|
|
277
|
-
| Change
|
|
278
|
-
|
|
|
279
|
-
| Add unique
|
|
280
|
-
|
|
|
281
|
-
|
|
|
282
|
-
|
|
|
283
|
-
|
|
|
284
|
-
|
|
|
285
|
-
|
|
|
286
|
-
|
|
|
287
|
-
|
|
|
288
|
-
|
|
|
289
|
-
|
|
|
290
|
-
|
|
|
291
|
-
| Change
|
|
292
|
-
| Change
|
|
293
|
-
| Change
|
|
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 "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. |
|
|
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 "OldTable:NewTable"` — see [Renaming a table](#renaming-a-table). Auto-generated script copies all rows preserving ids; both tables coexist until post-migration cleanup. |
|
|
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) |
|
|
348
|
+
|
|
349
|
+
### Field type changes
|
|
350
|
+
|
|
351
|
+
These pairs change in place, in a single migration:
|
|
352
|
+
|
|
353
|
+
| From | To |
|
|
354
|
+
| --------- | ---------------------------- |
|
|
355
|
+
| `integer` | `string`, `float`, `decimal` |
|
|
356
|
+
| `float` | `string`, `decimal` |
|
|
357
|
+
| `decimal` | `string`, `float` |
|
|
358
|
+
| `boolean` | `string` |
|
|
359
|
+
| `uuid` | `string` |
|
|
360
|
+
| `enum` | `string` |
|
|
361
|
+
|
|
362
|
+
Every pair here accepts every value its source type allows, which is what lets the change happen in one migration: the field keeps its previous type until the migration finishes, so your application can keep writing to it throughout.
|
|
363
|
+
|
|
364
|
+
Every other scalar pair needs a temporary field. Eligible fields can use the generated [expand-contract pair](#converting-a-field-type); fields the generator rejects still need the manual three-step sequence described below. Three groups are worth calling out:
|
|
365
|
+
|
|
366
|
+
- Converting to a narrower type — `string` → `integer`, `string` → `uuid`, `integer` → `boolean` and similar — is excluded because values the source type still accepts, such as `"abc"` in a `string` field, cannot be cast. Your script could clean up the rows it sees, but the field goes on accepting new uncastable values until the migration completes.
|
|
367
|
+
- `boolean` → `integer`, `float` → `integer`, and `string` → `date` are excluded because the stored values cannot be cast to the new type.
|
|
368
|
+
- `date`, `datetime`, and `time` fields are not stored in the textual form you wrote them in, so converting them to or from another type reads back as a different instant. Convert them through a temporary field where your script controls the formatting.
|
|
369
|
+
|
|
370
|
+
Converting to `decimal` reformats values to the field's scale, so `42` reads back as `42.000000`. Values with more decimal places than the scale allows are rounded half-up, so `1.1234567` becomes `1.123457` at the default scale of 6.
|
|
371
|
+
|
|
372
|
+
A `float` field that is already unique cannot convert to `decimal` in place, because rounding can turn two distinct values into the same one and the existing constraint leaves no room to resolve the collision. Use the 3-step migration for those.
|
|
294
373
|
|
|
295
374
|
### Generated normalization script for field type changes
|
|
296
375
|
|
|
@@ -337,17 +416,40 @@ export async function main(trx: Transaction): Promise<void> {
|
|
|
337
416
|
|
|
338
417
|
The generated `never` annotation intentionally causes a TypeScript error until you review the normalization. If the existing values are already suitable for the target type, remove the annotation and review marker to accept the identity transformation; it does not write any rows. If values need application-specific normalization, replace the expression and remove the annotation and marker while keeping the result valid for both the active source type and the target type. The source field contract remains active until the script finishes; for example, an `integer` → `float` script cannot write fractional values during this phase.
|
|
339
418
|
|
|
340
|
-
###
|
|
419
|
+
### Converting a field type
|
|
420
|
+
|
|
421
|
+
A field type change outside the verified in-place pairs — `string` → `integer`, for example — cannot be applied in one step, because the field would have to hold both shapes at once. `migration generate` offers to carry the values through a temporary field instead:
|
|
422
|
+
|
|
423
|
+
```
|
|
424
|
+
User.price changes from string to integer, which cannot be applied in one step.
|
|
425
|
+
? Generate two migrations to convert User.price through a temporary field? (Y/n)
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
Confirming writes two migrations:
|
|
429
|
+
|
|
430
|
+
1. **The conversion.** Adds a temporary field (`priceMigrate`), converts each stored value into it, and clears and removes the original field. Edit the conversion expression before deploying: the generated `never` annotation fails your typecheck, and `tailordb migration validate` rejects the migration while the review marker is still there.
|
|
431
|
+
2. **The rename.** Renames the temporary field back to `price`. Its copy script is complete, but this migration also carries every other schema change the same run picked up, so review it as you would any generated migration.
|
|
432
|
+
|
|
433
|
+
`tailor deploy` applies both. Because the conversion only touches rows whose original value is still set, a re-run resumes where it stopped rather than converting a row twice.
|
|
434
|
+
|
|
435
|
+
The original field is removed in the first migration rather than the second, because the rename needs its name free. Your script can still read it while the conversion runs.
|
|
436
|
+
|
|
437
|
+
In a non-interactive run — `--yes`, or CI — name each field explicitly:
|
|
438
|
+
|
|
439
|
+
```bash
|
|
440
|
+
tailor tailordb migration generate --yes --expand-contract "User.price"
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
Without the flag the command fails rather than converting anything, so a scripted run cannot start a two-migration change by accident.
|
|
341
444
|
|
|
342
|
-
|
|
445
|
+
> **Why the conversion clears the original field.** Removing a field from the schema does not necessarily remove its stored value. Reusing the name for an incompatible type while a stale value remains can deploy successfully and then make subsequent reads fail. Clearing the original in the same update is what prevents that, which is why the generated script writes both fields at once.
|
|
343
446
|
|
|
344
|
-
|
|
345
|
-
2. **Migration N+1**: Remove the old field.
|
|
346
|
-
3. **Migration N+2**: Add the field back with the original name and the new type. Script copies from the temporary field, then remove the temporary field in migration N+3 (or in the same step if you can express it).
|
|
447
|
+
> **Writes that land while the conversion runs are not carried across.** The original field keeps its old type until the conversion finishes, so an application can still write to it after the script has read the last row — and that value is dropped with the field rather than converted. Stop writes to the field, or accept the loss, before deploying a conversion on a live workspace.
|
|
347
448
|
|
|
348
|
-
|
|
449
|
+
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:
|
|
349
450
|
|
|
350
|
-
|
|
451
|
+
- 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 table-level script names. Those keep pointing at the original name, which the conversion removes.
|
|
351
453
|
|
|
352
454
|
## Testing Pending Migrations
|
|
353
455
|
|
|
@@ -363,25 +465,25 @@ The command performs the following sequence:
|
|
|
363
465
|
6. Optionally runs an assertion script against the migrated data.
|
|
364
466
|
7. Deletes an automatically-created workspace after success or failure.
|
|
365
467
|
|
|
366
|
-
Both the pre-migration and final TailorDB schemas come from committed migration snapshots. Ungenerated changes in the current
|
|
468
|
+
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.
|
|
367
469
|
|
|
368
470
|
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.
|
|
369
471
|
|
|
370
472
|
### Seed mode
|
|
371
473
|
|
|
372
|
-
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
|
|
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 tables, then populate its `data/*.jsonl` files:
|
|
373
475
|
|
|
374
476
|
```bash
|
|
375
477
|
tailor tailordb migration test --data seed
|
|
376
478
|
```
|
|
377
479
|
|
|
378
|
-
Rows are loaded only for
|
|
480
|
+
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.
|
|
379
481
|
|
|
380
482
|
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.
|
|
381
483
|
|
|
382
484
|
### Clone mode
|
|
383
485
|
|
|
384
|
-
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
|
|
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 table changes:
|
|
385
487
|
|
|
386
488
|
```bash
|
|
387
489
|
tailor tailordb migration test --data clone
|
|
@@ -428,10 +530,10 @@ When you run `tailor deploy`, the SDK detects pending migrations (anything past
|
|
|
428
530
|
|
|
429
531
|
For each pending migration:
|
|
430
532
|
|
|
431
|
-
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
|
|
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 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.
|
|
432
534
|
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).
|
|
433
535
|
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.
|
|
434
|
-
4. **Checkpoint and cleanup**: The `sdk-migration` label is bumped to this migration's number, then removed GQL permissions and tables are deleted. Advancing the checkpoint first prevents a failed checkpoint write from requiring the SDK to recreate irreversibly deleted records.
|
|
536
|
+
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.
|
|
435
537
|
|
|
436
538
|
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.
|
|
437
539
|
|
|
@@ -449,7 +551,7 @@ On drift you'll see something like:
|
|
|
449
551
|
Namespace: tailordb
|
|
450
552
|
Remote migration: 0007
|
|
451
553
|
Differences:
|
|
452
|
-
|
|
554
|
+
Table 'User':
|
|
453
555
|
- Field 'email': required: remote=false, expected=true
|
|
454
556
|
```
|
|
455
557
|
|
|
@@ -463,7 +565,7 @@ tailor tailordb migration validate
|
|
|
463
565
|
|
|
464
566
|
It reports issues per namespace, exits with a non-zero code when any check fails, and supports `--json` for machine-readable output.
|
|
465
567
|
|
|
466
|
-
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
|
|
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 table and field and prints the exact command to record the acknowledgment.
|
|
467
569
|
|
|
468
570
|
To bypass both checks during deploy (not recommended outside of recovery scenarios):
|
|
469
571
|
|
|
@@ -493,7 +595,7 @@ Before running it:
|
|
|
493
595
|
|
|
494
596
|
1. Apply the latest migration to every environment. The CLI verifies the connected workspace, but it cannot inspect other workspaces.
|
|
495
597
|
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.
|
|
496
|
-
3. Make sure local
|
|
598
|
+
3. Make sure local table changes have been captured with `tailor tailordb migration generate`.
|
|
497
599
|
|
|
498
600
|
Then re-baseline one namespace:
|
|
499
601
|
|
|
@@ -501,7 +603,7 @@ Then re-baseline one namespace:
|
|
|
501
603
|
tailor tailordb migration rebaseline --namespace tailordb
|
|
502
604
|
```
|
|
503
605
|
|
|
504
|
-
The command validates the migration files, verifies that replaying the latest migration exactly reproduces the local
|
|
606
|
+
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.
|
|
505
607
|
|
|
506
608
|
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.
|
|
507
609
|
|
|
@@ -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
|
|
|
@@ -248,6 +248,8 @@ export const approval = createWaitPoint<
|
|
|
248
248
|
>("approval");
|
|
249
249
|
```
|
|
250
250
|
|
|
251
|
+
Keys must match `[a-z0-9-]`, be 3 to 63 characters long, and start and end with `[a-z0-9]`.
|
|
252
|
+
|
|
251
253
|
For multiple wait points, use `createWaitPoints` with a builder callback. Property names become wait point keys, and JSDoc on each property is preserved in IDE autocompletion:
|
|
252
254
|
|
|
253
255
|
```typescript
|
|
@@ -255,9 +257,19 @@ import { createWaitPoints } from "@tailor-platform/sdk";
|
|
|
255
257
|
|
|
256
258
|
export const waitPoints = createWaitPoints((define) => ({
|
|
257
259
|
/** Manager approval step */
|
|
258
|
-
|
|
260
|
+
"manager-approval": define<{ amount: number }, { approved: boolean }>(),
|
|
259
261
|
/** Finance review step */
|
|
260
|
-
|
|
262
|
+
"finance-review": define<{ invoiceId: string }, { validated: boolean }>(),
|
|
263
|
+
}));
|
|
264
|
+
|
|
265
|
+
await waitPoints["manager-approval"].wait({ amount: 50000 });
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Pass the key to `define` when the property name you want to read at the call site is not a valid key:
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
export const waitPoints = createWaitPoints((define) => ({
|
|
272
|
+
managerApproval: define.for("manager-approval")<{ amount: number }, { approved: boolean }>(),
|
|
261
273
|
}));
|
|
262
274
|
|
|
263
275
|
await waitPoints.managerApproval.wait({ amount: 50000 });
|
|
@@ -335,6 +347,44 @@ export default createResolver({
|
|
|
335
347
|
|
|
336
348
|
Wait points can be imported and used in any file (workflow jobs, resolvers, executors). For local testing, see [Jobs that wait on approval](../testing.md#jobs-that-wait-on-approval) in the testing guide.
|
|
337
349
|
|
|
350
|
+
### Keys With Runtime Values
|
|
351
|
+
|
|
352
|
+
A wait point key identifies one suspension inside one execution. When a job suspends more than once for the same reason — one approval per order line, one per approver — every suspension needs its own key, otherwise the second `wait()` fails because a suspension with that key is already pending.
|
|
353
|
+
|
|
354
|
+
Write `$paramName` as a whole `-`-delimited segment of the key to leave a slot for a runtime value — `line-approval-$lineId` works, `line-approval$lineId` does not. Declare such a key through `createWaitPoints`, passing it to `define` **before** the `Payload` and `Result` type arguments — the param names then become the argument of `.with()`, which builds the concrete key:
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
export const { lineApproval } = createWaitPoints((define) => ({
|
|
358
|
+
lineApproval: define.for("line-approval-$lineId")<{ message: string }, { approved: boolean }>(),
|
|
359
|
+
}));
|
|
360
|
+
|
|
361
|
+
// Suspends on "line-approval-<lineId>", so parallel lines never collide
|
|
362
|
+
const result = await lineApproval.with({ lineId: line.id }).wait({ message: "Please approve" });
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
The key has to come before the type arguments because TypeScript stops inferring it as a literal type once `Payload` and `Result` are given explicitly, and the param names can only be read off a literal. `createWaitPoint` takes its type arguments first, so it cannot type `$params` at all, and `deploy` rejects such a key — one wait point per key is what it is for, and a key with `$params` stands for a family of them.
|
|
366
|
+
|
|
367
|
+
`deploy` checks every declared key against the grammar above, so a key the platform would reject is reported before anything is deployed.
|
|
368
|
+
|
|
369
|
+
A parameterized wait point exposes only `.with()` — there is no way to wait on the unsubstituted key.
|
|
370
|
+
|
|
371
|
+
Resolve it from the same param values:
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
await lineApproval.with({ lineId: input.lineId }).resolve(input.executionId, (payload) => {
|
|
375
|
+
console.log("Resolving:", payload.message);
|
|
376
|
+
return { approved: input.approved };
|
|
377
|
+
});
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
Rules to keep in mind:
|
|
381
|
+
|
|
382
|
+
- Param values must match `[a-z0-9-]`, cannot be empty, and cannot start or end with `-`. Record IDs work as-is; uppercase or underscored values do not.
|
|
383
|
+
- The composed key still has to fit 63 characters. A UUID takes 36, so a key holding one leaves 26 characters for everything else.
|
|
384
|
+
- The key needs at least one literal segment alongside its `$params`, so `"$lineId"` alone is rejected: a key made only of caller data carries no identity of its own.
|
|
385
|
+
- Param values are part of the key, so they must be derived from the job's input. A value from `Date.now()` or `Math.random()` changes when the platform replays the job and the execution fails.
|
|
386
|
+
- Keys are compared exactly, and the SDK does not check whether two declared keys can produce the same string. `"a-$x"` with `x = "b-c"` and `"a-b-$y"` with `y = "c"` both produce `a-b-c`. Keep the literal part of each key distinct, and prefer putting `$params` last.
|
|
387
|
+
|
|
338
388
|
## Retry Policy
|
|
339
389
|
|
|
340
390
|
You can configure automatic retry behavior with exponential backoff by setting `retryPolicy` on a workflow. All fields are required when `retryPolicy` is set:
|
package/docs/testing.md
CHANGED
|
@@ -180,6 +180,18 @@ await approvalWaitPoint.wait({ message: "Please approve" });
|
|
|
180
180
|
expect(approvalMock.wait).toHaveBeenCalledWith({ message: "Please approve" });
|
|
181
181
|
```
|
|
182
182
|
|
|
183
|
+
For a wait point whose key contains `$params`, use `waitPointWith(definition, params)` to control one param binding at a time. Calls made with any other binding fall through to the platform mock:
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
using wf = mockWorkflow();
|
|
187
|
+
const lineOne = wf.waitPointWith(lineApproval, { lineId: "line-1" });
|
|
188
|
+
|
|
189
|
+
lineOne.wait.mockResolvedValue({ approved: true });
|
|
190
|
+
await lineApproval.with({ lineId: "line-1" }).wait({ message: "Please approve" });
|
|
191
|
+
|
|
192
|
+
expect(lineOne.wait).toHaveBeenCalledWith({ message: "Please approve" });
|
|
193
|
+
```
|
|
194
|
+
|
|
183
195
|
Use `wf.setEnv(...)` when locally-run workflow job bodies need configuration values. Per-run `runWorkflowLocally(..., { env })` options take precedence over the mock's env.
|
|
184
196
|
|
|
185
197
|
### SecretManager Mock
|
|
@@ -649,7 +661,7 @@ describe("retryFailedWorkflow resolver", () => {
|
|
|
649
661
|
|
|
650
662
|
### Testing Executors
|
|
651
663
|
|
|
652
|
-
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.
|
|
653
665
|
|
|
654
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:
|
|
655
667
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tailor-platform/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Tailor Platform SDK - The SDK to work with Tailor Platform",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -169,7 +169,7 @@
|
|
|
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.
|
|
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",
|
|
@@ -191,7 +191,7 @@
|
|
|
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,7 +207,7 @@
|
|
|
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.
|
|
210
|
+
"eslint-plugin-zod": "4.9.1",
|
|
211
211
|
"oxfmt": "0.61.0",
|
|
212
212
|
"oxlint": "1.76.0",
|
|
213
213
|
"oxlint-tsgolint": "7.0.2001",
|
|
@@ -215,9 +215,9 @@
|
|
|
215
215
|
"tsdown": "0.22.14",
|
|
216
216
|
"typescript": "6.0.3",
|
|
217
217
|
"vitest": "4.1.10",
|
|
218
|
-
"zinfer": "0.2.
|
|
219
|
-
"@tailor-platform/
|
|
220
|
-
"@tailor-platform/
|
|
218
|
+
"zinfer": "0.2.8",
|
|
219
|
+
"@tailor-platform/shared": "^0.0.0",
|
|
220
|
+
"@tailor-platform/tailor-proto": "^0.0.1"
|
|
221
221
|
},
|
|
222
222
|
"peerDependencies": {
|
|
223
223
|
"@electric-sql/pglite": ">=0.2.0",
|
|
@@ -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",
|