openxiangda 1.0.106 → 1.0.108

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/README.md CHANGED
@@ -105,7 +105,7 @@ openxiangda public-access grant-check public_register --form-code registration_f
105
105
  openxiangda auth-config methods --json
106
106
  openxiangda function invoke submit_public_registration --body-json '{"input":{}}'
107
107
  openxiangda connector invoke sms.sendCode --body-json '{"body":{"phone":"13800000000"}}'
108
- openxiangda notification preview public_register_notice --body-json '{"variables":{"title":"测试"}}'
108
+ openxiangda notification preview public_register_notice --body-json '{"payload":{"title":"测试"}}'
109
109
  openxiangda permission audit --json
110
110
  ```
111
111
 
package/lib/cli.js CHANGED
@@ -2856,7 +2856,12 @@ async function notification(args) {
2856
2856
  const { subcommand, rest } = parseSubcommandArgs(args);
2857
2857
  const { flags, positional } = parseArgs(rest);
2858
2858
  if (wantsSubcommandHelp(subcommand, flags)) {
2859
- print('用法: openxiangda notification template-list|template-get|template-upsert|template-delete|type-list|type-get|type-upsert|type-delete|preview|send|batch-send');
2859
+ print([
2860
+ '用法: openxiangda notification template-list|template-get|template-upsert|template-delete|type-list|type-get|type-upsert|type-delete|preview|send|batch-send',
2861
+ ' preview <templateCode> --body-json \'{"payload":{"title":"测试"}}\'',
2862
+ ' send <notificationType> --body-json \'{"recipientId":"USER_ID","payload":{"title":"测试"}}\' --force',
2863
+ ' batch-send <notificationType> --body-json \'{"recipients":[{"recipientId":"USER_ID","payload":{}}]}\' --force',
2864
+ ].join('\n'));
2860
2865
  return;
2861
2866
  }
2862
2867
  const config = loadConfig();
@@ -2955,13 +2960,20 @@ async function notification(args) {
2955
2960
  fail(`openxiangda notification ${subcommand} 是发送动作,必须加 --force`);
2956
2961
  }
2957
2962
  const code = positional[0] || flags.code;
2958
- const body = {
2959
- ...readDirectJsonBody(flags, `notification ${subcommand}`, { optional: true }),
2960
- ...(code ? { templateCode: code, notificationType: code } : {}),
2961
- };
2963
+ const body = normalizeNotificationActionBody(
2964
+ subcommand,
2965
+ code,
2966
+ readDirectJsonBody(flags, `notification ${subcommand}`, { optional: true })
2967
+ );
2968
+ const actionPath =
2969
+ subcommand === 'preview'
2970
+ ? 'templates/preview'
2971
+ : subcommand === 'batch-send'
2972
+ ? 'batch-send-by-type'
2973
+ : 'send-by-type';
2962
2974
  return runDirectRequest(config, target, flags, {
2963
2975
  method: 'POST',
2964
- path: `${appPrefix}/${subcommand === 'batch-send' ? 'batch-send' : subcommand}`,
2976
+ path: `${appPrefix}/${actionPath}`,
2965
2977
  body,
2966
2978
  strictEnvelope: true,
2967
2979
  });
@@ -4587,6 +4599,47 @@ function extractNotificationTypeConfigBody(bound, body) {
4587
4599
  };
4588
4600
  }
4589
4601
 
4602
+ function normalizeNotificationActionBody(subcommand, code, rawBody = {}) {
4603
+ const body = { ...(rawBody || {}) };
4604
+ if (body.variables && !body.payload) {
4605
+ body.payload = body.variables;
4606
+ }
4607
+ delete body.variables;
4608
+
4609
+ if (subcommand === 'preview') {
4610
+ if (code && !body.templateCode && !body.templateId && !body.code) {
4611
+ body.templateCode = code;
4612
+ }
4613
+ return body;
4614
+ }
4615
+
4616
+ if (code && !body.notificationType) {
4617
+ body.notificationType = code;
4618
+ }
4619
+
4620
+ if (subcommand === 'send') {
4621
+ if (!body.recipientId && Array.isArray(body.recipientIds) && body.recipientIds.length === 1) {
4622
+ body.recipientId = body.recipientIds[0];
4623
+ }
4624
+ delete body.recipientIds;
4625
+ return body;
4626
+ }
4627
+
4628
+ if (subcommand === 'batch-send') {
4629
+ if (!body.recipients && Array.isArray(body.recipientIds)) {
4630
+ body.recipients = body.recipientIds.map(recipientId => ({
4631
+ recipientId,
4632
+ payload: body.payload || {},
4633
+ ...(body.channels ? { channels: body.channels } : {}),
4634
+ }));
4635
+ }
4636
+ delete body.recipientIds;
4637
+ return body;
4638
+ }
4639
+
4640
+ return body;
4641
+ }
4642
+
4590
4643
  function buildPublicGrantChecks(bound, grants, flags = {}) {
4591
4644
  const checks = [];
4592
4645
  const formTargets = [
@@ -482,7 +482,27 @@ const RESOURCE_EXPLAINS = {
482
482
  },
483
483
  commands: [
484
484
  'openxiangda notification template-upsert --json-file src/resources/notifications/reservation_reminder.json',
485
- 'openxiangda notification preview reservation_reminder --body-json \'{"variables":{"title":"测试"}}\'',
485
+ 'openxiangda notification preview reservation_reminder --body-json \'{"payload":{"title":"测试"}}\'',
486
+ ],
487
+ },
488
+ workflow: {
489
+ dir: 'src/resources/workflows/*.json + src/workflows/<code>/workflow.ts',
490
+ minimalManifest: {
491
+ code: 'expense_approval',
492
+ name: '费用审批',
493
+ formCode: 'expense_request',
494
+ workflowFile: '../../workflows/expense_approval/workflow.ts',
495
+ definitionFile: '../../generated/workflows/expense_approval/definition.v3.json',
496
+ previewFile: '../../generated/workflows/expense_approval/preview.json',
497
+ publish: true,
498
+ enable: true,
499
+ },
500
+ commands: [
501
+ 'openxiangda workflow compile src/workflows/expense_approval/workflow.ts --check',
502
+ 'openxiangda workflow compile src/workflows/expense_approval/workflow.ts --out-definition src/generated/workflows/expense_approval/definition.v3.json --out-preview src/generated/workflows/expense_approval/preview.json',
503
+ 'openxiangda resource validate workflow',
504
+ 'openxiangda resource plan workflow',
505
+ 'openxiangda resource publish',
486
506
  ],
487
507
  },
488
508
  'data-view': {
@@ -513,7 +533,27 @@ const RESOURCE_EXPLAINS = {
513
533
  };
514
534
 
515
535
  function getResourceExplain(type) {
516
- const key = type || 'route';
536
+ const rawKey = String(type || 'route')
537
+ .trim()
538
+ .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
539
+ .replace(/[_\s]+/g, '-')
540
+ .toLowerCase();
541
+ const aliases = {
542
+ routes: 'route',
543
+ notifications: 'notification',
544
+ workflows: 'workflow',
545
+ dataview: 'data-view',
546
+ dataviews: 'data-view',
547
+ 'data-views': 'data-view',
548
+ publicaccess: 'public-access',
549
+ publicaccesspolicy: 'public-access',
550
+ publicaccesspolicies: 'public-access',
551
+ auth: 'auth-config',
552
+ authconfigs: 'auth-config',
553
+ functions: 'function',
554
+ connectors: 'connector',
555
+ };
556
+ const key = aliases[rawKey] || rawKey;
517
557
  return RESOURCE_EXPLAINS[key];
518
558
  }
519
559
 
@@ -61,6 +61,14 @@ await sdk.notification.sendByType({
61
61
  });
62
62
  ```
