@huanban/rulego-editor-core 1.4.2 → 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/README.md +20 -8
- package/dist/ai/ai-chat-options.d.ts +12 -0
- package/dist/api/AIAssistantAPI.d.ts +29 -0
- package/dist/api/AIManager.d.ts +7 -1
- package/dist/api/ApiProvider.d.ts +17 -4
- package/dist/api/DebugSocketClient.d.ts +2 -0
- package/dist/api/GlobalConfigAPI.d.ts +35 -0
- package/dist/api/IoTPointTemplateAPI.d.ts +32 -0
- package/dist/api/MarketplaceAPI.d.ts +39 -0
- package/dist/api/RuleChainAPI.d.ts +23 -4
- package/dist/api/RuleChainVersionsAPI.d.ts +28 -0
- package/dist/api/SkillsAPI.d.ts +31 -0
- package/dist/api/UserAPI.d.ts +39 -0
- package/dist/api/extended-api-shared.d.ts +25 -0
- package/dist/api/index.d.ts +19 -2
- package/dist/api/public-api.test-d.d.ts +87 -0
- package/dist/api/response-utils.d.ts +1 -0
- package/dist/api/types.d.ts +86 -14
- package/dist/chunks/editor-core-api-BQiYFuIO.js +1157 -0
- package/dist/chunks/editor-core-canvas-nodes-BE9eN51s.js +6921 -0
- package/dist/chunks/editor-core-code-editor-DFm5Owtv.js +660 -0
- package/dist/chunks/{editor-core-default-components-BjF65lar.js → editor-core-default-components-BsNP8ma1.js} +98 -98
- package/dist/chunks/editor-core-dialogs-D9YHvzys.js +12009 -0
- package/dist/chunks/{editor-core-locales-i6o28vm2.js → editor-core-locales-CsqTh7Wh.js} +1723 -11
- package/dist/chunks/{editor-core-node-patches-BJTT3TuX.js → editor-core-node-patches-Dbi8XYxu.js} +633 -184
- package/dist/chunks/{editor-core-node-views-BOaPVdmN.js → editor-core-node-views-C8FQYC3E.js} +39 -29
- package/dist/chunks/editor-core-property-drawers-Bqmp9B_J.js +9562 -0
- package/dist/chunks/editor-core-settings-DcGCJSc7.js +4161 -0
- package/dist/chunks/editor-core-standalone-C7pzm8ZB.js +10013 -0
- package/dist/chunks/{editor-core-styles-DFhXz0vB.js → editor-core-styles-CwjFPfAo.js} +967 -510
- package/dist/chunks/vendor-highlight-acC2fLd8.js +5868 -0
- package/dist/chunks/vendor-logicflow-core-runtime-DpsWXOGl.js +4 -0
- package/dist/chunks/vendor-logicflow-shared-C_kIdBKO.js +4 -0
- package/dist/core/ActionRegistry.d.ts +4 -2
- package/dist/core/DataAdapter.d.ts +17 -1
- package/dist/core/DialogProvider.d.ts +33 -0
- package/dist/core/EditorCore.d.ts +16 -3
- package/dist/core/FieldCapabilityRegistry.d.ts +4 -1
- package/dist/core/FieldChangeRegistry.d.ts +3 -1
- package/dist/core/I18nManager.d.ts +1 -1
- package/dist/core/IdentityProvider.d.ts +32 -0
- package/dist/core/OptionSourceRegistry.d.ts +4 -1
- package/dist/core/PropertyControlRegistry.d.ts +29 -0
- package/dist/core/ThemeManager.d.ts +7 -0
- package/dist/core/anchored-popover.d.ts +16 -0
- package/dist/core/assistant-dsl.d.ts +18 -0
- package/dist/core/business-log-config.d.ts +18 -0
- package/dist/core/clean-snapshot.d.ts +14 -0
- package/dist/core/component-localization.d.ts +17 -0
- package/dist/core/component-palette.d.ts +3 -0
- package/dist/core/connection-status.d.ts +11 -0
- package/dist/core/dialog-styles.d.ts +1 -0
- package/dist/core/editor-capabilities.d.ts +82 -1
- package/dist/core/editor-edge-anchors.d.ts +16 -0
- package/dist/core/endpoint-protocol.d.ts +15 -0
- package/dist/core/expression-preview.d.ts +6 -0
- package/dist/core/field-protocol.d.ts +19 -4
- package/dist/core/global-config.d.ts +47 -0
- package/dist/core/global-search.d.ts +31 -0
- package/dist/core/group-protocol.d.ts +56 -0
- package/dist/core/identity-provider-default.d.ts +32 -0
- package/dist/core/index.d.ts +31 -5
- package/dist/core/keymap.d.ts +10 -0
- package/dist/core/payload-kv.d.ts +7 -0
- package/dist/core/rule-chain-versions.d.ts +143 -0
- package/dist/core/run-analysis.d.ts +126 -0
- package/dist/core/runtime-field-dictionary.d.ts +3 -0
- package/dist/core/save-conflict.d.ts +1 -0
- package/dist/core/server-status.d.ts +1 -0
- package/dist/core/toolbar-icons.d.ts +1 -1
- package/dist/core/variable-completion.d.ts +13 -0
- package/dist/core/websocket-auth.d.ts +2 -0
- package/dist/defaults/analysis-locales.d.ts +241 -0
- package/dist/defaults/component-locale-categories.d.ts +14 -0
- package/dist/defaults/component-locale-data.d.ts +4 -0
- package/dist/defaults/component-locale-en-US.d.ts +10 -0
- package/dist/defaults/component-locale-summaries.d.ts +15 -0
- package/dist/defaults/component-locale-zh-CN.d.ts +10 -0
- package/dist/defaults/editor-shell-locales.d.ts +290 -0
- package/dist/defaults/example-chain.d.ts +2 -0
- package/dist/defaults/field-interaction-locales.d.ts +19 -0
- package/dist/defaults/global-config-locales.d.ts +166 -0
- package/dist/defaults/official-component-fallbacks.d.ts +2 -1
- package/dist/defaults/point-template-locales.d.ts +64 -0
- package/dist/index.cjs +2856 -2086
- package/dist/index.d.ts +33 -10
- package/dist/index.esm.js +1182 -810
- package/dist/index.umd.js +2850 -2080
- package/dist/nodes/UnknownNodeModel.d.ts +12 -1
- package/dist/standalone/HuanbanRulegoEditor.d.ts +145 -13
- package/dist/standalone/auth-fetch.d.ts +1 -0
- package/dist/standalone/auth-ui-defaults.d.ts +15 -0
- package/dist/standalone/code-editor.d.ts +7 -5
- package/dist/standalone/connection-status-binding.d.ts +3 -2
- package/dist/standalone/custom-nodes.d.ts +13 -0
- package/dist/standalone/drawer-locale.d.ts +12 -0
- package/dist/standalone/drawer-unsaved-guard.d.ts +6 -1
- package/dist/standalone/dynamic-field-browse.d.ts +25 -0
- package/dist/standalone/edge-label-quick-editor.d.ts +2 -1
- package/dist/standalone/editor-actions.d.ts +1 -0
- package/dist/standalone/editor-canvas-anchors.d.ts +19 -0
- package/dist/standalone/editor-canvas-shortcuts.d.ts +1 -0
- package/dist/standalone/editor-chain-info.d.ts +1 -0
- package/dist/standalone/editor-debug-data.d.ts +18 -0
- package/dist/standalone/editor-debug-ws.d.ts +2 -0
- package/dist/standalone/editor-delete.d.ts +5 -3
- package/dist/standalone/editor-dialog-provider.d.ts +3 -0
- package/dist/standalone/editor-dialogs.d.ts +25 -2
- package/dist/standalone/editor-global-config.d.ts +44 -0
- package/dist/standalone/editor-group-interactions.d.ts +1 -0
- package/dist/standalone/editor-host-region-styles.d.ts +1 -0
- package/dist/standalone/editor-host-regions.d.ts +53 -0
- package/dist/standalone/editor-login.d.ts +15 -0
- package/dist/standalone/editor-overlays.d.ts +5 -0
- package/dist/standalone/editor-property-drawers.d.ts +3 -1
- package/dist/standalone/editor-run-analysis.d.ts +81 -0
- package/dist/standalone/editor-run-compare.d.ts +20 -0
- package/dist/standalone/editor-run-waterfall.d.ts +11 -0
- package/dist/standalone/editor-toast.d.ts +1 -1
- package/dist/standalone/editor-toolbar-presentation.d.ts +12 -0
- package/dist/standalone/editor-toolbar.d.ts +5 -1
- package/dist/standalone/editor-ui-configuration.d.ts +55 -0
- package/dist/standalone/editor-ui-settings.d.ts +26 -0
- package/dist/standalone/editor-user-menu.d.ts +8 -0
- package/dist/standalone/editor-version-history.d.ts +82 -0
- package/dist/standalone/editor-workspace-shell.d.ts +47 -0
- package/dist/standalone/editor-workspace-styles.d.ts +1 -0
- package/dist/standalone/field-expression-preview.d.ts +12 -0
- package/dist/standalone/group-node.d.ts +19 -3
- package/dist/standalone/icon-utils.d.ts +7 -0
- package/dist/standalone/index.d.ts +17 -5
- package/dist/standalone/keyboard-events.d.ts +3 -0
- package/dist/standalone/multi-select-popover.d.ts +16 -0
- package/dist/standalone/node-copy.d.ts +1 -0
- package/dist/standalone/node-definitions.d.ts +4 -0
- package/dist/standalone/node-renderer-utils.d.ts +21 -0
- package/dist/standalone/node-theme.d.ts +1 -1
- package/dist/standalone/point-template-actions.d.ts +43 -0
- package/dist/standalone/property-field-draft.d.ts +5 -0
- package/dist/standalone/question-list-editor.d.ts +35 -0
- package/dist/standalone/shared-node-manager.d.ts +14 -0
- package/dist/standalone/single-select-popover.d.ts +6 -0
- package/dist/standalone/theme-scope.d.ts +15 -0
- package/dist/standalone/themes.d.ts +4 -0
- package/dist/standalone/variable-completion-dropdown.d.ts +18 -0
- package/dist/types/component.d.ts +22 -1
- package/dist/types/editor.d.ts +41 -0
- package/dist/utils/relation-utils.d.ts +19 -1
- package/dist/version.d.ts +2 -2
- package/package.json +3 -3
- package/vite-chunks.mjs +66 -0
- package/dist/chunks/editor-core-code-editor-CRki2wA_.js +0 -512
- package/dist/chunks/editor-core-dialogs-BMWb0WRN.js +0 -17228
- package/dist/chunks/editor-core-property-drawers-BPh-jj1b.js +0 -7998
- package/dist/chunks/editor-core-standalone-Cls7lcgT.js +0 -11302
- package/dist/chunks/vendor-logicflow-core-runtime-Cp6IBEjB.js +0 -217
- package/dist/chunks/vendor-logicflow-shared-C7YynLDn.js +0 -4
|
@@ -0,0 +1,1157 @@
|
|
|
1
|
+
import { u as E, n as $ } from "./editor-core-canvas-nodes-BE9eN51s.js";
|
|
2
|
+
class J {
|
|
3
|
+
/**
|
|
4
|
+
* 创建状态容器
|
|
5
|
+
* @param initialState - 初始状态对象
|
|
6
|
+
*/
|
|
7
|
+
constructor(e) {
|
|
8
|
+
this.listeners = /* @__PURE__ */ new Set(), this.version = 0, this.batchDepth = 0, this.batchPrevState = null, this.batchStartVersion = 0, this.state = { ...e };
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* 获取当前状态的只读快照
|
|
12
|
+
*
|
|
13
|
+
* 注意: 返回的是浅冻结对象,不应直接修改属性。
|
|
14
|
+
* 修改状态只能通过 setState 方法。
|
|
15
|
+
*
|
|
16
|
+
* @returns 当前状态的只读引用
|
|
17
|
+
*/
|
|
18
|
+
getState() {
|
|
19
|
+
return this.state;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 获取当前版本号
|
|
23
|
+
* 每次 setState 调用版本号 +1,用于变更检测
|
|
24
|
+
*
|
|
25
|
+
* @returns 版本号
|
|
26
|
+
*/
|
|
27
|
+
getVersion() {
|
|
28
|
+
return this.version;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 更新状态 (支持部分更新和函数式更新)
|
|
32
|
+
*
|
|
33
|
+
* 部分更新: 传入一个 Partial<T> 对象,自动与现有状态合并
|
|
34
|
+
* 函数式更新: 传入一个函数,接收当前状态,返回需要更新的部分
|
|
35
|
+
*
|
|
36
|
+
* @param partial - 部分状态对象或更新函数
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```typescript
|
|
40
|
+
* // 对象方式
|
|
41
|
+
* store.setState({ selectedNode: node, isDirty: true })
|
|
42
|
+
*
|
|
43
|
+
* // 函数方式 (适合依赖当前状态的更新)
|
|
44
|
+
* store.setState(prev => ({
|
|
45
|
+
* nodeCount: prev.nodeCount + 1
|
|
46
|
+
* }))
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
setState(e) {
|
|
50
|
+
const t = this.state, r = typeof e == "function" ? e(t) : e;
|
|
51
|
+
this.state = { ...t, ...r }, this.version++, this.batchDepth === 0 && this.notify(this.state, t);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* 批量更新状态 (只触发一次通知)
|
|
55
|
+
*
|
|
56
|
+
* 适用于需要同时修改多个状态但只想触发一次更新的场景
|
|
57
|
+
*
|
|
58
|
+
* @param updater - 更新函数,可多次调用 setState
|
|
59
|
+
*/
|
|
60
|
+
batch(e) {
|
|
61
|
+
const t = this.batchDepth === 0;
|
|
62
|
+
t && (this.batchPrevState = this.state, this.batchStartVersion = this.version), this.batchDepth++;
|
|
63
|
+
try {
|
|
64
|
+
e();
|
|
65
|
+
} finally {
|
|
66
|
+
if (this.batchDepth--, !t) return;
|
|
67
|
+
const r = this.batchPrevState || this.state, s = this.version !== this.batchStartVersion;
|
|
68
|
+
this.batchPrevState = null, this.batchStartVersion = 0, s && this.notify(this.state, r);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 通知当前订阅者。批处理通过 batchDepth 延迟调用,避免临时清空监听器,
|
|
73
|
+
* 从而保证异常路径、嵌套批处理和批处理期间的新订阅都不会丢失。
|
|
74
|
+
*/
|
|
75
|
+
notify(e, t) {
|
|
76
|
+
this.listeners.forEach((r) => {
|
|
77
|
+
try {
|
|
78
|
+
r(e, t);
|
|
79
|
+
} catch (s) {
|
|
80
|
+
console.error("[StateStore] 监听器执行出错:", s);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* 订阅状态变化
|
|
86
|
+
*
|
|
87
|
+
* @param listener - 状态变更回调函数
|
|
88
|
+
* @returns 取消订阅函数 (调用后停止接收通知)
|
|
89
|
+
*/
|
|
90
|
+
subscribe(e) {
|
|
91
|
+
return this.listeners.add(e), () => {
|
|
92
|
+
this.listeners.delete(e);
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 选择性订阅 (只关注特定字段的变化)
|
|
97
|
+
*
|
|
98
|
+
* 通过 selector 函数提取状态的一个切片。
|
|
99
|
+
* 只有当该切片发生变化时才触发通知,减少不必要的 UI 更新。
|
|
100
|
+
*
|
|
101
|
+
* 使用浅比较 (===) 进行变更检测,
|
|
102
|
+
* 如果 selector 返回引用类型,需注意引用是否真正发生了变化。
|
|
103
|
+
*
|
|
104
|
+
* @param selector - 状态选择器函数
|
|
105
|
+
* @returns 包含 get 和 subscribe 的句柄
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* const nodeHandle = store.select(s => s.selectedNode)
|
|
110
|
+
*
|
|
111
|
+
* // 获取当前值
|
|
112
|
+
* console.log(nodeHandle.get())
|
|
113
|
+
*
|
|
114
|
+
* // 只在 selectedNode 变化时收到通知
|
|
115
|
+
* nodeHandle.subscribe((node, prevNode) => {
|
|
116
|
+
* console.log('节点变化:', prevNode, '->', node)
|
|
117
|
+
* })
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
select(e) {
|
|
121
|
+
return {
|
|
122
|
+
get: () => e(this.state),
|
|
123
|
+
subscribe: (t) => {
|
|
124
|
+
let r = e(this.state);
|
|
125
|
+
return this.subscribe((s, o) => {
|
|
126
|
+
const n = e(s);
|
|
127
|
+
if (n !== r) {
|
|
128
|
+
const a = r;
|
|
129
|
+
r = n, t(n, a);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* 重置状态为指定值 (全量替换)
|
|
137
|
+
*
|
|
138
|
+
* @param newState - 新的完整状态
|
|
139
|
+
*/
|
|
140
|
+
reset(e) {
|
|
141
|
+
const t = this.state;
|
|
142
|
+
this.state = { ...e }, this.version++, this.batchDepth === 0 && this.notify(this.state, t);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* 销毁状态容器,清除所有监听器
|
|
146
|
+
*/
|
|
147
|
+
destroy() {
|
|
148
|
+
this.listeners.clear();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function R(i, e = "") {
|
|
152
|
+
var s;
|
|
153
|
+
const t = String(i || "").trim().replace(/\/+$/, ""), r = String(e || "").trim();
|
|
154
|
+
if (!t) return "";
|
|
155
|
+
try {
|
|
156
|
+
const o = typeof globalThis < "u" && "location" in globalThis ? String(((s = globalThis.location) == null ? void 0 : s.href) || "") : "", n = new URL(t, o || void 0);
|
|
157
|
+
if (n.protocol === "http:" ? n.protocol = "ws:" : n.protocol === "https:" && (n.protocol = "wss:"), r) {
|
|
158
|
+
const a = r.startsWith("/") ? r : `${n.pathname.replace(/\/+$/, "")}/${r.replace(/^\/+/, "")}`;
|
|
159
|
+
n.pathname = a.replace(/\/+/g, "/");
|
|
160
|
+
}
|
|
161
|
+
return n.toString().replace(/\/$/, "");
|
|
162
|
+
} catch {
|
|
163
|
+
const o = t.startsWith("https:") ? "wss:" : t.startsWith("http:") ? "ws:" : "";
|
|
164
|
+
return o ? `${o}${t.replace(/^https?:/, "")}${r ? `/${r.replace(/^\/+/, "")}` : ""}` : `${t}${r ? `/${r.replace(/^\/+/, "")}` : ""}`;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function N() {
|
|
168
|
+
return Date.now();
|
|
169
|
+
}
|
|
170
|
+
function k(i) {
|
|
171
|
+
return Number.isFinite(i) ? Math.max(0, Math.floor(i)) : 0;
|
|
172
|
+
}
|
|
173
|
+
class ne {
|
|
174
|
+
constructor(e = {}) {
|
|
175
|
+
this.destroyed = !1;
|
|
176
|
+
const t = String(e.baseUrl || "").trim().replace(/\/+$/, "");
|
|
177
|
+
this.store = new J({
|
|
178
|
+
api: "unknown",
|
|
179
|
+
ws: "idle",
|
|
180
|
+
status: "unknown",
|
|
181
|
+
baseUrl: t,
|
|
182
|
+
wsUrl: e.wsUrl || R(t),
|
|
183
|
+
httpStatus: null,
|
|
184
|
+
wsCloseCode: null,
|
|
185
|
+
reconnectAttempt: 0,
|
|
186
|
+
lastChangedAt: null
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
getState() {
|
|
190
|
+
return { ...this.store.getState() };
|
|
191
|
+
}
|
|
192
|
+
subscribe(e) {
|
|
193
|
+
return this.destroyed ? () => {
|
|
194
|
+
} : this.store.subscribe((t, r) => e({ ...t }, { ...r }));
|
|
195
|
+
}
|
|
196
|
+
setServerUrl(e, t) {
|
|
197
|
+
if (this.destroyed) return;
|
|
198
|
+
const r = String(e || "").trim().replace(/\/+$/, "");
|
|
199
|
+
this.store.setState({
|
|
200
|
+
baseUrl: r,
|
|
201
|
+
wsUrl: t || R(r),
|
|
202
|
+
api: "unknown",
|
|
203
|
+
ws: "idle",
|
|
204
|
+
status: "unknown",
|
|
205
|
+
httpStatus: null,
|
|
206
|
+
wsCloseCode: null,
|
|
207
|
+
reconnectAttempt: 0,
|
|
208
|
+
lastChangedAt: N(),
|
|
209
|
+
errorMessage: void 0
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
setServerStatus(e, t = {}) {
|
|
213
|
+
if (this.destroyed) return;
|
|
214
|
+
const r = this.store.getState();
|
|
215
|
+
this.store.setState({
|
|
216
|
+
...t,
|
|
217
|
+
reconnectAttempt: t.reconnectAttempt === void 0 ? r.reconnectAttempt : k(t.reconnectAttempt),
|
|
218
|
+
status: e,
|
|
219
|
+
lastChangedAt: e === r.status && !t.errorMessage ? r.lastChangedAt : N()
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Mark a successful API interaction without a concrete HTTP response.
|
|
224
|
+
* Promotes `unknown`, `offline`, and `error` to `online`; leaves
|
|
225
|
+
* `unauthorized`, `forbidden`, `checking`, and `online` unchanged so
|
|
226
|
+
* richer signals are not overwritten.
|
|
227
|
+
*/
|
|
228
|
+
markApiSuccess() {
|
|
229
|
+
if (this.destroyed) return;
|
|
230
|
+
const { api: e } = this.store.getState();
|
|
231
|
+
(e === "unknown" || e === "offline" || e === "error") && this.setServerStatus("online", { api: "online", errorMessage: void 0 });
|
|
232
|
+
}
|
|
233
|
+
recordHttpStatus(e, t) {
|
|
234
|
+
if (this.destroyed) return "unknown";
|
|
235
|
+
const r = e === 401 ? "unauthorized" : e === 403 ? "forbidden" : e >= 200 && e < 300 ? "online" : e === 0 ? "offline" : "error", s = r;
|
|
236
|
+
return this.setServerStatus(s, {
|
|
237
|
+
api: r,
|
|
238
|
+
httpStatus: e,
|
|
239
|
+
errorMessage: s === "online" ? void 0 : t
|
|
240
|
+
}), s;
|
|
241
|
+
}
|
|
242
|
+
recordWebSocketStatus(e, t = null, r) {
|
|
243
|
+
if (this.destroyed) return "unknown";
|
|
244
|
+
const s = e === "live" ? "connected" : e === "disconnected" ? "closed" : e, o = this.store.getState().api, n = o === "unauthorized" || o === "forbidden" ? o : s === "connected" ? "online" : s === "connecting" || s === "reconnecting" ? "checking" : s === "closed" ? "offline" : "error";
|
|
245
|
+
return this.setServerStatus(n, {
|
|
246
|
+
api: o,
|
|
247
|
+
ws: s,
|
|
248
|
+
wsCloseCode: t,
|
|
249
|
+
errorMessage: r || (t === 1006 ? "WebSocket unexpected disconnect (1006)" : void 0)
|
|
250
|
+
}), n;
|
|
251
|
+
}
|
|
252
|
+
setReconnectAttempt(e) {
|
|
253
|
+
this.destroyed || this.store.setState({ reconnectAttempt: k(e) });
|
|
254
|
+
}
|
|
255
|
+
destroy() {
|
|
256
|
+
this.destroyed || (this.destroyed = !0, this.store.destroy());
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
const _ = 1200, x = /* @__PURE__ */ new WeakMap();
|
|
260
|
+
let G = 1;
|
|
261
|
+
const D = /* @__PURE__ */ new WeakMap();
|
|
262
|
+
let W = 1;
|
|
263
|
+
const O = /* @__PURE__ */ new Map();
|
|
264
|
+
let j = 1;
|
|
265
|
+
function T() {
|
|
266
|
+
if (typeof localStorage > "u") return "";
|
|
267
|
+
try {
|
|
268
|
+
return localStorage.getItem("token") || localStorage.getItem("access_token") || "";
|
|
269
|
+
} catch {
|
|
270
|
+
return "";
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
function M(i) {
|
|
274
|
+
const e = x.get(i);
|
|
275
|
+
if (e !== void 0) return e;
|
|
276
|
+
const t = G++;
|
|
277
|
+
return x.set(i, t), t;
|
|
278
|
+
}
|
|
279
|
+
function V(i) {
|
|
280
|
+
const e = D.get(i);
|
|
281
|
+
if (e !== void 0) return e;
|
|
282
|
+
const t = W++;
|
|
283
|
+
return D.set(i, t), t;
|
|
284
|
+
}
|
|
285
|
+
function K(i) {
|
|
286
|
+
const e = String(i), t = O.get(e);
|
|
287
|
+
if (t !== void 0) return t;
|
|
288
|
+
const r = j++;
|
|
289
|
+
return O.set(e, r), r;
|
|
290
|
+
}
|
|
291
|
+
function Y(i) {
|
|
292
|
+
return !!(i && Object.keys(i).some((e) => e.toLowerCase() === "authorization"));
|
|
293
|
+
}
|
|
294
|
+
function q(i = "/api/v1") {
|
|
295
|
+
const e = String(i).trim().replace(/^\/+|\/+$/g, "");
|
|
296
|
+
if (e.includes("://") || /[?#]/.test(e)) throw new Error("apiPrefix must be a path");
|
|
297
|
+
return e ? `/${e}` : "";
|
|
298
|
+
}
|
|
299
|
+
function Q(i, e) {
|
|
300
|
+
const t = String(i || "").trim().replace(/\/+$/, ""), r = q(e);
|
|
301
|
+
return r && t.toLowerCase().endsWith(r.toLowerCase()) ? t.slice(0, -r.length) : t;
|
|
302
|
+
}
|
|
303
|
+
function oe(i, e) {
|
|
304
|
+
const t = String(i || "").trim().replace(/\/+$/, "");
|
|
305
|
+
if (!t) return "";
|
|
306
|
+
const r = q(e);
|
|
307
|
+
return r && !t.toLowerCase().endsWith(r.toLowerCase()) ? `${t}${r}` : t;
|
|
308
|
+
}
|
|
309
|
+
class X {
|
|
310
|
+
constructor(e = {}) {
|
|
311
|
+
this.config = { baseUrl: "", includeStoredToken: !0 }, this.configGeneration = 0, this.debugClientId = `editor-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`, this.lastAuthNotifyAt = /* @__PURE__ */ new WeakMap(), this.updateConfig(e);
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* 更新 API 全局配置
|
|
315
|
+
* @param {Partial<EditorApiConfig>} newConfig - 要合并的新配置项
|
|
316
|
+
*/
|
|
317
|
+
updateConfig(e) {
|
|
318
|
+
this.config = { ...this.config, ...e }, e.baseUrl !== void 0 && (this.config.baseUrl = Q(e.baseUrl, this.config.apiPrefix)), this.configGeneration += 1;
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* 获取当前配置的基础 URL
|
|
322
|
+
* @returns {string} baseUrl
|
|
323
|
+
*/
|
|
324
|
+
getBaseUrl() {
|
|
325
|
+
return this.config.baseUrl;
|
|
326
|
+
}
|
|
327
|
+
getApiPrefix() {
|
|
328
|
+
return q(this.config.apiPrefix);
|
|
329
|
+
}
|
|
330
|
+
/** Whether metadata discovery may retain a result or share an in-flight request. */
|
|
331
|
+
isSharedCacheEnabled() {
|
|
332
|
+
return this.config.cacheKey !== void 0 ? !0 : !(this.config.identityProvider || typeof this.config.fetchHeaders == "function" || this.config.includeStoredToken !== !1 && !Y(this.config.fetchHeaders) && T());
|
|
333
|
+
}
|
|
334
|
+
/** @deprecated Use isSharedCacheEnabled for model and component metadata. */
|
|
335
|
+
isModelCacheEnabled() {
|
|
336
|
+
return this.isSharedCacheEnabled();
|
|
337
|
+
}
|
|
338
|
+
/** Stable identity for capability caches; a changed backend must not reuse old data. */
|
|
339
|
+
getCacheKey() {
|
|
340
|
+
const e = this.config.fetchHeaders, t = typeof e == "function" ? this.config.cacheKey !== void 0 ? "dynamic" : `dynamic:${M(e)}` : e ? `static:${V(e)}` : "static:none", r = this.config.customFetch ? `|fetch:${M(this.config.customFetch)}` : "", s = this.config.cacheKey !== void 0 ? `|cache:${K(this.config.cacheKey)}` : "";
|
|
341
|
+
return `${this.config.baseUrl}|prefix:${this.getApiPrefix()}|${t}${r}${s}`;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* 内部统一请求通道
|
|
345
|
+
* 负责拼装 URL、注入自定义 Headers,或派发至自定义 fetch 方法
|
|
346
|
+
* @private
|
|
347
|
+
*/
|
|
348
|
+
async request(e, t) {
|
|
349
|
+
var w, A;
|
|
350
|
+
const r = this.config, s = this.configGeneration, o = `${r.baseUrl}${e}`, n = t == null ? void 0 : t.signal;
|
|
351
|
+
if (n != null && n.aborted) throw n.reason ?? new DOMException("Aborted", "AbortError");
|
|
352
|
+
const a = () => {
|
|
353
|
+
const h = typeof r.fetchHeaders == "function" ? r.fetchHeaders() : r.fetchHeaders, S = new Headers(h), g = r.identityProvider ? r.identityProvider.getToken() || "" : r.includeStoredToken !== !1 ? T() : "";
|
|
354
|
+
return !S.has("Authorization") && g && S.set("Authorization", `Bearer ${g}`), { headers: S, token: g };
|
|
355
|
+
}, c = a(), u = new Headers(c.headers);
|
|
356
|
+
new Headers(t == null ? void 0 : t.headers).forEach((h, S) => u.set(S, h));
|
|
357
|
+
const p = { ...t, headers: u };
|
|
358
|
+
if (n != null && n.aborted) throw n.reason ?? new DOMException("Aborted", "AbortError");
|
|
359
|
+
let y = () => {
|
|
360
|
+
};
|
|
361
|
+
const f = new Promise((h, S) => {
|
|
362
|
+
y = () => S((n == null ? void 0 : n.reason) ?? new DOMException("Aborted", "AbortError")), n == null || n.addEventListener("abort", y, { once: !0 });
|
|
363
|
+
});
|
|
364
|
+
let l;
|
|
365
|
+
try {
|
|
366
|
+
const h = async () => r.customFetch ? r.customFetch(o, p) : fetch(o, p);
|
|
367
|
+
if (l = await Promise.race([h(), f]), n != null && n.aborted) throw n.reason ?? new DOMException("Aborted", "AbortError");
|
|
368
|
+
} catch (h) {
|
|
369
|
+
if (this.isCurrentRequestGeneration(s) && !(n != null && n.aborted) && (h == null ? void 0 : h.name) !== "AbortError") {
|
|
370
|
+
const S = h instanceof Error ? h.message : String(h || "Network request failed");
|
|
371
|
+
(w = r.serverStatus) == null || w.recordHttpStatus(0, S);
|
|
372
|
+
}
|
|
373
|
+
throw h;
|
|
374
|
+
} finally {
|
|
375
|
+
n == null || n.removeEventListener("abort", y);
|
|
376
|
+
}
|
|
377
|
+
if (!this.isCurrentRequestGeneration(s)) return l;
|
|
378
|
+
const d = l.status === 401 || l.status === 403;
|
|
379
|
+
if (d)
|
|
380
|
+
try {
|
|
381
|
+
const h = a();
|
|
382
|
+
if (c.token !== h.token || JSON.stringify([...c.headers]) !== JSON.stringify([...h.headers]) || u.get("Authorization") !== c.headers.get("Authorization") || r.identityProvider && u.get("Authorization") !== (c.token ? `Bearer ${c.token}` : null)) return l;
|
|
383
|
+
} catch {
|
|
384
|
+
return l;
|
|
385
|
+
}
|
|
386
|
+
if ((A = r.serverStatus) == null || A.recordHttpStatus(l.status, l.ok ? void 0 : `HTTP ${l.status}`), d) {
|
|
387
|
+
const h = r.identityProvider;
|
|
388
|
+
if (h)
|
|
389
|
+
try {
|
|
390
|
+
Promise.resolve(h.handleAuthError({ status: l.status, url: o })).catch(() => {
|
|
391
|
+
});
|
|
392
|
+
} catch {
|
|
393
|
+
}
|
|
394
|
+
else
|
|
395
|
+
this.notifyAuthRequired(l.status, o, r.onAuthRequired);
|
|
396
|
+
}
|
|
397
|
+
return l;
|
|
398
|
+
}
|
|
399
|
+
isCurrentRequestGeneration(e) {
|
|
400
|
+
return e === this.configGeneration;
|
|
401
|
+
}
|
|
402
|
+
notifyAuthRequired(e, t, r) {
|
|
403
|
+
if (!r) return;
|
|
404
|
+
const s = Date.now(), o = this.lastAuthNotifyAt.get(r) ?? Number.NEGATIVE_INFINITY;
|
|
405
|
+
if (!(s - o < _)) {
|
|
406
|
+
this.lastAuthNotifyAt.set(r, s);
|
|
407
|
+
try {
|
|
408
|
+
Promise.resolve(r({ status: e, url: t })).catch(() => {
|
|
409
|
+
});
|
|
410
|
+
} catch {
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// ==========================================
|
|
415
|
+
// 核心业务 API 集合
|
|
416
|
+
// ==========================================
|
|
417
|
+
/**
|
|
418
|
+
* 获取平台全量的节点组件注册列表
|
|
419
|
+
* API: /api/v1/components
|
|
420
|
+
* @returns {Promise<any>} 返回 JSON 数据字典
|
|
421
|
+
*/
|
|
422
|
+
async fetchComponents(e) {
|
|
423
|
+
const t = await this.request(`${this.getApiPrefix()}/components`, e);
|
|
424
|
+
if (!t.ok) throw new Error(`HTTP Error ${t.status}`);
|
|
425
|
+
return E(await t.json());
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* 下发测试指令到规则引擎
|
|
429
|
+
* @param {string} chainId - 规则链ID
|
|
430
|
+
* @param {any} data - 需要灌入的 JSON 报文
|
|
431
|
+
* @returns {Promise<any>}
|
|
432
|
+
*/
|
|
433
|
+
async runDebug(e, t, r = {}) {
|
|
434
|
+
var c;
|
|
435
|
+
const s = new URLSearchParams(r.metadata);
|
|
436
|
+
s.set("msgId", r.msgId || `debug-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`), s.set("_debugMode", "true"), s.set("_rootChainId", e);
|
|
437
|
+
const o = await this.request(`${this.getApiPrefix()}/rules/${encodeURIComponent(e)}/execute/${encodeURIComponent(r.msgType || "TEST")}?${s}`, {
|
|
438
|
+
method: "POST",
|
|
439
|
+
headers: { "Content-Type": "application/json" },
|
|
440
|
+
body: typeof t == "string" ? t : JSON.stringify(t),
|
|
441
|
+
signal: r.signal
|
|
442
|
+
}), n = await o.text();
|
|
443
|
+
let a = n;
|
|
444
|
+
try {
|
|
445
|
+
a = n ? JSON.parse(n) : void 0;
|
|
446
|
+
} catch {
|
|
447
|
+
}
|
|
448
|
+
if (!o.ok) throw new Error(String(((c = a == null ? void 0 : a.error) == null ? void 0 : c.message) || (a == null ? void 0 : a.error) || (a == null ? void 0 : a.message) || n || `HTTP Error ${o.status}`));
|
|
449
|
+
return E(a);
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* 根据当前 HTTP 地址,自动换算获取 WebSocket 的连接地址
|
|
453
|
+
* @param {string} chainId - 规则链ID
|
|
454
|
+
* @returns {string} 完整的 ws:// 或 wss:// 地址
|
|
455
|
+
*/
|
|
456
|
+
getDebugWsUrl(e, t = this.debugClientId) {
|
|
457
|
+
var a;
|
|
458
|
+
if (!this.config.baseUrl) return "";
|
|
459
|
+
const r = R(this.config.baseUrl, `${this.getApiPrefix().replace(/^\//, "")}/logs/ws/${encodeURIComponent(e)}/${encodeURIComponent(t)}`.replace(/^\//, "")), s = new Headers(typeof this.config.fetchHeaders == "function" ? this.config.fetchHeaders() : this.config.fetchHeaders), o = s.get("Authorization"), n = s.has("Authorization") ? ((a = o == null ? void 0 : o.match(/^Bearer\s+(.+)$/i)) == null ? void 0 : a[1]) || "" : this.config.identityProvider ? this.config.identityProvider.getToken() || "" : this.config.includeStoredToken !== !1 ? T() : "";
|
|
460
|
+
return n ? `${r}${r.includes("?") ? "&" : "?"}token=${encodeURIComponent(n)}` : r;
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
const ie = new X();
|
|
464
|
+
function ae() {
|
|
465
|
+
return T() || null;
|
|
466
|
+
}
|
|
467
|
+
function ce() {
|
|
468
|
+
try {
|
|
469
|
+
localStorage.removeItem("token"), localStorage.removeItem("access_token");
|
|
470
|
+
} catch {
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
const m = {
|
|
474
|
+
list: "/rules",
|
|
475
|
+
create: "/rules/:id",
|
|
476
|
+
remove: (i) => `/rules/${encodeURIComponent(i)}`,
|
|
477
|
+
operate: (i, e) => `/rules/${encodeURIComponent(i)}/operate/${encodeURIComponent(e)}`,
|
|
478
|
+
getContent: (i) => i === "get/latest" ? "/rules/get/latest" : `/rules/${encodeURIComponent(i)}`,
|
|
479
|
+
status: (i) => `/rules/${encodeURIComponent(i)}/status`,
|
|
480
|
+
sharedNodeStatuses: "/shared-node-statuses",
|
|
481
|
+
sharedNodes: "/shared-nodes",
|
|
482
|
+
sharedNode: (i, e) => `/shared-nodes/${i}/${e}`,
|
|
483
|
+
saveBaseInfo: (i) => `/rules/${encodeURIComponent(i)}/base`,
|
|
484
|
+
saveConfig: (i, e) => `/rules/${encodeURIComponent(i)}/config/${encodeURIComponent(e)}`,
|
|
485
|
+
notifyRule: (i, e) => `/rules/${encodeURIComponent(i)}/notify/${encodeURIComponent(e)}`,
|
|
486
|
+
executeRule: (i, e) => `/rules/${encodeURIComponent(i)}/execute/${encodeURIComponent(e)}`,
|
|
487
|
+
ruleCategories: "/category/rule",
|
|
488
|
+
debugData: "/logs/debug",
|
|
489
|
+
runsList: "/logs/runs",
|
|
490
|
+
dynamicComponent: (i) => `/dynamic-components/${encodeURIComponent(i)}`,
|
|
491
|
+
queryDynamicBuiltin: (i) => `/builtins/${encodeURIComponent(i)}`
|
|
492
|
+
}, Z = 1200;
|
|
493
|
+
function ee() {
|
|
494
|
+
if (typeof localStorage > "u") return "";
|
|
495
|
+
try {
|
|
496
|
+
return localStorage.getItem("token") || localStorage.getItem("access_token") || "";
|
|
497
|
+
} catch {
|
|
498
|
+
return "";
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
function te(i) {
|
|
502
|
+
const e = i.split(";", 1)[0].trim().toLowerCase();
|
|
503
|
+
return e === "application/json" || e.startsWith("application/") && e.endsWith("+json");
|
|
504
|
+
}
|
|
505
|
+
function re(i, e, t) {
|
|
506
|
+
if (!(!e.trim() || te(e))) return i;
|
|
507
|
+
try {
|
|
508
|
+
const s = JSON.parse(i);
|
|
509
|
+
return t ? E(s) : s;
|
|
510
|
+
} catch (s) {
|
|
511
|
+
if (!e.trim() && s instanceof SyntaxError) return i;
|
|
512
|
+
throw s;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
function b(i, e) {
|
|
516
|
+
const t = i.indexOf("?"), r = t < 0 ? i : i.slice(0, t), s = new URLSearchParams(t < 0 ? "" : i.slice(t + 1));
|
|
517
|
+
for (const n of new Set(e.keys())) s.delete(n);
|
|
518
|
+
e.forEach((n, a) => s.append(a, n));
|
|
519
|
+
const o = s.toString();
|
|
520
|
+
return `${r}${o ? `?${o}` : ""}`;
|
|
521
|
+
}
|
|
522
|
+
function L(i) {
|
|
523
|
+
const e = new URLSearchParams(i.metadata);
|
|
524
|
+
return i.msgId !== void 0 && e.set("msgId", i.msgId), {
|
|
525
|
+
query: e,
|
|
526
|
+
body: typeof i.body == "string" ? i.body : JSON.stringify(i.body)
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
class H extends Error {
|
|
530
|
+
constructor(e, t, r) {
|
|
531
|
+
super(e), this.name = "RuleChainApiError", this.status = t, this.url = r;
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
const v = class v {
|
|
535
|
+
/**
|
|
536
|
+
* 创建 API 客户端实例
|
|
537
|
+
*
|
|
538
|
+
* @param options - 配置项
|
|
539
|
+
* @param options.apiBase - API 基础地址(如 'http://127.0.0.1:9090/api/v1')
|
|
540
|
+
* @param options.timeout - 请求超时毫秒数,默认 8000
|
|
541
|
+
* @param options.headers - 自定义请求头
|
|
542
|
+
* @param options.authToken - Bearer Token
|
|
543
|
+
*/
|
|
544
|
+
constructor(e) {
|
|
545
|
+
this.lastAuthNotifyAt = Number.NEGATIVE_INFINITY, this.apiBase = e.apiBase.replace(/\/+$/, ""), this.timeout = e.timeout ?? 8e3, this.customFetch = e.customFetch, this.credentials = e.credentials, this.onAuthRequired = e.onAuthRequired, this.serverStatus = e.serverStatus, this.includeStoredToken = e.includeStoredToken !== !1, this.authToken = e.authToken, this.headers = typeof e.headers == "function" ? e.headers : { ...e.headers }, this.routes = {
|
|
546
|
+
...m,
|
|
547
|
+
...Object.fromEntries(Object.entries(e.routes ?? {}).filter(([, t]) => t !== void 0))
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
// ============================================================
|
|
551
|
+
// 内部工具
|
|
552
|
+
// ============================================================
|
|
553
|
+
/**
|
|
554
|
+
* 发起 fetch 请求(带超时控制)
|
|
555
|
+
*
|
|
556
|
+
* @param path - API 路径(相对 apiBase)
|
|
557
|
+
* @param init - fetch 配置
|
|
558
|
+
* @returns 解析后的 JSON
|
|
559
|
+
*/
|
|
560
|
+
async request(e, t, r = !0) {
|
|
561
|
+
var l;
|
|
562
|
+
const s = t == null ? void 0 : t.signal;
|
|
563
|
+
if (s != null && s.aborted) throw s.reason ?? new DOMException("Aborted", "AbortError");
|
|
564
|
+
const o = new AbortController(), n = setTimeout(() => o.abort(new DOMException("Request timed out", "TimeoutError")), this.timeout);
|
|
565
|
+
let a = !1, c = !1;
|
|
566
|
+
const u = () => o.abort(s == null ? void 0 : s.reason);
|
|
567
|
+
s == null || s.addEventListener("abort", u, { once: !0 });
|
|
568
|
+
const p = `${this.apiBase}${e}`;
|
|
569
|
+
let y = () => {
|
|
570
|
+
};
|
|
571
|
+
const f = new Promise((d, w) => {
|
|
572
|
+
y = () => w(o.signal.reason ?? new DOMException("Aborted", "AbortError")), o.signal.addEventListener("abort", y, { once: !0 });
|
|
573
|
+
});
|
|
574
|
+
try {
|
|
575
|
+
const d = async () => {
|
|
576
|
+
var U;
|
|
577
|
+
const w = this.getHeaders(), A = new Headers(w);
|
|
578
|
+
new Headers(t == null ? void 0 : t.headers).forEach((z, F) => A.set(F, z));
|
|
579
|
+
const h = {
|
|
580
|
+
...t,
|
|
581
|
+
headers: A,
|
|
582
|
+
signal: o.signal,
|
|
583
|
+
credentials: (t == null ? void 0 : t.credentials) ?? this.credentials
|
|
584
|
+
};
|
|
585
|
+
if (o.signal.aborted) throw o.signal.reason ?? new DOMException("Aborted", "AbortError");
|
|
586
|
+
const S = this.customFetch || fetch;
|
|
587
|
+
c = !0;
|
|
588
|
+
const g = await S(p, h);
|
|
589
|
+
if (o.signal.aborted) throw o.signal.reason ?? new DOMException("Aborted", "AbortError");
|
|
590
|
+
a = !0;
|
|
591
|
+
const I = g.status === 401 || g.status === 403;
|
|
592
|
+
let C = !0;
|
|
593
|
+
if (I)
|
|
594
|
+
try {
|
|
595
|
+
C = JSON.stringify([...w]) === JSON.stringify([...this.getHeaders()]) && A.get("Authorization") === w.get("Authorization");
|
|
596
|
+
} catch {
|
|
597
|
+
C = !1;
|
|
598
|
+
}
|
|
599
|
+
(!I || C) && ((U = this.serverStatus) == null || U.recordHttpStatus(g.status, g.ok ? void 0 : `HTTP ${g.status}`)), I && C && this.notifyAuthRequired(g.status, p);
|
|
600
|
+
const P = g.ok ? await g.text() : await g.text().catch(() => "");
|
|
601
|
+
if (o.signal.aborted) throw o.signal.reason ?? new DOMException("Aborted", "AbortError");
|
|
602
|
+
if (!g.ok)
|
|
603
|
+
throw new H(`API 请求失败 [${g.status}]: ${P || g.statusText}`, g.status, p);
|
|
604
|
+
if (P.trim())
|
|
605
|
+
return re(P, g.headers.get("content-type") || "", r);
|
|
606
|
+
};
|
|
607
|
+
return await Promise.race([d(), f]);
|
|
608
|
+
} catch (d) {
|
|
609
|
+
if (d instanceof H) throw d;
|
|
610
|
+
const w = d instanceof Error ? d.message : String(d || "Network request failed");
|
|
611
|
+
throw c && !a && !(s != null && s.aborted) && (d == null ? void 0 : d.name) !== "AbortError" && ((l = this.serverStatus) == null || l.recordHttpStatus(0, w)), d;
|
|
612
|
+
} finally {
|
|
613
|
+
clearTimeout(n), s == null || s.removeEventListener("abort", u), o.signal.removeEventListener("abort", y);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
notifyAuthRequired(e, t) {
|
|
617
|
+
if (!this.onAuthRequired || e !== 401 && e !== 403) return;
|
|
618
|
+
const r = Date.now();
|
|
619
|
+
if (!(r - this.lastAuthNotifyAt < Z)) {
|
|
620
|
+
this.lastAuthNotifyAt = r;
|
|
621
|
+
try {
|
|
622
|
+
Promise.resolve(this.onAuthRequired({ status: e, url: t })).catch(() => {
|
|
623
|
+
});
|
|
624
|
+
} catch {
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
getHeaders() {
|
|
629
|
+
const e = new Headers(typeof this.headers == "function" ? this.headers() : this.headers);
|
|
630
|
+
if (e.has("Content-Type") || e.set("Content-Type", "application/json"), !e.has("Authorization")) {
|
|
631
|
+
const t = this.authToken || (this.includeStoredToken ? ee() : "");
|
|
632
|
+
t && e.set("Authorization", `Bearer ${t}`);
|
|
633
|
+
}
|
|
634
|
+
return e;
|
|
635
|
+
}
|
|
636
|
+
getRuleChainId(e) {
|
|
637
|
+
const t = e.ruleChain ?? e, r = String((t == null ? void 0 : t.id) ?? "").trim();
|
|
638
|
+
if (!r) throw new Error("规则链 ID 不能为空");
|
|
639
|
+
return r;
|
|
640
|
+
}
|
|
641
|
+
resolveCreatePath(e) {
|
|
642
|
+
const t = encodeURIComponent(this.getRuleChainId(e)), r = this.routes.create, s = r.indexOf("?"), o = s < 0 ? r : r.slice(0, s), n = s < 0 ? "" : r.slice(s);
|
|
643
|
+
return `${o.includes(":id") ? o.replace(":id", t) : o.includes("{id}") ? o.replace("{id}", t) : `${o.replace(/\/+$/, "")}/${t}`}${n}`;
|
|
644
|
+
}
|
|
645
|
+
resolveSharedNodePath(e, t) {
|
|
646
|
+
const r = this.routes.sharedNode || m.sharedNode, s = t === "endpoint" || t.startsWith("endpoint/") ? "endpoint" : "node";
|
|
647
|
+
return r(encodeURIComponent(e), s);
|
|
648
|
+
}
|
|
649
|
+
// ============================================================
|
|
650
|
+
// 静态工具方法
|
|
651
|
+
// ============================================================
|
|
652
|
+
/**
|
|
653
|
+
* 将后端 RuleChain DSL 对象转为前端扁平化 WorkflowItem
|
|
654
|
+
*
|
|
655
|
+
* @description 后端返回 { ruleChain: { id, name, root, disabled, additionalInfo }, metadata: {...} }
|
|
656
|
+
* 前端通过此方法转换为扁平化结构。
|
|
657
|
+
*
|
|
658
|
+
* @param raw - 后端原始对象
|
|
659
|
+
* @returns 扁平化的 WorkflowItem
|
|
660
|
+
*/
|
|
661
|
+
static parseRuleChain(e) {
|
|
662
|
+
const t = e, r = (t == null ? void 0 : t.ruleChain) ?? t, s = (r == null ? void 0 : r.additionalInfo) ?? {};
|
|
663
|
+
return {
|
|
664
|
+
id: String((r == null ? void 0 : r.id) ?? ""),
|
|
665
|
+
name: String((r == null ? void 0 : r.name) ?? ""),
|
|
666
|
+
root: !!((r == null ? void 0 : r.root) ?? !1),
|
|
667
|
+
disabled: !!((r == null ? void 0 : r.disabled) ?? !1),
|
|
668
|
+
debugMode: !!((r == null ? void 0 : r.debugMode) ?? (s == null ? void 0 : s.debugMode) ?? !1),
|
|
669
|
+
description: String((s == null ? void 0 : s.description) ?? (r == null ? void 0 : r.description) ?? ""),
|
|
670
|
+
additionalInfo: s,
|
|
671
|
+
createTime: String((r == null ? void 0 : r.createTime) ?? (s == null ? void 0 : s.createTime) ?? ""),
|
|
672
|
+
updateTime: String((r == null ? void 0 : r.updateTime) ?? (s == null ? void 0 : s.updateTime) ?? ""),
|
|
673
|
+
deployed: !((r == null ? void 0 : r.disabled) ?? !1)
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
/**
|
|
677
|
+
* 生成随机规则链 ID(12 位字母数字)
|
|
678
|
+
* @returns 生成的 ID
|
|
679
|
+
*/
|
|
680
|
+
static generateChainId() {
|
|
681
|
+
const e = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
682
|
+
let t = "";
|
|
683
|
+
for (let r = 0; r < 12; r++)
|
|
684
|
+
t += e.charAt(Math.floor(Math.random() * e.length));
|
|
685
|
+
return t;
|
|
686
|
+
}
|
|
687
|
+
// ============================================================
|
|
688
|
+
// WorkflowFetcher 接口实现
|
|
689
|
+
// ============================================================
|
|
690
|
+
/**
|
|
691
|
+
* 查询规则链列表(分页 + 搜索)
|
|
692
|
+
*
|
|
693
|
+
* @param page - 页码(从 1 开始)
|
|
694
|
+
* @param size - 每页条数
|
|
695
|
+
* @param keywords - 搜索关键词
|
|
696
|
+
* @param signal - 可选的取消信号
|
|
697
|
+
* @returns 分页结果
|
|
698
|
+
*/
|
|
699
|
+
async list(e = 1, t = 20, r = "", s) {
|
|
700
|
+
const o = new URLSearchParams({
|
|
701
|
+
page: String(e),
|
|
702
|
+
size: String(t)
|
|
703
|
+
});
|
|
704
|
+
r && o.set("keywords", r);
|
|
705
|
+
const n = await this.request(b(this.routes.list, o), { signal: s }, !1);
|
|
706
|
+
return $(n, v.parseRuleChain, e, t, { includeMetadata: !0, strict: !0 });
|
|
707
|
+
}
|
|
708
|
+
/**
|
|
709
|
+
* 分页读取全部规则链,供资源树和跨链搜索使用。
|
|
710
|
+
* 默认最多读取 100 页,避免错误的后端 total 或分页响应导致无限请求。
|
|
711
|
+
*/
|
|
712
|
+
async listAll(e = 100, t = "", r = 100) {
|
|
713
|
+
return (await this.listAllDetailed(e, t, r)).items;
|
|
714
|
+
}
|
|
715
|
+
async listAllDetailed(e = 100, t = "", r = 100) {
|
|
716
|
+
const s = Math.max(1, Math.min(1e3, Math.floor(Number.isFinite(e) ? e : 100))), o = Math.max(1, Math.min(1e3, Math.floor(Number.isFinite(r) ? r : 100))), n = [], a = /* @__PURE__ */ new Set();
|
|
717
|
+
let c = 0, u = null, p = !1;
|
|
718
|
+
for (let y = 1; y <= o; y += 1) {
|
|
719
|
+
const f = await this.list(y, s, t);
|
|
720
|
+
c = y, f.totalIsAuthoritative && (u = f.total);
|
|
721
|
+
for (const d of f.items)
|
|
722
|
+
a.has(d.id) || (a.add(d.id), n.push(d));
|
|
723
|
+
const l = Math.max(1, f.pageSize || s);
|
|
724
|
+
if (f.totalIsAuthoritative && n.length >= f.total) {
|
|
725
|
+
p = !0;
|
|
726
|
+
break;
|
|
727
|
+
}
|
|
728
|
+
if (f.items.length === 0 || f.items.length < l) {
|
|
729
|
+
p = !0;
|
|
730
|
+
break;
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
return { items: n, complete: p, pages: c, total: u, maxPages: o };
|
|
734
|
+
}
|
|
735
|
+
// ============================================================
|
|
736
|
+
// 共享节点管理
|
|
737
|
+
// ============================================================
|
|
738
|
+
async getSharedNodes(e = "", t = 1, r = 20, s, o) {
|
|
739
|
+
const n = new URLSearchParams({ keywords: e, page: String(t), size: String(r) });
|
|
740
|
+
s && n.set("type", s);
|
|
741
|
+
const a = this.routes.sharedNodes || m.sharedNodes, c = await this.request(b(a, n), { method: "GET", signal: o }, !1);
|
|
742
|
+
return $(c, (u) => u, t, r, { includeMetadata: !0, strict: !0 });
|
|
743
|
+
}
|
|
744
|
+
async getSharedNode(e, t, r) {
|
|
745
|
+
return this.request(this.resolveSharedNodePath(e, t), { method: "GET", signal: r });
|
|
746
|
+
}
|
|
747
|
+
async saveSharedNode(e, t, r, s) {
|
|
748
|
+
return this.request(this.resolveSharedNodePath(e, t), {
|
|
749
|
+
method: "POST",
|
|
750
|
+
body: JSON.stringify(r),
|
|
751
|
+
signal: s
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
async deleteSharedNode(e, t, r) {
|
|
755
|
+
return this.request(this.resolveSharedNodePath(e, t), { method: "DELETE", signal: r });
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* 创建规则链
|
|
759
|
+
*
|
|
760
|
+
* @param data - 规则链 DSL 数据
|
|
761
|
+
* @returns 操作结果
|
|
762
|
+
*/
|
|
763
|
+
async create(e, t = {}) {
|
|
764
|
+
try {
|
|
765
|
+
const r = this.resolveCreatePath(e), [s, o = ""] = r.split("?"), n = new URLSearchParams(o);
|
|
766
|
+
t.draft ? n.delete("versionMark") : n.set("versionMark", "1");
|
|
767
|
+
const a = n.toString(), c = `${s}${a ? `?${a}` : ""}`;
|
|
768
|
+
return { success: !0, data: await this.request(c, {
|
|
769
|
+
method: "POST",
|
|
770
|
+
body: JSON.stringify(e)
|
|
771
|
+
}) };
|
|
772
|
+
} catch (r) {
|
|
773
|
+
return { success: !1, msg: r.message };
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
/**
|
|
777
|
+
* 删除规则链
|
|
778
|
+
*
|
|
779
|
+
* @param id - 规则链 ID
|
|
780
|
+
* @returns 操作结果
|
|
781
|
+
*/
|
|
782
|
+
async remove(e) {
|
|
783
|
+
try {
|
|
784
|
+
return await this.request(this.routes.remove(e), { method: "DELETE" }), { success: !0 };
|
|
785
|
+
} catch (t) {
|
|
786
|
+
return { success: !1, msg: t.message };
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* 部署/下线规则链
|
|
791
|
+
*
|
|
792
|
+
* @param id - 规则链 ID
|
|
793
|
+
* @param type - 'start'(部署/启动)| 'stop'(下线)
|
|
794
|
+
* @returns 操作结果
|
|
795
|
+
*/
|
|
796
|
+
async operate(e, t) {
|
|
797
|
+
try {
|
|
798
|
+
return await this.request(this.routes.operate(e, t), { method: "POST" }), { success: !0 };
|
|
799
|
+
} catch (r) {
|
|
800
|
+
return { success: !1, msg: r.message };
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* 重启运行中的规则链。
|
|
805
|
+
*
|
|
806
|
+
* RuleGo 的 operate 接口只支持 start/stop。重启由服务端已保存 DSL
|
|
807
|
+
* 重新走一次保存加载流程触发,因此这里必须先 GET,再把该响应原样 POST
|
|
808
|
+
* 回同一规则链地址。调用方负责在 dirty 状态下先确认并保存编辑器草稿。
|
|
809
|
+
*/
|
|
810
|
+
async restart(e) {
|
|
811
|
+
try {
|
|
812
|
+
const t = await this.getContent(e), r = this.getRuleChainId(t);
|
|
813
|
+
if (r !== e)
|
|
814
|
+
throw new Error(`规则链重启响应 ID 不一致:期望 ${e},实际 ${r}`);
|
|
815
|
+
return await this.create(t, { draft: !0 });
|
|
816
|
+
} catch (t) {
|
|
817
|
+
return { success: !1, msg: t.message };
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* 复制规则链
|
|
822
|
+
*
|
|
823
|
+
* @description 获取完整内容 → 修改名称和 ID → 创建新的
|
|
824
|
+
* @param id - 原始规则链 ID
|
|
825
|
+
* @param newName - 新名称(不传则自动加 _副本)
|
|
826
|
+
* @returns 操作结果
|
|
827
|
+
*/
|
|
828
|
+
async copy(e, t) {
|
|
829
|
+
try {
|
|
830
|
+
const r = await this.getContent(e), s = (r == null ? void 0 : r.ruleChain) ?? r, o = String((s == null ? void 0 : s.name) ?? ""), n = v.generateChainId(), a = {
|
|
831
|
+
...r,
|
|
832
|
+
ruleChain: {
|
|
833
|
+
...s,
|
|
834
|
+
id: n,
|
|
835
|
+
name: t ?? `${o}_副本`
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
return this.create(a);
|
|
839
|
+
} catch (r) {
|
|
840
|
+
return { success: !1, msg: r.message };
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* 获取规则链完整内容(包含 metadata)
|
|
845
|
+
*
|
|
846
|
+
* @param id - 规则链 ID
|
|
847
|
+
* @param signal - 可选的取消信号
|
|
848
|
+
* @returns 完整的 RuleChain DSL
|
|
849
|
+
*/
|
|
850
|
+
async getContent(e, t) {
|
|
851
|
+
return this.request(this.routes.getContent(e), { signal: t });
|
|
852
|
+
}
|
|
853
|
+
/** 获取规则链内普通节点和 endpoint 的真实连接状态。 */
|
|
854
|
+
async getChainStatuses(e, t) {
|
|
855
|
+
const r = this.routes.status || m.status;
|
|
856
|
+
return this.request(r(e), { signal: t });
|
|
857
|
+
}
|
|
858
|
+
/** 获取共享节点真实连接状态。调用方负责按管理界面生命周期启停轮询。 */
|
|
859
|
+
async getSharedNodeStatuses(e) {
|
|
860
|
+
return this.request(this.routes.sharedNodeStatuses || m.sharedNodeStatuses, { signal: e });
|
|
861
|
+
}
|
|
862
|
+
/**
|
|
863
|
+
* 保存/更新规则链基础信息
|
|
864
|
+
*
|
|
865
|
+
* @param id - 规则链 ID
|
|
866
|
+
* @param info - 基础信息字段(name/description 等)
|
|
867
|
+
* @returns 操作结果
|
|
868
|
+
*/
|
|
869
|
+
async saveBaseInfo(e, t) {
|
|
870
|
+
try {
|
|
871
|
+
return await this.request(this.routes.saveBaseInfo(e), {
|
|
872
|
+
method: "POST",
|
|
873
|
+
body: JSON.stringify(t)
|
|
874
|
+
}), { success: !0 };
|
|
875
|
+
} catch (r) {
|
|
876
|
+
return { success: !1, msg: r.message };
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* 保存规则链配置(变量或秘钥)
|
|
881
|
+
*
|
|
882
|
+
* @param id - 规则链 ID
|
|
883
|
+
* @param configType - 'vars'(变量)| 'secrets'(秘钥)
|
|
884
|
+
* @param data - key-value 配置数据
|
|
885
|
+
* @returns 操作结果
|
|
886
|
+
*/
|
|
887
|
+
async saveConfig(e, t, r) {
|
|
888
|
+
try {
|
|
889
|
+
return await this.request(this.routes.saveConfig(e, t), {
|
|
890
|
+
method: "POST",
|
|
891
|
+
body: JSON.stringify(r)
|
|
892
|
+
}), { success: !0 };
|
|
893
|
+
} catch (s) {
|
|
894
|
+
return { success: !1, msg: s.message };
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
async validateUpstream(e, t, r) {
|
|
898
|
+
if (!this.routes.validateUpstream) throw new Error("Host route validateUpstream is not configured");
|
|
899
|
+
return this.request(this.routes.validateUpstream(e), {
|
|
900
|
+
method: "POST",
|
|
901
|
+
body: JSON.stringify({ chainId: e, dsl: t, ...r ? { options: r } : {} })
|
|
902
|
+
});
|
|
903
|
+
}
|
|
904
|
+
async getSchemaDiff(e) {
|
|
905
|
+
if (!this.routes.schemaDiff) throw new Error("Host route schemaDiff is not configured");
|
|
906
|
+
return this.request(this.routes.schemaDiff(e));
|
|
907
|
+
}
|
|
908
|
+
async getRepairPlan(e, t, r) {
|
|
909
|
+
if (!this.routes.repairPlan) throw new Error("Host route repairPlan is not configured");
|
|
910
|
+
return this.request(this.routes.repairPlan(e), {
|
|
911
|
+
method: "POST",
|
|
912
|
+
body: JSON.stringify({ chainId: e, dsl: t, ...r ? { options: r } : {} })
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
async previewPatch(e, t, r) {
|
|
916
|
+
if (!this.routes.patchPreview) throw new Error("Host route patchPreview is not configured");
|
|
917
|
+
return this.request(this.routes.patchPreview(e), {
|
|
918
|
+
method: "POST",
|
|
919
|
+
body: JSON.stringify({ chainId: e, dsl: t, operations: r })
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
// ============================================================
|
|
923
|
+
// P2 API: 消息投递 / 执行
|
|
924
|
+
// ============================================================
|
|
925
|
+
/**
|
|
926
|
+
* 异步消息通知(fire-and-forget)
|
|
927
|
+
*
|
|
928
|
+
* @param chainId - 规则链 ID
|
|
929
|
+
* @param msgType - 消息类型
|
|
930
|
+
* @param body - 消息体
|
|
931
|
+
*/
|
|
932
|
+
async notifyRule(e, t, r = {}) {
|
|
933
|
+
const o = (this.routes.notifyRule || m.notifyRule)(e, t), n = L(r);
|
|
934
|
+
await this.request(b(o, n.query), {
|
|
935
|
+
...r.config,
|
|
936
|
+
method: "POST",
|
|
937
|
+
body: n.body
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* 同步执行规则链(不带调试标志)
|
|
942
|
+
*
|
|
943
|
+
* @param chainId - 规则链 ID
|
|
944
|
+
* @param msgType - 消息类型
|
|
945
|
+
* @param body - 消息体
|
|
946
|
+
* @returns 执行结果
|
|
947
|
+
*/
|
|
948
|
+
async executeRule(e, t, r = {}) {
|
|
949
|
+
const o = (this.routes.executeRule || m.executeRule)(e, t), n = L(r);
|
|
950
|
+
return this.request(b(o, n.query), {
|
|
951
|
+
...r.config,
|
|
952
|
+
method: "POST",
|
|
953
|
+
body: n.body
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
// ============================================================
|
|
957
|
+
// P2 API: 扩展列表过滤 + 分类
|
|
958
|
+
// ============================================================
|
|
959
|
+
/**
|
|
960
|
+
* 查询规则链列表(扩展过滤参数)
|
|
961
|
+
*
|
|
962
|
+
* @param options - 过滤参数(page, size, keywords, root, disabled, category)
|
|
963
|
+
* @returns 分页结果
|
|
964
|
+
*/
|
|
965
|
+
async listFiltered(e = {}, t) {
|
|
966
|
+
const { page: r = 1, size: s = 20, keywords: o, root: n, disabled: a, category: c } = e, u = new URLSearchParams({
|
|
967
|
+
page: String(r),
|
|
968
|
+
size: String(s)
|
|
969
|
+
});
|
|
970
|
+
o && u.set("keywords", o), n !== void 0 && u.set("root", String(n)), a !== void 0 && u.set("disabled", String(a)), c && u.set("category", c);
|
|
971
|
+
const p = await this.request(b(this.routes.list, u), { signal: t }, !1);
|
|
972
|
+
return $(p, v.parseRuleChain, r, s, { includeMetadata: !0, strict: !0 });
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* 获取规则链分类列表
|
|
976
|
+
*
|
|
977
|
+
* @returns 分类名称数组
|
|
978
|
+
*/
|
|
979
|
+
async getRuleCategories(e) {
|
|
980
|
+
const t = this.routes.ruleCategories || m.ruleCategories, r = await this.request(t, { signal: e }, !1);
|
|
981
|
+
return $(r, (s) => {
|
|
982
|
+
if (typeof s != "string") throw new Error("Invalid rule category response: expected a string");
|
|
983
|
+
return s;
|
|
984
|
+
}, 1, 20, { strict: !0 }).items;
|
|
985
|
+
}
|
|
986
|
+
// ============================================================
|
|
987
|
+
// P2 API: 调试数据 / 运行历史
|
|
988
|
+
// ============================================================
|
|
989
|
+
/**
|
|
990
|
+
* 获取调试数据
|
|
991
|
+
*
|
|
992
|
+
* @param chainId - 规则链 ID
|
|
993
|
+
* @param nodeId - 可选节点 ID
|
|
994
|
+
* @param page - 页码
|
|
995
|
+
* @param size - 每页条数
|
|
996
|
+
* @returns 调试数据列表
|
|
997
|
+
*/
|
|
998
|
+
async getDebugData(e, t, r, s, o) {
|
|
999
|
+
const n = this.routes.debugData || m.debugData, a = new URLSearchParams({ chainId: e });
|
|
1000
|
+
t && a.set("nodeId", t), r !== void 0 && a.set("page", String(r)), s !== void 0 && a.set("size", String(s));
|
|
1001
|
+
const c = await this.request(b(n, a), { signal: o }, !1);
|
|
1002
|
+
return $(c, (u) => u, r, s, { strict: !0 }).items;
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* 获取运行记录列表
|
|
1006
|
+
*
|
|
1007
|
+
* @param chainId - 规则链 ID
|
|
1008
|
+
* @param options - 查询参数
|
|
1009
|
+
* @returns 分页运行记录
|
|
1010
|
+
*/
|
|
1011
|
+
async getRunsList(e, t = {}, r) {
|
|
1012
|
+
const s = this.routes.runsList || m.runsList, { page: o = 1, size: n = 20, status: a, msgType: c, source: u } = t, p = t.startTime ?? t.startDate, y = t.endTime ?? t.endDate, f = new URLSearchParams({
|
|
1013
|
+
chainId: e,
|
|
1014
|
+
page: String(o),
|
|
1015
|
+
size: String(n)
|
|
1016
|
+
});
|
|
1017
|
+
a && f.set("status", a), c && f.set("msgType", c), u && f.set("source", u), p !== void 0 && f.set("startTime", String(p)), y !== void 0 && f.set("endTime", String(y));
|
|
1018
|
+
const l = await this.request(b(s, f), { signal: r }, !1);
|
|
1019
|
+
return $(l, (d) => d, o, n, { includeMetadata: !0, strict: !0 });
|
|
1020
|
+
}
|
|
1021
|
+
/** 获取单次运行的完整记录,复用 /logs/runs 的 chainId + id 查询。 */
|
|
1022
|
+
async getRuns(e, t, r) {
|
|
1023
|
+
if (!e.trim() || !t.trim()) throw new Error("chainId and run id must not be empty");
|
|
1024
|
+
const s = this.routes.runsList || m.runsList, o = await this.request(b(s, new URLSearchParams({ chainId: e, id: t })), { method: "GET", signal: r }, !1), n = (o == null ? void 0 : o.id) === t && !("code" in o) && !("data" in o) ? o : E(o);
|
|
1025
|
+
if (!n || typeof n != "object" || Array.isArray(n)) throw new Error("Invalid run detail response");
|
|
1026
|
+
return n;
|
|
1027
|
+
}
|
|
1028
|
+
/**
|
|
1029
|
+
* 删除运行记录
|
|
1030
|
+
*
|
|
1031
|
+
* @param chainId - 规则链 ID
|
|
1032
|
+
* @param ids - 单个 ID 或逐条删除的 ID 数组;省略或空字符串清空全部,空数组不发请求
|
|
1033
|
+
*/
|
|
1034
|
+
async deleteRuns(e, t, r) {
|
|
1035
|
+
if (!e.trim()) throw new Error("chainId must not be empty");
|
|
1036
|
+
if (t !== void 0 && typeof t != "string" && !Array.isArray(t)) throw new Error("Invalid run ids");
|
|
1037
|
+
const s = this.routes.runsList || m.runsList, o = Array.isArray(t) ? [...t] : [t ?? ""];
|
|
1038
|
+
if (o.some((n) => typeof n != "string" || !n.trim() && (Array.isArray(t) || n !== "")))
|
|
1039
|
+
throw new Error("run ids must not contain empty values");
|
|
1040
|
+
for (const n of o)
|
|
1041
|
+
await this.request(b(s, new URLSearchParams({ chainId: e, id: n })), {
|
|
1042
|
+
method: "DELETE",
|
|
1043
|
+
signal: r
|
|
1044
|
+
});
|
|
1045
|
+
}
|
|
1046
|
+
// ============================================================
|
|
1047
|
+
// P2 API: 动态组件管理
|
|
1048
|
+
// ============================================================
|
|
1049
|
+
/**
|
|
1050
|
+
* 获取动态组件 DSL
|
|
1051
|
+
*
|
|
1052
|
+
* @param nodeType - 组件类型标识
|
|
1053
|
+
* @returns 组件 DSL 定义
|
|
1054
|
+
*/
|
|
1055
|
+
async getComponentDSL(e, t) {
|
|
1056
|
+
const r = this.routes.dynamicComponent || m.dynamicComponent;
|
|
1057
|
+
return this.request(r(e), { method: "GET", signal: t });
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* 安装/更新动态组件
|
|
1061
|
+
*
|
|
1062
|
+
* @param nodeType - 组件类型标识
|
|
1063
|
+
* @param dsl - 组件 DSL 定义
|
|
1064
|
+
*/
|
|
1065
|
+
async installComponent(e, t, r) {
|
|
1066
|
+
const s = this.routes.dynamicComponent || m.dynamicComponent;
|
|
1067
|
+
await this.request(s(e), {
|
|
1068
|
+
method: "POST",
|
|
1069
|
+
body: JSON.stringify(t),
|
|
1070
|
+
signal: r
|
|
1071
|
+
});
|
|
1072
|
+
}
|
|
1073
|
+
/**
|
|
1074
|
+
* 卸载动态组件
|
|
1075
|
+
*
|
|
1076
|
+
* @param nodeType - 组件类型标识
|
|
1077
|
+
*/
|
|
1078
|
+
async uninstallComponent(e, t) {
|
|
1079
|
+
const r = this.routes.dynamicComponent || m.dynamicComponent;
|
|
1080
|
+
await this.request(r(e), {
|
|
1081
|
+
method: "DELETE",
|
|
1082
|
+
signal: t
|
|
1083
|
+
});
|
|
1084
|
+
}
|
|
1085
|
+
// ============================================================
|
|
1086
|
+
// P2 API: 内置组件运行时查询
|
|
1087
|
+
// ============================================================
|
|
1088
|
+
/**
|
|
1089
|
+
* 动态查询内置组件运行时数据(如 OPC UA 在线浏览)
|
|
1090
|
+
*
|
|
1091
|
+
* @param name - 内置组件名称
|
|
1092
|
+
* @param params - 查询参数
|
|
1093
|
+
* @returns 查询结果
|
|
1094
|
+
*/
|
|
1095
|
+
async queryDynamicBuiltin(e, t, r) {
|
|
1096
|
+
const s = this.routes.queryDynamicBuiltin || m.queryDynamicBuiltin;
|
|
1097
|
+
return this.request(s(e), {
|
|
1098
|
+
method: "POST",
|
|
1099
|
+
body: JSON.stringify(t ?? {}),
|
|
1100
|
+
signal: r
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
1103
|
+
// ============================================================
|
|
1104
|
+
// 实用方法
|
|
1105
|
+
// ============================================================
|
|
1106
|
+
/**
|
|
1107
|
+
* 获取当前 API 基础地址
|
|
1108
|
+
* @returns apiBase
|
|
1109
|
+
*/
|
|
1110
|
+
getApiBase() {
|
|
1111
|
+
return this.apiBase;
|
|
1112
|
+
}
|
|
1113
|
+
async getLocales(e) {
|
|
1114
|
+
const t = new URL(this.routes.list, "http://route.invalid");
|
|
1115
|
+
return t.pathname = `${t.pathname.replace(/\/rules\/?$/, "").replace(/\/+$/, "")}/locales`, e && t.searchParams.set("lang", e), this.request(`${t.pathname}${t.search}`);
|
|
1116
|
+
}
|
|
1117
|
+
async getLocalesCached(e) {
|
|
1118
|
+
const t = `rulego:locales:${this.apiBase}:${e || ""}`, r = 24 * 60 * 60 * 1e3;
|
|
1119
|
+
if (typeof localStorage < "u")
|
|
1120
|
+
try {
|
|
1121
|
+
const o = localStorage.getItem(t);
|
|
1122
|
+
if (o) {
|
|
1123
|
+
const n = JSON.parse(o);
|
|
1124
|
+
if (Date.now() - n.ts < r) return n.data;
|
|
1125
|
+
}
|
|
1126
|
+
} catch {
|
|
1127
|
+
}
|
|
1128
|
+
const s = await this.getLocales(e);
|
|
1129
|
+
if (typeof localStorage < "u")
|
|
1130
|
+
try {
|
|
1131
|
+
localStorage.setItem(t, JSON.stringify({ ts: Date.now(), data: s }));
|
|
1132
|
+
} catch {
|
|
1133
|
+
}
|
|
1134
|
+
return s;
|
|
1135
|
+
}
|
|
1136
|
+
getChatCompletionsUrl(e) {
|
|
1137
|
+
const t = e || v.RULE_CHAIN_ASSISTANT_ID;
|
|
1138
|
+
return `${this.apiBase}/rules/${encodeURIComponent(t)}/v1/chat/completions`;
|
|
1139
|
+
}
|
|
1140
|
+
};
|
|
1141
|
+
v.RULE_CHAIN_ASSISTANT_ID = "_assistant";
|
|
1142
|
+
let B = v;
|
|
1143
|
+
export {
|
|
1144
|
+
X as A,
|
|
1145
|
+
m as D,
|
|
1146
|
+
B as R,
|
|
1147
|
+
J as S,
|
|
1148
|
+
ie as a,
|
|
1149
|
+
H as b,
|
|
1150
|
+
ne as c,
|
|
1151
|
+
Q as d,
|
|
1152
|
+
R as e,
|
|
1153
|
+
ce as f,
|
|
1154
|
+
ae as g,
|
|
1155
|
+
q as h,
|
|
1156
|
+
oe as n
|
|
1157
|
+
};
|