@tailor-platform/sdk 2.0.0-next.0 → 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.
- package/CHANGELOG.md +161 -0
- package/dist/application-Dtqap5jM.mjs +3 -0
- package/dist/{client-CobIRHl-.mjs → application-XuMWK4eq.mjs} +5869 -25
- package/dist/application-XuMWK4eq.mjs.map +1 -0
- package/dist/{assert-CKfwrmCV.mjs → assert-DBxo8jPo.mjs} +1 -2
- package/dist/{assert-CKfwrmCV.mjs.map → assert-DBxo8jPo.mjs.map} +1 -1
- package/dist/{authconnection-D8SJGMpj.mjs → authconnection-D2MhtTN5.mjs} +2 -3
- package/dist/{authconnection-D8SJGMpj.mjs.map → authconnection-D2MhtTN5.mjs.map} +1 -1
- package/dist/{authconnection-BIYzEh2p.d.mts → authconnection-DvUQAjQS.d.mts} +1 -1
- package/dist/{brand-DlnJ375c.mjs → brand-Eo4pLXPJ.mjs} +1 -2
- package/dist/{brand-DlnJ375c.mjs.map → brand-Eo4pLXPJ.mjs.map} +1 -1
- package/dist/cli/index.mjs +241 -237
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/lib.d.mts +547 -620
- package/dist/cli/lib.mjs +9 -11
- package/dist/cli/lib.mjs.map +1 -1
- package/dist/completion/zsh-worker.zsh +4108 -0
- package/dist/configure/index.d.mts +9 -7
- package/dist/configure/index.mjs +76 -40
- package/dist/configure/index.mjs.map +1 -1
- package/dist/{context-s0lxhu8_.mjs → context-Bd266-ru.mjs} +2 -3
- package/dist/context-Bd266-ru.mjs.map +1 -0
- package/dist/{context-CUBwSBq4.d.mts → context-C2lEi9uw.d.mts} +7 -28
- package/dist/{crashreport-D1wKBJ8N.mjs → crashreport-BMWcxeSE.mjs} +1 -2
- package/dist/{crashreport-BhD0y14F.mjs → crashreport-DFq-vsU0.mjs} +21 -14
- package/dist/{crashreport-BhD0y14F.mjs.map → crashreport-DFq-vsU0.mjs.map} +1 -1
- package/dist/{enum-constants-C7DaWeQo.mjs → enum-constants-j9QBF0cB.mjs} +1 -2
- package/dist/enum-constants-j9QBF0cB.mjs.map +1 -0
- package/dist/{errors-EsY4XO6O.mjs → errors-Dtf2WPaW.mjs} +1 -2
- package/dist/{errors-EsY4XO6O.mjs.map → errors-Dtf2WPaW.mjs.map} +1 -1
- package/dist/{field-C4zdJLW5.mjs → field-DOsJCPFa.mjs} +1 -2
- package/dist/field-DOsJCPFa.mjs.map +1 -0
- package/dist/{file-B58Dm-2P.mjs → file-BbdFGdMV.mjs} +3 -12
- package/dist/file-BbdFGdMV.mjs.map +1 -0
- package/dist/{file-BzK8z3X-.d.mts → file-Dq3NIt_F.d.mts} +3 -42
- package/dist/{file-utils-BHPxPXmn.mjs → file-utils-CYZnO1pX.mjs} +6 -7
- package/dist/file-utils-CYZnO1pX.mjs.map +1 -0
- package/dist/{globals-ByrCoDip.mjs → globals-Cf0sxIt8.mjs} +53 -5
- package/dist/globals-Cf0sxIt8.mjs.map +1 -0
- package/dist/http-adapter.generated-DFsXDdm5.d.mts +581 -0
- package/dist/{iconv-kwrmd1U_.d.mts → iconv-Co-TOPuH.d.mts} +1 -1
- package/dist/{iconv-DreIffeM.mjs → iconv-D2vi8G36.mjs} +2 -3
- package/dist/{iconv-DreIffeM.mjs.map → iconv-D2vi8G36.mjs.map} +1 -1
- package/dist/{idp-Ch95ag8h.mjs → idp-BDbK5gjm.mjs} +2 -3
- package/dist/{idp-Ch95ag8h.mjs.map → idp-BDbK5gjm.mjs.map} +1 -1
- package/dist/{idp-BlBPtXJ-.d.mts → idp-DrhVrLmV.d.mts} +1 -1
- package/dist/{index-CLxubakC.d.mts → index-BI-_j9Z3.d.mts} +49 -261
- package/dist/{index-CPRnOjjt.d.mts → index-C4JirJH8.d.mts} +2 -2
- package/dist/{index-CQZVJ5SX.d.mts → index-CZfWhr0a.d.mts} +2 -2
- package/dist/{index-DRhMpdnA.d.mts → index-Cg8VKAdN.d.mts} +8 -8
- package/dist/{index-CfRFkXIO.d.mts → index-DYRjoLXD.d.mts} +2 -2
- package/dist/index-lFpcjHPU.d.mts +201 -0
- package/dist/{index-DUupuPhZ.d.mts → index-nW7hE6oE.d.mts} +2 -2
- package/dist/{interceptor-DOqRkCya.mjs → interceptor-D-q1rvRl.mjs} +1 -2
- package/dist/{interceptor-DOqRkCya.mjs.map → interceptor-D-q1rvRl.mjs.map} +1 -1
- package/dist/kysely/index.mjs +0 -1
- package/dist/kysely/index.mjs.map +1 -1
- package/dist/{kysely-type-D1e0Vwkd.mjs → kysely-type-DR8uzZTA.mjs} +2 -3
- package/dist/kysely-type-DR8uzZTA.mjs.map +1 -0
- package/dist/{logger-DpJyJvNz.mjs → logger-CxF-Ex5d.mjs} +1 -2
- package/dist/{logger-DpJyJvNz.mjs.map → logger-CxF-Ex5d.mjs.map} +1 -1
- package/dist/{mock-DMgIygjE.mjs → mock-FPxmnt-y.mjs} +9 -56
- package/dist/mock-FPxmnt-y.mjs.map +1 -0
- package/dist/{multiline-Cf9ODpr1.mjs → multiline-sfHpTZZK.mjs} +1 -2
- package/dist/{multiline-Cf9ODpr1.mjs.map → multiline-sfHpTZZK.mjs.map} +1 -1
- package/dist/{package-json-DcQApfPQ.mjs → package-json-8b0O9TlX.mjs} +1 -2
- package/dist/{package-json-DcQApfPQ.mjs.map → package-json-8b0O9TlX.mjs.map} +1 -1
- package/dist/package-json-Cv2Z-TqQ.mjs +3 -0
- package/dist/plugin/builtin/enum-constants/index.d.mts +1 -1
- package/dist/plugin/builtin/enum-constants/index.mjs +1 -2
- package/dist/plugin/builtin/file-utils/index.d.mts +1 -1
- package/dist/plugin/builtin/file-utils/index.mjs +1 -2
- package/dist/plugin/builtin/kysely-type/index.d.mts +1 -1
- package/dist/plugin/builtin/kysely-type/index.mjs +1 -2
- package/dist/plugin/builtin/seed/index.d.mts +1 -1
- package/dist/plugin/builtin/seed/index.mjs +1 -2
- package/dist/plugin/index.d.mts +4 -5
- package/dist/plugin/index.mjs +0 -1
- package/dist/plugin/index.mjs.map +1 -1
- package/dist/registry-DH4m7eYo.mjs +53 -0
- package/dist/registry-DH4m7eYo.mjs.map +1 -0
- package/dist/{repl-editor-CJG3sz7A.mjs → repl-editor-DmGr9zMw.mjs} +2 -3
- package/dist/{repl-editor-CJG3sz7A.mjs.map → repl-editor-DmGr9zMw.mjs.map} +1 -1
- package/dist/{chunk-BkoGK1jX.mjs → rolldown-runtime-DXywRVcq.mjs} +0 -1
- package/dist/runtime/authconnection.d.mts +1 -1
- package/dist/runtime/authconnection.mjs +1 -2
- package/dist/runtime/context.d.mts +1 -1
- package/dist/runtime/context.mjs +1 -2
- package/dist/runtime/file.d.mts +2 -2
- package/dist/runtime/file.mjs +2 -3
- package/dist/runtime/globals.d.mts +8 -41
- package/dist/runtime/globals.mjs +0 -1
- package/dist/runtime/iconv.d.mts +1 -1
- package/dist/runtime/iconv.mjs +1 -2
- package/dist/runtime/idp.d.mts +1 -1
- package/dist/runtime/idp.mjs +1 -2
- package/dist/runtime/index.d.mts +8 -8
- package/dist/runtime/index.mjs +7 -8
- package/dist/runtime/secretmanager.d.mts +1 -1
- package/dist/runtime/secretmanager.mjs +1 -2
- package/dist/runtime/workflow.d.mts +2 -2
- package/dist/runtime/workflow.mjs +1 -2
- package/dist/{runtime-C7qTBDD2.mjs → runtime-CY4JvrDj.mjs} +1069 -542
- package/dist/runtime-CY4JvrDj.mjs.map +1 -0
- package/dist/{schema-1msIhXwA.mjs → schema-Dtw9Orye.mjs} +18 -16
- package/dist/schema-Dtw9Orye.mjs.map +1 -0
- package/dist/{secret-file-CWzF8rry.mjs → secret-file-VSVGy1V0.mjs} +27 -3
- package/dist/{secret-file-CWzF8rry.mjs.map → secret-file-VSVGy1V0.mjs.map} +1 -1
- package/dist/{secretmanager-CKLB3wAQ.d.mts → secretmanager-B3n4KHfm.d.mts} +1 -1
- package/dist/{secretmanager-B9h-U_8U.mjs → secretmanager-BVxw3ih_.mjs} +2 -3
- package/dist/{secretmanager-B9h-U_8U.mjs.map → secretmanager-BVxw3ih_.mjs.map} +1 -1
- package/dist/seed/index.mjs +0 -1
- package/dist/seed/index.mjs.map +1 -1
- package/dist/{seed-BH2FbrPV.mjs → seed-izIEyP3z.mjs} +7 -19
- package/dist/seed-izIEyP3z.mjs.map +1 -0
- package/dist/service-DCqIWibD.mjs +3 -0
- package/dist/{service-DMohAx8a2.mjs → service-DU1mVzri2.mjs} +3 -4
- package/dist/{service-DMohAx8a2.mjs.map → service-DU1mVzri2.mjs.map} +1 -1
- package/dist/{service-wI3Hvrgx.mjs → service-DjyqbCaJ.mjs} +9 -10
- package/dist/service-DjyqbCaJ.mjs.map +1 -0
- package/dist/{telemetry-BQbbVo2t.mjs → telemetry-CdqJEzkj.mjs} +2 -3
- package/dist/{telemetry-BQbbVo2t.mjs.map → telemetry-CdqJEzkj.mjs.map} +1 -1
- package/dist/telemetry-ClwW5ohF.mjs +3 -0
- package/dist/test-env-key-D7UkZp99.mjs +75 -0
- package/dist/test-env-key-D7UkZp99.mjs.map +1 -0
- package/dist/type-source-DH_LH20p.mjs +13 -0
- package/dist/type-source-DH_LH20p.mjs.map +1 -0
- package/dist/types-74etvaxy.mjs +4 -0
- package/dist/{plugin-C_FyVSdl.d.mts → types-BDRml5C3.d.mts} +128 -188
- package/dist/{types-CmzfQP_m.mjs → types-BQijbo4m.mjs} +10 -11
- package/dist/types-BQijbo4m.mjs.map +1 -0
- package/dist/types-BX4q6Mo6.d.mts +339 -0
- package/dist/types-BZ7QKVE8.d.mts +21 -0
- package/dist/{tailordb-BlBGmQK-.d.mts → types-CdcQh4Z2.d.mts} +92 -242
- package/dist/utils/test/index.d.mts +6 -14
- package/dist/utils/test/index.mjs +4 -14
- package/dist/utils/test/index.mjs.map +1 -1
- package/dist/vitest/environment.mjs +1 -2
- package/dist/vitest/environment.mjs.map +1 -1
- package/dist/vitest/index.d.mts +42 -5
- package/dist/vitest/index.mjs +133 -4
- package/dist/vitest/index.mjs.map +1 -1
- package/dist/vitest/setup.mjs +2 -3
- package/dist/vitest/setup.mjs.map +1 -1
- package/dist/{workflow--aPbA8Uq.mjs → workflow-BOmaZwwG.mjs} +9 -5
- package/dist/workflow-BOmaZwwG.mjs.map +1 -0
- package/dist/{workflow-CMamswkK.d.mts → workflow-BVy4XWjS.d.mts} +15 -10
- package/dist/workflow.generated-ClEjBYhm.d.mts +671 -0
- package/docs/cli/application.md +0 -2
- package/docs/cli/completion.md +3 -0
- package/docs/cli/crashreport.md +0 -2
- package/docs/cli/executor.md +53 -0
- package/docs/cli/function.md +1 -1
- package/docs/cli/setup.md +35 -33
- package/docs/cli/user.md +3 -3
- package/docs/cli/workflow.md +157 -20
- package/docs/cli/workspace.md +3 -3
- package/docs/cli-reference.md +26 -20
- package/docs/configuration.md +0 -2
- package/docs/github-actions.md +29 -16
- package/docs/migration/v2.md +475 -0
- package/docs/plugin/custom.md +2 -2
- package/docs/plugin/index.md +1 -1
- package/docs/runtime.md +4 -4
- package/docs/services/aigateway.md +97 -0
- package/docs/services/auth.md +31 -14
- package/docs/services/executor.md +3 -5
- package/docs/services/resolver.md +8 -10
- package/docs/services/tailordb.md +15 -13
- package/docs/services/workflow.md +17 -19
- package/docs/testing.md +75 -56
- package/package.json +18 -17
- package/dist/actor-J2gJ0eK5.d.mts +0 -24
- package/dist/application-76hhIhnJ.mjs +0 -5594
- package/dist/application-76hhIhnJ.mjs.map +0 -1
- package/dist/application-av2raLs6.mjs +0 -4
- package/dist/cli/skills.d.mts +0 -1
- package/dist/cli/skills.mjs +0 -22
- package/dist/cli/skills.mjs.map +0 -1
- package/dist/client-C68VWo4g.mjs +0 -4
- package/dist/client-CobIRHl-.mjs.map +0 -1
- package/dist/context-s0lxhu8_.mjs.map +0 -1
- package/dist/enum-constants-C7DaWeQo.mjs.map +0 -1
- package/dist/env-B-g-qgE4.d.mts +0 -7
- package/dist/field-C4zdJLW5.mjs.map +0 -1
- package/dist/file-B58Dm-2P.mjs.map +0 -1
- package/dist/file-utils-BHPxPXmn.mjs.map +0 -1
- package/dist/globals-ByrCoDip.mjs.map +0 -1
- package/dist/job-BpsFXPbi.mjs +0 -54
- package/dist/job-BpsFXPbi.mjs.map +0 -1
- package/dist/kysely-type-D1e0Vwkd.mjs.map +0 -1
- package/dist/mock-DMgIygjE.mjs.map +0 -1
- package/dist/package-json-wzO6nV9O.mjs +0 -4
- package/dist/registry-D0uB0OrK.mjs +0 -178
- package/dist/registry-D0uB0OrK.mjs.map +0 -1
- package/dist/runtime-C7qTBDD2.mjs.map +0 -1
- package/dist/schema-1msIhXwA.mjs.map +0 -1
- package/dist/seed-BH2FbrPV.mjs.map +0 -1
- package/dist/service-BHQIerYh.mjs +0 -4
- package/dist/service-wI3Hvrgx.mjs.map +0 -1
- package/dist/telemetry-w92bvGdC.mjs +0 -4
- package/dist/types-2Be3wSMc.mjs +0 -5
- package/dist/types-CmzfQP_m.mjs.map +0 -1
- package/dist/workflow--aPbA8Uq.mjs.map +0 -1
- package/dist/workflow.generated-Bf1tWylx.d.mts +0 -1416
- package/docs/generator/builtin.md +0 -257
- package/docs/generator/custom.md +0 -147
- package/docs/generator/index.md +0 -66
package/docs/testing.md
CHANGED
|
@@ -11,18 +11,21 @@ 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,
|
|
15
|
-
- `workflowJob.body(input, { env })`
|
|
16
|
-
- `
|
|
14
|
+
- `resolver.body({ input, caller, invoker, env })` — invoke a resolver
|
|
15
|
+
- `workflowJob.body(input, { env, invoker })` — invoke a workflow job body directly
|
|
16
|
+
- `workflowJob.trigger(input)` — chain a workflow job through the workflow runtime
|
|
17
|
+
- `runWorkflowLocally(workflow, args)` — run a workflow chain locally with real job bodies
|
|
18
|
+
- `executor.operation.body({ ...args, invoker })` — invoke a function-kind executor
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
For anonymous direct calls:
|
|
19
21
|
|
|
20
|
-
- `
|
|
22
|
+
- Pass `null` for anonymous `caller` / `invoker` context in direct unit tests.
|
|
21
23
|
|
|
22
24
|
Platform API mocks under `@tailor-platform/sdk/vitest` (for use with the [`tailor-runtime` Vitest environment](#runtime-environment-emulation-beta) below):
|
|
23
25
|
|
|
24
26
|
- `mockTailordb` — TailorDB query stubs and call recording
|
|
25
27
|
- `mockWorkflow` — `tailor.workflow` job / wait / resolve mocks
|
|
28
|
+
- `runWorkflowLocally` — local full-chain workflow runner
|
|
26
29
|
- `mockSecretmanager`, `mockAuthconnection`, `mockIdp`, `mockFile`, `mockIconv` — corresponding platform API mocks
|
|
27
30
|
|
|
28
31
|
For tighter alignment with the production runtime — Node.js module blocking, Web-only globals, and platform API mocks — pair the resolver helpers with the [`tailor-runtime` Vitest environment](#runtime-environment-emulation-beta) below.
|
|
@@ -96,7 +99,12 @@ test("resolver queries the database", async () => {
|
|
|
96
99
|
[], // COMMIT
|
|
97
100
|
);
|
|
98
101
|
|
|
99
|
-
const result = await resolver.body({
|
|
102
|
+
const result = await resolver.body({
|
|
103
|
+
input: { email: "test@example.com" },
|
|
104
|
+
caller: null,
|
|
105
|
+
invoker: null,
|
|
106
|
+
env: {},
|
|
107
|
+
});
|
|
100
108
|
|
|
101
109
|
expect(result).toEqual({ oldAge: 30, newAge: 31 });
|
|
102
110
|
expect(db.executedQueries).toHaveLength(3);
|
|
@@ -118,7 +126,12 @@ test("content-based mock", async () => {
|
|
|
118
126
|
return [];
|
|
119
127
|
});
|
|
120
128
|
|
|
121
|
-
const result = await resolver.body({
|
|
129
|
+
const result = await resolver.body({
|
|
130
|
+
input: { userId: "1" },
|
|
131
|
+
caller: null,
|
|
132
|
+
invoker: null,
|
|
133
|
+
env: {},
|
|
134
|
+
});
|
|
122
135
|
|
|
123
136
|
expect(db.executedQueries[0].query).toContain("SELECT");
|
|
124
137
|
});
|
|
@@ -126,7 +139,7 @@ test("content-based mock", async () => {
|
|
|
126
139
|
|
|
127
140
|
### Workflow Mock
|
|
128
141
|
|
|
129
|
-
`.trigger()`
|
|
142
|
+
Workflow job `.trigger()` calls use the platform workflow runtime. Acquire `mockWorkflow()` when you want to provide trigger responses with `setJobHandler` / `enqueueResult` or assert on `triggeredJobs`. If no response is configured, the mock throws so missing job mocks fail loudly:
|
|
130
143
|
|
|
131
144
|
```typescript
|
|
132
145
|
import { mockWorkflow } from "@tailor-platform/sdk/vitest";
|
|
@@ -160,6 +173,8 @@ wf.enqueueResult({ valid: true });
|
|
|
160
173
|
wf.enqueueResults({ valid: true }, { txnId: "txn-1" });
|
|
161
174
|
```
|
|
162
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
|
+
|
|
163
178
|
### SecretManager Mock
|
|
164
179
|
|
|
165
180
|
```typescript
|
|
@@ -262,28 +277,6 @@ test("mock file download stream", async () => {
|
|
|
262
277
|
});
|
|
263
278
|
```
|
|
264
279
|
|
|
265
|
-
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.
|
|
266
|
-
|
|
267
|
-
```typescript
|
|
268
|
-
test("mock file download stream (deprecated openDownloadStream)", async () => {
|
|
269
|
-
using file = mockFile();
|
|
270
|
-
file.enqueueResult([
|
|
271
|
-
{
|
|
272
|
-
type: "metadata",
|
|
273
|
-
metadata: { contentType: "image/png", fileSize: 3, sha256sum: "abc" },
|
|
274
|
-
},
|
|
275
|
-
{ type: "chunk", data: new Uint8Array([1, 2]), position: 0 },
|
|
276
|
-
{ type: "chunk", data: new Uint8Array([3]), position: 2 },
|
|
277
|
-
{ type: "complete" },
|
|
278
|
-
]);
|
|
279
|
-
|
|
280
|
-
const stream = await tailordb.file.openDownloadStream("ns", "Doc", "attachment", "r-1");
|
|
281
|
-
const items = [];
|
|
282
|
-
for await (const item of stream) items.push(item);
|
|
283
|
-
expect(items).toHaveLength(4);
|
|
284
|
-
});
|
|
285
|
-
```
|
|
286
|
-
|
|
287
280
|
### Iconv Mock
|
|
288
281
|
|
|
289
282
|
```typescript
|
|
@@ -364,7 +357,6 @@ Unit tests call `.body()` (or `.trigger()`) directly on a resolver, workflow job
|
|
|
364
357
|
For pure logic with no external dependencies, invoke `.body()` directly:
|
|
365
358
|
|
|
366
359
|
```typescript
|
|
367
|
-
import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
|
|
368
360
|
import { describe, expect, test } from "vitest";
|
|
369
361
|
import resolver from "../src/resolver/add";
|
|
370
362
|
|
|
@@ -372,7 +364,8 @@ describe("add resolver", () => {
|
|
|
372
364
|
test("adds two numbers", async () => {
|
|
373
365
|
const result = await resolver.body({
|
|
374
366
|
input: { left: 1, right: 2 },
|
|
375
|
-
|
|
367
|
+
caller: null,
|
|
368
|
+
invoker: null,
|
|
376
369
|
env: {},
|
|
377
370
|
});
|
|
378
371
|
expect(result).toBe(3);
|
|
@@ -389,7 +382,6 @@ Stub the global `tailordb.Client` and queue raw query results in order. Best for
|
|
|
389
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()`.
|
|
390
383
|
|
|
391
384
|
```typescript
|
|
392
|
-
import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
|
|
393
385
|
import { afterAll, afterEach, beforeAll, describe, expect, test, vi } from "vitest";
|
|
394
386
|
import resolver from "../src/resolver/incrementUserAge";
|
|
395
387
|
|
|
@@ -419,7 +411,8 @@ describe("incrementUserAge resolver", () => {
|
|
|
419
411
|
|
|
420
412
|
const result = await resolver.body({
|
|
421
413
|
input: { email: "test@example.com" },
|
|
422
|
-
|
|
414
|
+
caller: null,
|
|
415
|
+
invoker: null,
|
|
423
416
|
env: {},
|
|
424
417
|
});
|
|
425
418
|
|
|
@@ -490,7 +483,6 @@ describe("decrementUserAge", () => {
|
|
|
490
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:
|
|
491
484
|
|
|
492
485
|
```typescript
|
|
493
|
-
import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
|
|
494
486
|
import { createKyselyMock } from "@tailor-platform/sdk/vitest";
|
|
495
487
|
import { describe, expect, test, vi } from "vitest";
|
|
496
488
|
import { getDB, type Namespace } from "../generated/db";
|
|
@@ -522,7 +514,8 @@ describe("upsertUsers resolver", () => {
|
|
|
522
514
|
{ name: "Existing", email: "exists@example.com", age: 41 },
|
|
523
515
|
],
|
|
524
516
|
},
|
|
525
|
-
|
|
517
|
+
caller: null,
|
|
518
|
+
invoker: null,
|
|
526
519
|
env: { appName: "Resolver Template", version: 1 },
|
|
527
520
|
});
|
|
528
521
|
|
|
@@ -541,7 +534,6 @@ Reach for [`mockTailordb`](#mocking-the-tailordb-client) instead when you want t
|
|
|
541
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`:
|
|
542
535
|
|
|
543
536
|
```typescript
|
|
544
|
-
import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
|
|
545
537
|
import { mockWorkflow } from "@tailor-platform/sdk/vitest";
|
|
546
538
|
import { describe, expect, test } from "vitest";
|
|
547
539
|
import resolver from "./resolveApproval";
|
|
@@ -556,7 +548,8 @@ describe("resolveApproval resolver", () => {
|
|
|
556
548
|
|
|
557
549
|
const result = await resolver.body({
|
|
558
550
|
input: { executionId: "exec-1", approved: true },
|
|
559
|
-
|
|
551
|
+
caller: null,
|
|
552
|
+
invoker: null,
|
|
560
553
|
env: {},
|
|
561
554
|
});
|
|
562
555
|
|
|
@@ -570,7 +563,7 @@ describe("resolveApproval resolver", () => {
|
|
|
570
563
|
|
|
571
564
|
### Testing Executors
|
|
572
565
|
|
|
573
|
-
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
|
|
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.
|
|
574
567
|
|
|
575
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:
|
|
576
569
|
|
|
@@ -587,6 +580,14 @@ describe("onUserCreated executor", () => {
|
|
|
587
580
|
throw new Error("expected function operation");
|
|
588
581
|
}
|
|
589
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",
|
|
590
591
|
newRecord: {
|
|
591
592
|
id: "user-1",
|
|
592
593
|
name: "Alice",
|
|
@@ -615,7 +616,7 @@ Workflow jobs expose the same `.body()` entrypoint as resolvers, plus `.trigger(
|
|
|
615
616
|
|
|
616
617
|
#### Simple job
|
|
617
618
|
|
|
618
|
-
Call `.body()` with the input and a stub `{ env: {} }`:
|
|
619
|
+
Call `.body()` with the input and a stub `{ env: {}, invoker: null }`:
|
|
619
620
|
|
|
620
621
|
```typescript
|
|
621
622
|
import { describe, expect, test } from "vitest";
|
|
@@ -623,14 +624,17 @@ import { validateOrder } from "./order-fulfillment";
|
|
|
623
624
|
|
|
624
625
|
describe("validateOrder", () => {
|
|
625
626
|
test("accepts a valid order", () => {
|
|
626
|
-
const result = validateOrder.body(
|
|
627
|
+
const result = validateOrder.body(
|
|
628
|
+
{ orderId: "order-1", amount: 100 },
|
|
629
|
+
{ env: {}, invoker: null },
|
|
630
|
+
);
|
|
627
631
|
expect(result).toEqual({ valid: true, orderId: "order-1" });
|
|
628
632
|
});
|
|
629
633
|
|
|
630
634
|
test("rejects a non-positive amount", () => {
|
|
631
|
-
expect(() =>
|
|
632
|
-
"
|
|
633
|
-
);
|
|
635
|
+
expect(() =>
|
|
636
|
+
validateOrder.body({ orderId: "order-1", amount: 0 }, { env: {}, invoker: null }),
|
|
637
|
+
).toThrow("Order amount must be positive");
|
|
634
638
|
});
|
|
635
639
|
});
|
|
636
640
|
```
|
|
@@ -645,22 +649,25 @@ import { fulfillOrder, processPayment, sendConfirmation, validateOrder } from ".
|
|
|
645
649
|
|
|
646
650
|
describe("fulfillOrder", () => {
|
|
647
651
|
test("chains validate → pay → confirm", async () => {
|
|
648
|
-
using _validateSpy = vi.spyOn(validateOrder, "trigger").
|
|
652
|
+
using _validateSpy = vi.spyOn(validateOrder, "trigger").mockReturnValue({
|
|
649
653
|
valid: true,
|
|
650
654
|
orderId: "order-1",
|
|
651
655
|
});
|
|
652
|
-
using _paymentSpy = vi.spyOn(processPayment, "trigger").
|
|
656
|
+
using _paymentSpy = vi.spyOn(processPayment, "trigger").mockReturnValue({
|
|
653
657
|
transactionId: "txn-order-1",
|
|
654
658
|
amount: 100,
|
|
655
659
|
status: "completed",
|
|
656
660
|
});
|
|
657
|
-
using _confirmSpy = vi.spyOn(sendConfirmation, "trigger").
|
|
661
|
+
using _confirmSpy = vi.spyOn(sendConfirmation, "trigger").mockReturnValue({
|
|
658
662
|
orderId: "order-1",
|
|
659
663
|
transactionId: "txn-order-1",
|
|
660
664
|
confirmed: true,
|
|
661
665
|
});
|
|
662
666
|
|
|
663
|
-
const result = await fulfillOrder.body(
|
|
667
|
+
const result = await fulfillOrder.body(
|
|
668
|
+
{ orderId: "order-1", amount: 100 },
|
|
669
|
+
{ env: {}, invoker: null },
|
|
670
|
+
);
|
|
664
671
|
|
|
665
672
|
expect(validateOrder.trigger).toHaveBeenCalledWith({ orderId: "order-1", amount: 100 });
|
|
666
673
|
expect(result).toMatchObject({ confirmed: true, paymentStatus: "completed" });
|
|
@@ -684,7 +691,10 @@ describe("processWithApproval", () => {
|
|
|
684
691
|
using wf = mockWorkflow();
|
|
685
692
|
wf.setWaitHandler({ approved: true });
|
|
686
693
|
|
|
687
|
-
const result = await processWithApproval.body(
|
|
694
|
+
const result = await processWithApproval.body(
|
|
695
|
+
{ orderId: "order-1" },
|
|
696
|
+
{ env: {}, invoker: null },
|
|
697
|
+
);
|
|
688
698
|
|
|
689
699
|
expect(result).toEqual({ orderId: "order-1", status: "approved" });
|
|
690
700
|
expect(wf.waitCalls[0]).toEqual({
|
|
@@ -697,7 +707,10 @@ describe("processWithApproval", () => {
|
|
|
697
707
|
using wf = mockWorkflow();
|
|
698
708
|
wf.setWaitHandler({ approved: false });
|
|
699
709
|
|
|
700
|
-
const result = await processWithApproval.body(
|
|
710
|
+
const result = await processWithApproval.body(
|
|
711
|
+
{ orderId: "order-2" },
|
|
712
|
+
{ env: {}, invoker: null },
|
|
713
|
+
);
|
|
701
714
|
|
|
702
715
|
expect(result.status).toBe("rejected");
|
|
703
716
|
});
|
|
@@ -708,22 +721,29 @@ describe("processWithApproval", () => {
|
|
|
708
721
|
|
|
709
722
|
#### Running a full workflow locally
|
|
710
723
|
|
|
711
|
-
To exercise the full chain with real job bodies,
|
|
724
|
+
To exercise the full chain with real job bodies, call `runWorkflowLocally(workflow, args)`. Dependent jobs run their real `.body()` functions, and trigger args/results cross the same JSON boundary as the platform, so a non-serializable payload fails the test exactly as it would in production:
|
|
712
725
|
|
|
713
726
|
```typescript
|
|
727
|
+
import { runWorkflowLocally } from "@tailor-platform/sdk/vitest";
|
|
714
728
|
import { describe, expect, test } from "vitest";
|
|
715
729
|
import workflow from "./order-fulfillment";
|
|
716
730
|
|
|
717
731
|
describe("order-fulfillment workflow", () => {
|
|
718
|
-
test("
|
|
719
|
-
const result = await workflow
|
|
732
|
+
test("runWorkflowLocally() executes all jobs", async () => {
|
|
733
|
+
const result = await runWorkflowLocally(workflow, { orderId: "order-3", amount: 300 });
|
|
720
734
|
|
|
721
735
|
expect(result).toMatchObject({ confirmed: true, paymentStatus: "completed" });
|
|
722
736
|
});
|
|
723
737
|
});
|
|
724
738
|
```
|
|
725
739
|
|
|
726
|
-
|
|
740
|
+
Pass `{ env }` as the third argument when job bodies need configuration values during the local run.
|
|
741
|
+
|
|
742
|
+
If you already acquired `mockWorkflow()`, you can also call `wf.setEnv(...)` to reuse the same env across local workflow runs.
|
|
743
|
+
|
|
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.
|
|
745
|
+
|
|
746
|
+
This helper is still a local runner. Use E2E tests when you need to verify deployed workflow scheduling, suspension, or replay behavior.
|
|
727
747
|
|
|
728
748
|
**Use when:** you want to verify orchestration end to end without the cost of a real deployment.
|
|
729
749
|
|
|
@@ -823,14 +843,13 @@ Use `startWorkflow` from the CLI helpers. It starts the workflow on the deployed
|
|
|
823
843
|
import { randomUUID } from "node:crypto";
|
|
824
844
|
import { startWorkflow } from "@tailor-platform/sdk/cli";
|
|
825
845
|
import { describe, expect, test } from "vitest";
|
|
826
|
-
import config from "../tailor.config";
|
|
827
846
|
import userProfileSync from "../src/workflow/sync-profile";
|
|
828
847
|
|
|
829
848
|
describe("user-profile-sync workflow", () => {
|
|
830
849
|
test("executes end to end", { timeout: 180_000 }, async () => {
|
|
831
850
|
const { executionId, wait } = await startWorkflow({
|
|
832
851
|
workflow: userProfileSync,
|
|
833
|
-
|
|
852
|
+
invoker: "admin",
|
|
834
853
|
arg: {
|
|
835
854
|
name: "workflow-test",
|
|
836
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.
|
|
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": {
|
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
"directory": "packages/sdk"
|
|
10
10
|
},
|
|
11
11
|
"bin": {
|
|
12
|
-
"tailor-sdk": "./dist/cli/index.mjs"
|
|
13
|
-
"tailor-sdk-skills": "./dist/cli/skills.mjs"
|
|
12
|
+
"tailor-sdk": "./dist/cli/index.mjs"
|
|
14
13
|
},
|
|
15
14
|
"files": [
|
|
16
15
|
"CHANGELOG.md",
|
|
@@ -135,12 +134,12 @@
|
|
|
135
134
|
}
|
|
136
135
|
},
|
|
137
136
|
"dependencies": {
|
|
138
|
-
"@0no-co/graphql.web": "1.2
|
|
137
|
+
"@0no-co/graphql.web": "1.3.2",
|
|
139
138
|
"@badgateway/oauth2-client": "3.3.1",
|
|
140
139
|
"@bufbuild/protobuf": "2.12.0",
|
|
141
140
|
"@bufbuild/protovalidate": "1.2.0",
|
|
142
|
-
"@connectrpc/connect": "2.1.
|
|
143
|
-
"@connectrpc/connect-node": "2.1.
|
|
141
|
+
"@connectrpc/connect": "2.1.2",
|
|
142
|
+
"@connectrpc/connect-node": "2.1.2",
|
|
144
143
|
"@inquirer/core": "11.2.1",
|
|
145
144
|
"@inquirer/prompts": "8.5.2",
|
|
146
145
|
"@jridgewell/trace-mapping": "0.3.31",
|
|
@@ -160,10 +159,10 @@
|
|
|
160
159
|
"chokidar": "5.0.0",
|
|
161
160
|
"confbox": "0.2.4",
|
|
162
161
|
"date-fns": "4.4.0",
|
|
163
|
-
"es-toolkit": "1.47.
|
|
162
|
+
"es-toolkit": "1.47.1",
|
|
164
163
|
"find-up-simple": "1.0.1",
|
|
165
164
|
"globals": "17.6.0",
|
|
166
|
-
"graphql": "16.14.
|
|
165
|
+
"graphql": "16.14.2",
|
|
167
166
|
"inflection": "3.0.2",
|
|
168
167
|
"kysely": "0.29.2",
|
|
169
168
|
"madge": "8.0.0",
|
|
@@ -174,16 +173,16 @@
|
|
|
174
173
|
"pathe": "2.0.3",
|
|
175
174
|
"pgsql-ast-parser": "12.0.2",
|
|
176
175
|
"pkg-types": "2.3.1",
|
|
177
|
-
"politty": "0.
|
|
178
|
-
"rolldown": "1.1.
|
|
179
|
-
"semver": "7.8.
|
|
176
|
+
"politty": "0.6.0",
|
|
177
|
+
"rolldown": "1.1.1",
|
|
178
|
+
"semver": "7.8.5",
|
|
180
179
|
"sql-highlight": "6.1.0",
|
|
181
180
|
"std-env": "4.1.0",
|
|
182
181
|
"table": "6.9.0",
|
|
183
182
|
"ts-cron-validator": "1.1.5",
|
|
184
183
|
"tsx": "4.22.4",
|
|
185
184
|
"type-fest": "5.7.0",
|
|
186
|
-
"undici": "8.
|
|
185
|
+
"undici": "8.5.0",
|
|
187
186
|
"xdg-basedir": "5.1.0",
|
|
188
187
|
"zod": "4.4.3"
|
|
189
188
|
},
|
|
@@ -191,16 +190,16 @@
|
|
|
191
190
|
"@opentelemetry/sdk-trace-base": "2.8.0",
|
|
192
191
|
"@types/madge": "5.0.3",
|
|
193
192
|
"@types/mime-types": "3.0.1",
|
|
194
|
-
"@types/node": "24.13.
|
|
193
|
+
"@types/node": "24.13.2",
|
|
195
194
|
"@types/semver": "7.7.1",
|
|
196
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
195
|
+
"@typescript/native-preview": "7.0.0-dev.20260614.1",
|
|
197
196
|
"@vitest/coverage-v8": "4.1.8",
|
|
198
197
|
"oxfmt": "0.54.0",
|
|
199
198
|
"oxlint": "1.69.0",
|
|
200
199
|
"oxlint-tsgolint": "0.23.0",
|
|
201
|
-
"sonda": "0.
|
|
200
|
+
"sonda": "0.13.1",
|
|
202
201
|
"tsdown": "0.22.2",
|
|
203
|
-
"typescript": "
|
|
202
|
+
"typescript": "6.0.3",
|
|
204
203
|
"vitest": "4.1.8",
|
|
205
204
|
"zinfer": "0.1.8"
|
|
206
205
|
},
|
|
@@ -227,9 +226,11 @@
|
|
|
227
226
|
"test:coverage": "vitest --coverage",
|
|
228
227
|
"docs:check": "vitest run --project=unit* src/cli/docs.test.ts",
|
|
229
228
|
"docs:update": "POLITTY_DOCS_UPDATE=true vitest run --project=unit* src/cli/docs.test.ts",
|
|
230
|
-
"build": "tsdown",
|
|
229
|
+
"build": "tsdown && politty generate-worker --bin dist/cli/index.mjs --program tailor-sdk --shell zsh --verify",
|
|
231
230
|
"lint": "oxlint --type-aware .",
|
|
232
231
|
"check:public-api-jsdoc": "tsx scripts/check-public-api-jsdoc.ts",
|
|
232
|
+
"check:zod-isolation": "tsx scripts/check-zod-isolation.ts",
|
|
233
|
+
"check:import-cycles": "tsx scripts/check-import-cycles.ts",
|
|
233
234
|
"lint:fix": "oxlint --type-aware . --fix",
|
|
234
235
|
"typecheck": "tsc --noEmit",
|
|
235
236
|
"typecheck:go": "tsgo",
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { A as InferredAttributeList, j as InferredAttributeMap } from "./tailordb-BlBGmQK-.mjs";
|
|
2
|
-
|
|
3
|
-
//#region src/types/actor.d.ts
|
|
4
|
-
/** User type enum values from the Tailor Platform server. */
|
|
5
|
-
type TailorActorType = "USER_TYPE_USER" | "USER_TYPE_MACHINE_USER" | "USER_TYPE_UNSPECIFIED";
|
|
6
|
-
/** Represents an actor in event triggers. */
|
|
7
|
-
type TailorActor = {
|
|
8
|
-
/** The ID of the workspace the user belongs to. */workspaceId: string; /** The ID of the user. */
|
|
9
|
-
userId: string;
|
|
10
|
-
/**
|
|
11
|
-
* A map of the user's attributes.
|
|
12
|
-
* Maps from server's `attributeMap` field.
|
|
13
|
-
*/
|
|
14
|
-
attributes: InferredAttributeMap | null;
|
|
15
|
-
/**
|
|
16
|
-
* A list of the user's attributes.
|
|
17
|
-
* Maps from server's `attributes` field.
|
|
18
|
-
*/
|
|
19
|
-
attributeList: InferredAttributeList; /** The type of the user. */
|
|
20
|
-
userType: TailorActorType;
|
|
21
|
-
};
|
|
22
|
-
//#endregion
|
|
23
|
-
export { TailorActor as t };
|
|
24
|
-
//# sourceMappingURL=actor-J2gJ0eK5.d.mts.map
|