63
63
 
64
+ CLI smoke tests:
65
+
66
+ ```bash
67
+ openxiangda notification preview reservation_reminder --body-json '{"payload":{"title":"测试"}}'
68
+ openxiangda notification send reservation_reminder --body-json '{"recipientId":"USER_ID","payload":{"title":"测试"}}' --force
69
+ openxiangda notification batch-send reservation_reminder --body-json '{"recipients":[{"recipientId":"USER_ID","payload":{"title":"测试"}}]}' --force
70
+ ```
71
+
64
72
  Automation or workflow JS_CODE:
65
73
 
66
74
  ```ts
@@ -334,6 +334,21 @@ Requires Bearer token. Sends a notification in the current app scope.
334
334
 
335
335
  Requires Bearer token. Sends one notification type to multiple recipients.
336
336
 
337
+ ```json
338
+ {
339
+ "notificationType": "reservation_reminder",
340
+ "recipients": [
341
+ {
342
+ "recipientId": "user-id",
343
+ "payload": {
344
+ "title": "预约提醒"
345
+ },
346
+ "channels": ["inapp"]
347
+ }
348
+ ]
349
+ }
350
+ ```
351
+
337
352
  ### GET `/apps/:appType/notifications/templates`
338
353
 
339
354
  Requires Bearer token. Lists app/form notification templates.
@@ -344,7 +359,7 @@ Requires app admin permission. Upserts an app/form notification template by code
344
359
 
345
360
  ### POST `/apps/:appType/notifications/templates/preview`
346
361
 
347
- Requires Bearer token. Body uses `templateCode` or `templateId` plus `payload`.
362
+ Requires Bearer token. Body uses `templateCode` or `templateId` plus `payload`. The CLI command is `openxiangda notification preview <templateCode> --body-json '{"payload":{...}}'`.
348
363
 
349
364
  ### GET `/apps/:appType/notifications/type-configs`
350
365
 
@@ -47,7 +47,7 @@ openxiangda connector invoke sms.sendCode --body-json '{"body":{"phone":"1380000
47
47
 
48
48
  openxiangda notification template-upsert --json-file src/resources/notifications/register.json
49
49
  openxiangda notification type-upsert --json-file src/resources/notifications/register.json
50
- openxiangda notification preview public_register_notice --body-json '{"variables":{"title":"测试"}}'
50
+ openxiangda notification preview public_register_notice --body-json '{"payload":{"title":"测试"}}'
51
51
 
52
52
  openxiangda data-view upsert --json-file src/resources/data-views/public_lookup.json
53
53
  openxiangda menu update public_register --json-file src/resources/menus/public_register.json --write-manifest
@@ -44,6 +44,41 @@ export default defineWorkflow({
44
44
  });
45
45
  ```
