openxiangda 1.0.26 → 1.0.28

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.
@@ -0,0 +1,61 @@
1
+ type WorkflowNodeRef = string;
2
+ interface WorkflowCompileResult {
3
+ definitionJson: {
4
+ version: "v3";
5
+ nodes: any[];
6
+ edges: any[];
7
+ flowConfig: Record<string, any[]>;
8
+ globalSettings: Record<string, any>;
9
+ };
10
+ previewJson: {
11
+ kind: "workflow_code_preview";
12
+ version: "preview_v1";
13
+ steps: any[];
14
+ edges: any[];
15
+ sourceMode: "workflow_code_ts";
16
+ };
17
+ }
18
+ interface WorkflowDefinitionInput {
19
+ name?: string;
20
+ formCode?: string;
21
+ formUuid?: string;
22
+ globalSettings?: Record<string, any>;
23
+ build: (flow: WorkflowBuilder) => void;
24
+ }
25
+ type NodeOptions = Record<string, any>;
26
+ declare class WorkflowBuilder {
27
+ private readonly meta;
28
+ private nodes;
29
+ private edges;
30
+ private flowConfig;
31
+ private globalSettings;
32
+ constructor(meta?: Omit<WorkflowDefinitionInput, "build">);
33
+ start(id?: string, data?: NodeOptions): WorkflowNodeRef;
34
+ end(id?: string, data?: NodeOptions): WorkflowNodeRef;
35
+ approval(id: string, data: NodeOptions): WorkflowNodeRef;
36
+ copy(id: string, data: NodeOptions): WorkflowNodeRef;
37
+ jsCode(id: string, data: NodeOptions): WorkflowNodeRef;
38
+ callbackWait(id: string, data: NodeOptions): WorkflowNodeRef;
39
+ connectorCall(id: string, data: NodeOptions): WorkflowNodeRef;
40
+ workNotification(id: string, data: NodeOptions): WorkflowNodeRef;
41
+ dingtalkCard(id: string, data: NodeOptions): WorkflowNodeRef;
42
+ condition(id: string, data: NodeOptions): WorkflowNodeRef;
43
+ data: {
44
+ retrieveSingle: (id: string, data: NodeOptions) => string;
45
+ retrieveBatch: (id: string, data: NodeOptions) => string;
46
+ create: (id: string, data: NodeOptions) => string;
47
+ update: (id: string, data: NodeOptions) => string;
48
+ };
49
+ node(type: string, id: string, data: NodeOptions): WorkflowNodeRef;
50
+ edge(source: WorkflowNodeRef, target: WorkflowNodeRef, data?: NodeOptions): void;
51
+ sequence(...refs: WorkflowNodeRef[]): void;
52
+ setFieldPermissions(nodeId: WorkflowNodeRef, permissions: any[]): void;
53
+ setGlobalSettings(settings: Record<string, any>): void;
54
+ compile(): WorkflowCompileResult;
55
+ }
56
+ declare function defineWorkflow(input: WorkflowDefinitionInput): {
57
+ __openxiangdaWorkflow: boolean;
58
+ compile(): WorkflowCompileResult;
59
+ };
60
+
61
+ export { WorkflowBuilder, type WorkflowCompileResult, type WorkflowDefinitionInput, type WorkflowNodeRef, defineWorkflow };
@@ -0,0 +1,61 @@
1
+ type WorkflowNodeRef = string;
2
+ interface WorkflowCompileResult {
3
+ definitionJson: {
4
+ version: "v3";
5
+ nodes: any[];
6
+ edges: any[];
7
+ flowConfig: Record<string, any[]>;
8
+ globalSettings: Record<string, any>;
9
+ };
10
+ previewJson: {
11
+ kind: "workflow_code_preview";
12
+ version: "preview_v1";
13
+ steps: any[];
14
+ edges: any[];
15
+ sourceMode: "workflow_code_ts";
16
+ };
17
+ }
18
+ interface WorkflowDefinitionInput {
19
+ name?: string;
20
+ formCode?: string;
21
+ formUuid?: string;
22
+ globalSettings?: Record<string, any>;
23
+ build: (flow: WorkflowBuilder) => void;
24
+ }
25
+ type NodeOptions = Record<string, any>;
26
+ declare class WorkflowBuilder {
27
+ private readonly meta;
28
+ private nodes;
29
+ private edges;
30
+ private flowConfig;
31
+ private globalSettings;
32
+ constructor(meta?: Omit<WorkflowDefinitionInput, "build">);
33
+ start(id?: string, data?: NodeOptions): WorkflowNodeRef;
34
+ end(id?: string, data?: NodeOptions): WorkflowNodeRef;
35
+ approval(id: string, data: NodeOptions): WorkflowNodeRef;
36
+ copy(id: string, data: NodeOptions): WorkflowNodeRef;
37
+ jsCode(id: string, data: NodeOptions): WorkflowNodeRef;
38
+ callbackWait(id: string, data: NodeOptions): WorkflowNodeRef;
39
+ connectorCall(id: string, data: NodeOptions): WorkflowNodeRef;
40
+ workNotification(id: string, data: NodeOptions): WorkflowNodeRef;
41
+ dingtalkCard(id: string, data: NodeOptions): WorkflowNodeRef;
42
+ condition(id: string, data: NodeOptions): WorkflowNodeRef;
43
+ data: {
44
+ retrieveSingle: (id: string, data: NodeOptions) => string;
45
+ retrieveBatch: (id: string, data: NodeOptions) => string;
46
+ create: (id: string, data: NodeOptions) => string;
47
+ update: (id: string, data: NodeOptions) => string;
48
+ };
49
+ node(type: string, id: string, data: NodeOptions): WorkflowNodeRef;
50
+ edge(source: WorkflowNodeRef, target: WorkflowNodeRef, data?: NodeOptions): void;
51
+ sequence(...refs: WorkflowNodeRef[]): void;
52
+ setFieldPermissions(nodeId: WorkflowNodeRef, permissions: any[]): void;
53
+ setGlobalSettings(settings: Record<string, any>): void;
54
+ compile(): WorkflowCompileResult;
55
+ }
56
+ declare function defineWorkflow(input: WorkflowDefinitionInput): {
57
+ __openxiangdaWorkflow: boolean;
58
+ compile(): WorkflowCompileResult;
59
+ };
60
+
61
+ export { WorkflowBuilder, type WorkflowCompileResult, type WorkflowDefinitionInput, type WorkflowNodeRef, defineWorkflow };
@@ -0,0 +1,209 @@
1
+ // packages/sdk/src/workflow/index.ts
2
+ function sanitizeId(value) {
3
+ return String(value || "").trim().replace(/[^a-zA-Z0-9_-]/g, "_");
4
+ }
5
+ function createPosition(index) {
6
+ return { x: 400, y: 100 + index * 150 };
7
+ }
8
+ var WorkflowBuilder = class {
9
+ constructor(meta = {}) {
10
+ this.meta = meta;
11
+ this.nodes = [];
12
+ this.edges = [];
13
+ this.flowConfig = {};
14
+ this.globalSettings = {};
15
+ this.data = {
16
+ retrieveSingle: (id, data) => this.node("data_retrieve_single", id, {
17
+ type: "data_retrieve_single",
18
+ label: data.label || "\u83B7\u53D6\u5355\u6761\u6570\u636E",
19
+ filterType: data.filterType || "condition",
20
+ ...data
21
+ }),
22
+ retrieveBatch: (id, data) => this.node("data_retrieve_batch", id, {
23
+ type: "data_retrieve_batch",
24
+ label: data.label || "\u83B7\u53D6\u591A\u6761\u6570\u636E",
25
+ filterType: data.filterType || "condition",
26
+ ...data
27
+ }),
28
+ create: (id, data) => this.node("data_create", id, {
29
+ type: "data_create",
30
+ label: data.label || "\u65B0\u589E\u6570\u636E",
31
+ insertType: data.insertType || "form",
32
+ assignments: data.assignments || [],
33
+ ...data
34
+ }),
35
+ update: (id, data) => this.node("data_update", id, {
36
+ type: "data_update",
37
+ label: data.label || "\u66F4\u65B0\u6570\u636E",
38
+ updateType: data.updateType || "direct_form",
39
+ assignments: data.assignments || [],
40
+ noneOperation: data.noneOperation || "ignored",
41
+ ...data
42
+ })
43
+ };
44
+ this.globalSettings = { ...meta.globalSettings || {} };
45
+ }
46
+ start(id = "start", data = {}) {
47
+ return this.node("start", id, { label: "\u5F00\u59CB\u8282\u70B9", ...data });
48
+ }
49
+ end(id = "end", data = {}) {
50
+ return this.node("end", id, { label: "\u7ED3\u675F\u8282\u70B9", ...data });
51
+ }
52
+ approval(id, data) {
53
+ return this.node("approval", id, {
54
+ label: data.label || "\u5BA1\u6279",
55
+ value: data.value || "",
56
+ approverType: data.approverType || "ext_target_approval",
57
+ approvals: data.approvals || [],
58
+ approvalNames: data.approvalNames || [],
59
+ multiApprove: data.multiApprove || "or",
60
+ ...data
61
+ });
62
+ }
63
+ copy(id, data) {
64
+ return this.node("copy", id, {
65
+ label: data.label || "\u6284\u9001",
66
+ value: data.value || "",
67
+ approverType: data.approverType || "ext_target_approval",
68
+ approvals: data.approvals || [],
69
+ approvalNames: data.approvalNames || [],
70
+ ...data
71
+ });
72
+ }
73
+ jsCode(id, data) {
74
+ return this.node("js_code", id, {
75
+ label: data.label || "JS\u4EE3\u7801\u8282\u70B9",
76
+ runtimeMode: "trusted_node",
77
+ sourceType: data.sourceFile ? "file_snapshot" : data.sourceType || "inline",
78
+ timeout: data.timeout || data.timeoutMs || 3e4,
79
+ ...data
80
+ });
81
+ }
82
+ callbackWait(id, data) {
83
+ return this.node("callback_wait", id, {
84
+ type: "callback_wait",
85
+ label: data.label || "\u56DE\u8C03\u7B49\u5F85",
86
+ timeoutSeconds: data.timeoutSeconds || 86400,
87
+ timeoutStrategy: data.timeoutStrategy || "FAIL",
88
+ ...data
89
+ });
90
+ }
91
+ connectorCall(id, data) {
92
+ return this.node("connector_call", id, {
93
+ type: "connector_call",
94
+ label: data.label || "\u8FDE\u63A5\u5668",
95
+ timeout: data.timeout || 3e4,
96
+ ...data
97
+ });
98
+ }
99
+ workNotification(id, data) {
100
+ return this.node("work_notification", id, {
101
+ label: data.label || "\u5DE5\u4F5C\u901A\u77E5",
102
+ buttonText: data.buttonText || "\u67E5\u770B\u8BE6\u60C5",
103
+ linkType: data.linkType || "current_form",
104
+ ...data
105
+ });
106
+ }
107
+ dingtalkCard(id, data) {
108
+ return this.node("dingtalk_card", id, {
109
+ config: {
110
+ type: "dingtalk_card",
111
+ label: data.label || "\u9489\u9489\u6D88\u606F\u5361\u7247",
112
+ sameFieldStrategy: "create",
113
+ ...data.config || data
114
+ }
115
+ });
116
+ }
117
+ condition(id, data) {
118
+ return this.node("condition_branch", id, {
119
+ type: "condition_branch",
120
+ label: data.label || "\u6761\u4EF6\u5206\u652F",
121
+ condition: data.condition || { ruleType: "group", condition: "AND", rules: [] },
122
+ isElse: data.isElse === true,
123
+ priority: data.priority || "1",
124
+ trueNodeId: data.trueNodeId,
125
+ falseNodeId: data.falseNodeId,
126
+ ...data
127
+ });
128
+ }
129
+ node(type, id, data) {
130
+ const nodeId = sanitizeId(id);
131
+ if (!nodeId) throw new Error("workflow node id is required");
132
+ if (this.nodes.some((node) => node.id === nodeId)) {
133
+ throw new Error(`duplicate workflow node id: ${nodeId}`);
134
+ }
135
+ this.nodes.push({
136
+ id: nodeId,
137
+ type,
138
+ data,
139
+ position: createPosition(this.nodes.length)
140
+ });
141
+ if (Array.isArray(data.fieldPermissions)) {
142
+ this.flowConfig[nodeId] = data.fieldPermissions;
143
+ }
144
+ return nodeId;
145
+ }
146
+ edge(source, target, data = {}) {
147
+ const id = data.id || `edge_${source}_${target}`;
148
+ this.edges.push({
149
+ id,
150
+ source,
151
+ target,
152
+ type: data.type || "custom",
153
+ ...data.label ? { label: data.label } : {}
154
+ });
155
+ }
156
+ sequence(...refs) {
157
+ for (let index = 0; index < refs.length - 1; index += 1) {
158
+ this.edge(refs[index], refs[index + 1]);
159
+ }
160
+ }
161
+ setFieldPermissions(nodeId, permissions) {
162
+ this.flowConfig[nodeId] = permissions;
163
+ }
164
+ setGlobalSettings(settings) {
165
+ this.globalSettings = { ...this.globalSettings, ...settings };
166
+ }
167
+ compile() {
168
+ return {
169
+ definitionJson: {
170
+ version: "v3",
171
+ nodes: this.nodes,
172
+ edges: this.edges,
173
+ flowConfig: this.flowConfig,
174
+ globalSettings: this.globalSettings
175
+ },
176
+ previewJson: {
177
+ kind: "workflow_code_preview",
178
+ version: "preview_v1",
179
+ sourceMode: "workflow_code_ts",
180
+ steps: this.nodes.map((node) => ({
181
+ id: node.id,
182
+ type: node.type,
183
+ label: node.data?.label || node.id,
184
+ config: node.data
185
+ })),
186
+ edges: this.edges.map((edge) => ({
187
+ source: edge.source,
188
+ target: edge.target,
189
+ label: edge.label
190
+ }))
191
+ }
192
+ };
193
+ }
194
+ };
195
+ function defineWorkflow(input) {
196
+ return {
197
+ __openxiangdaWorkflow: true,
198
+ compile() {
199
+ const builder = new WorkflowBuilder(input);
200
+ input.build(builder);
201
+ return builder.compile();
202
+ }
203
+ };
204
+ }
205
+ export {
206
+ WorkflowBuilder,
207
+ defineWorkflow
208
+ };
209
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/workflow/index.ts"],"sourcesContent":["export type WorkflowNodeRef = string;\n\nexport interface WorkflowCompileResult {\n definitionJson: {\n version: \"v3\";\n nodes: any[];\n edges: any[];\n flowConfig: Record<string, any[]>;\n globalSettings: Record<string, any>;\n };\n previewJson: {\n kind: \"workflow_code_preview\";\n version: \"preview_v1\";\n steps: any[];\n edges: any[];\n sourceMode: \"workflow_code_ts\";\n };\n}\n\nexport interface WorkflowDefinitionInput {\n name?: string;\n formCode?: string;\n formUuid?: string;\n globalSettings?: Record<string, any>;\n build: (flow: WorkflowBuilder) => void;\n}\n\ntype NodeOptions = Record<string, any>;\n\nfunction sanitizeId(value: string) {\n return String(value || \"\")\n .trim()\n .replace(/[^a-zA-Z0-9_-]/g, \"_\");\n}\n\nfunction createPosition(index: number) {\n return { x: 400, y: 100 + index * 150 };\n}\n\nexport class WorkflowBuilder {\n private nodes: any[] = [];\n private edges: any[] = [];\n private flowConfig: Record<string, any[]> = {};\n private globalSettings: Record<string, any> = {};\n\n constructor(private readonly meta: Omit<WorkflowDefinitionInput, \"build\"> = {}) {\n this.globalSettings = { ...(meta.globalSettings || {}) };\n }\n\n start(id = \"start\", data: NodeOptions = {}): WorkflowNodeRef {\n return this.node(\"start\", id, { label: \"开始节点\", ...data });\n }\n\n end(id = \"end\", data: NodeOptions = {}): WorkflowNodeRef {\n return this.node(\"end\", id, { label: \"结束节点\", ...data });\n }\n\n approval(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"approval\", id, {\n label: data.label || \"审批\",\n value: data.value || \"\",\n approverType: data.approverType || \"ext_target_approval\",\n approvals: data.approvals || [],\n approvalNames: data.approvalNames || [],\n multiApprove: data.multiApprove || \"or\",\n ...data,\n });\n }\n\n copy(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"copy\", id, {\n label: data.label || \"抄送\",\n value: data.value || \"\",\n approverType: data.approverType || \"ext_target_approval\",\n approvals: data.approvals || [],\n approvalNames: data.approvalNames || [],\n ...data,\n });\n }\n\n jsCode(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"js_code\", id, {\n label: data.label || \"JS代码节点\",\n runtimeMode: \"trusted_node\",\n sourceType: data.sourceFile ? \"file_snapshot\" : data.sourceType || \"inline\",\n timeout: data.timeout || data.timeoutMs || 30000,\n ...data,\n });\n }\n\n callbackWait(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"callback_wait\", id, {\n type: \"callback_wait\",\n label: data.label || \"回调等待\",\n timeoutSeconds: data.timeoutSeconds || 86400,\n timeoutStrategy: data.timeoutStrategy || \"FAIL\",\n ...data,\n });\n }\n\n connectorCall(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"connector_call\", id, {\n type: \"connector_call\",\n label: data.label || \"连接器\",\n timeout: data.timeout || 30000,\n ...data,\n });\n }\n\n workNotification(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"work_notification\", id, {\n label: data.label || \"工作通知\",\n buttonText: data.buttonText || \"查看详情\",\n linkType: data.linkType || \"current_form\",\n ...data,\n });\n }\n\n dingtalkCard(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"dingtalk_card\", id, {\n config: {\n type: \"dingtalk_card\",\n label: data.label || \"钉钉消息卡片\",\n sameFieldStrategy: \"create\",\n ...(data.config || data),\n },\n });\n }\n\n condition(id: string, data: NodeOptions): WorkflowNodeRef {\n return this.node(\"condition_branch\", id, {\n type: \"condition_branch\",\n label: data.label || \"条件分支\",\n condition: data.condition || { ruleType: \"group\", condition: \"AND\", rules: [] },\n isElse: data.isElse === true,\n priority: data.priority || \"1\",\n trueNodeId: data.trueNodeId,\n falseNodeId: data.falseNodeId,\n ...data,\n });\n }\n\n data = {\n retrieveSingle: (id: string, data: NodeOptions) =>\n this.node(\"data_retrieve_single\", id, {\n type: \"data_retrieve_single\",\n label: data.label || \"获取单条数据\",\n filterType: data.filterType || \"condition\",\n ...data,\n }),\n retrieveBatch: (id: string, data: NodeOptions) =>\n this.node(\"data_retrieve_batch\", id, {\n type: \"data_retrieve_batch\",\n label: data.label || \"获取多条数据\",\n filterType: data.filterType || \"condition\",\n ...data,\n }),\n create: (id: string, data: NodeOptions) =>\n this.node(\"data_create\", id, {\n type: \"data_create\",\n label: data.label || \"新增数据\",\n insertType: data.insertType || \"form\",\n assignments: data.assignments || [],\n ...data,\n }),\n update: (id: string, data: NodeOptions) =>\n this.node(\"data_update\", id, {\n type: \"data_update\",\n label: data.label || \"更新数据\",\n updateType: data.updateType || \"direct_form\",\n assignments: data.assignments || [],\n noneOperation: data.noneOperation || \"ignored\",\n ...data,\n }),\n };\n\n node(type: string, id: string, data: NodeOptions): WorkflowNodeRef {\n const nodeId = sanitizeId(id);\n if (!nodeId) throw new Error(\"workflow node id is required\");\n if (this.nodes.some((node) => node.id === nodeId)) {\n throw new Error(`duplicate workflow node id: ${nodeId}`);\n }\n this.nodes.push({\n id: nodeId,\n type,\n data,\n position: createPosition(this.nodes.length),\n });\n if (Array.isArray(data.fieldPermissions)) {\n this.flowConfig[nodeId] = data.fieldPermissions;\n }\n return nodeId;\n }\n\n edge(source: WorkflowNodeRef, target: WorkflowNodeRef, data: NodeOptions = {}) {\n const id = data.id || `edge_${source}_${target}`;\n this.edges.push({\n id,\n source,\n target,\n type: data.type || \"custom\",\n ...(data.label ? { label: data.label } : {}),\n });\n }\n\n sequence(...refs: WorkflowNodeRef[]) {\n for (let index = 0; index < refs.length - 1; index += 1) {\n this.edge(refs[index], refs[index + 1]);\n }\n }\n\n setFieldPermissions(nodeId: WorkflowNodeRef, permissions: any[]) {\n this.flowConfig[nodeId] = permissions;\n }\n\n setGlobalSettings(settings: Record<string, any>) {\n this.globalSettings = { ...this.globalSettings, ...settings };\n }\n\n compile(): WorkflowCompileResult {\n return {\n definitionJson: {\n version: \"v3\",\n nodes: this.nodes,\n edges: this.edges,\n flowConfig: this.flowConfig,\n globalSettings: this.globalSettings,\n },\n previewJson: {\n kind: \"workflow_code_preview\",\n version: \"preview_v1\",\n sourceMode: \"workflow_code_ts\",\n steps: this.nodes.map((node) => ({\n id: node.id,\n type: node.type,\n label: node.data?.label || node.id,\n config: node.data,\n })),\n edges: this.edges.map((edge) => ({\n source: edge.source,\n target: edge.target,\n label: edge.label,\n })),\n },\n };\n }\n}\n\nexport function defineWorkflow(input: WorkflowDefinitionInput) {\n return {\n __openxiangdaWorkflow: true,\n compile() {\n const builder = new WorkflowBuilder(input);\n input.build(builder);\n return builder.compile();\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -24,6 +24,10 @@ OpenXiangda business apps should feel like focused operational tools.
24
24
 
25
25
  - Use platform CSS variables, Tailwind semantic classes, Ant Design, and
26
26
  antd-mobile.
27
+ - Treat platform tokens as the default baseline, not a hard limit. Tailwind
28
+ ordinary utilities, arbitrary values, page CSS variables, scoped CSS, and
29
+ small dynamic inline styles are acceptable when they better match the product
30
+ design.
27
31
  - Use mature packages for mature interactions: antd controls instead of native
28
32
  inputs, ECharts for charts, GSAP for complex animation timelines, and
29
33
  maintained drag/drop or virtual-list libraries when those behaviors are
@@ -8,10 +8,23 @@ import { fileURLToPath } from "node:url";
8
8
  import { build } from "vite";
9
9
 
10
10
  const rootDir = fileURLToPath(new URL("..", import.meta.url));
11
- const sourceRoot = path.join(rootDir, "src", "js-code-nodes");
12
- const outputRoot = path.join(rootDir, "dist", "js-code-nodes");
13
11
  const args = process.argv.slice(2);
14
12
 
13
+ const sourceKinds = {
14
+ "js-code-nodes": {
15
+ name: "js-code-nodes",
16
+ sourceRoot: path.join(rootDir, "src", "js-code-nodes"),
17
+ outputRoot: path.join(rootDir, "dist", "js-code-nodes"),
18
+ label: "JS_CODE",
19
+ },
20
+ automations: {
21
+ name: "automations",
22
+ sourceRoot: path.join(rootDir, "src", "automations"),
23
+ outputRoot: path.join(rootDir, "dist", "automations"),
24
+ label: "automation code",
25
+ },
26
+ };
27
+
15
28
  function readArg(name) {
16
29
  const prefix = `--${name}=`;
17
30
  const inline = args.find((arg) => arg.startsWith(prefix));
@@ -20,12 +33,12 @@ function readArg(name) {
20
33
  return index >= 0 ? args[index + 1] : undefined;
21
34
  }
22
35
 
23
- async function listScriptCodes() {
24
- if (!existsSync(sourceRoot)) return [];
25
- const entries = await readdir(sourceRoot);
36
+ async function listScriptCodes(kind) {
37
+ if (!existsSync(kind.sourceRoot)) return [];
38
+ const entries = await readdir(kind.sourceRoot);
26
39
  const result = [];
27
40
  for (const entry of entries) {
28
- const entryDir = path.join(sourceRoot, entry);
41
+ const entryDir = path.join(kind.sourceRoot, entry);
29
42
  const entryStat = await stat(entryDir);
30
43
  if (!entryStat.isDirectory()) continue;
31
44
  if (existsSync(path.join(entryDir, "index.ts"))) result.push(entry);
@@ -45,11 +58,11 @@ function typecheckScripts() {
45
58
  if (result.status !== 0) throw new Error("JS_CODE TypeScript validation failed");
46
59
  }
47
60
 
48
- async function buildScript(scriptCode) {
49
- const entry = path.join(sourceRoot, scriptCode, "index.ts");
50
- if (!existsSync(entry)) throw new Error(`JS_CODE script not found: ${entry}`);
61
+ async function buildScript(kind, scriptCode) {
62
+ const entry = path.join(kind.sourceRoot, scriptCode, "index.ts");
63
+ if (!existsSync(entry)) throw new Error(`${kind.label} script not found: ${entry}`);
51
64
 
52
- const outDir = path.join(outputRoot, scriptCode);
65
+ const outDir = path.join(kind.outputRoot, scriptCode);
53
66
  const external = Array.from(
54
67
  new Set([...builtinModules, ...builtinModules.map((name) => `node:${name}`)]),
55
68
  );
@@ -82,19 +95,46 @@ async function buildScript(scriptCode) {
82
95
  },
83
96
  });
84
97
 
85
- console.log(`built ${scriptCode} -> ${path.relative(rootDir, path.join(outDir, "index.cjs"))}`);
98
+ console.log(`built ${kind.name}/${scriptCode} -> ${path.relative(rootDir, path.join(outDir, "index.cjs"))}`);
86
99
  }
87
100
 
88
101
  const onlyScript = readArg("script");
89
- const scriptCodes = onlyScript ? [onlyScript] : await listScriptCodes();
102
+ const sourceArg = readArg("source");
103
+ const selectedKind = sourceArg ? sourceKinds[sourceArg] : undefined;
104
+ if (sourceArg && !selectedKind) {
105
+ throw new Error(`unsupported source: ${sourceArg}. Expected js-code-nodes or automations`);
106
+ }
107
+
108
+ async function resolveBuildTargets() {
109
+ if (onlyScript) {
110
+ if (selectedKind) return [{ kind: selectedKind, scriptCode: onlyScript }];
111
+ for (const kind of Object.values(sourceKinds)) {
112
+ if (existsSync(path.join(kind.sourceRoot, onlyScript, "index.ts"))) {
113
+ return [{ kind, scriptCode: onlyScript }];
114
+ }
115
+ }
116
+ return [{ kind: sourceKinds["js-code-nodes"], scriptCode: onlyScript }];
117
+ }
118
+
119
+ const kinds = selectedKind ? [selectedKind] : Object.values(sourceKinds);
120
+ const targets = [];
121
+ for (const kind of kinds) {
122
+ for (const scriptCode of await listScriptCodes(kind)) {
123
+ targets.push({ kind, scriptCode });
124
+ }
125
+ }
126
+ return targets;
127
+ }
128
+
129
+ const targets = await resolveBuildTargets();
90
130
 
91
- if (scriptCodes.length === 0) {
92
- console.log("no JS_CODE scripts found under src/js-code-nodes/<scriptCode>/index.ts");
131
+ if (targets.length === 0) {
132
+ console.log("no JS_CODE scripts found under src/js-code-nodes/<scriptCode>/index.ts or src/automations/<scriptCode>/index.ts");
93
133
  process.exit(0);
94
134
  }
95
135
 
96
136
  typecheckScripts();
97
137
 
98
- for (const scriptCode of scriptCodes) {
99
- await buildScript(scriptCode);
138
+ for (const target of targets) {
139
+ await buildScript(target.kind, target.scriptCode);
100
140
  }
@@ -11,5 +11,5 @@
11
11
  "@/*": ["src/*"]
12
12
  }
13
13
  },
14
- "include": ["src/js-code-nodes/**/*.ts"]
14
+ "include": ["src/js-code-nodes/**/*.ts", "src/automations/**/*.ts"]
15
15
  }