@tailor-platform/sdk 2.0.0-next.1 → 2.0.0-next.2

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.
Files changed (119) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/dist/application-Dtqap5jM.mjs +3 -0
  3. package/dist/{client-z_oHGVNy.mjs → application-XuMWK4eq.mjs} +5861 -20
  4. package/dist/application-XuMWK4eq.mjs.map +1 -0
  5. package/dist/cli/index.mjs +179 -122
  6. package/dist/cli/index.mjs.map +1 -1
  7. package/dist/cli/lib.d.mts +75 -16
  8. package/dist/cli/lib.mjs +5 -6
  9. package/dist/cli/lib.mjs.map +1 -1
  10. package/dist/completion/zsh-worker.zsh +105 -26
  11. package/dist/configure/index.d.mts +9 -8
  12. package/dist/configure/index.mjs +56 -19
  13. package/dist/configure/index.mjs.map +1 -1
  14. package/dist/context-Bd266-ru.mjs.map +1 -1
  15. package/dist/{context-BuuIb8CC.d.mts → context-C2lEi9uw.d.mts} +7 -28
  16. package/dist/{crashreport-pr6Rhvza.mjs → crashreport-BMWcxeSE.mjs} +1 -1
  17. package/dist/{crashreport-BsjAkFWw.mjs → crashreport-DFq-vsU0.mjs} +5 -7
  18. package/dist/{crashreport-BsjAkFWw.mjs.map → crashreport-DFq-vsU0.mjs.map} +1 -1
  19. package/dist/{file-_oUZo76X.mjs → file-BbdFGdMV.mjs} +2 -10
  20. package/dist/file-BbdFGdMV.mjs.map +1 -0
  21. package/dist/{file-BB8Vs9O_.d.mts → file-Dq3NIt_F.d.mts} +3 -42
  22. package/dist/{file-utils-DcyIPFQh.mjs → file-utils-CYZnO1pX.mjs} +5 -5
  23. package/dist/file-utils-CYZnO1pX.mjs.map +1 -0
  24. package/dist/{globals-Crz8o65k.mjs → globals-Cf0sxIt8.mjs} +2 -2
  25. package/dist/{globals-Crz8o65k.mjs.map → globals-Cf0sxIt8.mjs.map} +1 -1
  26. package/dist/{http-adapter.generated-WgMnb7Sb.d.mts → http-adapter.generated-DFsXDdm5.d.mts} +11 -10
  27. package/dist/{index-BlpzXncY.d.mts → index-BI-_j9Z3.d.mts} +29 -32
  28. package/dist/{index-DjUdWlzf.d.mts → index-C4JirJH8.d.mts} +2 -2
  29. package/dist/{index-5vPyRu1y.d.mts → index-CZfWhr0a.d.mts} +2 -2
  30. package/dist/{index-CK7u9isy.d.mts → index-Cg8VKAdN.d.mts} +4 -4
  31. package/dist/{index-B7AKc18V.d.mts → index-DYRjoLXD.d.mts} +2 -2
  32. package/dist/{index-ZePLwxw7.d.mts → index-lFpcjHPU.d.mts} +8 -15
  33. package/dist/{index-CNYe5lnW.d.mts → index-nW7hE6oE.d.mts} +2 -2
  34. package/dist/{mock-BjFj5o1I.mjs → mock-FPxmnt-y.mjs} +4 -49
  35. package/dist/{mock-BjFj5o1I.mjs.map → mock-FPxmnt-y.mjs.map} +1 -1
  36. package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
  37. package/dist/plugin/builtin/file-utils/index.d.mts +1 -1
  38. package/dist/plugin/builtin/file-utils/index.mjs +1 -1
  39. package/dist/plugin/builtin/kysely-type/index.d.mts +1 -1
  40. package/dist/plugin/builtin/seed/index.d.mts +1 -1
  41. package/dist/plugin/builtin/seed/index.mjs +1 -1
  42. package/dist/plugin/index.d.mts +4 -3
  43. package/dist/plugin/index.mjs.map +1 -1
  44. package/dist/{registry-DdsYlL_P.mjs → registry-DH4m7eYo.mjs} +4 -2
  45. package/dist/registry-DH4m7eYo.mjs.map +1 -0
  46. package/dist/runtime/context.d.mts +1 -1
  47. package/dist/runtime/file.d.mts +2 -2
  48. package/dist/runtime/file.mjs +2 -2
  49. package/dist/runtime/globals.d.mts +6 -6
  50. package/dist/runtime/index.d.mts +4 -4
  51. package/dist/runtime/index.mjs +2 -2
  52. package/dist/runtime/workflow.d.mts +2 -2
  53. package/dist/runtime/workflow.mjs +1 -1
  54. package/dist/{runtime-n9NCkjee.mjs → runtime-CY4JvrDj.mjs} +777 -234
  55. package/dist/runtime-CY4JvrDj.mjs.map +1 -0
  56. package/dist/{schema-BhkpP5Hw.mjs → schema-Dtw9Orye.mjs} +16 -13
  57. package/dist/schema-Dtw9Orye.mjs.map +1 -0
  58. package/dist/{secret-file-DBqZhjFQ.mjs → secret-file-VSVGy1V0.mjs} +27 -2
  59. package/dist/{secret-file-DBqZhjFQ.mjs.map → secret-file-VSVGy1V0.mjs.map} +1 -1
  60. package/dist/{seed-jf3008-h.mjs → seed-izIEyP3z.mjs} +3 -4
  61. package/dist/seed-izIEyP3z.mjs.map +1 -0
  62. package/dist/service-DCqIWibD.mjs +3 -0
  63. package/dist/{service-DU1mVzri.mjs → service-DU1mVzri2.mjs} +1 -1
  64. package/dist/service-DU1mVzri2.mjs.map +1 -0
  65. package/dist/{service-CCL8ruDf.mjs → service-DjyqbCaJ.mjs} +7 -7
  66. package/dist/{service-CCL8ruDf.mjs.map → service-DjyqbCaJ.mjs.map} +1 -1
  67. package/dist/test-env-key-D7UkZp99.mjs +75 -0
  68. package/dist/test-env-key-D7UkZp99.mjs.map +1 -0
  69. package/dist/{types-ClhIrW_C.mjs → types-74etvaxy.mjs} +1 -1
  70. package/dist/{types-DhO_VEZd.d.mts → types-BDRml5C3.d.mts} +12 -12
  71. package/dist/{types-B2RpYyA_.mjs → types-BQijbo4m.mjs} +9 -9
  72. package/dist/types-BQijbo4m.mjs.map +1 -0
  73. package/dist/{types-DwDgacni.d.mts → types-BX4q6Mo6.d.mts} +3 -2
  74. package/dist/types-BZ7QKVE8.d.mts +21 -0
  75. package/dist/{types-DCUhgpyI.d.mts → types-CdcQh4Z2.d.mts} +5 -76
  76. package/dist/utils/test/index.d.mts +6 -15
  77. package/dist/utils/test/index.mjs +4 -13
  78. package/dist/utils/test/index.mjs.map +1 -1
  79. package/dist/vitest/environment.mjs +1 -1
  80. package/dist/vitest/index.d.mts +2 -2
  81. package/dist/vitest/index.mjs +4 -4
  82. package/dist/vitest/setup.mjs +2 -2
  83. package/dist/{workflow-DgemCAz3.mjs → workflow-BOmaZwwG.mjs} +8 -3
  84. package/dist/workflow-BOmaZwwG.mjs.map +1 -0
  85. package/dist/{workflow-BbKvGLQg.d.mts → workflow-BVy4XWjS.d.mts} +15 -10
  86. package/dist/{workflow.generated-DtQwEo-x.d.mts → workflow.generated-ClEjBYhm.d.mts} +3 -3
  87. package/docs/cli/executor.md +53 -0
  88. package/docs/cli/setup.md +35 -33
  89. package/docs/cli/workflow.md +157 -20
  90. package/docs/cli-reference.md +26 -20
  91. package/docs/github-actions.md +29 -16
  92. package/docs/migration/v2.md +475 -0
  93. package/docs/runtime.md +1 -1
  94. package/docs/services/auth.md +12 -12
  95. package/docs/services/executor.md +3 -3
  96. package/docs/services/resolver.md +6 -6
  97. package/docs/services/tailordb.md +14 -12
  98. package/docs/services/workflow.md +4 -4
  99. package/docs/testing.md +59 -47
  100. package/package.json +7 -7
  101. package/dist/application-DB2r36Et.mjs +0 -3
  102. package/dist/application-DqS1yBg3.mjs +0 -5680
  103. package/dist/application-DqS1yBg3.mjs.map +0 -1
  104. package/dist/client-Dbohmtkv.mjs +0 -3
  105. package/dist/client-z_oHGVNy.mjs.map +0 -1
  106. package/dist/file-_oUZo76X.mjs.map +0 -1
  107. package/dist/file-utils-DcyIPFQh.mjs.map +0 -1
  108. package/dist/job-fuc3j1Ma.mjs +0 -53
  109. package/dist/job-fuc3j1Ma.mjs.map +0 -1
  110. package/dist/registry-DdsYlL_P.mjs.map +0 -1
  111. package/dist/runtime-n9NCkjee.mjs.map +0 -1
  112. package/dist/schema-BhkpP5Hw.mjs.map +0 -1
  113. package/dist/seed-jf3008-h.mjs.map +0 -1
  114. package/dist/service-D6yonf2I.mjs +0 -3
  115. package/dist/service-DU1mVzri.mjs.map +0 -1
  116. package/dist/test-env-key-D9kM6ETE.mjs +0 -49
  117. package/dist/test-env-key-D9kM6ETE.mjs.map +0 -1
  118. package/dist/types-B2RpYyA_.mjs.map +0 -1
  119. package/dist/workflow-DgemCAz3.mjs.map +0 -1