46
46
 
47
+ For compact AI-authored drafts, `flow.define` is also exported. It accepts
48
+ declarative node and edge helpers, then compiles to the same v3 JSON:
49
+
50
+ ```ts
51
+ import { flow } from "openxiangda/workflow";
52
+
53
+ export default flow.define({
54
+ name: "费用审批",
55
+ formUuid: "FORM_UUID",
56
+ nodes: [
57
+ flow.start("start"),
58
+ flow.approval("manager_approval", {
59
+ label: "主管审批",
60
+ assignees: [flow.assignee.initiator()],
61
+ actions: [
62
+ flow.action.approve("通过"),
63
+ flow.action.returnToInitiator(),
64
+ flow.action.transfer(),
65
+ ],
66
+ fieldPermissions: { amount: "readonly" },
67
+ }),
68
+ flow.functionCall("sync_budget", {
69
+ functionName: "sync_budget",
70
+ input: { amount: "${amount}" },
71
+ }),
72
+ flow.end("end"),
73
+ ],
74
+ edges: [
75
+ flow.connect("start", "manager_approval"),
76
+ flow.connect("manager_approval", "sync_budget"),
77
+ flow.connect("sync_budget", "end"),
78
+ ],
79
+ });
80
+ ```
81
+
47
82
  Resource manifest:
48
83
 
