@tailor-platform/create-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.
- package/CHANGELOG.md +24 -0
- package/package.json +2 -2
- package/templates/executor/package.json +2 -2
- package/templates/executor/src/generated/db.ts +3 -3
- package/templates/generators/package.json +2 -2
- package/templates/generators/src/generated/db.ts +3 -3
- package/templates/generators/src/generated/files.ts +4 -4
- package/templates/generators/src/resolver/getProduct.test.ts +4 -3
- package/templates/generators/src/seed/data/Order.schema.ts +2 -2
- package/templates/generators/src/seed/data/Product.schema.ts +2 -2
- package/templates/generators/src/seed/data/User.schema.ts +2 -2
- package/templates/generators/src/seed/exec.mjs +1 -1
- package/templates/hello-world/package.json +2 -2
- package/templates/hello-world/src/generated/kysely-tailordb.ts +1 -1
- package/templates/inventory-management/package.json +2 -2
- package/templates/inventory-management/src/executor/checkInventory.ts +1 -1
- package/templates/inventory-management/src/generated/kysely-tailordb.ts +8 -8
- package/templates/inventory-management/src/resolver/registerOrder.ts +2 -2
- package/templates/multi-application/apps/admin/db/adminNote.ts +1 -1
- package/templates/multi-application/package.json +2 -2
- package/templates/resolver/README.md +2 -2
- package/templates/resolver/package.json +2 -2
- package/templates/resolver/src/generated/db.ts +1 -1
- package/templates/resolver/src/resolver/add.test.ts +4 -3
- package/templates/resolver/src/resolver/incrementUserAge.test.ts +4 -3
- package/templates/resolver/src/resolver/showEnv.test.ts +2 -2
- package/templates/resolver/src/resolver/showUserInfo.test.ts +12 -9
- package/templates/resolver/src/resolver/showUserInfo.ts +3 -3
- package/templates/resolver/src/resolver/upsertUsers.test.ts +2 -2
- package/templates/static-web-site/package.json +2 -2
- package/templates/tailordb/package.json +2 -2
- package/templates/tailordb/src/generated/db.ts +3 -3
- package/templates/workflow/e2e/workflow.test.ts +1 -1
- package/templates/workflow/package.json +2 -2
- package/templates/workflow/src/generated/db.ts +2 -2
- package/templates/workflow/src/resolver/resolveApproval.test.ts +4 -3
- package/templates/workflow/src/workflow/approval.test.ts +8 -2
- package/templates/workflow/src/workflow/order-fulfillment.test.ts +20 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @tailor-platform/create-sdk
|
|
2
2
|
|
|
3
|
+
## 2.0.0-next.2
|
|
4
|
+
### Major Changes
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
- [#1498](https://github.com/tailor-platform/sdk/pull/1498) [`83145db`](https://github.com/tailor-platform/sdk/commit/83145db9a0d243aa68c1b641c2b6026771a62188) Thanks [@dqn](https://github.com/dqn)! - Set `db.fields.timestamps()` `updatedAt` when records are created and make the generated field non-null. `createdAt` keeps its existing create-time behavior, while `updatedAt` keeps its update-time behavior and now also gets a create hook that preserves provided values and falls back to the current time.
|
|
9
|
+
|
|
10
|
+
Update create-sdk templates so scaffolded projects use the new non-null `updatedAt` Kysely types and seed schemas.
|
|
11
|
+
|
|
12
|
+
Existing TailorDB schemas that already use this helper will change `updatedAt` from optional to required. Backfill existing records that have `updatedAt: null` before applying the schema change.
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
- [#1509](https://github.com/tailor-platform/sdk/pull/1509) [`7cadaa7`](https://github.com/tailor-platform/sdk/commit/7cadaa7c4987b81130ca80ba80bc5d5b26276394) Thanks [@dqn](https://github.com/dqn)! - Rename resolver, executor, workflow trigger, and typed workflow start machine-user options from `authInvoker` to `invoker`.
|
|
19
|
+
|
|
20
|
+
Update create-sdk templates and the v2 auth invoker codemod to generate the new `invoker` option.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
- [#1484](https://github.com/tailor-platform/sdk/pull/1484) [`a376dc8`](https://github.com/tailor-platform/sdk/commit/a376dc8cd053d20744c90104e8b44ed2729ffe8c) Thanks [@dqn](https://github.com/dqn)! - Remove the deprecated `openDownloadStream` file streaming API. Use `downloadStream` for streamed file downloads.
|
|
24
|
+
|
|
25
|
+
The generated file utilities now emit `downloadFileStream`, which calls `downloadStream` and returns `FileDownloadStreamResponse`, instead of the removed `openFileDownloadStream` helper.
|
|
26
|
+
|
|
3
27
|
## 2.0.0-next.1
|
|
4
28
|
|
|
5
29
|
## 2.0.0-next.0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tailor-platform/create-sdk",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.2",
|
|
4
4
|
"description": "A CLI tool to quickly create a new Tailor Platform SDK project",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"oxlint": "1.69.0",
|
|
30
30
|
"oxlint-tsgolint": "0.23.0",
|
|
31
31
|
"tsdown": "0.22.2",
|
|
32
|
-
"typescript": "
|
|
32
|
+
"typescript": "6.0.3"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
35
|
"build": "tsdown",
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"typecheck": "tsc --noEmit"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@tailor-platform/sdk": "2.0.0-next.
|
|
17
|
+
"@tailor-platform/sdk": "2.0.0-next.2",
|
|
18
18
|
"@types/node": "24.13.2",
|
|
19
19
|
"oxfmt": "0.54.0",
|
|
20
20
|
"oxlint": "1.69.0",
|
|
21
21
|
"oxlint-tsgolint": "0.23.0",
|
|
22
|
-
"typescript": "
|
|
22
|
+
"typescript": "6.0.3",
|
|
23
23
|
"vitest": "4.1.8"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -20,7 +20,7 @@ export interface Namespace {
|
|
|
20
20
|
entityId: string;
|
|
21
21
|
message: string;
|
|
22
22
|
createdAt: Generated<Timestamp>;
|
|
23
|
-
updatedAt: Timestamp
|
|
23
|
+
updatedAt: Generated<Timestamp>;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
Notification: {
|
|
@@ -30,7 +30,7 @@ export interface Namespace {
|
|
|
30
30
|
body: string;
|
|
31
31
|
isRead: boolean;
|
|
32
32
|
createdAt: Generated<Timestamp>;
|
|
33
|
-
updatedAt: Timestamp
|
|
33
|
+
updatedAt: Generated<Timestamp>;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
User: {
|
|
@@ -39,7 +39,7 @@ export interface Namespace {
|
|
|
39
39
|
email: string;
|
|
40
40
|
role: "ADMIN" | "MEMBER";
|
|
41
41
|
createdAt: Generated<Timestamp>;
|
|
42
|
-
updatedAt: Timestamp
|
|
42
|
+
updatedAt: Generated<Timestamp>;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"typecheck": "tsc --noEmit"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@tailor-platform/sdk": "2.0.0-next.
|
|
17
|
+
"@tailor-platform/sdk": "2.0.0-next.2",
|
|
18
18
|
"@types/node": "24.13.2",
|
|
19
19
|
"oxfmt": "0.54.0",
|
|
20
20
|
"oxlint": "1.69.0",
|
|
21
21
|
"oxlint-tsgolint": "0.23.0",
|
|
22
|
-
"typescript": "
|
|
22
|
+
"typescript": "6.0.3",
|
|
23
23
|
"vitest": "4.1.8"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -28,7 +28,7 @@ export interface Namespace {
|
|
|
28
28
|
totalPrice: number;
|
|
29
29
|
status: "PENDING" | "CONFIRMED" | "SHIPPED" | "DELIVERED" | "CANCELLED";
|
|
30
30
|
createdAt: Generated<Timestamp>;
|
|
31
|
-
updatedAt: Timestamp
|
|
31
|
+
updatedAt: Generated<Timestamp>;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
Product: {
|
|
@@ -39,7 +39,7 @@ export interface Namespace {
|
|
|
39
39
|
status: "DRAFT" | "ACTIVE" | "DISCONTINUED";
|
|
40
40
|
categoryId: string | null;
|
|
41
41
|
createdAt: Generated<Timestamp>;
|
|
42
|
-
updatedAt: Timestamp
|
|
42
|
+
updatedAt: Generated<Timestamp>;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
User: {
|
|
@@ -48,7 +48,7 @@ export interface Namespace {
|
|
|
48
48
|
email: string;
|
|
49
49
|
role: "ADMIN" | "MEMBER" | "VIEWER";
|
|
50
50
|
createdAt: Generated<Timestamp>;
|
|
51
|
-
updatedAt: Timestamp
|
|
51
|
+
updatedAt: Generated<Timestamp>;
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -3,7 +3,7 @@ import type {
|
|
|
3
3
|
FileUploadOptions,
|
|
4
4
|
FileUploadResponse,
|
|
5
5
|
FileMetadata,
|
|
6
|
-
|
|
6
|
+
FileDownloadStreamResponse,
|
|
7
7
|
} from "@tailor-platform/sdk/runtime/file";
|
|
8
8
|
|
|
9
9
|
export interface TypeWithFiles {
|
|
@@ -50,10 +50,10 @@ export async function getFileMetadata<T extends keyof TypeWithFiles>(
|
|
|
50
50
|
return await file.getMetadata(namespaces[type], type, field, recordId);
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
export async function
|
|
53
|
+
export async function downloadFileStream<T extends keyof TypeWithFiles>(
|
|
54
54
|
type: T,
|
|
55
55
|
field: TypeWithFiles[T]["fields"],
|
|
56
56
|
recordId: string,
|
|
57
|
-
): Promise<
|
|
58
|
-
return await file.
|
|
57
|
+
): Promise<FileDownloadStreamResponse> {
|
|
58
|
+
return await file.downloadStream(namespaces[type], type, field, recordId);
|
|
59
59
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
|
|
2
1
|
import { mockTailordb } from "@tailor-platform/sdk/vitest";
|
|
3
2
|
import { describe, expect, test } from "vitest";
|
|
4
3
|
import resolver from "./getProduct";
|
|
@@ -22,7 +21,8 @@ describe("getProduct resolver", () => {
|
|
|
22
21
|
|
|
23
22
|
const result = await resolver.body({
|
|
24
23
|
input: { productId: "product-1" },
|
|
25
|
-
|
|
24
|
+
caller: null,
|
|
25
|
+
invoker: null,
|
|
26
26
|
env: {},
|
|
27
27
|
});
|
|
28
28
|
|
|
@@ -51,7 +51,8 @@ describe("getProduct resolver", () => {
|
|
|
51
51
|
|
|
52
52
|
const result = await resolver.body({
|
|
53
53
|
input: { productId: "product-2" },
|
|
54
|
-
|
|
54
|
+
caller: null,
|
|
55
|
+
invoker: null,
|
|
55
56
|
env: {},
|
|
56
57
|
});
|
|
57
58
|
|
|
@@ -4,8 +4,8 @@ import { createTailorDBHook, createStandardSchema } from "@tailor-platform/sdk/t
|
|
|
4
4
|
import { order } from "../../db/order";
|
|
5
5
|
|
|
6
6
|
const schemaType = t.object({
|
|
7
|
-
...order.pickFields(["id","createdAt"], { optional: true }),
|
|
8
|
-
...order.omitFields(["id","createdAt"]),
|
|
7
|
+
...order.pickFields(["id","createdAt","updatedAt"], { optional: true }),
|
|
8
|
+
...order.omitFields(["id","createdAt","updatedAt"]),
|
|
9
9
|
});
|
|
10
10
|
|
|
11
11
|
const hook = createTailorDBHook(order);
|
|
@@ -4,8 +4,8 @@ import { createTailorDBHook, createStandardSchema } from "@tailor-platform/sdk/t
|
|
|
4
4
|
import { product } from "../../db/product";
|
|
5
5
|
|
|
6
6
|
const schemaType = t.object({
|
|
7
|
-
...product.pickFields(["id","createdAt"], { optional: true }),
|
|
8
|
-
...product.omitFields(["id","createdAt"]),
|
|
7
|
+
...product.pickFields(["id","createdAt","updatedAt"], { optional: true }),
|
|
8
|
+
...product.omitFields(["id","createdAt","updatedAt"]),
|
|
9
9
|
});
|
|
10
10
|
|
|
11
11
|
const hook = createTailorDBHook(product);
|
|
@@ -4,8 +4,8 @@ import { createTailorDBHook, createStandardSchema } from "@tailor-platform/sdk/t
|
|
|
4
4
|
import { user } from "../../db/user";
|
|
5
5
|
|
|
6
6
|
const schemaType = t.object({
|
|
7
|
-
...user.pickFields(["id","createdAt"], { optional: true }),
|
|
8
|
-
...user.omitFields(["id","createdAt"]),
|
|
7
|
+
...user.pickFields(["id","createdAt","updatedAt"], { optional: true }),
|
|
8
|
+
...user.omitFields(["id","createdAt","updatedAt"]),
|
|
9
9
|
});
|
|
10
10
|
|
|
11
11
|
const hook = createTailorDBHook(user);
|
|
@@ -388,7 +388,7 @@ const seedViaTestExecScript = async (namespace, typesToSeed, deps, selfRefTypes)
|
|
|
388
388
|
workspaceId,
|
|
389
389
|
name: `seed-${namespace}.ts`,
|
|
390
390
|
code: bundled.bundledCode,
|
|
391
|
-
arg:
|
|
391
|
+
arg: { data: chunk.data, order: chunk.order, selfRefTypes },
|
|
392
392
|
invoker: {
|
|
393
393
|
namespace: authNamespace,
|
|
394
394
|
machineUserName,
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
"typecheck": "tsc --noEmit"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@tailor-platform/sdk": "2.0.0-next.
|
|
15
|
+
"@tailor-platform/sdk": "2.0.0-next.2",
|
|
16
16
|
"@types/node": "24.13.2",
|
|
17
17
|
"oxfmt": "0.54.0",
|
|
18
18
|
"oxlint": "1.69.0",
|
|
19
19
|
"oxlint-tsgolint": "0.23.0",
|
|
20
|
-
"typescript": "
|
|
20
|
+
"typescript": "6.0.3"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
"typecheck": "tsc --noEmit"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@tailor-platform/sdk": "2.0.0-next.
|
|
15
|
+
"@tailor-platform/sdk": "2.0.0-next.2",
|
|
16
16
|
"@types/node": "24.13.2",
|
|
17
17
|
"oxfmt": "0.54.0",
|
|
18
18
|
"oxlint": "1.69.0",
|
|
19
19
|
"oxlint-tsgolint": "0.23.0",
|
|
20
|
-
"typescript": "
|
|
20
|
+
"typescript": "6.0.3"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -18,7 +18,7 @@ export interface Namespace {
|
|
|
18
18
|
name: string;
|
|
19
19
|
description: string | null;
|
|
20
20
|
createdAt: Generated<Timestamp>;
|
|
21
|
-
updatedAt: Timestamp
|
|
21
|
+
updatedAt: Generated<Timestamp>;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
Contact: {
|
|
@@ -28,7 +28,7 @@ export interface Namespace {
|
|
|
28
28
|
phone: string | null;
|
|
29
29
|
address: string | null;
|
|
30
30
|
createdAt: Generated<Timestamp>;
|
|
31
|
-
updatedAt: Timestamp
|
|
31
|
+
updatedAt: Generated<Timestamp>;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
Inventory: {
|
|
@@ -36,14 +36,14 @@ export interface Namespace {
|
|
|
36
36
|
productId: string;
|
|
37
37
|
quantity: number;
|
|
38
38
|
createdAt: Generated<Timestamp>;
|
|
39
|
-
updatedAt: Timestamp
|
|
39
|
+
updatedAt: Generated<Timestamp>;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
Notification: {
|
|
43
43
|
id: Generated<string>;
|
|
44
44
|
message: string;
|
|
45
45
|
createdAt: Generated<Timestamp>;
|
|
46
|
-
updatedAt: Timestamp
|
|
46
|
+
updatedAt: Generated<Timestamp>;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
Order: {
|
|
@@ -54,7 +54,7 @@ export interface Namespace {
|
|
|
54
54
|
orderType: "PURCHASE" | "SALES";
|
|
55
55
|
contactId: string;
|
|
56
56
|
createdAt: Generated<Timestamp>;
|
|
57
|
-
updatedAt: Timestamp
|
|
57
|
+
updatedAt: Generated<Timestamp>;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
OrderItem: {
|
|
@@ -65,7 +65,7 @@ export interface Namespace {
|
|
|
65
65
|
unitPrice: number;
|
|
66
66
|
totalPrice: Generated<number | null>;
|
|
67
67
|
createdAt: Generated<Timestamp>;
|
|
68
|
-
updatedAt: Timestamp
|
|
68
|
+
updatedAt: Generated<Timestamp>;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
Product: {
|
|
@@ -74,7 +74,7 @@ export interface Namespace {
|
|
|
74
74
|
description: string | null;
|
|
75
75
|
categoryId: string;
|
|
76
76
|
createdAt: Generated<Timestamp>;
|
|
77
|
-
updatedAt: Timestamp
|
|
77
|
+
updatedAt: Generated<Timestamp>;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
User: {
|
|
@@ -83,7 +83,7 @@ export interface Namespace {
|
|
|
83
83
|
email: string;
|
|
84
84
|
role: "MANAGER" | "STAFF";
|
|
85
85
|
createdAt: Generated<Timestamp>;
|
|
86
|
-
updatedAt: Timestamp
|
|
86
|
+
updatedAt: Generated<Timestamp>;
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -4,8 +4,8 @@ import { orderItem } from "../db/orderItem";
|
|
|
4
4
|
import { type DB, getDB } from "../generated/kysely-tailordb";
|
|
5
5
|
|
|
6
6
|
const input = {
|
|
7
|
-
order: t.object(order.omitFields(["id", "createdAt"])),
|
|
8
|
-
items: t.object(orderItem.omitFields(["id", "createdAt"]), { array: true }),
|
|
7
|
+
order: t.object(order.omitFields(["id", "createdAt", "updatedAt"])),
|
|
8
|
+
items: t.object(orderItem.omitFields(["id", "createdAt", "updatedAt"]), { array: true }),
|
|
9
9
|
};
|
|
10
10
|
interface Input {
|
|
11
11
|
order: t.infer<typeof input.order>;
|
|
@@ -8,7 +8,7 @@ export const adminNote = db
|
|
|
8
8
|
.type("AdminNote", {
|
|
9
9
|
title: db.string(),
|
|
10
10
|
content: db.string(),
|
|
11
|
-
authorId: db.uuid().hooks({ create: ({
|
|
11
|
+
authorId: db.uuid().hooks({ create: ({ invoker }) => invoker?.id ?? crypto.randomUUID() }),
|
|
12
12
|
...db.fields.timestamps(),
|
|
13
13
|
})
|
|
14
14
|
// NOTE: This permits all operations for simplicity.
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
"typecheck": "tsc --noEmit"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@tailor-platform/sdk": "2.0.0-next.
|
|
16
|
+
"@tailor-platform/sdk": "2.0.0-next.2",
|
|
17
17
|
"@types/node": "24.13.2",
|
|
18
18
|
"oxfmt": "0.54.0",
|
|
19
19
|
"oxlint": "1.69.0",
|
|
20
20
|
"oxlint-tsgolint": "0.23.0",
|
|
21
|
-
"typescript": "
|
|
21
|
+
"typescript": "6.0.3"
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -8,11 +8,11 @@ Demonstrates all resolver patterns with comprehensive testing approaches.
|
|
|
8
8
|
- Database query resolver (Kysely with transactions)
|
|
9
9
|
- Database mutation resolver (dependency injection pattern)
|
|
10
10
|
- Environment variable access
|
|
11
|
-
-
|
|
11
|
+
- Caller and invoker context access
|
|
12
12
|
|
|
13
13
|
## Testing Approaches
|
|
14
14
|
|
|
15
|
-
1. **Direct `body()` call** - Simple resolvers with `
|
|
15
|
+
1. **Direct `body()` call** - Simple resolvers with explicit `caller` / `invoker` context values
|
|
16
16
|
2. **`tailor-runtime` environment + `mockTailordb`** - Database resolvers via `mockTailordb` from `@tailor-platform/sdk/vitest` (no `vi.stubGlobal` needed)
|
|
17
17
|
3. **Dependency injection** - Extract `DbOperations` interface for testability
|
|
18
18
|
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"typecheck": "tsc --noEmit"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@tailor-platform/sdk": "2.0.0-next.
|
|
17
|
+
"@tailor-platform/sdk": "2.0.0-next.2",
|
|
18
18
|
"@types/node": "24.13.2",
|
|
19
19
|
"oxfmt": "0.54.0",
|
|
20
20
|
"oxlint": "1.69.0",
|
|
21
21
|
"oxlint-tsgolint": "0.23.0",
|
|
22
|
-
"typescript": "
|
|
22
|
+
"typescript": "6.0.3",
|
|
23
23
|
"vitest": "4.1.8"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
|
|
2
1
|
import { describe, expect, test } from "vitest";
|
|
3
2
|
import resolver from "./add";
|
|
4
3
|
|
|
@@ -6,7 +5,8 @@ describe("add resolver", () => {
|
|
|
6
5
|
test("adds two positive numbers", async () => {
|
|
7
6
|
const result = await resolver.body({
|
|
8
7
|
input: { left: 1, right: 2 },
|
|
9
|
-
|
|
8
|
+
caller: null,
|
|
9
|
+
invoker: null,
|
|
10
10
|
env: { appName: "Resolver Template", version: 1 },
|
|
11
11
|
});
|
|
12
12
|
expect(result).toBe(3);
|
|
@@ -15,7 +15,8 @@ describe("add resolver", () => {
|
|
|
15
15
|
test("handles negative numbers", async () => {
|
|
16
16
|
const result = await resolver.body({
|
|
17
17
|
input: { left: -5, right: 3 },
|
|
18
|
-
|
|
18
|
+
caller: null,
|
|
19
|
+
invoker: null,
|
|
19
20
|
env: { appName: "Resolver Template", version: 1 },
|
|
20
21
|
});
|
|
21
22
|
expect(result).toBe(-2);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
|
|
2
1
|
import { mockTailordb } from "@tailor-platform/sdk/vitest";
|
|
3
2
|
import { describe, expect, test } from "vitest";
|
|
4
3
|
import resolver from "./incrementUserAge";
|
|
@@ -15,7 +14,8 @@ describe("incrementUserAge resolver", () => {
|
|
|
15
14
|
|
|
16
15
|
const result = await resolver.body({
|
|
17
16
|
input: { email: "test@example.com" },
|
|
18
|
-
|
|
17
|
+
caller: null,
|
|
18
|
+
invoker: null,
|
|
19
19
|
env: { appName: "Resolver Template", version: 1 },
|
|
20
20
|
});
|
|
21
21
|
expect(result).toEqual({ oldAge: 30, newAge: 31 });
|
|
@@ -32,7 +32,8 @@ describe("incrementUserAge resolver", () => {
|
|
|
32
32
|
|
|
33
33
|
const result = resolver.body({
|
|
34
34
|
input: { email: "test@example.com" },
|
|
35
|
-
|
|
35
|
+
caller: null,
|
|
36
|
+
invoker: null,
|
|
36
37
|
env: { appName: "Resolver Template", version: 1 },
|
|
37
38
|
});
|
|
38
39
|
await expect(result).rejects.toThrowError(/no result/i);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
|
|
2
1
|
import { describe, expect, test } from "vitest";
|
|
3
2
|
import resolver from "./showEnv";
|
|
4
3
|
|
|
@@ -6,7 +5,8 @@ describe("showEnv resolver", () => {
|
|
|
6
5
|
test("returns environment variables", async () => {
|
|
7
6
|
const result = await resolver.body({
|
|
8
7
|
input: undefined as never,
|
|
9
|
-
|
|
8
|
+
caller: null,
|
|
9
|
+
invoker: null,
|
|
10
10
|
env: { appName: "Resolver Template", version: 1 },
|
|
11
11
|
});
|
|
12
12
|
expect(result).toEqual({ appName: "Resolver Template", version: 1 });
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { TailorPrincipal } from "@tailor-platform/sdk";
|
|
2
2
|
import { describe, expect, test } from "vitest";
|
|
3
3
|
import resolver from "./showUserInfo";
|
|
4
4
|
|
|
@@ -6,26 +6,29 @@ describe("showUserInfo resolver", () => {
|
|
|
6
6
|
test("returns default user info", async () => {
|
|
7
7
|
const result = await resolver.body({
|
|
8
8
|
input: undefined as never,
|
|
9
|
-
|
|
9
|
+
caller: null,
|
|
10
|
+
invoker: null,
|
|
10
11
|
env: { appName: "Resolver Template", version: 1 },
|
|
11
12
|
});
|
|
12
13
|
expect(result).toEqual({
|
|
13
|
-
userId:
|
|
14
|
-
userType:
|
|
15
|
-
workspaceId:
|
|
14
|
+
userId: "anonymous",
|
|
15
|
+
userType: "anonymous",
|
|
16
|
+
workspaceId: "",
|
|
16
17
|
});
|
|
17
18
|
});
|
|
18
19
|
|
|
19
20
|
test("returns custom user info", async () => {
|
|
20
|
-
const
|
|
21
|
-
...unauthenticatedTailorUser,
|
|
21
|
+
const customCaller = {
|
|
22
22
|
id: "user-123",
|
|
23
23
|
type: "machine_user" as const,
|
|
24
24
|
workspaceId: "ws-456",
|
|
25
|
-
|
|
25
|
+
attributes: { role: "admin" },
|
|
26
|
+
attributeList: [],
|
|
27
|
+
} satisfies TailorPrincipal;
|
|
26
28
|
const result = await resolver.body({
|
|
27
29
|
input: undefined as never,
|
|
28
|
-
|
|
30
|
+
caller: customCaller,
|
|
31
|
+
invoker: customCaller,
|
|
29
32
|
env: { appName: "Resolver Template", version: 1 },
|
|
30
33
|
});
|
|
31
34
|
expect(result).toEqual({
|
|
@@ -6,9 +6,9 @@ const resolver = createResolver({
|
|
|
6
6
|
operation: "query",
|
|
7
7
|
body: (context) => {
|
|
8
8
|
return {
|
|
9
|
-
userId: context.
|
|
10
|
-
userType: context.
|
|
11
|
-
workspaceId: context.
|
|
9
|
+
userId: context.caller?.id ?? "anonymous",
|
|
10
|
+
userType: context.caller?.type ?? "anonymous",
|
|
11
|
+
workspaceId: context.caller?.workspaceId ?? "",
|
|
12
12
|
};
|
|
13
13
|
},
|
|
14
14
|
output: t.object({
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
|
|
2
1
|
import { createKyselyMock } from "@tailor-platform/sdk/vitest";
|
|
3
2
|
import { describe, expect, test, vi } from "vitest";
|
|
4
3
|
import { getDB, type Namespace } from "../generated/db";
|
|
@@ -30,7 +29,8 @@ describe("upsertUsers resolver", () => {
|
|
|
30
29
|
{ name: "Existing", email: "exists@example.com", age: 41 },
|
|
31
30
|
],
|
|
32
31
|
},
|
|
33
|
-
|
|
32
|
+
caller: null,
|
|
33
|
+
invoker: null,
|
|
34
34
|
env: { appName: "Resolver Template", version: 1 },
|
|
35
35
|
});
|
|
36
36
|
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
"typecheck": "tsc --noEmit"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@tailor-platform/sdk": "2.0.0-next.
|
|
15
|
+
"@tailor-platform/sdk": "2.0.0-next.2",
|
|
16
16
|
"@types/node": "24.13.2",
|
|
17
17
|
"oxfmt": "0.54.0",
|
|
18
18
|
"oxlint": "1.69.0",
|
|
19
19
|
"oxlint-tsgolint": "0.23.0",
|
|
20
|
-
"typescript": "
|
|
20
|
+
"typescript": "6.0.3"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"typecheck": "tsc --noEmit"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@tailor-platform/sdk": "2.0.0-next.
|
|
17
|
+
"@tailor-platform/sdk": "2.0.0-next.2",
|
|
18
18
|
"@types/node": "24.13.2",
|
|
19
19
|
"oxfmt": "0.54.0",
|
|
20
20
|
"oxlint": "1.69.0",
|
|
21
21
|
"oxlint-tsgolint": "0.23.0",
|
|
22
|
-
"typescript": "
|
|
22
|
+
"typescript": "6.0.3",
|
|
23
23
|
"vitest": "4.1.8"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -32,7 +32,7 @@ export interface Namespace {
|
|
|
32
32
|
isInternal: boolean;
|
|
33
33
|
}>;
|
|
34
34
|
createdAt: Generated<Timestamp>;
|
|
35
|
-
updatedAt: Timestamp
|
|
35
|
+
updatedAt: Generated<Timestamp>;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
Task: {
|
|
@@ -46,7 +46,7 @@ export interface Namespace {
|
|
|
46
46
|
categoryId: string | null;
|
|
47
47
|
isArchived: Generated<boolean>;
|
|
48
48
|
createdAt: Generated<Timestamp>;
|
|
49
|
-
updatedAt: Timestamp
|
|
49
|
+
updatedAt: Generated<Timestamp>;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
User: {
|
|
@@ -56,7 +56,7 @@ export interface Namespace {
|
|
|
56
56
|
role: "ADMIN" | "MEMBER" | "VIEWER";
|
|
57
57
|
bio: string | null;
|
|
58
58
|
createdAt: Generated<Timestamp>;
|
|
59
|
-
updatedAt: Timestamp
|
|
59
|
+
updatedAt: Generated<Timestamp>;
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
"typecheck": "tsc --noEmit"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@tailor-platform/sdk": "2.0.0-next.
|
|
18
|
+
"@tailor-platform/sdk": "2.0.0-next.2",
|
|
19
19
|
"@types/node": "24.13.2",
|
|
20
20
|
"graphql": "16.14.2",
|
|
21
21
|
"graphql-request": "7.4.0",
|
|
22
22
|
"oxfmt": "0.54.0",
|
|
23
23
|
"oxlint": "1.69.0",
|
|
24
24
|
"oxlint-tsgolint": "0.23.0",
|
|
25
|
-
"typescript": "
|
|
25
|
+
"typescript": "6.0.3",
|
|
26
26
|
"vitest": "4.1.8"
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -19,7 +19,7 @@ export interface Namespace {
|
|
|
19
19
|
amount: number;
|
|
20
20
|
status: "PENDING" | "PROCESSING" | "COMPLETED" | "FAILED";
|
|
21
21
|
createdAt: Generated<Timestamp>;
|
|
22
|
-
updatedAt: Timestamp
|
|
22
|
+
updatedAt: Generated<Timestamp>;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
User: {
|
|
@@ -28,7 +28,7 @@ export interface Namespace {
|
|
|
28
28
|
email: string;
|
|
29
29
|
age: number;
|
|
30
30
|
createdAt: Generated<Timestamp>;
|
|
31
|
-
updatedAt: Timestamp
|
|
31
|
+
updatedAt: Generated<Timestamp>;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "vitest";
|
|
2
2
|
import { mockWorkflow } from "@tailor-platform/sdk/vitest";
|
|
3
|
-
import { unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
|
|
4
3
|
import resolver from "./resolveApproval";
|
|
5
4
|
|
|
6
5
|
describe("resolveApproval resolver", () => {
|
|
@@ -16,7 +15,8 @@ describe("resolveApproval resolver", () => {
|
|
|
16
15
|
|
|
17
16
|
const result = await resolver.body({
|
|
18
17
|
input: { executionId: "exec-1", approved: true },
|
|
19
|
-
|
|
18
|
+
caller: null,
|
|
19
|
+
invoker: null,
|
|
20
20
|
env: {},
|
|
21
21
|
});
|
|
22
22
|
|
|
@@ -33,7 +33,8 @@ describe("resolveApproval resolver", () => {
|
|
|
33
33
|
|
|
34
34
|
const result = await resolver.body({
|
|
35
35
|
input: { executionId: "exec-2", approved: false },
|
|
36
|
-
|
|
36
|
+
caller: null,
|
|
37
|
+
invoker: null,
|
|
37
38
|
env: {},
|
|
38
39
|
});
|
|
39
40
|
|
|
@@ -7,7 +7,10 @@ describe("approval workflow", () => {
|
|
|
7
7
|
using wf = mockWorkflow();
|
|
8
8
|
wf.setWaitHandler((_key, _payload) => ({ approved: true }));
|
|
9
9
|
|
|
10
|
-
const result = await processWithApproval.body(
|
|
10
|
+
const result = await processWithApproval.body(
|
|
11
|
+
{ orderId: "order-1" },
|
|
12
|
+
{ env: {}, invoker: null },
|
|
13
|
+
);
|
|
11
14
|
|
|
12
15
|
expect(result).toEqual({ orderId: "order-1", status: "approved" });
|
|
13
16
|
expect(wf.waitCalls).toEqual([
|
|
@@ -22,7 +25,10 @@ describe("approval workflow", () => {
|
|
|
22
25
|
using wf = mockWorkflow();
|
|
23
26
|
wf.setWaitHandler({ approved: false });
|
|
24
27
|
|
|
25
|
-
const result = await processWithApproval.body(
|
|
28
|
+
const result = await processWithApproval.body(
|
|
29
|
+
{ orderId: "order-2" },
|
|
30
|
+
{ env: {}, invoker: null },
|
|
31
|
+
);
|
|
26
32
|
|
|
27
33
|
expect(result).toEqual({ orderId: "order-2", status: "rejected" });
|
|
28
34
|
});
|
|
@@ -10,18 +10,24 @@ import workflow, {
|
|
|
10
10
|
describe("order fulfillment workflow", () => {
|
|
11
11
|
describe("individual job tests with .body()", () => {
|
|
12
12
|
test("validateOrder accepts valid order", () => {
|
|
13
|
-
const result = validateOrder.body(
|
|
13
|
+
const result = validateOrder.body(
|
|
14
|
+
{ orderId: "order-1", amount: 100 },
|
|
15
|
+
{ env: {}, invoker: null },
|
|
16
|
+
);
|
|
14
17
|
expect(result).toEqual({ valid: true, orderId: "order-1" });
|
|
15
18
|
});
|
|
16
19
|
|
|
17
20
|
test("validateOrder rejects zero amount", () => {
|
|
18
|
-
expect(() =>
|
|
19
|
-
"
|
|
20
|
-
);
|
|
21
|
+
expect(() =>
|
|
22
|
+
validateOrder.body({ orderId: "order-1", amount: 0 }, { env: {}, invoker: null }),
|
|
23
|
+
).toThrow("Order amount must be positive");
|
|
21
24
|
});
|
|
22
25
|
|
|
23
26
|
test("processPayment returns transaction", () => {
|
|
24
|
-
const result = processPayment.body(
|
|
27
|
+
const result = processPayment.body(
|
|
28
|
+
{ orderId: "order-1", amount: 100 },
|
|
29
|
+
{ env: {}, invoker: null },
|
|
30
|
+
);
|
|
25
31
|
expect(result).toEqual({
|
|
26
32
|
transactionId: "txn-order-1",
|
|
27
33
|
amount: 100,
|
|
@@ -32,7 +38,7 @@ describe("order fulfillment workflow", () => {
|
|
|
32
38
|
test("sendConfirmation returns confirmation", () => {
|
|
33
39
|
const result = sendConfirmation.body(
|
|
34
40
|
{ orderId: "order-1", transactionId: "txn-1" },
|
|
35
|
-
{ env: {} },
|
|
41
|
+
{ env: {}, invoker: null },
|
|
36
42
|
);
|
|
37
43
|
expect(result).toEqual({
|
|
38
44
|
orderId: "order-1",
|
|
@@ -59,7 +65,10 @@ describe("order fulfillment workflow", () => {
|
|
|
59
65
|
confirmed: true,
|
|
60
66
|
});
|
|
61
67
|
|
|
62
|
-
const result = await fulfillOrder.body(
|
|
68
|
+
const result = await fulfillOrder.body(
|
|
69
|
+
{ orderId: "order-1", amount: 100 },
|
|
70
|
+
{ env: {}, invoker: null },
|
|
71
|
+
);
|
|
63
72
|
|
|
64
73
|
expect(validateOrder.trigger).toHaveBeenCalledWith({
|
|
65
74
|
orderId: "order-1",
|
|
@@ -97,7 +106,10 @@ describe("order fulfillment workflow", () => {
|
|
|
97
106
|
confirmed: true,
|
|
98
107
|
});
|
|
99
108
|
|
|
100
|
-
const result = await workflow.mainJob.body(
|
|
109
|
+
const result = await workflow.mainJob.body(
|
|
110
|
+
{ orderId: "order-2", amount: 200 },
|
|
111
|
+
{ env: {}, invoker: null },
|
|
112
|
+
);
|
|
101
113
|
|
|
102
114
|
expect(result).toEqual({
|
|
103
115
|
orderId: "order-2",
|