@tailor-platform/create-sdk 2.0.0-next.8 → 2.0.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 +164 -0
- package/package.json +6 -6
- package/templates/executor/.oxlintrc.json +1 -0
- package/templates/executor/package.json +5 -5
- package/templates/generators/.oxlintrc.json +1 -0
- package/templates/generators/README.md +1 -1
- package/templates/generators/package.json +8 -5
- package/templates/hello-world/.oxlintrc.json +1 -0
- package/templates/hello-world/package.json +5 -5
- package/templates/inventory-management/.oxlintrc.json +1 -0
- package/templates/inventory-management/package.json +5 -5
- package/templates/multi-application/.oxlintrc.json +1 -0
- package/templates/multi-application/package.json +5 -5
- package/templates/resolver/.oxlintrc.json +1 -0
- package/templates/resolver/package.json +5 -5
- package/templates/resolver/tailor.d.ts +2 -2
- package/templates/static-web-site/.oxlintrc.json +1 -0
- package/templates/static-web-site/package.json +5 -5
- package/templates/tailordb/.oxlintrc.json +1 -0
- package/templates/tailordb/package.json +5 -5
- package/templates/workflow/.oxlintrc.json +1 -0
- package/templates/workflow/package.json +5 -5
- package/templates/generators/src/seed/exec.mjs +0 -485
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,169 @@
|
|
|
1
1
|
# @tailor-platform/create-sdk
|
|
2
2
|
|
|
3
|
+
## 2.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`1a055c9`](https://github.com/tailor-platform/sdk/commit/1a055c9909ac951f807fc2249c9abc1d5805398f) Thanks [@toiroakr](https://github.com/toiroakr)! - Rename the TailorDB schema builder from `db.type()` to `db.table()`.
|
|
8
|
+
|
|
9
|
+
Update TailorDB definitions:
|
|
10
|
+
|
|
11
|
+
```diff
|
|
12
|
+
import { db } from "@tailor-platform/sdk";
|
|
13
|
+
|
|
14
|
+
-export const user = db.type("User", {
|
|
15
|
+
+export const user = db.table("User", {
|
|
16
|
+
name: db.string(),
|
|
17
|
+
});
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`3dcd82d`](https://github.com/tailor-platform/sdk/commit/3dcd82d54d6c059df90f2dc4788a7059fe4004ab) Thanks [@toiroakr](https://github.com/toiroakr)! - Restore Tailor field outputs for UUID, date, datetime, time, and decimal fields to plain string-compatible types and remove the strict scalar string migration guidance.
|
|
21
|
+
|
|
22
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`a3bd9fb`](https://github.com/tailor-platform/sdk/commit/a3bd9fb1c22d7062c8627c80ebc5ebb3b1db0dc3) Thanks [@toiroakr](https://github.com/toiroakr)! - 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.
|
|
23
|
+
|
|
24
|
+
Update create-sdk templates so scaffolded projects use the new non-null `updatedAt` Kysely types and seed schemas.
|
|
25
|
+
|
|
26
|
+
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.
|
|
27
|
+
|
|
28
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`eeb235d`](https://github.com/tailor-platform/sdk/commit/eeb235debe910c05f755f036486878e7c763cb7e) Thanks [@toiroakr](https://github.com/toiroakr)! - Rename `defineWaitPoint` and `defineWaitPoints` to `createWaitPoint` and `createWaitPoints`.
|
|
29
|
+
|
|
30
|
+
These functions create runtime instances with `.wait()` and `.resolve()` methods that call the platform API at runtime, so the `create*` prefix is more accurate. Update any usages:
|
|
31
|
+
|
|
32
|
+
```diff
|
|
33
|
+
-import { defineWaitPoint, defineWaitPoints } from "@tailor-platform/sdk";
|
|
34
|
+
+import { createWaitPoint, createWaitPoints } from "@tailor-platform/sdk";
|
|
35
|
+
|
|
36
|
+
-export const approval = defineWaitPoint<Payload, Result>("approval");
|
|
37
|
+
+export const approval = createWaitPoint<Payload, Result>("approval");
|
|
38
|
+
|
|
39
|
+
-export const waitPoints = defineWaitPoints((define) => ({ ... }));
|
|
40
|
+
+export const waitPoints = createWaitPoints((define) => ({ ... }));
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`93b68ac`](https://github.com/tailor-platform/sdk/commit/93b68ace83dcb0af2a8b0afa8aa3336cb18c818b) Thanks [@toiroakr](https://github.com/toiroakr)! - Rename `Workflow.trigger()` (returned by `createWorkflow()`) and `WorkflowJob.trigger()` (returned by `createWorkflowJob()`) to `.start()`, aligning the SDK's ergonomic verb with the platform's `start*` RPC vocabulary:
|
|
44
|
+
|
|
45
|
+
```diff
|
|
46
|
+
const inventory = checkInventory.trigger({ orderId: input.orderId });
|
|
47
|
+
+const inventory = checkInventory.start({ orderId: input.orderId });
|
|
48
|
+
|
|
49
|
+
-const workflowRunId = await orderProcessingWorkflow.trigger(args, { invoker: "manager" });
|
|
50
|
+
+const workflowRunId = await orderProcessingWorkflow.start(args, { invoker: "manager" });
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`mockWorkflow()`'s `wf.job(definition)` / `wf.workflow(definition)` now return a mock of the `.start` method, and `wf.setTriggerHandler` / `wf.triggeredJobs` are renamed to `wf.setStartHandler` / `wf.startedJobs`. No codemod ships for the `.trigger()` → `.start()` call-site rename itself — see the `v2/workflow-start-rename` migration guide entry for manual migration steps.
|
|
54
|
+
|
|
55
|
+
### Minor Changes
|
|
56
|
+
|
|
57
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`152a2de`](https://github.com/tailor-platform/sdk/commit/152a2de92db8565791dc1ec8aab29f2a75c94913) Thanks [@toiroakr](https://github.com/toiroakr)! - Add a lint rule (`no-execute-script-arg-stringify`) that flags passing a `JSON.stringify(...)` result as `executeScript`'s `arg` option — `executeScript` serializes `arg` internally, so a pre-stringified value silently double-encodes at runtime. Enabled in newly scaffolded projects.
|
|
58
|
+
|
|
59
|
+
### Patch Changes
|
|
60
|
+
|
|
61
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`6519a54`](https://github.com/tailor-platform/sdk/commit/6519a5434f0cc664a609ef2cae2398b19cad4673) Thanks [@toiroakr](https://github.com/toiroakr)! - Rename auth attribute module augmentation from `AttributeMap` to `Attributes`.
|
|
62
|
+
|
|
63
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`039389d`](https://github.com/tailor-platform/sdk/commit/039389d17ddf3014fc53ffdb756ec6ea1425826c) Thanks [@toiroakr](https://github.com/toiroakr)! - Generate the `Env` interface in `tailor.d.ts` from the type of each `defineConfig({ env })` value instead of the value itself. The resolved value used to be written in as a literal type, so running `generate` or `deploy` with real environment variables loaded stamped those values into a file that is normally committed.
|
|
64
|
+
|
|
65
|
+
```diff
|
|
66
|
+
interface Env {
|
|
67
|
+
- API_BASE: "https://api.example.com";
|
|
68
|
+
- RETRIES: 3;
|
|
69
|
+
- VERBOSE: true;
|
|
70
|
+
+ API_BASE: string;
|
|
71
|
+
+ RETRIES: number;
|
|
72
|
+
+ VERBOSE: boolean;
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`env` keys that aren't valid TypeScript identifiers (for example `"API-BASE"`) are now quoted as well; previously they were emitted bare and produced a `tailor.d.ts` that failed to parse.
|
|
77
|
+
|
|
78
|
+
Run `tailor generate` after upgrading to refresh the file. Code that relied on the literal narrowing — comparing `env.STAGE` against a literal union, for example — has to widen its own types or read the value through a local narrowing check. If a `tailor.d.ts` you already committed contains a sensitive value, treat that value as exposed and rotate it; keep secrets in [Secret Manager](https://github.com/tailor-platform/sdk/blob/main/packages/sdk/docs/services/secret.md) rather than `env`.
|
|
79
|
+
|
|
80
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`cd48fda`](https://github.com/tailor-platform/sdk/commit/cd48fdab46746aa2e8f5d8dd43073e3b4832c07c) Thanks [@toiroakr](https://github.com/toiroakr)! - Rename resolver, executor, workflow trigger, and typed workflow start machine-user options from `authInvoker` to `invoker`.
|
|
81
|
+
|
|
82
|
+
Update create-sdk templates and the v2 auth invoker codemod to generate the new `invoker` option.
|
|
83
|
+
|
|
84
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`0676403`](https://github.com/tailor-platform/sdk/commit/0676403f0c2686a9b861047af105661bf52e9d9a) Thanks [@toiroakr](https://github.com/toiroakr)! - Remove the deprecated `openDownloadStream` file streaming API. Use `downloadStream` for streamed file downloads.
|
|
85
|
+
|
|
86
|
+
The generated file utilities now emit `downloadFileStream`, which calls `downloadStream` and returns `FileDownloadStreamResponse`, instead of the removed `openFileDownloadStream` helper.
|
|
87
|
+
|
|
88
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`20aa5a9`](https://github.com/tailor-platform/sdk/commit/20aa5a95167d370b4b3cc7352cb60a22a695d673) Thanks [@toiroakr](https://github.com/toiroakr)! - Remove the APIs that were marked `@deprecated` on the way to v2, so 2.0.0 ships without deprecated aliases. Each removal has migration coverage in `tailor upgrade`:
|
|
89
|
+
|
|
90
|
+
- `@tailor-platform/sdk/cli` no longer re-exports `kyselyTypePlugin`, `enumConstantsPlugin`, `fileUtilsPlugin`, and `seedPlugin`. Import them from `@tailor-platform/sdk/plugin/kysely-type`, `/plugin/enum-constants`, `/plugin/file-utils`, and `/plugin/seed` (codemod `v2/plugin-cli-import`).
|
|
91
|
+
- `tailor.workflow.startJobFunction` and the `StartJobFunctionOptions` type are removed; use the canonical `execJobFunction` / `ExecJobFunctionOptions` (new codemod `v2/exec-job-function-rename`). `mockWorkflow()` no longer exposes the `startJobFunction` alias — assert on its `execJobFunction` mock instead — and `v2/workflow-trigger-rename` now rewrites `triggerJobFunction` straight to `execJobFunction`.
|
|
92
|
+
- `@tailor-platform/sdk/test` no longer exports the platform-global mocks `setupTailordbMock`, `setupWorkflowMock`, `setupWaitPointMock`, `setupInvokerMock`, and `setupTailorErrorsMock`, nor the bundled-output helper `createImportMain`. Use the `tailor-runtime` environment from `@tailor-platform/sdk/vitest` with `mockTailordb` / `mockWorkflow` (migration guidance: `v2/sdk-test-mocks-to-vitest`). `createTailorDBHook`, `createStandardSchema`, and `unauthenticatedTailorUser` are unchanged.
|
|
93
|
+
- The programmatic CLI functions no longer accept name-keyed options: `GetWorkflowOptions`, `StartWorkflowOptions`, `ListWorkflowExecutionsOptions`, `GetExecutorOptions`, `TriggerExecutorOptions`, `ListExecutorJobsOptions`, `GetExecutorJobOptions`, and `WatchExecutorJobOptions` are removed along with the overloads that took them. Pass the definition itself — `startWorkflow({ workflow: myWorkflow, invoker: "admin" })`, `watchExecutorJob({ executor: myExecutor, jobId })` — which also types `arg` and `payload` from the definition (migration guidance: `v2/cli-typed-options`). The name-keyed entry points remain available as CLI commands (`tailor workflow start <name>`, `tailor executor trigger <name>`).
|
|
94
|
+
|
|
95
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`8b03f82`](https://github.com/tailor-platform/sdk/commit/8b03f827642e64f3b3af5a05ecdef405028a803a) Thanks [@toiroakr](https://github.com/toiroakr)! - Standardize SDK-owned environment variables on the `TAILOR_*` namespace.
|
|
96
|
+
|
|
97
|
+
Replace the removed SDK-specific environment variables with their new names: `TAILOR_CONFIG_PATH`, `TAILOR_DTS_PATH`, `TAILOR_CI_ALLOW_ID_INJECTION`, `TAILOR_DEPLOY_BUILD_ONLY`, `TAILOR_BUILD_OUTPUT_DIR`, `TAILOR_SKILLS_SOURCE`, `TAILOR_TEMPLATE_SDK_VERSION`, `TAILOR_PLATFORM_URL`, `TAILOR_PLATFORM_OAUTH2_CLIENT_ID`, `TAILOR_INLINE_SOURCEMAP`, `TAILOR_QUERY_NEWLINE_ON_ENTER`, and `TAILOR_APP_LOG_LEVEL`. The deprecated `TAILOR_TOKEN` fallback is removed; use `TAILOR_PLATFORM_TOKEN`. The v2 codemod rewrites unambiguous removed SDK environment variable names and flags generic names such as `LOG_LEVEL` and `PLATFORM_URL` for manual review.
|
|
98
|
+
|
|
99
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`04ca361`](https://github.com/tailor-platform/sdk/commit/04ca3619c4d2d88afe8ee3b25d4ba47ac799de51) Thanks [@toiroakr](https://github.com/toiroakr)! - Remove flat value and default exports from `@tailor-platform/sdk/runtime/*` subpath modules. Import each subpath through its self-named namespace export instead, for example `import { iconv } from "@tailor-platform/sdk/runtime/iconv"`.
|
|
100
|
+
|
|
101
|
+
The aggregate `@tailor-platform/sdk/runtime` entry remains named-only, and its deprecated `file.deleteFile` alias is removed in favor of `file.delete`. The v2 codemod rewrites straightforward namespace-star subpath imports, flat named value imports, and aggregate `file.deleteFile` calls to the new namespace-object style.
|
|
102
|
+
|
|
103
|
+
`TailorContextAPI` and `TailorWorkflowAPI` now describe the SDK wrapper objects. Code that types the platform-provided `globalThis.tailor.context` or `globalThis.tailor.workflow` objects directly must use `PlatformContextAPI` or `PlatformWorkflowAPI` instead.
|
|
104
|
+
|
|
105
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`bf11bf8`](https://github.com/tailor-platform/sdk/commit/bf11bf8d3bad6195c86ed289c764490dc6d680ee) Thanks [@toiroakr](https://github.com/toiroakr)! - Update politty to v0.11.3
|
|
106
|
+
|
|
107
|
+
## 2.0.0-next.11
|
|
108
|
+
|
|
109
|
+
### Minor Changes
|
|
110
|
+
|
|
111
|
+
- [#1890](https://github.com/tailor-platform/sdk/pull/1890) [`9fdacdc`](https://github.com/tailor-platform/sdk/commit/9fdacdcbbdcb18f4b324470ac34ca70215f962aa) Thanks [@toiroakr](https://github.com/toiroakr)! - Add a lint rule (`no-execute-script-arg-stringify`) that flags passing a `JSON.stringify(...)` result as `executeScript`'s `arg` option — `executeScript` serializes `arg` internally, so a pre-stringified value silently double-encodes at runtime. Enabled in newly scaffolded projects.
|
|
112
|
+
|
|
113
|
+
### Patch Changes
|
|
114
|
+
|
|
115
|
+
- [#1915](https://github.com/tailor-platform/sdk/pull/1915) [`dc691ec`](https://github.com/tailor-platform/sdk/commit/dc691ec1e2181400c6715233f0588a1b5150038f) Thanks [@toiroakr](https://github.com/toiroakr)! - Generate the `Env` interface in `tailor.d.ts` from the type of each `defineConfig({ env })` value instead of the value itself. The resolved value used to be written in as a literal type, so running `generate` or `deploy` with real environment variables loaded stamped those values into a file that is normally committed.
|
|
116
|
+
|
|
117
|
+
```diff
|
|
118
|
+
interface Env {
|
|
119
|
+
- API_BASE: "https://api.example.com";
|
|
120
|
+
- RETRIES: 3;
|
|
121
|
+
- VERBOSE: true;
|
|
122
|
+
+ API_BASE: string;
|
|
123
|
+
+ RETRIES: number;
|
|
124
|
+
+ VERBOSE: boolean;
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`env` keys that aren't valid TypeScript identifiers (for example `"API-BASE"`) are now quoted as well; previously they were emitted bare and produced a `tailor.d.ts` that failed to parse.
|
|
129
|
+
|
|
130
|
+
Run `tailor generate` after upgrading to refresh the file. Code that relied on the literal narrowing — comparing `env.STAGE` against a literal union, for example — has to widen its own types or read the value through a local narrowing check. If a `tailor.d.ts` you already committed contains a sensitive value, treat that value as exposed and rotate it; keep secrets in [Secret Manager](https://github.com/tailor-platform/sdk/blob/main/packages/sdk/docs/services/secret.md) rather than `env`.
|
|
131
|
+
|
|
132
|
+
- [#1808](https://github.com/tailor-platform/sdk/pull/1808) [`a4cdee0`](https://github.com/tailor-platform/sdk/commit/a4cdee079707105213f8e5833dcaa613f39c8464) Thanks [@toiroakr](https://github.com/toiroakr)! - Remove the APIs that were marked `@deprecated` on the way to v2, so 2.0.0 ships without deprecated aliases. Each removal has migration coverage in `tailor upgrade`:
|
|
133
|
+
|
|
134
|
+
- `@tailor-platform/sdk/cli` no longer re-exports `kyselyTypePlugin`, `enumConstantsPlugin`, `fileUtilsPlugin`, and `seedPlugin`. Import them from `@tailor-platform/sdk/plugin/kysely-type`, `/plugin/enum-constants`, `/plugin/file-utils`, and `/plugin/seed` (codemod `v2/plugin-cli-import`).
|
|
135
|
+
- `tailor.workflow.startJobFunction` and the `StartJobFunctionOptions` type are removed; use the canonical `execJobFunction` / `ExecJobFunctionOptions` (new codemod `v2/exec-job-function-rename`). `mockWorkflow()` no longer exposes the `startJobFunction` alias — assert on its `execJobFunction` mock instead — and `v2/workflow-trigger-rename` now rewrites `triggerJobFunction` straight to `execJobFunction`.
|
|
136
|
+
- `@tailor-platform/sdk/test` no longer exports the platform-global mocks `setupTailordbMock`, `setupWorkflowMock`, `setupWaitPointMock`, `setupInvokerMock`, and `setupTailorErrorsMock`, nor the bundled-output helper `createImportMain`. Use the `tailor-runtime` environment from `@tailor-platform/sdk/vitest` with `mockTailordb` / `mockWorkflow` (migration guidance: `v2/sdk-test-mocks-to-vitest`). `createTailorDBHook`, `createStandardSchema`, and `unauthenticatedTailorUser` are unchanged.
|
|
137
|
+
- The programmatic CLI functions no longer accept name-keyed options: `GetWorkflowOptions`, `StartWorkflowOptions`, `ListWorkflowExecutionsOptions`, `GetExecutorOptions`, `TriggerExecutorOptions`, `ListExecutorJobsOptions`, `GetExecutorJobOptions`, and `WatchExecutorJobOptions` are removed along with the overloads that took them. Pass the definition itself — `startWorkflow({ workflow: myWorkflow, invoker: "admin" })`, `watchExecutorJob({ executor: myExecutor, jobId })` — which also types `arg` and `payload` from the definition (migration guidance: `v2/cli-typed-options`). The name-keyed entry points remain available as CLI commands (`tailor workflow start <name>`, `tailor executor trigger <name>`).
|
|
138
|
+
|
|
139
|
+
## 2.0.0-next.10
|
|
140
|
+
|
|
141
|
+
### Patch Changes
|
|
142
|
+
|
|
143
|
+
- [#1837](https://github.com/tailor-platform/sdk/pull/1837) [`b74966b`](https://github.com/tailor-platform/sdk/commit/b74966bcefa499df1cbb5ef7e36ca76442658579) Thanks [@toiroakr](https://github.com/toiroakr)! - Update politty to v0.11.3
|
|
144
|
+
|
|
145
|
+
## 2.0.0-next.9
|
|
146
|
+
|
|
147
|
+
## 1.85.0
|
|
148
|
+
|
|
149
|
+
## 1.84.0
|
|
150
|
+
|
|
151
|
+
## 1.83.0
|
|
152
|
+
|
|
153
|
+
## 1.82.0
|
|
154
|
+
|
|
155
|
+
## 1.81.0
|
|
156
|
+
|
|
157
|
+
## 1.80.1
|
|
158
|
+
|
|
159
|
+
## 1.80.0
|
|
160
|
+
|
|
161
|
+
### Minor Changes
|
|
162
|
+
|
|
163
|
+
- [#1737](https://github.com/tailor-platform/sdk/pull/1737) [`e349b9e`](https://github.com/tailor-platform/sdk/commit/e349b9e3d9c61f324f21dea92dd08055493a2c6d) Thanks [@dqn](https://github.com/dqn)! - Add lint rules that flag the external /api prefix in HTTP adapter path patterns and permission settings that grant access unconditionally, and enable them in newly scaffolded projects.
|
|
164
|
+
|
|
165
|
+
## 1.79.0
|
|
166
|
+
|
|
3
167
|
## 2.0.0-next.8
|
|
4
168
|
|
|
5
169
|
## 2.0.0-next.7
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tailor-platform/create-sdk",
|
|
3
|
-
"version": "2.0.0
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "A CLI tool to quickly create a new Tailor Platform SDK project",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -18,18 +18,18 @@
|
|
|
18
18
|
"type": "module",
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@clack/prompts": "1.7.0",
|
|
21
|
-
"execa": "
|
|
21
|
+
"execa": "10.0.0",
|
|
22
22
|
"picocolors": "1.1.1",
|
|
23
23
|
"pkg-types": "2.3.1",
|
|
24
|
-
"politty": "0.11.
|
|
24
|
+
"politty": "0.11.6",
|
|
25
25
|
"zod": "4.4.3"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "24.13.3",
|
|
29
29
|
"eslint-plugin-zod": "4.7.0",
|
|
30
|
-
"oxlint": "1.
|
|
31
|
-
"oxlint-tsgolint": "0.
|
|
32
|
-
"tsdown": "0.22.
|
|
30
|
+
"oxlint": "1.76.0",
|
|
31
|
+
"oxlint-tsgolint": "7.0.2001",
|
|
32
|
+
"tsdown": "0.22.14",
|
|
33
33
|
"typescript": "6.0.3"
|
|
34
34
|
},
|
|
35
35
|
"scripts": {
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"ignorePatterns": [".tailor/", "src/generated/", "tailor.d.ts"],
|
|
17
17
|
"rules": {
|
|
18
18
|
"tailor-sdk/no-api-prefix-in-path-pattern": "warn",
|
|
19
|
+
"tailor-sdk/no-execute-script-arg-stringify": "warn",
|
|
19
20
|
"tailor-sdk/no-unconditional-permit": "warn",
|
|
20
21
|
"no-case-declarations": "error",
|
|
21
22
|
"no-empty": "error",
|
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
"typecheck": "tsc --noEmit"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@tailor-platform/eslint-plugin-sdk": "0.
|
|
19
|
-
"@tailor-platform/sdk": "2.0.0
|
|
18
|
+
"@tailor-platform/eslint-plugin-sdk": "0.2.0",
|
|
19
|
+
"@tailor-platform/sdk": "2.0.0",
|
|
20
20
|
"@types/node": "24.13.3",
|
|
21
|
-
"oxfmt": "0.
|
|
22
|
-
"oxlint": "1.
|
|
23
|
-
"oxlint-tsgolint": "0.
|
|
21
|
+
"oxfmt": "0.61.0",
|
|
22
|
+
"oxlint": "1.76.0",
|
|
23
|
+
"oxlint-tsgolint": "7.0.2001",
|
|
24
24
|
"typescript": "6.0.3",
|
|
25
25
|
"vitest": "4.1.10"
|
|
26
26
|
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"ignorePatterns": [".tailor/", "src/generated/", "src/seed/", "tailor.d.ts"],
|
|
17
17
|
"rules": {
|
|
18
18
|
"tailor-sdk/no-api-prefix-in-path-pattern": "warn",
|
|
19
|
+
"tailor-sdk/no-execute-script-arg-stringify": "warn",
|
|
19
20
|
"tailor-sdk/no-unconditional-permit": "warn",
|
|
20
21
|
"no-case-declarations": "error",
|
|
21
22
|
"no-empty": "error",
|
|
@@ -7,7 +7,7 @@ Demonstrates all built-in generator plugins for the Tailor Platform SDK.
|
|
|
7
7
|
- **kyselyTypePlugin** - Generates Kysely type definitions for type-safe database queries
|
|
8
8
|
- **enumConstantsPlugin** - Generates enum constant objects from `db.enum()` fields
|
|
9
9
|
- **fileUtilsPlugin** - Generates file upload/download utility functions
|
|
10
|
-
- **seedPlugin** - Generates seed data templates and
|
|
10
|
+
- **seedPlugin** - Generates seed data templates and schemas (run them with the `tailor seed` commands from `@tailor-platform/sdk-plugin-seed`)
|
|
11
11
|
|
|
12
12
|
## Generated Files
|
|
13
13
|
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
"scripts": {
|
|
7
7
|
"generate": "tailor generate",
|
|
8
8
|
"deploy": "tailor deploy",
|
|
9
|
+
"seed": "tailor seed apply",
|
|
10
|
+
"seed:validate": "tailor seed validate",
|
|
9
11
|
"test": "vitest --project unit",
|
|
10
12
|
"test:unit": "vitest --project unit",
|
|
11
13
|
"format": "oxfmt --write .",
|
|
@@ -15,12 +17,13 @@
|
|
|
15
17
|
"typecheck": "tsc --noEmit"
|
|
16
18
|
},
|
|
17
19
|
"devDependencies": {
|
|
18
|
-
"@tailor-platform/eslint-plugin-sdk": "0.
|
|
19
|
-
"@tailor-platform/sdk": "2.0.0
|
|
20
|
+
"@tailor-platform/eslint-plugin-sdk": "0.2.0",
|
|
21
|
+
"@tailor-platform/sdk": "2.0.0",
|
|
22
|
+
"@tailor-platform/sdk-plugin-seed": "0.1.0",
|
|
20
23
|
"@types/node": "24.13.3",
|
|
21
|
-
"oxfmt": "0.
|
|
22
|
-
"oxlint": "1.
|
|
23
|
-
"oxlint-tsgolint": "0.
|
|
24
|
+
"oxfmt": "0.61.0",
|
|
25
|
+
"oxlint": "1.76.0",
|
|
26
|
+
"oxlint-tsgolint": "7.0.2001",
|
|
24
27
|
"typescript": "6.0.3",
|
|
25
28
|
"vitest": "4.1.10"
|
|
26
29
|
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"ignorePatterns": [".tailor/", "tailor.d.ts"],
|
|
17
17
|
"rules": {
|
|
18
18
|
"tailor-sdk/no-api-prefix-in-path-pattern": "warn",
|
|
19
|
+
"tailor-sdk/no-execute-script-arg-stringify": "warn",
|
|
19
20
|
"tailor-sdk/no-unconditional-permit": "warn",
|
|
20
21
|
"no-case-declarations": "error",
|
|
21
22
|
"no-empty": "error",
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
"typecheck": "tsc --noEmit"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@tailor-platform/eslint-plugin-sdk": "0.
|
|
17
|
-
"@tailor-platform/sdk": "2.0.0
|
|
16
|
+
"@tailor-platform/eslint-plugin-sdk": "0.2.0",
|
|
17
|
+
"@tailor-platform/sdk": "2.0.0",
|
|
18
18
|
"@types/node": "24.13.3",
|
|
19
|
-
"oxfmt": "0.
|
|
20
|
-
"oxlint": "1.
|
|
21
|
-
"oxlint-tsgolint": "0.
|
|
19
|
+
"oxfmt": "0.61.0",
|
|
20
|
+
"oxlint": "1.76.0",
|
|
21
|
+
"oxlint-tsgolint": "7.0.2001",
|
|
22
22
|
"typescript": "6.0.3"
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"ignorePatterns": [".tailor/", "src/generated/", "tailor.d.ts"],
|
|
17
17
|
"rules": {
|
|
18
18
|
"tailor-sdk/no-api-prefix-in-path-pattern": "warn",
|
|
19
|
+
"tailor-sdk/no-execute-script-arg-stringify": "warn",
|
|
19
20
|
"tailor-sdk/no-unconditional-permit": "warn",
|
|
20
21
|
"no-case-declarations": "error",
|
|
21
22
|
"no-empty": "error",
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
"typecheck": "tsc --noEmit"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@tailor-platform/eslint-plugin-sdk": "0.
|
|
17
|
-
"@tailor-platform/sdk": "2.0.0
|
|
16
|
+
"@tailor-platform/eslint-plugin-sdk": "0.2.0",
|
|
17
|
+
"@tailor-platform/sdk": "2.0.0",
|
|
18
18
|
"@types/node": "24.13.3",
|
|
19
|
-
"oxfmt": "0.
|
|
20
|
-
"oxlint": "1.
|
|
21
|
-
"oxlint-tsgolint": "0.
|
|
19
|
+
"oxfmt": "0.61.0",
|
|
20
|
+
"oxlint": "1.76.0",
|
|
21
|
+
"oxlint-tsgolint": "7.0.2001",
|
|
22
22
|
"typescript": "6.0.3"
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"ignorePatterns": [".tailor/", "tailor.d.ts"],
|
|
17
17
|
"rules": {
|
|
18
18
|
"tailor-sdk/no-api-prefix-in-path-pattern": "warn",
|
|
19
|
+
"tailor-sdk/no-execute-script-arg-stringify": "warn",
|
|
19
20
|
"tailor-sdk/no-unconditional-permit": "warn",
|
|
20
21
|
"no-case-declarations": "error",
|
|
21
22
|
"no-empty": "error",
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"typecheck": "tsc --noEmit"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@tailor-platform/eslint-plugin-sdk": "0.
|
|
18
|
-
"@tailor-platform/sdk": "2.0.0
|
|
17
|
+
"@tailor-platform/eslint-plugin-sdk": "0.2.0",
|
|
18
|
+
"@tailor-platform/sdk": "2.0.0",
|
|
19
19
|
"@types/node": "24.13.3",
|
|
20
|
-
"oxfmt": "0.
|
|
21
|
-
"oxlint": "1.
|
|
22
|
-
"oxlint-tsgolint": "0.
|
|
20
|
+
"oxfmt": "0.61.0",
|
|
21
|
+
"oxlint": "1.76.0",
|
|
22
|
+
"oxlint-tsgolint": "7.0.2001",
|
|
23
23
|
"typescript": "6.0.3"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"ignorePatterns": [".tailor/", "src/generated/", "tailor.d.ts"],
|
|
17
17
|
"rules": {
|
|
18
18
|
"tailor-sdk/no-api-prefix-in-path-pattern": "warn",
|
|
19
|
+
"tailor-sdk/no-execute-script-arg-stringify": "warn",
|
|
19
20
|
"tailor-sdk/no-unconditional-permit": "warn",
|
|
20
21
|
"no-case-declarations": "error",
|
|
21
22
|
"no-empty": "error",
|
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
"typecheck": "tsc --noEmit"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@tailor-platform/eslint-plugin-sdk": "0.
|
|
19
|
-
"@tailor-platform/sdk": "2.0.0
|
|
18
|
+
"@tailor-platform/eslint-plugin-sdk": "0.2.0",
|
|
19
|
+
"@tailor-platform/sdk": "2.0.0",
|
|
20
20
|
"@types/node": "24.13.3",
|
|
21
|
-
"oxfmt": "0.
|
|
22
|
-
"oxlint": "1.
|
|
23
|
-
"oxlint-tsgolint": "0.
|
|
21
|
+
"oxfmt": "0.61.0",
|
|
22
|
+
"oxlint": "1.76.0",
|
|
23
|
+
"oxlint-tsgolint": "7.0.2001",
|
|
24
24
|
"typescript": "6.0.3",
|
|
25
25
|
"vitest": "4.1.10"
|
|
26
26
|
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"ignorePatterns": [".tailor/", "src/generated/", "tailor.d.ts"],
|
|
17
17
|
"rules": {
|
|
18
18
|
"tailor-sdk/no-api-prefix-in-path-pattern": "warn",
|
|
19
|
+
"tailor-sdk/no-execute-script-arg-stringify": "warn",
|
|
19
20
|
"tailor-sdk/no-unconditional-permit": "warn",
|
|
20
21
|
"no-case-declarations": "error",
|
|
21
22
|
"no-empty": "error",
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
"typecheck": "tsc --noEmit"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
|
-
"@tailor-platform/eslint-plugin-sdk": "0.
|
|
17
|
-
"@tailor-platform/sdk": "2.0.0
|
|
16
|
+
"@tailor-platform/eslint-plugin-sdk": "0.2.0",
|
|
17
|
+
"@tailor-platform/sdk": "2.0.0",
|
|
18
18
|
"@types/node": "24.13.3",
|
|
19
|
-
"oxfmt": "0.
|
|
20
|
-
"oxlint": "1.
|
|
21
|
-
"oxlint-tsgolint": "0.
|
|
19
|
+
"oxfmt": "0.61.0",
|
|
20
|
+
"oxlint": "1.76.0",
|
|
21
|
+
"oxlint-tsgolint": "7.0.2001",
|
|
22
22
|
"typescript": "6.0.3"
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"ignorePatterns": [".tailor/", "src/generated/", "tailor.d.ts"],
|
|
17
17
|
"rules": {
|
|
18
18
|
"tailor-sdk/no-api-prefix-in-path-pattern": "warn",
|
|
19
|
+
"tailor-sdk/no-execute-script-arg-stringify": "warn",
|
|
19
20
|
"tailor-sdk/no-unconditional-permit": "warn",
|
|
20
21
|
"no-case-declarations": "error",
|
|
21
22
|
"no-empty": "error",
|
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
"typecheck": "tsc --noEmit"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@tailor-platform/eslint-plugin-sdk": "0.
|
|
19
|
-
"@tailor-platform/sdk": "2.0.0
|
|
18
|
+
"@tailor-platform/eslint-plugin-sdk": "0.2.0",
|
|
19
|
+
"@tailor-platform/sdk": "2.0.0",
|
|
20
20
|
"@types/node": "24.13.3",
|
|
21
|
-
"oxfmt": "0.
|
|
22
|
-
"oxlint": "1.
|
|
23
|
-
"oxlint-tsgolint": "0.
|
|
21
|
+
"oxfmt": "0.61.0",
|
|
22
|
+
"oxlint": "1.76.0",
|
|
23
|
+
"oxlint-tsgolint": "7.0.2001",
|
|
24
24
|
"typescript": "6.0.3",
|
|
25
25
|
"vitest": "4.1.10"
|
|
26
26
|
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"ignorePatterns": [".tailor/", "src/generated/", "tailor.d.ts"],
|
|
17
17
|
"rules": {
|
|
18
18
|
"tailor-sdk/no-api-prefix-in-path-pattern": "warn",
|
|
19
|
+
"tailor-sdk/no-execute-script-arg-stringify": "warn",
|
|
19
20
|
"tailor-sdk/no-unconditional-permit": "warn",
|
|
20
21
|
"no-case-declarations": "error",
|
|
21
22
|
"no-empty": "error",
|
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
"typecheck": "tsc --noEmit"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@tailor-platform/eslint-plugin-sdk": "0.
|
|
20
|
-
"@tailor-platform/sdk": "2.0.0
|
|
19
|
+
"@tailor-platform/eslint-plugin-sdk": "0.2.0",
|
|
20
|
+
"@tailor-platform/sdk": "2.0.0",
|
|
21
21
|
"@types/node": "24.13.3",
|
|
22
22
|
"graphql": "17.0.2",
|
|
23
23
|
"graphql-request": "7.4.0",
|
|
24
|
-
"oxfmt": "0.
|
|
25
|
-
"oxlint": "1.
|
|
26
|
-
"oxlint-tsgolint": "0.
|
|
24
|
+
"oxfmt": "0.61.0",
|
|
25
|
+
"oxlint": "1.76.0",
|
|
26
|
+
"oxlint-tsgolint": "7.0.2001",
|
|
27
27
|
"typescript": "6.0.3",
|
|
28
28
|
"vitest": "4.1.10"
|
|
29
29
|
}
|
|
@@ -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: { 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
|
-
}
|