@tailor-platform/create-sdk 2.0.0-next.1 → 2.0.0-next.10

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 (100) hide show
  1. package/CHANGELOG.md +175 -0
  2. package/package.json +10 -9
  3. package/templates/executor/.oxlintrc.json +9 -1
  4. package/templates/executor/__dot__gitignore +1 -1
  5. package/templates/executor/package.json +11 -9
  6. package/templates/executor/src/db/auditLog.ts +1 -1
  7. package/templates/executor/src/db/notification.ts +1 -1
  8. package/templates/executor/src/db/user.ts +1 -1
  9. package/templates/executor/src/generated/db.ts +3 -3
  10. package/templates/executor/tailor.d.ts +4 -2
  11. package/templates/generators/.oxlintrc.json +9 -1
  12. package/templates/generators/README.md +1 -1
  13. package/templates/generators/__dot__gitignore +1 -1
  14. package/templates/generators/package.json +14 -9
  15. package/templates/generators/src/db/category.ts +1 -1
  16. package/templates/generators/src/db/order.ts +1 -1
  17. package/templates/generators/src/db/product.ts +1 -1
  18. package/templates/generators/src/db/user.ts +1 -1
  19. package/templates/generators/src/generated/db.ts +3 -3
  20. package/templates/generators/src/generated/files.ts +5 -5
  21. package/templates/generators/src/resolver/getProduct.test.ts +31 -27
  22. package/templates/generators/src/seed/data/Order.schema.ts +2 -2
  23. package/templates/generators/src/seed/data/Product.schema.ts +2 -2
  24. package/templates/generators/src/seed/data/User.schema.ts +2 -2
  25. package/templates/generators/tailor.d.ts +4 -2
  26. package/templates/hello-world/.oxlintrc.json +9 -1
  27. package/templates/hello-world/README.md +6 -6
  28. package/templates/hello-world/__dot__gitignore +1 -1
  29. package/templates/hello-world/package.json +10 -8
  30. package/templates/hello-world/src/db/user.ts +1 -1
  31. package/templates/hello-world/src/generated/kysely-tailordb.ts +1 -1
  32. package/templates/hello-world/tailor.d.ts +4 -2
  33. package/templates/inventory-management/.oxlintrc.json +9 -1
  34. package/templates/inventory-management/README.md +8 -8
  35. package/templates/inventory-management/__dot__gitignore +1 -1
  36. package/templates/inventory-management/package.json +10 -8
  37. package/templates/inventory-management/src/db/category.ts +1 -1
  38. package/templates/inventory-management/src/db/contact.ts +1 -1
  39. package/templates/inventory-management/src/db/inventory.ts +2 -2
  40. package/templates/inventory-management/src/db/notification.ts +1 -1
  41. package/templates/inventory-management/src/db/order.ts +1 -1
  42. package/templates/inventory-management/src/db/orderItem.ts +12 -8
  43. package/templates/inventory-management/src/db/product.ts +1 -1
  44. package/templates/inventory-management/src/db/user.ts +1 -1
  45. package/templates/inventory-management/src/executor/checkInventory.ts +0 -1
  46. package/templates/inventory-management/src/generated/kysely-tailordb.ts +9 -9
  47. package/templates/inventory-management/src/resolver/registerOrder.ts +4 -2
  48. package/templates/inventory-management/tailor.d.ts +4 -2
  49. package/templates/multi-application/.oxlintrc.json +9 -1
  50. package/templates/multi-application/README.md +2 -2
  51. package/templates/multi-application/__dot__gitignore +1 -1
  52. package/templates/multi-application/apps/admin/db/adminNote.ts +2 -2
  53. package/templates/multi-application/apps/admin/tailor.config.ts +1 -1
  54. package/templates/multi-application/apps/user/db/user.ts +1 -1
  55. package/templates/multi-application/apps/user/tailor.config.ts +1 -1
  56. package/templates/multi-application/package.json +10 -8
  57. package/templates/resolver/.oxlintrc.json +9 -1
  58. package/templates/resolver/README.md +2 -2
  59. package/templates/resolver/__dot__gitignore +1 -1
  60. package/templates/resolver/package.json +11 -9
  61. package/templates/resolver/src/db/user.ts +1 -1
  62. package/templates/resolver/src/generated/db.ts +1 -1
  63. package/templates/resolver/src/resolver/add.test.ts +4 -3
  64. package/templates/resolver/src/resolver/incrementUserAge.test.ts +6 -5
  65. package/templates/resolver/src/resolver/showEnv.test.ts +2 -2
  66. package/templates/resolver/src/resolver/showUserInfo.test.ts +12 -9
  67. package/templates/resolver/src/resolver/showUserInfo.ts +3 -3
  68. package/templates/resolver/src/resolver/upsertUsers.test.ts +2 -2
  69. package/templates/resolver/tailor.d.ts +4 -2
  70. package/templates/static-web-site/.oxlintrc.json +9 -1
  71. package/templates/static-web-site/__dot__gitignore +1 -1
  72. package/templates/static-web-site/package.json +10 -8
  73. package/templates/static-web-site/src/db/user.ts +1 -1
  74. package/templates/static-web-site/tailor.d.ts +4 -2
  75. package/templates/tailordb/.oxlintrc.json +9 -1
  76. package/templates/tailordb/README.md +1 -1
  77. package/templates/tailordb/__dot__gitignore +1 -1
  78. package/templates/tailordb/package.json +11 -9
  79. package/templates/tailordb/src/db/category.ts +1 -1
  80. package/templates/tailordb/src/db/comment.ts +4 -2
  81. package/templates/tailordb/src/db/task.ts +19 -27
  82. package/templates/tailordb/src/db/user.ts +1 -1
  83. package/templates/tailordb/src/generated/db.ts +3 -3
  84. package/templates/tailordb/tailor.d.ts +4 -2
  85. package/templates/workflow/.oxlintrc.json +9 -1
  86. package/templates/workflow/README.md +2 -2
  87. package/templates/workflow/__dot__gitignore +1 -1
  88. package/templates/workflow/e2e/globalSetup.ts +1 -1
  89. package/templates/workflow/e2e/workflow.test.ts +1 -1
  90. package/templates/workflow/package.json +12 -10
  91. package/templates/workflow/src/db/order.ts +1 -1
  92. package/templates/workflow/src/db/user.ts +1 -1
  93. package/templates/workflow/src/generated/db.ts +2 -2
  94. package/templates/workflow/src/resolver/resolveApproval.test.ts +18 -13
  95. package/templates/workflow/src/workflow/approval.test.ts +16 -11
  96. package/templates/workflow/src/workflow/approval.ts +2 -2
  97. package/templates/workflow/src/workflow/order-fulfillment.test.ts +30 -18
  98. package/templates/workflow/src/workflow/order-fulfillment.ts +3 -3
  99. package/templates/workflow/tailor.d.ts +4 -2
  100. package/templates/generators/src/seed/exec.mjs +0 -485