49
84
  ```json
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda",
3
- "version": "1.0.106",
3
+ "version": "1.0.108",
4
4
  "description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
5
5
  "private": false,
6
6
  "bin": {
@@ -21,7 +21,8 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var workflow_exports = {};
22
22
  __export(workflow_exports, {
23
23
  WorkflowBuilder: () => WorkflowBuilder,
24
- defineWorkflow: () => defineWorkflow
24
+ defineWorkflow: () => defineWorkflow,
25
+ flow: () => flow
25
26
  });
26
27
  module.exports = __toCommonJS(workflow_exports);
27
28
  function sanitizeId(value) {
@@ -37,6 +38,30 @@ function normalizeAction(action, label, extra = {}) {
37
38
  ...extra
38
39
  };
39
40
  }
41
+ var workflowActions = {
42
+ approve: (label = "\u540C\u610F", extra = {}) => normalizeAction("agree", label, extra),
43
+ reject: (label = "\u62D2\u7EDD", extra = {}) => normalizeAction("rejected", label, extra),
44
+ transfer: (label = "\u8F6C\u4EA4", extra = {}) => normalizeAction("transfer", label, {
45
+ remark: { popUp: true, required: false },
46
+ ...extra
47
+ }),
48
+ return: (label = "\u9000\u56DE", extra = {}) => normalizeAction("return", label, {
49
+ remark: { popUp: true, required: false },
50
+ ...extra
51
+ }),
52
+ returnToInitiator: (label = "\u9000\u56DE\u53D1\u8D77\u4EBA", extra = {}) => normalizeAction("return", label, {
53
+ remark: { popUp: true, required: false },
54
+ returnTarget: "initiator",
55
+ returnScope: "initiator",
56
+ ...extra
57
+ }),
58
+ save: (label = "\u6682\u5B58", extra = {}) => normalizeAction("save", label, extra),
59
+ withdraw: (label = "\u64A4\u56DE", extra = {}) => normalizeAction("withdraw", label, extra),
60
+ resubmit: (label = "\u91CD\u65B0\u63D0\u4EA4", extra = {}) => normalizeAction("resubmit", label, extra),
61
+ callback: (label = "\u89E6\u53D1\u56DE\u8C03", extra = {}) => normalizeAction("callback", label, extra),
62
+ retryException: (label = "\u91CD\u8BD5\u5F02\u5E38", extra = {}) => normalizeAction("retryException", label, extra),
63
+ adminTransfer: (label = "\u7BA1\u7406\u5458\u8F6C\u4EA4", extra = {}) => normalizeAction("adminTransfer", label, extra)
64
+ };
40
65
  function normalizeReturnConfig(value) {
41
66
  if (value === false) return { enabled: false };
42
67
  if (value === true || value === void 0) {
@@ -49,6 +74,111 @@ function normalizeReturnConfig(value) {
49
74
  ...value
50
75
  };
51
76
  }
77
+ function findInitiatorReturnAction(actions) {
78
+ return actions.find(
79
+ (action) => action?.action === "return" && (action.returnTarget === "initiator" || action.returnScope === "initiator")
80
+ );
81
+ }
82
+ function inferReturnConfigFromActions(actions, explicitReturnConfig) {
83
+ const initiatorReturnAction = findInitiatorReturnAction(actions);
84
+ if (!initiatorReturnAction) return explicitReturnConfig;
85
+ const base = explicitReturnConfig || normalizeReturnConfig({
86
+ scopeType: "previous_all",
87
+ resubmitMode: initiatorReturnAction.resubmitMode || "replay"
88
+ });
89
+ return {
90
+ ...base,
91
+ allowOriginatorReturn: true
92
+ };
93
+ }
94
+ function normalizeFieldBehavior(value) {
95
+ const normalized = String(value || "").trim().toLowerCase();
96
+ if (["normal", "edit", "editable", "write", "writable"].includes(normalized)) return "NORMAL";
97
+ if (["readonly", "read", "view", "visible"].includes(normalized)) return "READONLY";
98
+ if (["hidden", "hide", "invisible"].includes(normalized)) return "HIDDEN";
99
+ return String(value || "READONLY").toUpperCase();
100
+ }
101
+ function normalizeFieldPermissions(value) {
102
+ if (Array.isArray(value)) {
103
+ return value.map((item) => {
104
+ if (!item || typeof item !== "object") return item;
105
+ return {
106
+ ...item,
107
+ fieldId: item.fieldId || item.field || item.id,
108
+ fieldBehavior: normalizeFieldBehavior(item.fieldBehavior || item.behavior || item.permission)
109
+ };
110
+ });
111
+ }
112
+ if (value && typeof value === "object") {
113
+ return Object.entries(value).map(([fieldId, fieldBehavior]) => ({
114
+ fieldId,
115
+ fieldBehavior: normalizeFieldBehavior(fieldBehavior)
116
+ }));
117
+ }
118
+ return void 0;
119
+ }
120
+ function createDeclarativeNode(type, id, data = {}) {
121
+ return {
122
+ __openxiangdaWorkflowNode: true,
123
+ id: sanitizeId(id),
124
+ type,
125
+ data
126
+ };
127
+ }
128
+ function createDeclarativeEdge(source, target, data = {}) {
129
+ return {
130
+ __openxiangdaWorkflowEdge: true,
131
+ source,
132
+ target,
133
+ data
134
+ };
135
+ }
136
+ function isDeclarativeInput(input) {
137
+ return input && Array.isArray(input.nodes);
138
+ }
139
+ function isWorkflowNodeDescriptor(value) {
140
+ return Boolean(value?.__openxiangdaWorkflowNode);
141
+ }
142
+ function normalizeAssignee(value) {
143
+ if (typeof value === "string") {
144
+ return { type: value === "originator" ? "originator" : "user", id: value, name: value };
145
+ }
146
+ return value || {};
147
+ }
148
+ function normalizeApprovalData(data = {}) {
149
+ const normalized = { ...data };
150
+ const assignees = Array.isArray(data.assignees) ? data.assignees.map(normalizeAssignee) : void 0;
151
+ if (assignees && !normalized.approverType) {
152
+ const supervisor = assignees.find((item) => item.type === "department_supervisor");
153
+ const initiatorSelect = assignees.find((item) => item.type === "initiator_select");
154
+ const roleAssignees = assignees.filter((item) => item.type === "role");
155
+ const userAssignees = assignees.filter((item) => item.type === "user" || item.type === "originator");
156
+ if (supervisor) {
157
+ normalized.approverType = "ext_target_approval_department_supervisor";
158
+ normalized.supervisorConfig = {
159
+ level: supervisor.level || 1,
160
+ fallbackToAncestorSupervisor: supervisor.fallbackToAncestorSupervisor !== false,
161
+ ...normalized.supervisorConfig || {}
162
+ };
163
+ normalized.approvals = normalized.approvals || [];
164
+ normalized.approvalNames = normalized.approvalNames || [];
165
+ } else if (initiatorSelect) {
166
+ normalized.approverType = "ext_target_approval_initiator_select";
167
+ normalized.initiatorSelectScope = initiatorSelect.scope || initiatorSelect.initiatorSelectScope || "all";
168
+ normalized.approvals = normalized.approvals || (Array.isArray(initiatorSelect.approvals) ? initiatorSelect.approvals : roleAssignees.map((item) => item.id).filter(Boolean));
169
+ normalized.approvalNames = normalized.approvalNames || (Array.isArray(initiatorSelect.approvalNames) ? initiatorSelect.approvalNames : roleAssignees.map((item) => item.name || item.id).filter(Boolean));
170
+ } else if (roleAssignees.length > 0 && userAssignees.length === 0) {
171
+ normalized.approverType = "ext_target_approval_role";
172
+ normalized.approvals = normalized.approvals || roleAssignees.map((item) => item.id).filter(Boolean);
173
+ normalized.approvalNames = normalized.approvalNames || roleAssignees.map((item) => item.name || item.id).filter(Boolean);
174
+ } else {
175
+ normalized.approverType = "ext_target_approval";
176
+ normalized.approvals = normalized.approvals || userAssignees.map((item) => item.type === "originator" ? "originator" : item.id).filter(Boolean);
177
+ normalized.approvalNames = normalized.approvalNames || userAssignees.map((item) => item.name || (item.type === "originator" ? "\u53D1\u8D77\u4EBA" : item.id)).filter(Boolean);
178
+ }
179
+ }
180
+ return normalized;
181
+ }
52
182
  var WorkflowBuilder = class {
53
183
  constructor(meta = {}) {
54
184
  this.meta = meta;
@@ -56,19 +186,7 @@ var WorkflowBuilder = class {
56
186
  this.edges = [];
57
187
  this.flowConfig = {};
58
188
  this.globalSettings = {};
59
- this.action = {
60
- approve: (label = "\u540C\u610F", extra = {}) => normalizeAction("agree", label, extra),
61
- reject: (label = "\u62D2\u7EDD", extra = {}) => normalizeAction("rejected", label, extra),
62
- transfer: (label = "\u8F6C\u4EA4", extra = {}) => normalizeAction("transfer", label, {
63
- remark: { popUp: true, required: false },
64
- ...extra
65
- }),
66
- return: (label = "\u9000\u56DE", extra = {}) => normalizeAction("return", label, {
67
- remark: { popUp: true, required: false },
68
- ...extra
69
- }),
70
- save: (label = "\u6682\u5B58", extra = {}) => normalizeAction("save", label, extra)
71
- };
189
+ this.action = workflowActions;
72
190
  this.data = {
73
191
  retrieveSingle: (id, data) => this.node("data_retrieve_single", id, {
74
192
  type: "data_retrieve_single",
@@ -107,21 +225,23 @@ var WorkflowBuilder = class {
107
225
  return this.node("end", id, { label: "\u7ED3\u675F\u8282\u70B9", ...data });
108
226
  }
109
227
  approval(id, data) {
110
- const actions = data.buttons || data.actions || [
228
+ const approvalData = normalizeApprovalData(data);
229
+ const actions = approvalData.buttons || approvalData.actions || [
111
230
  this.action.approve(),
112
231
  this.action.reject()
113
232
  ];
114
- const returnConfig = data.returnConfig !== void 0 ? normalizeReturnConfig(data.returnConfig) : data.returnPolicy !== void 0 ? normalizeReturnConfig(data.returnPolicy) : void 0;
233
+ const returnConfig = approvalData.returnConfig !== void 0 ? normalizeReturnConfig(approvalData.returnConfig) : approvalData.returnPolicy !== void 0 ? normalizeReturnConfig(approvalData.returnPolicy) : void 0;
234
+ const inferredReturnConfig = inferReturnConfigFromActions(actions, returnConfig);
115
235
  return this.node("approval", id, {
116
- label: data.label || "\u5BA1\u6279",
117
- value: data.value || "",
118
- approverType: data.approverType || "ext_target_approval",
119
- approvals: data.approvals || [],
120
- approvalNames: data.approvalNames || [],
121
- multiApprove: data.multiApprove || "or",
122
- ...data,
236
+ label: approvalData.label || "\u5BA1\u6279",
237
+ value: approvalData.value || "",
238
+ approverType: approvalData.approverType || "ext_target_approval",
239
+ approvals: approvalData.approvals || [],
240
+ approvalNames: approvalData.approvalNames || [],
241
+ multiApprove: approvalData.multiApprove || "or",
242
+ ...approvalData,
123
243
  actions,
124
- ...returnConfig ? { returnConfig } : {}
244
+ ...inferredReturnConfig ? { returnConfig: inferredReturnConfig } : {}
125
245
  });
126
246
  }
127
247
  copy(id, data) {
@@ -302,8 +422,9 @@ var WorkflowBuilder = class {
302
422
  data,
303
423
  position: createPosition(this.nodes.length)
304
424
  });
305
- if (Array.isArray(data.fieldPermissions)) {
306
- this.flowConfig[nodeId] = data.fieldPermissions;
425
+ const fieldPermissions = normalizeFieldPermissions(data.fieldPermissions);
426
+ if (fieldPermissions) {
427
+ this.flowConfig[nodeId] = fieldPermissions;
307
428
  }
308
429
  return nodeId;
309
430
  }
@@ -369,4 +490,119 @@ function defineWorkflow(input) {
369
490
  }
370
491
  };
371
492
  }
493
+ function addDeclarativeNode(builder, node) {
494
+ if (!isWorkflowNodeDescriptor(node)) {
495
+ throw new Error("workflow declarative nodes must be created by flow.* helpers");
496
+ }
497
+ switch (node.type) {
498
+ case "start":
499
+ builder.start(node.id, node.data);
500
+ return;
501
+ case "end":
502
+ builder.end(node.id, node.data);
503
+ return;
504
+ case "approval":
505
+ builder.approval(node.id, node.data);
506
+ return;
507
+ case "copy":
508
+ builder.copy(node.id, node.data);
509
+ return;
510
+ case "js_code":
511
+ builder.jsCode(node.id, node.data);
512
+ return;
513
+ case "function_call":
514
+ builder.functionCall(node.id, node.data);
515
+ return;
516
+ case "callback_wait":
517
+ builder.callbackWait(node.id, node.data);
518
+ return;
519
+ case "connector_call":
520
+ builder.connectorCall(node.id, node.data);
521
+ return;
522
+ case "work_notification":
523
+ builder.workNotification(node.id, node.data);
524
+ return;
525
+ case "condition_branch":
526
+ builder.condition(node.id, node.data);
527
+ return;
528
+ case "branch": {
529
+ builder.branch(node.id, node.data);
530
+ const branches = Array.isArray(node.data?.branches) ? node.data.branches : [];
531
+ branches.forEach((branch, index) => {
532
+ const conditionId = sanitizeId(`${node.id}_${branch.id || index + 1}`);
533
+ builder.condition(conditionId, {
534
+ label: branch.label || (branch.else || branch.isElse ? "\u5176\u4ED6\u60C5\u51B5" : `\u6761\u4EF6 ${index + 1}`),
535
+ condition: branch.condition || {
536
+ ruleType: "group",
537
+ condition: "AND",
538
+ rules: []
539
+ },
540
+ isElse: branch.else === true || branch.isElse === true,
541
+ priority: String(index + 1)
542
+ });
543
+ builder.edge(node.id, conditionId, {
544
+ id: `edge_${node.id}_${conditionId}`,
545
+ label: branch.label
546
+ });
547
+ if (branch.next) {
548
+ builder.edge(conditionId, sanitizeId(branch.next), {
549
+ id: `edge_${conditionId}_${sanitizeId(branch.next)}`,
550
+ label: branch.label
551
+ });
552
+ }
553
+ });
554
+ return;
555
+ }
556
+ default:
557
+ builder.node(node.type, node.id, node.data);
558
+ }
559
+ }
560
+ function defineDeclarativeWorkflow(input) {
561
+ return {
562
+ __openxiangdaWorkflow: true,
563
+ compile() {
564
+ const builder = new WorkflowBuilder(input);
565
+ input.nodes.forEach((node) => addDeclarativeNode(builder, node));
566
+ (input.edges || []).forEach((edge) => {
567
+ builder.edge(edge.source, edge.target, edge.data || {});
568
+ });
569
+ return builder.compile();
570
+ }
571
+ };
572
+ }
573
+ var flow = {
574
+ define(input) {
575
+ if (isDeclarativeInput(input)) {
576
+ return defineDeclarativeWorkflow(input);
577
+ }
578
+ return defineWorkflow(input);
579
+ },
580
+ action: workflowActions,
581
+ assignee: {
582
+ user: (id, name) => ({ type: "user", id, name: name || id }),
583
+ initiator: () => ({ type: "originator", id: "originator", name: "\u53D1\u8D77\u4EBA" }),
584
+ role: (id, name) => ({ type: "role", id, name: name || id }),
585
+ departmentSupervisor: (level = 1, extra = {}) => ({ type: "department_supervisor", level, ...extra }),
586
+ initiatorSelect: (scope = "all", extra = {}) => ({ type: "initiator_select", scope, ...extra })
587
+ },
588
+ start: (id = "start", data = {}) => createDeclarativeNode("start", id, data),
589
+ end: (id = "end", data = {}) => createDeclarativeNode("end", id, data),
590
+ approval: (id, data = {}) => createDeclarativeNode("approval", id, data),
591
+ copy: (id, data = {}) => createDeclarativeNode("copy", id, data),
592
+ jsCode: (id, data = {}) => createDeclarativeNode("js_code", id, data),
593
+ functionCall: (id, data = {}) => createDeclarativeNode("function_call", id, data),
594
+ callbackWait: (id, data = {}) => createDeclarativeNode("callback_wait", id, data),
595
+ connectorCall: (id, data = {}) => createDeclarativeNode("connector_call", id, data),
596
+ workNotification: (id, data = {}) => createDeclarativeNode("work_notification", id, data),
597
+ notification: (id, data = {}) => createDeclarativeNode("work_notification", id, data),
598
+ condition: (id, data = {}) => createDeclarativeNode("condition_branch", id, data),
599
+ branch: (id, data = {}) => createDeclarativeNode("branch", id, data),
600
+ data: {
601
+ retrieveSingle: (id, data = {}) => createDeclarativeNode("data_retrieve_single", id, data),
602
+ retrieveBatch: (id, data = {}) => createDeclarativeNode("data_retrieve_batch", id, data),
603
+ create: (id, data = {}) => createDeclarativeNode("data_create", id, data),
604
+ update: (id, data = {}) => createDeclarativeNode("data_update", id, data)
605
+ },
606
+ connect: createDeclarativeEdge
607
+ };
372
608
  //# sourceMappingURL=index.cjs.map