@tailor-platform/create-sdk 1.21.0 → 1.23.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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # @tailor-platform/create-sdk
2
2
 
3
+ ## 1.23.0
4
+
5
+ ## 1.22.0
6
+
3
7
  ## 1.21.0
4
8
 
5
9
  ## 1.20.0
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@tailor-platform/create-sdk",
3
- "version": "1.21.0",
3
+ "version": "1.23.0",
4
4
  "description": "A CLI tool to quickly create a new Tailor Platform SDK project",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
8
- "url": "https://github.com/tailor-platform/sdk.git",
8
+ "url": "git+https://github.com/tailor-platform/sdk.git",
9
9
  "directory": "packages/create-sdk"
10
10
  },
11
11
  "bin": "dist/index.js",
@@ -40,6 +40,7 @@
40
40
  "lint": "oxlint . && eslint --cache .",
41
41
  "lint:fix": "oxlint --fix . && eslint --cache --fix .",
42
42
  "typecheck": "tsc --noEmit",
43
- "prepublish": "node scripts/prepare-templates.js && pnpm run build"
43
+ "prepublish": "node scripts/prepare-templates.js && pnpm run build",
44
+ "publint": "publint --strict"
44
45
  }
45
46
  }
@@ -16,7 +16,7 @@
16
16
  "devDependencies": {
17
17
  "@eslint/js": "9.39.2",
18
18
  "@tailor-platform/function-types": "0.8.0",
19
- "@tailor-platform/sdk": "1.21.0",
19
+ "@tailor-platform/sdk": "1.23.0",
20
20
  "@types/node": "24.10.9",
21
21
  "eslint": "9.39.2",
22
22
  "eslint-plugin-oxlint": "1.39.0",
@@ -16,7 +16,7 @@
16
16
  "devDependencies": {
17
17
  "@eslint/js": "9.39.2",
18
18
  "@tailor-platform/function-types": "0.8.0",
19
- "@tailor-platform/sdk": "1.21.0",
19
+ "@tailor-platform/sdk": "1.23.0",
20
20
  "@types/node": "24.10.9",
21
21
  "eslint": "9.39.2",
22
22
  "eslint-plugin-oxlint": "1.39.0",
@@ -13,7 +13,7 @@
13
13
  },
14
14
  "devDependencies": {
15
15
  "@eslint/js": "9.39.2",
16
- "@tailor-platform/sdk": "1.21.0",
16
+ "@tailor-platform/sdk": "1.23.0",
17
17
  "@types/node": "24.10.9",
18
18
  "eslint": "9.39.2",
19
19
  "eslint-plugin-oxlint": "1.39.0",
@@ -14,7 +14,7 @@
14
14
  "devDependencies": {
15
15
  "@eslint/js": "9.39.2",
16
16
  "@tailor-platform/function-types": "0.8.0",
17
- "@tailor-platform/sdk": "1.21.0",
17
+ "@tailor-platform/sdk": "1.23.0",
18
18
  "@types/node": "24.10.9",
19
19
  "eslint": "9.39.2",
20
20
  "eslint-plugin-oxlint": "1.39.0",
@@ -14,7 +14,7 @@
14
14
  },
15
15
  "devDependencies": {
16
16
  "@eslint/js": "9.39.2",
17
- "@tailor-platform/sdk": "1.21.0",
17
+ "@tailor-platform/sdk": "1.23.0",
18
18
  "@types/node": "24.10.9",
19
19
  "eslint": "9.39.2",
20
20
  "eslint-plugin-oxlint": "1.39.0",
@@ -7,6 +7,8 @@
7
7
  "deploy": "tailor-sdk apply",
8
8
  "test": "vitest --project unit",
9
9
  "test:unit": "vitest --project unit",
10
+ "test:bundled:prepare": "TAILOR_PLATFORM_SDK_BUILD_ONLY=true tailor-sdk apply -c tailor.config.ts",
11
+ "test:bundled": "pnpm test:bundled:prepare && vitest --project bundled",
10
12
  "format": "oxfmt --write .",
11
13
  "format:check": "oxfmt --check .",
12
14
  "lint": "oxlint --type-aware . && eslint --cache .",
@@ -16,7 +18,7 @@
16
18
  "devDependencies": {
17
19
  "@eslint/js": "9.39.2",
18
20
  "@tailor-platform/function-types": "0.8.0",
19
- "@tailor-platform/sdk": "1.21.0",
21
+ "@tailor-platform/sdk": "1.23.0",
20
22
  "@types/node": "24.10.9",
21
23
  "eslint": "9.39.2",
22
24
  "eslint-plugin-oxlint": "1.39.0",
@@ -0,0 +1,97 @@
1
+ import path from "node:path";
2
+ import { createImportMain, setupTailordbMock } from "@tailor-platform/sdk/test";
3
+ import { beforeAll, beforeEach, describe, expect, test } from "vitest";
4
+
5
+ const outputDir = path.join(__dirname, "../.tailor-sdk");
6
+
7
+ describe("bundled resolver execution", () => {
8
+ let executedQueries: { query: string; params: unknown[] }[];
9
+
10
+ const importMain = createImportMain(outputDir);
11
+
12
+ beforeAll(() => {
13
+ ({ executedQueries } = setupTailordbMock());
14
+ });
15
+
16
+ beforeEach(() => {
17
+ executedQueries.length = 0;
18
+ });
19
+
20
+ describe("add resolver", () => {
21
+ test("returns sum of inputs", async () => {
22
+ const main = await importMain("resolvers/add.js");
23
+ const result = await main({ input: { left: 3, right: 4 } });
24
+ expect(result).toBe(7);
25
+ });
26
+ });
27
+
28
+ describe("incrementUserAge resolver", () => {
29
+ test("increments user age with DB mock", async () => {
30
+ setupTailordbMock((query) => {
31
+ if (query.includes("SELECT") || query.includes("select")) {
32
+ return [{ age: 30 }];
33
+ }
34
+ return [];
35
+ });
36
+
37
+ const main = await importMain("resolvers/incrementUserAge.js");
38
+ const result = await main({ input: { email: "test@example.com" } });
39
+ expect(result).toEqual({ oldAge: 30, newAge: 31 });
40
+ });
41
+ });
42
+
43
+ describe("decrementUserAge resolver", () => {
44
+ test("decrements user age with DB mock", async () => {
45
+ setupTailordbMock((query) => {
46
+ if (query.includes("SELECT") || query.includes("select")) {
47
+ return [
48
+ {
49
+ id: "user-1",
50
+ email: "test@example.com",
51
+ name: "Test",
52
+ age: 30,
53
+ createdAt: null,
54
+ updatedAt: null,
55
+ },
56
+ ];
57
+ }
58
+ return [];
59
+ });
60
+
61
+ const main = await importMain("resolvers/decrementUserAge.js");
62
+ const result = await main({ input: { email: "test@example.com" } });
63
+ expect(result).toEqual({ oldAge: 30, newAge: 29 });
64
+ });
65
+ });
66
+
67
+ describe("showUserInfo resolver", () => {
68
+ test("returns user info from context", async () => {
69
+ const main = await importMain("resolvers/showUserInfo.js");
70
+ const result = await main({
71
+ user: {
72
+ id: "test-id",
73
+ type: "machine_user",
74
+ workspaceId: "ws-id",
75
+ attributes: { role: "admin" },
76
+ attributeList: [],
77
+ },
78
+ });
79
+ expect(result).toEqual({
80
+ userId: "test-id",
81
+ userType: "machine_user",
82
+ workspaceId: "ws-id",
83
+ });
84
+ });
85
+ });
86
+
87
+ describe("showEnv resolver", () => {
88
+ test("returns env values embedded from config", async () => {
89
+ const main = await importMain("resolvers/showEnv.js");
90
+ const result = await main({ env: { appName: "Resolver Template", version: 1 } });
91
+ expect(result).toEqual({
92
+ appName: "Resolver Template",
93
+ version: 1,
94
+ });
95
+ });
96
+ });
97
+ });
@@ -10,6 +10,12 @@ export default defineConfig({
10
10
  include: ["src/**/*.test.ts"],
11
11
  },
12
12
  },
13
+ {
14
+ test: {
15
+ name: { label: "bundled", color: "yellow" },
16
+ include: ["tests/**/*.test.ts"],
17
+ },
18
+ },
13
19
  ],
14
20
  },
15
21
  });