@@ -1,485 +0,0 @@
1
- /**
2
- * @generated
3
- * This file is auto-generated by @tailor-platform/sdk's seedPlugin.
4
- * Do not edit by hand: changes will be overwritten on the next `sdk generate`.
5
- */
6
- import { readFileSync } from "node:fs";
7
- import { join, isAbsolute } from "node:path";
8
- import { parseArgs, styleText } from "node:util";
9
- import { createInterface } from "node:readline";
10
- import {
11
- show,
12
- truncate,
13
- bundleSeedScript,
14
- chunkSeedData,
15
- executeScript,
16
- initOperatorClient,
17
- loadAccessToken,
18
- loadWorkspaceId,
19
- } from "@tailor-platform/sdk/cli";
20
-
21
- // Handle "validate" subcommand before parseArgs
22
- const subcommand = process.argv[2];
23
- if (subcommand === "validate") {
24
- const { validateSeedData } = await import("@tailor-platform/sdk/seed");
25
- const validateArgs = parseArgs({
26
- args: process.argv.slice(3),
27
- options: {
28
- verbose: { type: "boolean", short: "v", default: false },
29
- help: { type: "boolean", short: "h", default: false },
30
- },
31
- allowPositionals: true,
32
- });
33
-
34
- if (validateArgs.values.help) {
35
- console.log(`
36
- Usage: node exec.mjs validate [options] [path]
37
-
38
- Validate JSONL seed data against schema definitions.
39
-
40
- Arguments:
41
- path File or directory to validate (default: ./data)
42
-
43
- Options:
44
- -v, --verbose Show verbose error output
45
- -h, --help Show help
46
-
47
- Examples:
48
- node exec.mjs validate # Validate all seed data
49
- node exec.mjs validate ./data/User.jsonl # Validate specific file
50
- node exec.mjs validate -v # Verbose error output
51
- `);
52
- process.exit(0);
53
- }
54
-
55
- const configDir = import.meta.dirname;
56
- const targetPath = validateArgs.positionals[0] || join(configDir, "data");
57
- const resolvedPath = isAbsolute(targetPath) ? targetPath : join(process.cwd(), targetPath);
58
-
59
- try {
60
- const result = await validateSeedData({ path: resolvedPath, verbose: validateArgs.values.verbose });
61
- if (result.output) console.log(result.output);
62
- if (!result.valid) {
63
- console.error(result.error);
64
- process.exit(1);
65
- }
66
- process.exit(0);
67
- } catch (error) {
68
- console.error(styleText("red", `Error: ${error instanceof Error ? error.message : String(error)}`));
69
- process.exit(1);
70
- }
71
- }
72
-
73
- // Parse command-line arguments
74
- const { values, positionals } = parseArgs({
75
- options: {
76
- "machine-user": { type: "string", short: "m" },
77
- namespace: { type: "string", short: "n" },
78
- "skip-idp": { type: "boolean", default: false },
79
- truncate: { type: "boolean", default: false },
80
- yes: { type: "boolean", default: false },
81
- profile: { type: "string", short: "p" },
82
- help: { type: "boolean", short: "h", default: false },
83
- },
84
- allowPositionals: true,
85
- });
86
-
87
- if (values.help) {
88
- console.log(`
89
- Usage: node exec.mjs [command] [options] [types...]
90
-
91
- Commands:
92
- validate [path] Validate seed data against schema (default: ./data)
93
-
94
- Options:
95
- -m, --machine-user <name> Machine user name for authentication (required if not configured)
96
- -n, --namespace <ns> Process all types in specified namespace (excludes _User)
97
- --skip-idp Skip IdP user (_User) entity
98
- --truncate Truncate tables before seeding
99
- --yes Skip confirmation prompts (for truncate)
100
- -p, --profile <name> Workspace profile name
101
- -h, --help Show help
102
-
103
- Examples:
104
- node exec.mjs -m admin # Process all types with machine user
105
- node exec.mjs --namespace <namespace> # Process tailordb namespace only (no _User)
106
- node exec.mjs User Order # Process specific types only
107
- node exec.mjs --skip-idp # Process all except _User
108
- node exec.mjs --truncate # Truncate all tables, then seed all
109
- node exec.mjs --truncate --yes # Truncate all tables without confirmation, then seed all
110
- node exec.mjs --truncate --namespace <namespace> # Truncate tailordb, then seed tailordb
111
- node exec.mjs --truncate User Order # Truncate User and Order, then seed them
112
- node exec.mjs validate # Validate all seed data
113
- node exec.mjs validate ./data/User.jsonl # Validate specific file
114
- `);
115
- process.exit(0);
116
- }
117
-
118
- // Helper function to prompt for y/n confirmation
119
- const promptConfirmation = (question) => {
120
- const rl = createInterface({
121
- input: process.stdin,
122
- output: process.stdout,
123
- });
124
-
125
- return new Promise((resolve) => {
126
- rl.question(styleText("yellow", question), (answer) => {
127
- rl.close();
128
- resolve(answer.toLowerCase().trim());
129
- });
130
- });
131
- };
132
-
133
- const configDir = import.meta.dirname;
134
- const configPath = join(configDir, "../../tailor.config.ts");
135
-
136
- // Determine machine user name (CLI argument takes precedence over config default)
137
- const defaultMachineUser = "admin";
138
- const machineUserName = values["machine-user"] || defaultMachineUser;
139
-
140
- if (!machineUserName) {
141
- console.error(styleText("red", "Error: Machine user name is required."));
142
- console.error(styleText("yellow", "Specify --machine-user <name> or configure machineUserName in generator options."));
143
- process.exit(1);
144
- }
145
-
146
- // Entity configuration
147
- const namespaceEntities = {
148
- "main-db": [
149
- "Category",
150
- "Order",
151
- "Product",
152
- "User",
153
- ]
154
- };
155
- const namespaceDeps = {
156
- "main-db": {
157
- "Category": [],
158
- "Order": ["Product", "User"],
159
- "Product": ["Category"],
160
- "User": []
161
- }
162
- };
163
- const namespaceSelfRefTypes = {
164
- "main-db": ["Category"]
165
- };
166
- const entities = Object.values(namespaceEntities).flat();
167
- const hasIdpUser = false;
168
-
169
- // Determine which entities to process
170
- let entitiesToProcess = null;
171
-
172
- const hasNamespace = !!values.namespace;
173
- const hasTypes = positionals.length > 0;
174
- const skipIdp = values["skip-idp"];
175
-
176
- // Validate mutually exclusive options
177
- const optionCount = [hasNamespace, hasTypes].filter(Boolean).length;
178
- if (optionCount > 1) {
179
- console.error(styleText("red", "Error: Options --namespace and type names are mutually exclusive."));
180
- process.exit(1);
181
- }
182
-
183
- // --skip-idp and --namespace are redundant (namespace already excludes _User)
184
- if (skipIdp && hasNamespace) {
185
- console.warn(styleText("yellow", "Warning: --skip-idp is redundant with --namespace (namespace filtering already excludes _User)."));
186
- }
187
-
188
- // Filter by namespace (automatically excludes _User as it has no namespace)
189
- if (hasNamespace) {
190
- const namespace = values.namespace;
191
- entitiesToProcess = namespaceEntities[namespace];
192
-
193
- if (!entitiesToProcess || entitiesToProcess.length === 0) {
194
- console.error(styleText("red", `Error: No entities found in namespace "${namespace}"`));
195
- console.error(styleText("yellow", `Available namespaces: ${Object.keys(namespaceEntities).join(", ")}`));
196
- process.exit(1);
197
- }
198
-
199
- console.log(styleText("cyan", `Filtering by namespace: ${namespace}`));
200
- console.log(styleText("dim", `Entities: ${entitiesToProcess.join(", ")}`));
201
- }
202
-
203
- // Filter by specific types
204
- if (hasTypes) {
205
- const requestedTypes = positionals;
206
- const notFoundTypes = [];
207
- const allTypes = hasIdpUser ? [...entities, "_User"] : entities;
208
-
209
- entitiesToProcess = requestedTypes.filter((type) => {
210
- if (!allTypes.includes(type)) {
211
- notFoundTypes.push(type);
212
- return false;
213
- }
214
- return true;
215
- });
216
-
217
- if (notFoundTypes.length > 0) {
218
- console.error(styleText("red", `Error: The following types were not found: ${notFoundTypes.join(", ")}`));
219
- console.error(styleText("yellow", `Available types: ${allTypes.join(", ")}`));
220
- process.exit(1);
221
- }
222
-
223
- console.log(styleText("cyan", `Filtering by types: ${entitiesToProcess.join(", ")}`));
224
- }
225
-
226
- // Apply --skip-idp filter
227
- if (skipIdp) {
228
- if (entitiesToProcess) {
229
- entitiesToProcess = entitiesToProcess.filter((entity) => entity !== "_User");
230
- } else {
231
- entitiesToProcess = entities.filter((entity) => entity !== "_User");
232
- }
233
- }
234
-
235
- // Get application info
236
- const appInfo = await show({ configPath, profile: values.profile });
237
- const authNamespace = appInfo.auth;
238
-
239
- // Initialize operator client (once for all namespaces)
240
- const accessToken = await loadAccessToken({ profile: values.profile });
241
- const workspaceId = await loadWorkspaceId({ profile: values.profile });
242
- const operatorClient = await initOperatorClient(accessToken);
243
-
244
-
245
-
246
- // Truncate tables if requested
247
- if (values.truncate) {
248
- const answer = values.yes ? "y" : await promptConfirmation("Are you sure you want to truncate? (y/n): ");
249
- if (answer !== "y") {
250
- console.log(styleText("yellow", "Truncate cancelled."));
251
- process.exit(0);
252
- }
253
-
254
- console.log(styleText("cyan", "Truncating tables..."));
255
-
256
- try {
257
- if (hasNamespace) {
258
- await truncate({
259
- configPath,
260
- profile: values.profile,
261
- namespace: values.namespace,
262
- });
263
- } else if (hasTypes) {
264
- const typesToTruncate = entitiesToProcess.filter((t) => t !== "_User");
265
- if (typesToTruncate.length > 0) {
266
- await truncate({
267
- configPath,
268
- profile: values.profile,
269
- types: typesToTruncate,
270
- });
271
- } else {
272
- console.log(styleText("dim", "No TailorDB types to truncate (only _User was specified)."));
273
- }
274
- } else {
275
- await truncate({
276
- configPath,
277
- profile: values.profile,
278
- all: true,
279
- });
280
- }
281
- } catch (error) {
282
- console.error(styleText("red", `Truncate failed: ${error.message}`));
283
- process.exit(1);
284
- }
285
-
286
-
287
-
288
- console.log(styleText("green", "Truncate completed."));
289
- }
290
-
291
- console.log(styleText("cyan", "\nStarting seed data generation..."));
292
- if (skipIdp) {
293
- console.log(styleText("dim", ` Skipping IdP user (_User)`));
294
- }
295
-
296
- // Load seed data from JSONL files
297
- const loadSeedData = (dataDir, typeNames) => {
298
- const data = {};
299
- for (const typeName of typeNames) {
300
- const jsonlPath = join(dataDir, `${typeName}.jsonl`);
301
- try {
302
- const content = readFileSync(jsonlPath, "utf-8").trim();
303
- if (content) {
304
- data[typeName] = content.split("\n").map((line) => JSON.parse(line));
305
- } else {
306
- data[typeName] = [];
307
- }
308
- } catch (error) {
309
- if (error.code === "ENOENT") {
310
- data[typeName] = [];
311
- } else {
312
- throw error;
313
- }
314
- }
315
- }
316
- return data;
317
- };
318
-
319
- // Topological sort for dependency order
320
- const topologicalSort = (types, deps) => {
321
- const visited = new Set();
322
- const result = [];
323
-
324
- const visit = (type) => {
325
- if (visited.has(type)) return;
326
- visited.add(type);
327
- const typeDeps = deps[type] || [];
328
- for (const dep of typeDeps) {
329
- if (types.includes(dep)) {
330
- visit(dep);
331
- }
332
- }
333
- result.push(type);
334
- };
335
-
336
- for (const type of types) {
337
- visit(type);
338
- }
339
- return result;
340
- };
341
-
342
- // Seed TailorDB types via testExecScript
343
- const seedViaTestExecScript = async (namespace, typesToSeed, deps, selfRefTypes) => {
344
- const dataDir = join(configDir, "data");
345
- const sortedTypes = topologicalSort(typesToSeed, deps);
346
- const data = loadSeedData(dataDir, sortedTypes);
347
-
348
- // Skip if no data
349
- const typesWithData = sortedTypes.filter((t) => data[t] && data[t].length > 0);
350
- if (typesWithData.length === 0) {
351
- console.log(styleText("dim", ` [${namespace}] No data to seed`));
352
- return { success: true, processed: {} };
353
- }
354
-
355
- console.log(styleText("cyan", ` [${namespace}] Seeding ${typesWithData.length} types via Kysely batch insert...`));
356
-
357
- // Bundle seed script
358
- const bundled = await bundleSeedScript(namespace, typesWithData);
359
-
360
- // Chunk seed data to fit within gRPC message size limits
361
- const chunks = chunkSeedData({
362
- data,
363
- order: sortedTypes,
364
- codeByteSize: new TextEncoder().encode(bundled.bundledCode).length,
365
- });
366
-
367
- if (chunks.length === 0) {
368
- console.log(styleText("dim", ` [${namespace}] No data to seed`));
369
- return { success: true, processed: {} };
370
- }
371
-
372
- if (chunks.length > 1) {
373
- console.log(styleText("dim", ` Split into ${chunks.length} chunks`));
374
- }
375
-
376
- const allProcessed = {};
377
- let hasError = false;
378
- const allErrors = [];
379
-
380
- for (const chunk of chunks) {
381
- if (chunks.length > 1) {
382
- console.log(styleText("dim", ` Chunk ${chunk.index + 1}/${chunk.total}: ${chunk.order.join(", ")}`));
383
- }
384
-
385
- // Execute seed script for this chunk
386
- const result = await executeScript({
387
- client: operatorClient,
388
- workspaceId,
389
- name: `seed-${namespace}.ts`,
390
- code: bundled.bundledCode,
391
- arg: JSON.stringify({ data: chunk.data, order: chunk.order, selfRefTypes }),
392
- invoker: {
393
- namespace: authNamespace,
394
- machineUserName,
395
- },
396
- });
397
-
398
- // Parse result and display logs
399
- if (result.logs) {
400
- for (const line of result.logs.split("\n").filter(Boolean)) {
401
- console.log(styleText("dim", ` ${line}`));
402
- }
403
- }
404
-
405
- if (result.success) {
406
- let parsed;
407
- try {
408
- const parsedResult = JSON.parse(result.result || "{}");
409
- parsed = parsedResult && typeof parsedResult === "object" ? parsedResult : {};
410
- } catch (error) {
411
- const message = error instanceof Error ? error.message : String(error);
412
- console.error(styleText("red", ` ✗ Failed to parse seed result: ${message}`));
413
- hasError = true;
414
- allErrors.push(message);
415
- continue;
416
- }
417
-
418
- const processed = parsed.processed || {};
419
- for (const [type, count] of Object.entries(processed)) {
420
- allProcessed[type] = (allProcessed[type] || 0) + count;
421
- console.log(styleText("green", ` ✓ ${type}: ${count} rows inserted`));
422
- }
423
-
424
- if (!parsed.success) {
425
- const errors = Array.isArray(parsed.errors) ? parsed.errors : [];
426
- const errorMessage =
427
- errors.length > 0 ? errors.join("\n ") : "Seed script reported failure";
428
- console.error(styleText("red", ` ✗ Seed failed:\n ${errorMessage}`));
429
- hasError = true;
430
- allErrors.push(errorMessage);
431
- }
432
- } else {
433
- console.error(styleText("red", ` ✗ Seed failed: ${result.error}`));
434
- hasError = true;
435
- allErrors.push(result.error);
436
- }
437
- }
438
-
439
- if (hasError) {
440
- return { success: false, error: allErrors.join("\n") };
441
- }
442
- return { success: true, processed: allProcessed };
443
- };
444
-
445
-
446
-
447
- // Main execution
448
- try {
449
- let allSuccess = true;
450
-
451
- // Determine which namespaces and types to process
452
- const namespacesToProcess = hasNamespace
453
- ? [values.namespace]
454
- : Object.keys(namespaceEntities);
455
-
456
- for (const namespace of namespacesToProcess) {
457
- const nsTypes = namespaceEntities[namespace] || [];
458
- const nsDeps = namespaceDeps[namespace] || {};
459
- const nsSelfRefTypes = namespaceSelfRefTypes[namespace] || [];
460
-
461
- // Filter types if specific types requested
462
- let typesToSeed = entitiesToProcess
463
- ? nsTypes.filter((t) => entitiesToProcess.includes(t))
464
- : nsTypes;
465
-
466
- if (typesToSeed.length === 0) continue;
467
-
468
- const result = await seedViaTestExecScript(namespace, typesToSeed, nsDeps, nsSelfRefTypes);
469
- if (!result.success) {
470
- allSuccess = false;
471
- }
472
- }
473
-
474
-
475
-
476
- if (allSuccess) {
477
- console.log(styleText("green", "\n✓ Seed data generation completed successfully"));
478
- } else {
479
- console.error(styleText("red", "\n✗ Seed data generation completed with errors"));
480
- process.exit(1);
481
- }
482
- } catch (error) {
483
- console.error(styleText("red", `\n✗ Seed data generation failed: ${error.message}`));
484
- process.exit(1);
485
- }