@tailor-platform/sdk 2.15.0 → 2.17.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 +109 -0
- package/dist/{application-BpoMu4Af.mjs → application-ChuNPwnl.mjs} +28 -28
- package/dist/application-ChuNPwnl.mjs.map +1 -0
- package/dist/application-Oh5dMmb5.mjs +1 -0
- package/dist/cli/commands/executor/jobs.d.mts +1 -0
- package/dist/cli/commands/generate/seed/bundler.d.mts +18 -0
- package/dist/cli/commands/tailordb/migrate/config.d.mts +1 -0
- package/dist/cli/commands/tailordb/migrate/snapshot-files.d.mts +5 -1
- package/dist/cli/commands/tailordb/migrate/snapshot.d.mts +2 -2
- package/dist/cli/commands/workflow/waiter.d.mts +1 -0
- package/dist/cli/commands/workspace/create.d.mts +16 -1
- package/dist/cli/commands/workspace/expiry.d.mts +5 -0
- package/dist/cli/commands/workspace/get.d.mts +6 -1
- package/dist/cli/commands/workspace/list.d.mts +1 -0
- package/dist/cli/lib.d.mts +4 -3
- package/dist/cli/lib.mjs +1 -1
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/cli/main.mjs +57 -59
- package/dist/cli/main.mjs.map +1 -1
- package/dist/cli/shared/command.d.mts +1 -1
- package/dist/cli/shared/error-json.d.mts +21 -1
- package/dist/cli/shared/errors.d.mts +1 -0
- package/dist/cli/shared/github-actions.d.mts +13 -0
- package/dist/cli/shared/logger.d.mts +18 -0
- package/dist/completion/zsh-worker.zsh +92 -4
- package/dist/configure/index.mjs +1 -1
- package/dist/configure/index.mjs.map +1 -1
- package/dist/crashreport-CgymxQDu.mjs +1 -0
- package/dist/crashreport-Cyuz1qiu.mjs +42 -0
- package/dist/crashreport-Cyuz1qiu.mjs.map +1 -0
- package/dist/errors-BjJnpXkK.mjs +7 -0
- package/dist/errors-BjJnpXkK.mjs.map +1 -0
- package/dist/field-parse-CzlKC4b7.mjs +2 -0
- package/dist/field-parse-CzlKC4b7.mjs.map +1 -0
- package/dist/guards-ForsrxnH.mjs +2 -0
- package/dist/guards-ForsrxnH.mjs.map +1 -0
- package/dist/kysely-type-B_oA8D1k.mjs +43 -0
- package/dist/kysely-type-B_oA8D1k.mjs.map +1 -0
- package/dist/{logger-CCjs1DuH.mjs → logger-72hM4JWZ.mjs} +4 -4
- package/dist/logger-72hM4JWZ.mjs.map +1 -0
- package/dist/manager-C26Gi1bX.mjs +2 -0
- package/dist/manager-C26Gi1bX.mjs.map +1 -0
- package/dist/node-builtins-DYfhPBnz.mjs +2 -0
- package/dist/node-builtins-DYfhPBnz.mjs.map +1 -0
- package/dist/plugin/builtin/kysely-type/index.d.mts +2 -0
- package/dist/plugin/builtin/kysely-type/index.mjs +1 -1
- package/dist/plugin/builtin/seed/index.mjs +1 -1
- package/dist/plugin/builtin/seed/seed-type-processor.d.mts +17 -0
- package/dist/plugin/get-generated-table.d.mts +13 -0
- package/dist/plugin/index.d.mts +2 -2
- package/dist/plugin/index.mjs +1 -1
- package/dist/plugin/index.mjs.map +1 -1
- package/dist/register-ts-hook-Dn-XlVSD.mjs +917 -0
- package/dist/register-ts-hook-Dn-XlVSD.mjs.map +1 -0
- package/dist/schema-DRyQEabV.mjs +2 -0
- package/dist/schema-DRyQEabV.mjs.map +1 -0
- package/dist/{seed-CCc9Xk66.mjs → seed-C3P_T_Eh.mjs} +28 -9
- package/dist/seed-C3P_T_Eh.mjs.map +1 -0
- package/dist/service-B3OiWCYg.mjs +1 -0
- package/dist/service-B4Gh_bbL.mjs +2 -0
- package/dist/service-B4Gh_bbL.mjs.map +1 -0
- package/dist/service-eM7Fd8zS.mjs +7 -0
- package/dist/service-eM7Fd8zS.mjs.map +1 -0
- package/dist/tailordb-ddl-Fgm2cNvT.mjs +7 -0
- package/dist/tailordb-ddl-Fgm2cNvT.mjs.map +1 -0
- package/dist/utils/test/index.d.mts +7 -5
- package/dist/utils/test/index.mjs +1 -1
- package/dist/utils/test/index.mjs.map +1 -1
- package/dist/vitest/index.mjs +1 -1
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/vitest/mocks/tailordb-pglite.d.mts +5 -4
- package/docs/cli/tailordb.md +9 -9
- package/docs/cli/workspace.md +133 -20
- package/docs/cli-reference.md +101 -28
- package/docs/plugin/custom.md +36 -4
- package/docs/services/tailordb-migration.md +31 -28
- package/docs/testing.md +23 -21
- package/package.json +11 -10
- package/dist/application-BpoMu4Af.mjs.map +0 -1
- package/dist/application-fIhVKX78.mjs +0 -1
- package/dist/crashreport-BN28xp5B.mjs +0 -42
- package/dist/crashreport-BN28xp5B.mjs.map +0 -1
- package/dist/crashreport-By23O2k-.mjs +0 -1
- package/dist/errors-BlX4gUw5.mjs +0 -4
- package/dist/errors-BlX4gUw5.mjs.map +0 -1
- package/dist/field-column-type-QMtF6lUp.mjs +0 -2
- package/dist/field-column-type-QMtF6lUp.mjs.map +0 -1
- package/dist/kysely-type-B-BOlXH7.mjs +0 -43
- package/dist/kysely-type-B-BOlXH7.mjs.map +0 -1
- package/dist/logger-CCjs1DuH.mjs.map +0 -1
- package/dist/node-builtins-TQHhwNzG.mjs +0 -2
- package/dist/node-builtins-TQHhwNzG.mjs.map +0 -1
- package/dist/register-ts-hook-CAUcxCt4.mjs +0 -711
- package/dist/register-ts-hook-CAUcxCt4.mjs.map +0 -1
- package/dist/schema-BTioi2dP.mjs +0 -2
- package/dist/schema-BTioi2dP.mjs.map +0 -1
- package/dist/seed-CCc9Xk66.mjs.map +0 -1
- package/dist/service-7SCy2bhm.mjs +0 -7
- package/dist/service-7SCy2bhm.mjs.map +0 -1
- package/dist/service-CWFQ8EVo.mjs +0 -1
- package/dist/service-CqbQXFDp.mjs +0 -2
- package/dist/service-CqbQXFDp.mjs.map +0 -1
|
@@ -24,7 +24,8 @@ migrations/
|
|
|
24
24
|
├── 0001/ # First change
|
|
25
25
|
│ ├── diff.json # Field-level diff from 0000
|
|
26
26
|
│ ├── migrate.ts # Data migration script (auto-generated for breaking changes; can be added manually via `migration script`)
|
|
27
|
-
│
|
|
27
|
+
│ ├── db.ts # Kysely types for the script (pre-migration shape)
|
|
28
|
+
│ └── db.pglite.ts # CREATE TABLE script of that shape, for PGlite tests
|
|
28
29
|
├── 0002/
|
|
29
30
|
│ └── diff.json # No script — non-breaking changes only
|
|
30
31
|
└── ...
|
|
@@ -129,7 +130,7 @@ No `migrate.ts` is generated automatically because the schema change itself is n
|
|
|
129
130
|
tailor tailordb migration script 0002
|
|
130
131
|
```
|
|
131
132
|
|
|
132
|
-
This writes `migrations/0002/migrate.ts` and `migrations/0002/db.ts` next to the existing `diff.json` (add `--with-test` to also scaffold
|
|
133
|
+
This writes `migrations/0002/migrate.ts`, `migrations/0002/db.ts`, and `migrations/0002/db.pglite.ts` next to the existing `diff.json` (add `--with-test` to also scaffold the tests — see [Testing Migrations Locally](#testing-migrations-locally)). The removed field stays readable inside `migrate.ts` because the pre-migration phase keeps it on the table until the script finishes (see [Per-migration phases](#per-migration-phases)). The next `tailor deploy` runs the script automatically — `migrate.ts` is executed whenever the file exists on disk, regardless of whether the diff itself required it.
|
|
133
134
|
|
|
134
135
|
If the data loss is intentional and no script is needed, record that decision the same way as for breaking changes (see [Breaking changes without a script](#breaking-changes-without-a-script)):
|
|
135
136
|
|
|
@@ -267,13 +268,15 @@ export default defineConfig({
|
|
|
267
268
|
|
|
268
269
|
## Generated Files
|
|
269
270
|
|
|
270
|
-
| File
|
|
271
|
-
|
|
|
272
|
-
| `0000/schema.json`
|
|
273
|
-
| `XXXX/diff.json`
|
|
274
|
-
| `XXXX/migrate.ts`
|
|
275
|
-
| `XXXX/db.ts`
|
|
276
|
-
| `XXXX/
|
|
271
|
+
| File | When generated | Description |
|
|
272
|
+
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
|
|
273
|
+
| `0000/schema.json` | First `migration generate` | Full snapshot of all tables in the namespace. |
|
|
274
|
+
| `XXXX/diff.json` | Every subsequent migration | Field-level diff against the previous snapshot. |
|
|
275
|
+
| `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`. |
|
|
276
|
+
| `XXXX/db.ts` | Generated once when `migrate.ts` is created | Kysely types reflecting the schema **before** this migration. Exports `Database`, `Transaction`, and `MigrationContext`. |
|
|
277
|
+
| `XXXX/db.pglite.ts` | Generated with `db.ts` | `CREATE TABLE` script of the same schema, for running `migrate.ts` on PGlite. Never deployed. |
|
|
278
|
+
| `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. |
|
|
279
|
+
| `XXXX/migrate.pglite.test.ts` | Added via `tailordb migration script --with-test` when `@electric-sql/pglite` is installed | PGlite test scaffold for `migrate.ts`. Never deployed. |
|
|
277
280
|
|
|
278
281
|
`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.
|
|
279
282
|
|
|
@@ -386,7 +389,7 @@ The `env` values are injected at bundle time (the same mechanism as resolvers/ex
|
|
|
386
389
|
| 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 |
|
|
387
390
|
| 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. |
|
|
388
391
|
| Change array → single value | - | - | **Not supported** — see [Converting a field type](#converting-a-field-type) |
|
|
389
|
-
| Change single value → array |
|
|
392
|
+
| Change single value → array | Yes | Yes | Two migrations, generated together after you confirm — see [Converting a field type](#converting-a-field-type). Each stored value becomes a one-element array, so the conversion needs no edits. |
|
|
390
393
|
|
|
391
394
|
### Field type changes
|
|
392
395
|
|
|
@@ -460,7 +463,7 @@ The generated `never` annotation intentionally causes a TypeScript error until y
|
|
|
460
463
|
|
|
461
464
|
### Converting a field type
|
|
462
465
|
|
|
463
|
-
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:
|
|
466
|
+
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. The same holds when a single value becomes an array (`string` → `string[]`): the stored values must be rewritten as arrays before the field can take the new shape. `migration generate` offers to carry the values through a temporary field instead:
|
|
464
467
|
|
|
465
468
|
```
|
|
466
469
|
User.price changes from string to integer, which cannot be applied in one step.
|
|
@@ -469,9 +472,11 @@ User.price changes from string to integer, which cannot be applied in one step.
|
|
|
469
472
|
|
|
470
473
|
Confirming writes two migrations:
|
|
471
474
|
|
|
472
|
-
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.
|
|
475
|
+
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. When only the array-ness changes (`string` → `string[]`), the conversion stores each value as a one-element array and carries no review marker; when the element type changes as well (`integer` → `string[]`), you convert the element and the script wraps it.
|
|
473
476
|
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.
|
|
474
477
|
|
|
478
|
+
If converting to an array also reduces a decimal field's `scale` or removes enum values, the conversion keeps the review marker. Edit the element conversion to satisfy the target field before deploying.
|
|
479
|
+
|
|
475
480
|
`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.
|
|
476
481
|
|
|
477
482
|
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.
|
|
@@ -490,7 +495,7 @@ Without the flag the command fails rather than converting anything, so a scripte
|
|
|
490
495
|
|
|
491
496
|
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:
|
|
492
497
|
|
|
493
|
-
-
|
|
498
|
+
- A field that is already an array: collapsing it into a single value has no answer the generated script could choose for you, and changing its element type (`string[]` → `integer[]`) is not generated either.
|
|
494
499
|
- 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.
|
|
495
500
|
|
|
496
501
|
## Testing Pending Migrations
|
|
@@ -809,7 +814,7 @@ Scaffold a ready-to-fill test next to the script with:
|
|
|
809
814
|
tailor tailordb migration script 0005 --with-test
|
|
810
815
|
```
|
|
811
816
|
|
|
812
|
-
When `migrate.ts` already exists (the usual case for breaking changes, where `migration generate` creates it), the command adds only `
|
|
817
|
+
When `migrate.ts` already exists (the usual case for breaking changes, where `migration generate` creates it), the command adds only the tests that do not exist yet, plus a missing `db.pglite.ts`. Or write the test by hand:
|
|
813
818
|
|
|
814
819
|
```typescript
|
|
815
820
|
// migrations/0005/migrate.test.ts
|
|
@@ -843,30 +848,24 @@ A statement-level test verifies what the script issues, not what it does to data
|
|
|
843
848
|
npm install -D @electric-sql/pglite
|
|
844
849
|
```
|
|
845
850
|
|
|
846
|
-
|
|
851
|
+
The generated `db.pglite.ts` exports the `CREATE TABLE` script for the same schema `db.ts` types — the tables as the pre-migration phase leaves them while `migrate.ts` runs, including relaxed constraints, renamed fields under both names, and retained removed fields. Run it once on the PGlite instance, stage rows, then run the script in a transaction. `tailor tailordb migration script <N> --with-test` scaffolds this test too when `@electric-sql/pglite` is installed. Type the instance with `Unmigrated<Database>` rather than `Database`: `db.ts` types a column the migration makes required as `T | null` on read but `T` on write (and an enum it narrows as the old values on read but the new ones on write), so that `migrate.ts` cannot write what the migration is removing — which would also stop the test from staging the rows the script has to convert. `Unmigrated` lets every column be written with whatever it can still be read as; `main` still receives a `Transaction<Database>`.
|
|
847
852
|
|
|
848
853
|
```typescript
|
|
849
854
|
// migrations/0005/migrate.pglite.test.ts
|
|
850
855
|
import { PGlite } from "@electric-sql/pglite";
|
|
851
|
-
import { sql } from "@tailor-platform/sdk/kysely";
|
|
852
856
|
import { createKyselyPGlite, type Unmigrated } from "@tailor-platform/sdk/vitest";
|
|
853
857
|
import { afterAll, beforeAll, describe, expect, test } from "vitest";
|
|
854
858
|
import type { Database } from "./db";
|
|
859
|
+
import { pgliteSchema } from "./db.pglite";
|
|
855
860
|
import { main } from "./migrate";
|
|
856
861
|
|
|
857
|
-
const
|
|
862
|
+
const pglite = new PGlite();
|
|
863
|
+
const db = createKyselyPGlite<Unmigrated<Database>>(pglite);
|
|
858
864
|
|
|
865
|
+
// PGlite loads Postgres on first use, which can take longer than the default hook timeout.
|
|
859
866
|
beforeAll(async () => {
|
|
860
|
-
await
|
|
861
|
-
|
|
862
|
-
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
863
|
-
"name" text NOT NULL,
|
|
864
|
-
"email" text,
|
|
865
|
-
"createdAt" timestamptz NOT NULL,
|
|
866
|
-
"updatedAt" timestamptz NOT NULL
|
|
867
|
-
)
|
|
868
|
-
`.execute(db);
|
|
869
|
-
});
|
|
867
|
+
await pglite.exec(pgliteSchema.tailordb);
|
|
868
|
+
}, 60_000);
|
|
870
869
|
|
|
871
870
|
afterAll(async () => {
|
|
872
871
|
await db.destroy();
|
|
@@ -894,10 +893,14 @@ describe("0005 add required email", () => {
|
|
|
894
893
|
});
|
|
895
894
|
```
|
|
896
895
|
|
|
896
|
+
Pass nested field values as JavaScript objects or arrays of objects, without `JSON.stringify`.
|
|
897
|
+
Generated migration types use `Record<string, unknown>` for each nested object so scripts can
|
|
898
|
+
work with both old and new members during a migration; narrow member values before using them.
|
|
899
|
+
|
|
897
900
|
Two caveats keep this from replacing a scratch workspace:
|
|
898
901
|
|
|
899
902
|
- PGlite runs full PostgreSQL, while TailorDB supports [a subset of it](https://docs.tailor.tech/guides/function/accessing-tailordb#supported-sql-queries) — a statement that passes here can still be rejected on deploy.
|
|
900
|
-
-
|
|
903
|
+
- `db.pglite.ts` mirrors the column shape, not the platform: hooks, validations, and permissions do not run, and the limits listed under [Real SQL execution with PGlite](../testing.md#real-sql-execution-with-pglite-mocktailordbwithpglite) apply.
|
|
901
904
|
|
|
902
905
|
### Beyond unit tests
|
|
903
906
|
|
package/docs/testing.md
CHANGED
|
@@ -149,26 +149,30 @@ Pass `{ onUnhandled: "error" }` to make an unmatched query fail instead of retur
|
|
|
149
149
|
|
|
150
150
|
Instead of staging responses, back TailorDB with [`@electric-sql/pglite`](https://pglite.dev/) — an in-memory PostgreSQL (install it as a devDependency) — so the queries a resolver, executor, or workflow job issues through `getDB()` execute against real data. `getDB(namespace)` needs no test-side swap: acquire the mock, and each namespace you list resolves to its PGlite instance.
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
Let `kyselyTypePlugin` generate the `CREATE TABLE` script for you: set `pgliteSchemaPath` next to `distPath`, and `tailor generate` writes a module exporting one script per namespace, derived from the same table definitions as the Kysely types.
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// tailor.config.ts
|
|
156
|
+
kyselyTypePlugin({
|
|
157
|
+
distPath: "./generated/db.ts",
|
|
158
|
+
pgliteSchemaPath: "./generated/db.pglite.ts",
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Run the namespace's script once per PGlite instance. Every statement is `IF NOT EXISTS`, so applying it again to an instance that already has the tables is harmless.
|
|
153
163
|
|
|
154
164
|
```typescript
|
|
155
165
|
import { PGlite } from "@electric-sql/pglite";
|
|
156
166
|
import { mockTailordbWithPGlite } from "@tailor-platform/sdk/vitest";
|
|
157
167
|
import { afterAll, beforeAll, expect, test } from "vitest";
|
|
158
168
|
import { getDB } from "../generated/db";
|
|
169
|
+
import { pgliteSchema } from "../generated/db.pglite";
|
|
159
170
|
import resolver from "./upsertUsers";
|
|
160
171
|
|
|
161
172
|
const pglite = new PGlite();
|
|
162
173
|
|
|
163
174
|
beforeAll(async () => {
|
|
164
|
-
await pglite.exec(
|
|
165
|
-
CREATE TABLE "User" (
|
|
166
|
-
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
167
|
-
"name" text NOT NULL,
|
|
168
|
-
"email" text NOT NULL,
|
|
169
|
-
"age" integer NOT NULL
|
|
170
|
-
);
|
|
171
|
-
`);
|
|
175
|
+
await pglite.exec(pgliteSchema["main-db"]);
|
|
172
176
|
});
|
|
173
177
|
|
|
174
178
|
afterAll(async () => {
|
|
@@ -201,21 +205,19 @@ test("upserts against real rows", async () => {
|
|
|
201
205
|
});
|
|
202
206
|
```
|
|
203
207
|
|
|
204
|
-
|
|
208
|
+
The generated columns follow the Kysely types, not TailorDB's storage: `text` for string and enum fields, `timestamptz` for datetime, `date` and `time` for date and time, `numeric` for decimal, rounded to the configured scale and read back with exactly that many fractional digits, `jsonb` for nested objects (and arrays of them), Postgres arrays for other array fields. `id` is a generated `uuid` primary key, `.unique()` fields and unique `.indexes()` are enforced, so `ON CONFLICT` upserts behave, and `.default()` values become column defaults (`"now"` becomes the current time). `.serial()` fields are assigned by the database from the configured `start`, `maxValue`, and format. Relations are not enforced.
|
|
205
209
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
);
|
|
213
|
-
```
|
|
210
|
+
What the script cannot reproduce:
|
|
211
|
+
|
|
212
|
+
- Hooks, validations, and permissions do not run. A required field whose value only its own field-level create hook supplies is created nullable, so inserts that omit it succeed; give it a `.default()` if the test reads it back. A field filled by a table-level hook stays `NOT NULL`, as its Kysely type still requires it on insert.
|
|
213
|
+
- Serial formats are reproduced for a single `%d`, `%x`, or `%X` specifier with an optional zero-padded width; an octal `%o` format fails generation with an error naming the field.
|
|
214
|
+
- A datetime inside a nested object reads back as a string from `jsonb`, not a `Date`.
|
|
215
|
+
- On a persistent PGlite (`dataDir`), tables created by an earlier run are kept as they were; drop them or start from an empty directory after changing a table definition.
|
|
214
216
|
|
|
215
|
-
|
|
217
|
+
To hand-write DDL instead — for a table not in the schema, or to add a constraint — run your own statements after the script, or without it.
|
|
216
218
|
|
|
217
219
|
- The PGlite instance is yours: the mock never closes it, so close it in `afterAll`. Reuse one instance across a suite — creating one per test is slow.
|
|
218
|
-
- Pass the same instance under several namespaces to drive them against one shared database.
|
|
220
|
+
- Pass the same instance under several namespaces to drive them against one shared database. Two namespaces with a same-named table cannot share one instance, because the second script leaves the first table as it is.
|
|
219
221
|
- Seed through `getDB` itself. When a column type rejects a value that only the test must stage, use `createKyselyPGlite<Unmigrated<...>>(pglite)` instead — see [Testing Migrations Locally](./services/tailordb-migration.md#testing-migrations-locally). This only affects test setup; it cannot supply a `.serial()` value for an insert issued by the code under test.
|
|
220
222
|
- Transactions on a shared instance are serialized: while one is open, queries from other `getDB` instances wait. Do not use `test.concurrent` with a shared instance, and do not query the same instance through a second `getDB` from inside a transaction — that waits on itself.
|
|
221
223
|
- PGlite runs full PostgreSQL while TailorDB supports a subset of it, and TailorDB hooks, validations, and permissions do not run here — a test passing on PGlite can still behave differently on the platform. Keep [`mockTailordb`](#tailordb-mock) or [`createKyselyMock`](#kysely-layer-mock-createkyselymock) tests for query shape and error paths, and E2E tests for platform behavior.
|
|
@@ -666,7 +668,7 @@ describe("upsertUsers resolver", () => {
|
|
|
666
668
|
|
|
667
669
|
Reach for [`mockTailordb`](#mocking-the-tailordb-client) instead when you want to drive the raw query sequence at the `tailordb.Client` level rather than at the Kysely layer, or [`mockTailordbWithPGlite`](#real-sql-execution-with-pglite-mocktailordbwithpglite) to execute the queries against a real in-memory Postgres.
|
|
668
670
|
|
|
669
|
-
TailorDB migration scripts (`migrate.ts`) are unit-tested the same way: the generated `db.ts` exports the `Database` interface to type the mock, and `tailor tailordb migration script <N> --with-test` scaffolds a ready-to-fill test. To execute a migration script against real rows in an in-memory Postgres, use `createKyselyPGlite` with `@electric-sql/pglite
|
|
671
|
+
TailorDB migration scripts (`migrate.ts`) are unit-tested the same way: the generated `db.ts` exports the `Database` interface to type the mock, and `tailor tailordb migration script <N> --with-test` scaffolds a ready-to-fill test. To execute a migration script against real rows in an in-memory Postgres, use `createKyselyPGlite` with `@electric-sql/pglite` and the generated `db.pglite.ts` schema. See [Testing Migrations Locally](./services/tailordb-migration.md#testing-migrations-locally).
|
|
670
672
|
|
|
671
673
|
#### Resolvers that resume a workflow
|
|
672
674
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tailor-platform/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.17.0",
|
|
4
4
|
"description": "Tailor Platform SDK - The SDK to work with Tailor Platform",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -153,10 +153,10 @@
|
|
|
153
153
|
"@badgateway/oauth2-client": "3.3.1",
|
|
154
154
|
"@bufbuild/protobuf": "2.14.1",
|
|
155
155
|
"@bufbuild/protovalidate": "1.2.0",
|
|
156
|
-
"@connectrpc/connect": "2.
|
|
157
|
-
"@connectrpc/connect-node": "2.
|
|
158
|
-
"@inquirer/core": "12.0.
|
|
159
|
-
"@inquirer/prompts": "8.7.
|
|
156
|
+
"@connectrpc/connect": "2.2.0",
|
|
157
|
+
"@connectrpc/connect-node": "2.2.0",
|
|
158
|
+
"@inquirer/core": "12.0.3",
|
|
159
|
+
"@inquirer/prompts": "8.7.2",
|
|
160
160
|
"@jridgewell/trace-mapping": "0.3.31",
|
|
161
161
|
"@napi-rs/keyring": "2.0.0",
|
|
162
162
|
"@opentelemetry/api": "1.9.1",
|
|
@@ -170,7 +170,7 @@
|
|
|
170
170
|
"@secretlint/secretlint-rule-preset-recommend": "13.0.5",
|
|
171
171
|
"@standard-schema/spec": "1.1.0",
|
|
172
172
|
"@tailor-platform/function-kysely-tailordb": "0.1.3",
|
|
173
|
-
"@toiroakr/lines-db": "0.12.
|
|
173
|
+
"@toiroakr/lines-db": "0.12.7",
|
|
174
174
|
"@toiroakr/read-multiline": "0.4.1",
|
|
175
175
|
"@urql/core": "6.0.3",
|
|
176
176
|
"amaro": "1.1.11",
|
|
@@ -190,7 +190,7 @@
|
|
|
190
190
|
"p-limit": "7.3.2",
|
|
191
191
|
"pathe": "2.0.3",
|
|
192
192
|
"pgsql-ast-parser": "12.0.2",
|
|
193
|
-
"pkg-types": "2.3.
|
|
193
|
+
"pkg-types": "2.3.3",
|
|
194
194
|
"rolldown": "1.2.7",
|
|
195
195
|
"semver": "7.8.5",
|
|
196
196
|
"sql-highlight": "6.1.0",
|
|
@@ -201,15 +201,16 @@
|
|
|
201
201
|
"zod": "4.5.4"
|
|
202
202
|
},
|
|
203
203
|
"devDependencies": {
|
|
204
|
+
"@electric-sql/pglite": "0.5.8",
|
|
204
205
|
"@opentelemetry/sdk-trace-base": "2.11.0",
|
|
205
206
|
"@tailor-platform/shared": "^0.0.0",
|
|
206
207
|
"@tailor-platform/tailor-proto": "^0.0.1",
|
|
207
208
|
"@types/mime-types": "3.0.1",
|
|
208
|
-
"@types/node": "24.13.
|
|
209
|
+
"@types/node": "24.13.4",
|
|
209
210
|
"@types/semver": "7.8.0",
|
|
210
211
|
"@typescript/native-preview": "7.0.0-dev.20260707.2",
|
|
211
212
|
"@vitest/coverage-v8": "5.0.0",
|
|
212
|
-
"eslint-plugin-zod": "4.12.
|
|
213
|
+
"eslint-plugin-zod": "4.12.1",
|
|
213
214
|
"oxfmt": "0.66.0",
|
|
214
215
|
"oxlint": "1.81.0",
|
|
215
216
|
"oxlint-tsgolint": "7.0.2001",
|
|
@@ -217,7 +218,7 @@
|
|
|
217
218
|
"tsdown": "0.23.0",
|
|
218
219
|
"typescript": "6.0.3",
|
|
219
220
|
"vitest": "5.0.0",
|
|
220
|
-
"zinfer": "0.4.
|
|
221
|
+
"zinfer": "0.4.6"
|
|
221
222
|
},
|
|
222
223
|
"peerDependencies": {
|
|
223
224
|
"@electric-sql/pglite": ">=0.2.0",
|