@@ -260,7 +260,7 @@ Add hooks to execute functions during data creation or update. Hooks receive thr
260
260
 
261
261
  - `value`: User input if provided, otherwise existing value on update or null on create
262
262
  - `data`: Entire record data (for accessing other field values)
263
- - `user`: User performing the operation
263
+ - `invoker`: Principal performing the operation
264
264
 
265
265
  #### Field-level Hooks
266
266
 
@@ -268,7 +268,7 @@ Set hooks directly on individual fields:
268
268
 
269
269
  ```typescript
270
270
  db.string().hooks({
271
- create: ({ user }) => user.id,
271
+ create: ({ invoker }) => invoker?.id ?? "",
272
272
  update: ({ value }) => value,
273
273
  });
274
274
  ```
@@ -323,7 +323,7 @@ Add validation rules to fields. Validators receive three arguments (executed aft
323
323
 
324
324
  - `value`: Field value after hook transformation
325
325
  - `data`: Entire record data after hook transformations (for accessing other field values)
326
- - `user`: User performing the operation
326
+ - `invoker`: Principal performing the operation
327
327
 
328
328
  Validators return `true` for success, `false` for failure. Use array form `[validator, errorMessage]` for custom error messages.
329
329
 
@@ -409,6 +409,8 @@ export const user = db.type("User", {
409
409
  });
410
410
  ```
411
411
 
412
+ `db.fields.timestamps()` adds non-null `createdAt` and `updatedAt` datetime fields. Both fields are populated when a record is created; provided values are preserved so seed data can use historical timestamps. `updatedAt` is also refreshed automatically when a record is updated.
413
+
412
414
  ## Type Modifiers
413
415
 
414
416
  ### Composite Indexes
@@ -516,8 +518,8 @@ const user = db.type("User", {
516
518
  ...db.fields.timestamps(),
517
519
  });
518
520
 
519
- // Pick id and createdAt, making them optional
520
- user.pickFields(["id", "createdAt"], { optional: true });
521
+ // Pick id, createdAt, and updatedAt, making them optional
522
+ user.pickFields(["id", "createdAt", "updatedAt"], { optional: true });
521
523
  ```
522
524
 
523
525
  Available options:
@@ -532,8 +534,8 @@ Available options:
532
534
  Return all fields except the specified ones:
533
535
 
534
536
  ```typescript
535
- // All fields except id and createdAt
536
- user.omitFields(["id", "createdAt"]);
537
+ // All fields except id, createdAt, and updatedAt
538
+ user.omitFields(["id", "createdAt", "updatedAt"]);
537
539
  ```
538
540
 
539
541
  #### Common Pattern: Input Schema Composition
@@ -548,9 +550,9 @@ export default createResolver({
548
550
  name: "createUser",
549
551
  operation: "mutation",
550
552
  input: {
551
- // id/createdAt are optional (auto-generated), other fields are required
552
- ...user.pickFields(["id", "createdAt"], { optional: true }),
553
- ...user.omitFields(["id", "createdAt"]),
553
+ // id/createdAt/updatedAt are optional (auto-generated), other fields are required
554
+ ...user.pickFields(["id", "createdAt", "updatedAt"], { optional: true }),
555
+ ...user.omitFields(["id", "createdAt", "updatedAt"]),
554
556
  },
555
557
  output: t.object({ id: t.uuid() }),
556
558
  body: async (context) => {
@@ -567,8 +569,8 @@ import { t } from "@tailor-platform/sdk";
567
569
  import { invoice } from "../../tailordb/invoice";
568
570
 
569
571
  const schemaType = t.object({
570
- ...invoice.pickFields(["id", "createdAt"], { optional: true }),
571
- ...invoice.omitFields(["id", "createdAt", "invoiceNumber", "sequentialId"]),
572
+ ...invoice.pickFields(["id", "createdAt", "updatedAt"], { optional: true }),
573
+ ...invoice.omitFields(["id", "createdAt", "updatedAt", "invoiceNumber", "sequentialId"]),
572
574
  });
573
575
  ```
574
576
 
@@ -180,8 +180,8 @@ export const processOrder = createWorkflowJob({
180
180
  name: "process-order",
181
181
  body: (input: { customerId: string }, { env, invoker }) => {
182
182
  // `env` contains values from `tailor.config.ts` -> `env`.
183
- // `invoker` is the principal running this job, overridden by `authInvoker`
184
- // when set; `null` for anonymous calls.
183
+ // `invoker` is the principal running this job, or the machine user
184
+ // configured through the trigger `invoker` option; `null` for anonymous calls.
185
185
  // Trigger other jobs by calling .trigger() on the job object.
186
186
  const customer = fetchCustomer.trigger({
187
187
  customerId: input.customerId,
@@ -356,7 +356,7 @@ export default createWorkflow({
356
356
  You can start a workflow execution from a resolver using `workflow.trigger()`.
357
357
 
358
358
  - `workflow.trigger(args, options?)` returns a workflow run ID (`Promise<string>`).
359
- - To run with machine-user permissions, pass `{ authInvoker: "<machine-user>" }`. The name is type-narrowed to the machine users defined in your auth config.
359
+ - To run with machine-user permissions, pass `{ invoker: "<machine-user>" }`. The name is type-narrowed to the machine users defined in your auth config.
360
360
 
361
361
  ```typescript
362
362
  import { createResolver, t } from "@tailor-platform/sdk";
@@ -372,7 +372,7 @@ export default createResolver({
372
372
  body: async ({ input }) => {
373
373
  const workflowRunId = await orderProcessingWorkflow.trigger(
374
374
  { orderId: input.orderId, customerId: input.customerId },
375
- { authInvoker: "manager-machine-user" },
375
+ { invoker: "manager-machine-user" },
376
376
  );
377
377
 
378
378
  return { workflowRunId };
package/docs/testing.md CHANGED
@@ -11,15 +11,15 @@ Lean on unit tests for the day-to-day feedback loop — they run fast and exerci
11
11
 
12
12
  Unit-test entrypoints exposed by the SDK:
13
13
 
14
- - `resolver.body({ input, user, env })` — invoke a resolver
15
- - `workflowJob.body(input, { env })` — invoke a workflow job body directly
14
+ - `resolver.body({ input, caller, invoker, env })` — invoke a resolver
15
+ - `workflowJob.body(input, { env, invoker })` — invoke a workflow job body directly
16
16
  - `workflowJob.trigger(input)` — chain a workflow job through the workflow runtime
17
17
  - `runWorkflowLocally(workflow, args)` — run a workflow chain locally with real job bodies
18
- - `executor.operation.body(args)` — invoke a function-kind executor
18
+ - `executor.operation.body({ ...args, invoker })` — invoke a function-kind executor
19
19
 
20
- Helpers under `@tailor-platform/sdk/test`:
20
+ For anonymous direct calls:
21
21
 
22
- - `unauthenticatedTailorUser` default `user` value for resolver contexts
22
+ - Pass `null` for anonymous `caller` / `invoker` context in direct unit tests.
23
23
 
24
24
  Platform API mocks under `@tailor-platform/sdk/vitest` (for use with the [`tailor-runtime` Vitest environment](#runtime-environment-emulation-beta) below):
25
25
 
@@ -99,7 +99,12 @@ test("resolver queries the database", async () => {
99
99
  [], // COMMIT
100
100
  );
101
101
 
102
- const result = await resolver.body({ input: { email: "test@example.com" } });
102
+ const result = await resolver.body({
103
+ input: { email: "test@example.com" },
104
+ caller: null,
105
+ invoker: null,
106
+ env: {},
107
+ });
103
108
 
104
109
  expect(result).toEqual({ oldAge: 30, newAge: 31 });
105
110
  expect(db.executedQueries).toHaveLength(3);
@@ -121,7 +126,12 @@ test("content-based mock", async () => {
121
126
  return [];
122
127
  });
123
128
 
124
- const result = await resolver.body({ input: { userId: "1" } });
129
+ const result = await resolver.body({
130
+ input: { userId: "1" },
131
+ caller: null,
132
+ invoker: null,
133
+ env: {},
134
+ });
125
135
 
126
136
  expect(db.executedQueries[0].query).toContain("SELECT");
127
137
  });
@@ -163,6 +173,8 @@ wf.enqueueResult({ valid: true });
163
173
  wf.enqueueResults({ valid: true }, { txnId: "txn-1" });
164
174
  ```
165
175
 
176
+ Use `wf.setEnv(...)` when locally-run workflow job bodies need configuration values. Per-run `runWorkflowLocally(..., { env })` options take precedence over the mock's env.
177
+
166
178
  ### SecretManager Mock
167
179
 
168
180
  ```typescript
@@ -265,28 +277,6 @@ test("mock file download stream", async () => {
265
277
  });
266
278
  ```
267
279
 
268
- For the deprecated `openDownloadStream`, enqueue an iterable of `StreamValue` items — `metadata`, one or more `chunk` items, and a terminal `complete`. Raw `Uint8Array` / `ArrayBuffer` chunks are rejected so tests stay aligned with the platform's structured stream contract.
269
-
270
- ```typescript
271
- test("mock file download stream (deprecated openDownloadStream)", async () => {
272
- using file = mockFile();
273
- file.enqueueResult([
274
- {
275
- type: "metadata",
276
- metadata: { contentType: "image/png", fileSize: 3, sha256sum: "abc" },
277
- },
278
- { type: "chunk", data: new Uint8Array([1, 2]), position: 0 },
279
- { type: "chunk", data: new Uint8Array([3]), position: 2 },
280
- { type: "complete" },
281
- ]);
282
-
283
- const stream = await tailordb.file.openDownloadStream("ns", "Doc", "attachment", "r-1");
284
- const items = [];
285
- for await (const item of stream) items.push(item);
286
- expect(items).toHaveLength(4);
287
- });
288
- ```
289
-
290
280
  ### Iconv Mock
291
281
 
292
282
  ```typescript
@@ -367,7 +357,6 @@ Unit tests call `.body()` (or `.trigger()`) directly on a resolver, workflow job
367
357
  For pure logic with no external dependencies, invoke `.body()` directly:
368
358
 
369
359
  ```typescript
370
- import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
371
360
  import { describe, expect, test } from "vitest";
372
361
  import resolver from "../src/resolver/add";
373
362
 
@@ -375,7 +364,8 @@ describe("add resolver", () => {
375
364
  test("adds two numbers", async () => {
376
365
  const result = await resolver.body({
377
366
  input: { left: 1, right: 2 },
378
- user: unauthenticatedTailorUser,
367
+ caller: null,
368
+ invoker: null,
379
369
  env: {},
380
370
  });
381
371
  expect(result).toBe(3);
@@ -392,7 +382,6 @@ Stub the global `tailordb.Client` and queue raw query results in order. Best for
392
382
  > If you are running with the [`tailor-runtime` Vitest environment](#runtime-environment-emulation-beta), acquire `using db = mockTailordb()` to install and drive the mock `tailordb.Client` instead of `vi.stubGlobal()`.
393
383
 
394
384
  ```typescript
395
- import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
396
385
  import { afterAll, afterEach, beforeAll, describe, expect, test, vi } from "vitest";
397
386
  import resolver from "../src/resolver/incrementUserAge";
398
387
 
@@ -422,7 +411,8 @@ describe("incrementUserAge resolver", () => {
422
411
 
423
412
  const result = await resolver.body({
424
413
  input: { email: "test@example.com" },
425
- user: unauthenticatedTailorUser,
414
+ caller: null,
415
+ invoker: null,
426
416
  env: {},
427
417
  });
428
418
 
@@ -493,7 +483,6 @@ describe("decrementUserAge", () => {
493
483
  Pass `mock.db` to functions that take a Kysely instance. When a resolver or executor calls `getDB()` internally there is no such seam, so spy the generated `getDB` and point it at the mock:
494
484
 
495
485
  ```typescript
496
- import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
497
486
  import { createKyselyMock } from "@tailor-platform/sdk/vitest";
498
487
  import { describe, expect, test, vi } from "vitest";
499
488
  import { getDB, type Namespace } from "../generated/db";
@@ -525,7 +514,8 @@ describe("upsertUsers resolver", () => {
525
514
  { name: "Existing", email: "exists@example.com", age: 41 },
526
515
  ],
527
516
  },
528
- user: unauthenticatedTailorUser,
517
+ caller: null,
518
+ invoker: null,
529
519
  env: { appName: "Resolver Template", version: 1 },
530
520
  });
531
521
 
@@ -544,7 +534,6 @@ Reach for [`mockTailordb`](#mocking-the-tailordb-client) instead when you want t
544
534
  Resolvers that call `waitPoint.resolve(...)` delegate to `tailor.workflow.resolve` at runtime. With the `tailor-runtime` environment active, use `mockWorkflow().setResolveHandler` to drive the user-supplied callback and inspect `resolveCalls`:
545
535
 
546
536
  ```typescript
547
- import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
548
537
  import { mockWorkflow } from "@tailor-platform/sdk/vitest";
549
538
  import { describe, expect, test } from "vitest";
550
539
  import resolver from "./resolveApproval";
@@ -559,7 +548,8 @@ describe("resolveApproval resolver", () => {
559
548
 
560
549
  const result = await resolver.body({
561
550
  input: { executionId: "exec-1", approved: true },
562
- user: unauthenticatedTailorUser,
551
+ caller: null,
552
+ invoker: null,
563
553
  env: {},
564
554
  });
565
555
 
@@ -573,7 +563,7 @@ describe("resolveApproval resolver", () => {
573
563
 
574
564
  ### Testing Executors
575
565
 
576
- 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 type's output. GraphQL, webhook, and workflow operation kinds are declarative and don't expose a user-authored body to test.
566
+ 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 type'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.
577
567
 
578
568
  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:
579
569
 
@@ -590,6 +580,14 @@ describe("onUserCreated executor", () => {
590
580
  throw new Error("expected function operation");
591
581
  }
592
582
  await onUserCreated.operation.body({
583
+ workspaceId: "workspace-1",
584
+ appNamespace: "app",
585
+ env: {},
586
+ actor: null,
587
+ invoker: null,
588
+ event: "created",
589
+ rawEvent: "tailordb.type_record.created",
590
+ typeName: "User",
593
591
  newRecord: {
594
592
  id: "user-1",
595
593
  name: "Alice",
@@ -618,7 +616,7 @@ Workflow jobs expose the same `.body()` entrypoint as resolvers, plus `.trigger(
618
616
 
619
617
  #### Simple job
620
618
 
621
- Call `.body()` with the input and a stub `{ env: {} }`:
619
+ Call `.body()` with the input and a stub `{ env: {}, invoker: null }`:
622
620
 
623
621
  ```typescript
624
622
  import { describe, expect, test } from "vitest";
@@ -626,14 +624,17 @@ import { validateOrder } from "./order-fulfillment";
626
624
 
627
625
  describe("validateOrder", () => {
628
626
  test("accepts a valid order", () => {
629
- const result = validateOrder.body({ orderId: "order-1", amount: 100 }, { env: {} });
627
+ const result = validateOrder.body(
628
+ { orderId: "order-1", amount: 100 },
629
+ { env: {}, invoker: null },
630
+ );
630
631
  expect(result).toEqual({ valid: true, orderId: "order-1" });
631
632
  });
632
633
 
633
634
  test("rejects a non-positive amount", () => {
634
- expect(() => validateOrder.body({ orderId: "order-1", amount: 0 }, { env: {} })).toThrow(
635
- "Order amount must be positive",
636
- );
635
+ expect(() =>
636
+ validateOrder.body({ orderId: "order-1", amount: 0 }, { env: {}, invoker: null }),
637
+ ).toThrow("Order amount must be positive");
637
638
  });
638
639
  });
639
640
  ```
@@ -663,7 +664,10 @@ describe("fulfillOrder", () => {
663
664
  confirmed: true,
664
665
  });
665
666
 
666
- const result = await fulfillOrder.body({ orderId: "order-1", amount: 100 }, { env: {} });
667
+ const result = await fulfillOrder.body(
668
+ { orderId: "order-1", amount: 100 },
669
+ { env: {}, invoker: null },
670
+ );
667
671
 
668
672
  expect(validateOrder.trigger).toHaveBeenCalledWith({ orderId: "order-1", amount: 100 });
669
673
  expect(result).toMatchObject({ confirmed: true, paymentStatus: "completed" });
@@ -687,7 +691,10 @@ describe("processWithApproval", () => {
687
691
  using wf = mockWorkflow();
688
692
  wf.setWaitHandler({ approved: true });
689
693
 
690
- const result = await processWithApproval.body({ orderId: "order-1" }, { env: {} });
694
+ const result = await processWithApproval.body(
695
+ { orderId: "order-1" },
696
+ { env: {}, invoker: null },
697
+ );
691
698
 
692
699
  expect(result).toEqual({ orderId: "order-1", status: "approved" });
693
700
  expect(wf.waitCalls[0]).toEqual({
@@ -700,7 +707,10 @@ describe("processWithApproval", () => {
700
707
  using wf = mockWorkflow();
701
708
  wf.setWaitHandler({ approved: false });
702
709
 
703
- const result = await processWithApproval.body({ orderId: "order-2" }, { env: {} });
710
+ const result = await processWithApproval.body(
711
+ { orderId: "order-2" },
712
+ { env: {}, invoker: null },
713
+ );
704
714
 
705
715
  expect(result.status).toBe("rejected");
706
716
  });
@@ -729,6 +739,8 @@ describe("order-fulfillment workflow", () => {
729
739
 
730
740
  Pass `{ env }` as the third argument when job bodies need configuration values during the local run.
731
741
 
742
+ If you already acquired `mockWorkflow()`, you can also call `wf.setEnv(...)` to reuse the same env across local workflow runs.
743
+
732
744
  Like the platform runtime, the local runner re-runs the orchestrator body once per `.trigger()` call (N triggers means N+1 passes), so any side effects outside the trigger results fire on every pass. Keep the body deterministic and move repeatable side effects into the triggered jobs.
733
745
 
734
746
  This helper is still a local runner. Use E2E tests when you need to verify deployed workflow scheduling, suspension, or replay behavior.
@@ -837,7 +849,7 @@ describe("user-profile-sync workflow", () => {
837
849
  test("executes end to end", { timeout: 180_000 }, async () => {
838
850
  const { executionId, wait } = await startWorkflow({
839
851
  workflow: userProfileSync,
840
- authInvoker: "admin",
852
+ invoker: "admin",
841
853
  arg: {
842
854
  name: "workflow-test",
843
855
  email: `wf-${randomUUID()}@example.com`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tailor-platform/sdk",
3
- "version": "2.0.0-next.1",
3
+ "version": "2.0.0-next.2",
4
4
  "description": "Tailor Platform SDK - The SDK to work with Tailor Platform",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -134,7 +134,7 @@
134
134
  }
135
135
  },
136
136
  "dependencies": {
137
- "@0no-co/graphql.web": "1.2.0",
137
+ "@0no-co/graphql.web": "1.3.2",
138
138
  "@badgateway/oauth2-client": "3.3.1",
139
139
  "@bufbuild/protobuf": "2.12.0",
140
140
  "@bufbuild/protovalidate": "1.2.0",
@@ -175,14 +175,14 @@
175
175
  "pkg-types": "2.3.1",
176
176
  "politty": "0.6.0",
177
177
  "rolldown": "1.1.1",
178
- "semver": "7.8.4",
178
+ "semver": "7.8.5",
179
179
  "sql-highlight": "6.1.0",
180
180
  "std-env": "4.1.0",
181
181
  "table": "6.9.0",
182
182
  "ts-cron-validator": "1.1.5",
183
183
  "tsx": "4.22.4",
184
184
  "type-fest": "5.7.0",
185
- "undici": "8.4.1",
185
+ "undici": "8.5.0",
186
186
  "xdg-basedir": "5.1.0",
187
187
  "zod": "4.4.3"
188
188
  },
@@ -192,14 +192,14 @@
192
192
  "@types/mime-types": "3.0.1",
193
193
  "@types/node": "24.13.2",
194
194
  "@types/semver": "7.7.1",
195
- "@typescript/native-preview": "7.0.0-dev.20260612.1",
195
+ "@typescript/native-preview": "7.0.0-dev.20260614.1",
196
196
  "@vitest/coverage-v8": "4.1.8",
197
197
  "oxfmt": "0.54.0",
198
198
  "oxlint": "1.69.0",
199
199
  "oxlint-tsgolint": "0.23.0",
200
- "sonda": "0.11.1",
200
+ "sonda": "0.13.1",
201
201
  "tsdown": "0.22.2",
202
- "typescript": "5.9.3",
202
+ "typescript": "6.0.3",
203
203
  "vitest": "4.1.8",
204
204
  "zinfer": "0.1.8"
205
205
  },
@@ -1,3 +0,0 @@
1
- import { n as generatePluginFilesIfNeeded, r as loadApplication, t as defineApplication } from "./application-DqS1yBg3.mjs";
2
-
3
- export { defineApplication, generatePluginFilesIfNeeded };