@@ -14,7 +14,7 @@
14
14
  "devDependencies": {
15
15
  "@eslint/js": "9.39.2",
16
16
  "@tailor-platform/function-types": "0.8.0",
17
- "@tailor-platform/sdk": "1.21.0",
17
+ "@tailor-platform/sdk": "1.23.0",
18
18
  "@types/node": "24.10.9",
19
19
  "eslint": "9.39.2",
20
20
  "eslint-plugin-oxlint": "1.39.0",
@@ -16,7 +16,7 @@
16
16
  "devDependencies": {
17
17
  "@eslint/js": "9.39.2",
18
18
  "@tailor-platform/function-types": "0.8.0",
19
- "@tailor-platform/sdk": "1.21.0",
19
+ "@tailor-platform/sdk": "1.23.0",
20
20
  "@types/node": "24.10.9",
21
21
  "eslint": "9.39.2",
22
22
  "eslint-plugin-oxlint": "1.39.0",
@@ -6,9 +6,8 @@ Demonstrates workflow patterns with job chaining, trigger testing, and dependenc
6
6
 
7
7
  - Workflow with multiple jobs (`createWorkflow`, `createWorkflowJob`)
8
8
  - Job chaining via `.trigger()`
9
- - User context access in jobs
10
9
  - Database operations in workflow jobs (DI pattern)
11
- - Integration testing with `WORKFLOW_TEST_ENV_KEY` / `WORKFLOW_TEST_USER_KEY`
10
+ - Integration testing with `WORKFLOW_TEST_ENV_KEY`
12
11
 
13
12
  ## Getting Started
14
13
 
@@ -7,6 +7,8 @@
7
7
  "deploy": "tailor-sdk apply",
8
8
  "test": "vitest --project unit",
9
9
  "test:unit": "vitest --project unit",
10
+ "test:bundled:prepare": "TAILOR_PLATFORM_SDK_BUILD_ONLY=true tailor-sdk apply -c tailor.config.ts",
11
+ "test:bundled": "pnpm test:bundled:prepare && vitest --project bundled",
10
12
  "test:e2e": "vitest --project e2e",
11
13
  "format": "oxfmt --write .",
12
14
  "format:check": "oxfmt --check .",
@@ -17,7 +19,7 @@
17
19
  "devDependencies": {
18
20
  "@eslint/js": "9.39.2",
19
21
  "@tailor-platform/function-types": "0.8.0",
20
- "@tailor-platform/sdk": "1.21.0",
22
+ "@tailor-platform/sdk": "1.23.0",
21
23
  "@types/node": "24.10.9",
22
24
  "eslint": "9.39.2",
23
25
  "eslint-plugin-oxlint": "1.39.0",
@@ -1,4 +1,4 @@
1
- import { WORKFLOW_TEST_ENV_KEY, unauthenticatedTailorUser } from "@tailor-platform/sdk/test";
1
+ import { WORKFLOW_TEST_ENV_KEY } from "@tailor-platform/sdk/test";
2
2
  import { afterEach, describe, expect, test, vi } from "vitest";
3
3
  import workflow, {
4
4
  fulfillOrder,
@@ -15,27 +15,18 @@ describe("order fulfillment workflow", () => {
15
15
 
16
16
  describe("individual job tests with .body()", () => {
17
17
  test("validateOrder accepts valid order", () => {
18
- const result = validateOrder.body(
19
- { orderId: "order-1", amount: 100 },
20
- { env: {}, user: unauthenticatedTailorUser },
21
- );
18
+ const result = validateOrder.body({ orderId: "order-1", amount: 100 }, { env: {} });
22
19
  expect(result).toEqual({ valid: true, orderId: "order-1" });
23
20
  });
24
21
 
25
22
  test("validateOrder rejects zero amount", () => {
26
- expect(() =>
27
- validateOrder.body(
28
- { orderId: "order-1", amount: 0 },
29
- { env: {}, user: unauthenticatedTailorUser },
30
- ),
31
- ).toThrow("Order amount must be positive");
23
+ expect(() => validateOrder.body({ orderId: "order-1", amount: 0 }, { env: {} })).toThrow(
24
+ "Order amount must be positive",
25
+ );
32
26
  });
33
27
 
34
28
  test("processPayment returns transaction", () => {
35
- const result = processPayment.body(
36
- { orderId: "order-1", amount: 100 },
37
- { env: {}, user: unauthenticatedTailorUser },
38
- );
29
+ const result = processPayment.body({ orderId: "order-1", amount: 100 }, { env: {} });
39
30
  expect(result).toEqual({
40
31
  transactionId: "txn-order-1",
41
32
  amount: 100,
@@ -46,7 +37,7 @@ describe("order fulfillment workflow", () => {
46
37
  test("sendConfirmation returns confirmation", () => {
47
38
  const result = sendConfirmation.body(
48
39
  { orderId: "order-1", transactionId: "txn-1" },
49
- { env: {}, user: unauthenticatedTailorUser },
40
+ { env: {} },
50
41
  );
51
42
  expect(result).toEqual({
52
43
  orderId: "order-1",
@@ -73,10 +64,7 @@ describe("order fulfillment workflow", () => {
73
64
  confirmed: true,
74
65
  });
75
66
 
76
- const result = await fulfillOrder.body(
77
- { orderId: "order-1", amount: 100 },
78
- { env: {}, user: unauthenticatedTailorUser },
79
- );
67
+ const result = await fulfillOrder.body({ orderId: "order-1", amount: 100 }, { env: {} });
80
68
 
81
69
  expect(validateOrder.trigger).toHaveBeenCalledWith({
82
70
  orderId: "order-1",
@@ -114,10 +102,7 @@ describe("order fulfillment workflow", () => {
114
102
  confirmed: true,
115
103
  });
116
104
 
117
- const result = await workflow.mainJob.body(
118
- { orderId: "order-2", amount: 200 },
119
- { env: {}, user: unauthenticatedTailorUser },
120
- );
105
+ const result = await workflow.mainJob.body({ orderId: "order-2", amount: 200 }, { env: {} });
121
106
 
122
107
  expect(result).toEqual({
123
108
  orderId: "order-2",
@@ -0,0 +1,145 @@
1
+ import path from "node:path";
2
+ import { createImportMain, setupTailordbMock, setupWorkflowMock } from "@tailor-platform/sdk/test";
3
+ import { beforeAll, beforeEach, describe, expect, test } from "vitest";
4
+
5
+ const outputDir = path.join(__dirname, "../.tailor-sdk");
6
+
7
+ describe("bundled workflow execution", () => {
8
+ let executedQueries: { query: string; params: unknown[] }[];
9
+
10
+ const importMain = createImportMain(outputDir);
11
+
12
+ beforeAll(() => {
13
+ ({ executedQueries } = setupTailordbMock());
14
+ });
15
+
16
+ beforeEach(() => {
17
+ executedQueries.length = 0;
18
+ });
19
+
20
+ describe("sync-profile job", () => {
21
+ test("creates new user when not found", async () => {
22
+ let selectCalled = false;
23
+ setupTailordbMock((query) => {
24
+ if (query.includes("SELECT") || query.includes("select")) {
25
+ if (!selectCalled) {
26
+ selectCalled = true;
27
+ return [];
28
+ }
29
+ }
30
+ if (query.includes("INSERT") || query.includes("insert")) {
31
+ return [
32
+ {
33
+ id: "new-id",
34
+ name: "Alice",
35
+ email: "alice@example.com",
36
+ age: 25,
37
+ createdAt: "2024-01-01",
38
+ updatedAt: null,
39
+ },
40
+ ];
41
+ }
42
+ return [];
43
+ });
44
+
45
+ const main = await importMain("workflow-jobs/sync-profile.js");
46
+ const result = await main({ name: "Alice", email: "alice@example.com", age: 25 });
47
+ expect(result).toEqual({
48
+ created: true,
49
+ profile: { name: "Alice", email: "alice@example.com", age: 25 },
50
+ });
51
+ });
52
+
53
+ test("updates existing user when found", async () => {
54
+ setupTailordbMock((query) => {
55
+ if (query.includes("SELECT") || query.includes("select")) {
56
+ return [
57
+ {
58
+ id: "existing-id",
59
+ name: "Old Name",
60
+ email: "alice@example.com",
61
+ age: 20,
62
+ createdAt: "2024-01-01",
63
+ updatedAt: null,
64
+ },
65
+ ];
66
+ }
67
+ return [];
68
+ });
69
+
70
+ const main = await importMain("workflow-jobs/sync-profile.js");
71
+ const result = await main({ name: "Alice Updated", email: "alice@example.com", age: 26 });
72
+ expect(result).toEqual({
73
+ created: false,
74
+ profile: { name: "Alice Updated", email: "alice@example.com", age: 26 },
75
+ });
76
+ });
77
+ });
78
+
79
+ describe("order-fulfillment jobs", () => {
80
+ test("validate-order validates positive amount", async () => {
81
+ const main = await importMain("workflow-jobs/validate-order.js");
82
+ const result = await main({ orderId: "order-1", amount: 100 });
83
+ expect(result).toEqual({ valid: true, orderId: "order-1" });
84
+ });
85
+
86
+ test("validate-order throws for non-positive amount", async () => {
87
+ const main = await importMain("workflow-jobs/validate-order.js");
88
+ await expect(main({ orderId: "order-1", amount: 0 })).rejects.toThrow(
89
+ "Order amount must be positive",
90
+ );
91
+ });
92
+
93
+ test("process-payment returns transaction", async () => {
94
+ const main = await importMain("workflow-jobs/process-payment.js");
95
+ const result = await main({ orderId: "order-1", amount: 100 });
96
+ expect(result).toEqual({
97
+ transactionId: "txn-order-1",
98
+ amount: 100,
99
+ status: "completed",
100
+ });
101
+ });
102
+
103
+ test("send-confirmation returns confirmation", async () => {
104
+ const main = await importMain("workflow-jobs/send-confirmation.js");
105
+ const result = await main({ orderId: "order-1", transactionId: "txn-order-1" });
106
+ expect(result).toEqual({
107
+ orderId: "order-1",
108
+ transactionId: "txn-order-1",
109
+ confirmed: true,
110
+ });
111
+ });
112
+
113
+ test("fulfill-order orchestrates all jobs", async () => {
114
+ setupWorkflowMock((jobName, args) => {
115
+ switch (jobName) {
116
+ case "validate-order":
117
+ return { valid: true, orderId: (args as { orderId: string }).orderId };
118
+ case "process-payment":
119
+ return {
120
+ transactionId: `txn-${(args as { orderId: string }).orderId}`,
121
+ amount: (args as { amount: number }).amount,
122
+ status: "completed",
123
+ };
124
+ case "send-confirmation":
125
+ return {
126
+ orderId: (args as { orderId: string }).orderId,
127
+ transactionId: (args as { transactionId: string }).transactionId,
128
+ confirmed: true,
129
+ };
130
+ default:
131
+ throw new Error(`Unknown job: ${jobName}`);
132
+ }
133
+ });
134
+
135
+ const main = await importMain("workflow-jobs/fulfill-order.js");
136
+ const result = await main({ orderId: "order-1", amount: 100 });
137
+ expect(result).toEqual({
138
+ orderId: "order-1",
139
+ transactionId: "txn-order-1",
140
+ confirmed: true,
141
+ paymentStatus: "completed",
142
+ });
143
+ });
144
+ });
145
+ });
@@ -10,6 +10,12 @@ export default defineConfig({
10
10
  include: ["src/**/*.test.ts"],
11
11
  },
12
12
  },
13
+ {
14
+ test: {
15
+ name: { label: "bundled", color: "yellow" },
16
+ include: ["tests/**/*.test.ts"],
17
+ },
18
+ },
13
19
  {
14
20
  test: {
15
21
  name: { label: "e2e", color: "green" },