@nocobase/plugin-flow-engine 2.0.60 → 2.0.62
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/dist/externalVersion.js +10 -10
- package/dist/node_modules/ses/package.json +1 -1
- package/dist/node_modules/zod/package.json +1 -1
- package/dist/server/repository.d.ts +15 -1
- package/dist/server/repository.js +262 -23
- package/dist/server/template/contexts.d.ts +2 -0
- package/dist/server/template/contexts.js +34 -0
- package/dist/server/template/resolver.js +233 -22
- package/package.json +2 -2
package/dist/externalVersion.js
CHANGED
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
module.exports = {
|
|
11
|
-
"@nocobase/client": "2.0.
|
|
11
|
+
"@nocobase/client": "2.0.62",
|
|
12
12
|
"lodash": "4.18.1",
|
|
13
|
-
"@nocobase/database": "2.0.
|
|
14
|
-
"@nocobase/data-source-manager": "2.0.
|
|
15
|
-
"@nocobase/resourcer": "2.0.
|
|
16
|
-
"@nocobase/utils": "2.0.
|
|
17
|
-
"@nocobase/cache": "2.0.
|
|
18
|
-
"@nocobase/plugin-localization": "2.0.
|
|
19
|
-
"@nocobase/server": "2.0.
|
|
20
|
-
"@nocobase/ai": "2.0.
|
|
21
|
-
"@nocobase/actions": "2.0.
|
|
13
|
+
"@nocobase/database": "2.0.62",
|
|
14
|
+
"@nocobase/data-source-manager": "2.0.62",
|
|
15
|
+
"@nocobase/resourcer": "2.0.62",
|
|
16
|
+
"@nocobase/utils": "2.0.62",
|
|
17
|
+
"@nocobase/cache": "2.0.62",
|
|
18
|
+
"@nocobase/plugin-localization": "2.0.62",
|
|
19
|
+
"@nocobase/server": "2.0.62",
|
|
20
|
+
"@nocobase/ai": "2.0.62",
|
|
21
|
+
"@nocobase/actions": "2.0.62"
|
|
22
22
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"ses","version":"1.14.0","description":"Hardened JavaScript for Fearless Cooperation","keywords":["lockdown","harden","Compartment","assert","security","confinement","isolation","object capabilities","ocaps","secure execution","third-party code","prototype pollution","supply-chain attack","plugin"],"author":"Agoric","license":"Apache-2.0","homepage":"https://github.com/Agoric/SES-shim/tree/master/packages/ses#readme","repository":{"type":"git","url":"git+https://github.com/endojs/endo.git","directory":"packages/ses"},"bugs":{"url":"https://github.com/endojs/endo/issues"},"type":"module","main":"./dist/ses.cjs","module":"./index.js","unpkg":"./dist/ses.umd.js","types":"./types.d.ts","exports":{".":{"import":{"types":"./types.d.ts","xs":"./src-xs/index.js","default":"./index.js"},"require":{"types":"./dist/types.d.cts","default":"./dist/ses.cjs"}},"./lockdown":{"import":{"types":"./types.d.ts","default":"./index.js"},"require":{"types":"./dist/types.d.cts","default":"./dist/ses.cjs"}},"./hermes":{"require":{"types":"./dist/types.d.cts","default":"./dist/ses-hermes.cjs"}},"./tools.js":"./tools.js","./assert-shim.js":"./assert-shim.js","./lockdown-shim.js":{"xs":"./src-xs/lockdown-shim.js","default":"./lockdown-shim.js"},"./compartment-shim.js":{"xs":"./src-xs/compartment-shim.js","default":"./compartment-shim.js"},"./console-shim.js":"./console-shim.js","./package.json":"./package.json"},"scripts":{"build:vanilla":"node scripts/bundle.js","build:hermes":"node scripts/bundle.js hermes","build":"yarn build:vanilla && yarn build:hermes","clean":"rm -rf dist","cover":"c8 ava","demo":"python3 -m http.server","lint":"yarn lint:types && yarn lint:eslint","lint-fix":"eslint --fix .","lint:eslint":"eslint .","lint:types":"tsc","prepare":"npm run clean && npm run build","qt":"ava","test":"tsd && ava","test:hermes":"./scripts/hermes-test.sh","test:xs":"xst dist/ses.umd.js test/_lockdown-safe.js && node scripts/generate-test-xs.js && xst tmp/test-xs.js && rm -rf tmp","postpack":"git clean -fX \"*.d.ts*\" \"*.d.cts*\" \"*.d.mts*\" \"*.tsbuildinfo\""},"dependencies":{"@endo/cache-map":"^1.1.0","@endo/env-options":"^1.1.11","@endo/immutable-arraybuffer":"^1.1.2"},"devDependencies":{"@babel/generator":"^7.26.3","@babel/parser":"~7.26.2","@babel/traverse":"~7.25.9","@babel/types":"~7.26.0","@endo/compartment-mapper":"^1.6.3","@endo/module-source":"^1.3.3","@endo/test262-runner":"^0.1.48","@types/babel__traverse":"^7.20.5","ava":"^6.1.3","babel-eslint":"^10.1.0","c8":"^7.14.0","core-js":"^3.31.0","eslint":"^8.57.1","eslint-config-airbnb-base":"^15.0.0","eslint-config-prettier":"^9.1.0","eslint-plugin-eslint-comments":"^3.2.0","eslint-plugin-import":"^2.31.0","hermes-engine-cli":"^0.12.0","prettier":"^3.5.3","terser":"^5.16.6","tsd":"^0.31.2","typescript":"~5.8.3"},"files":["./*.d.ts","./*.js","./*.map","LICENSE*","SECURITY*","dist","lib","src","tools"],"publishConfig":{"access":"public"},"eslintConfig":{"extends":["plugin:@endo/ses"]},"ava":{"files":["test/**/*.test.*"],"timeout":"2m"},"typeCoverage":{"atLeast":81.17},"gitHead":"9815aea9541f241389d2135c6097a7442bdffa17","_lastModified":"2026-
|
|
1
|
+
{"name":"ses","version":"1.14.0","description":"Hardened JavaScript for Fearless Cooperation","keywords":["lockdown","harden","Compartment","assert","security","confinement","isolation","object capabilities","ocaps","secure execution","third-party code","prototype pollution","supply-chain attack","plugin"],"author":"Agoric","license":"Apache-2.0","homepage":"https://github.com/Agoric/SES-shim/tree/master/packages/ses#readme","repository":{"type":"git","url":"git+https://github.com/endojs/endo.git","directory":"packages/ses"},"bugs":{"url":"https://github.com/endojs/endo/issues"},"type":"module","main":"./dist/ses.cjs","module":"./index.js","unpkg":"./dist/ses.umd.js","types":"./types.d.ts","exports":{".":{"import":{"types":"./types.d.ts","xs":"./src-xs/index.js","default":"./index.js"},"require":{"types":"./dist/types.d.cts","default":"./dist/ses.cjs"}},"./lockdown":{"import":{"types":"./types.d.ts","default":"./index.js"},"require":{"types":"./dist/types.d.cts","default":"./dist/ses.cjs"}},"./hermes":{"require":{"types":"./dist/types.d.cts","default":"./dist/ses-hermes.cjs"}},"./tools.js":"./tools.js","./assert-shim.js":"./assert-shim.js","./lockdown-shim.js":{"xs":"./src-xs/lockdown-shim.js","default":"./lockdown-shim.js"},"./compartment-shim.js":{"xs":"./src-xs/compartment-shim.js","default":"./compartment-shim.js"},"./console-shim.js":"./console-shim.js","./package.json":"./package.json"},"scripts":{"build:vanilla":"node scripts/bundle.js","build:hermes":"node scripts/bundle.js hermes","build":"yarn build:vanilla && yarn build:hermes","clean":"rm -rf dist","cover":"c8 ava","demo":"python3 -m http.server","lint":"yarn lint:types && yarn lint:eslint","lint-fix":"eslint --fix .","lint:eslint":"eslint .","lint:types":"tsc","prepare":"npm run clean && npm run build","qt":"ava","test":"tsd && ava","test:hermes":"./scripts/hermes-test.sh","test:xs":"xst dist/ses.umd.js test/_lockdown-safe.js && node scripts/generate-test-xs.js && xst tmp/test-xs.js && rm -rf tmp","postpack":"git clean -fX \"*.d.ts*\" \"*.d.cts*\" \"*.d.mts*\" \"*.tsbuildinfo\""},"dependencies":{"@endo/cache-map":"^1.1.0","@endo/env-options":"^1.1.11","@endo/immutable-arraybuffer":"^1.1.2"},"devDependencies":{"@babel/generator":"^7.26.3","@babel/parser":"~7.26.2","@babel/traverse":"~7.25.9","@babel/types":"~7.26.0","@endo/compartment-mapper":"^1.6.3","@endo/module-source":"^1.3.3","@endo/test262-runner":"^0.1.48","@types/babel__traverse":"^7.20.5","ava":"^6.1.3","babel-eslint":"^10.1.0","c8":"^7.14.0","core-js":"^3.31.0","eslint":"^8.57.1","eslint-config-airbnb-base":"^15.0.0","eslint-config-prettier":"^9.1.0","eslint-plugin-eslint-comments":"^3.2.0","eslint-plugin-import":"^2.31.0","hermes-engine-cli":"^0.12.0","prettier":"^3.5.3","terser":"^5.16.6","tsd":"^0.31.2","typescript":"~5.8.3"},"files":["./*.d.ts","./*.js","./*.map","LICENSE*","SECURITY*","dist","lib","src","tools"],"publishConfig":{"access":"public"},"eslintConfig":{"extends":["plugin:@endo/ses"]},"ava":{"files":["test/**/*.test.*"],"timeout":"2m"},"typeCoverage":{"atLeast":81.17},"gitHead":"9815aea9541f241389d2135c6097a7442bdffa17","_lastModified":"2026-06-10T17:41:35.706Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"zod","version":"4.3.5","type":"module","license":"MIT","author":"Colin McDonnell <zod@colinhacks.com>","description":"TypeScript-first schema declaration and validation library with static type inference","homepage":"https://zod.dev","llms":"https://zod.dev/llms.txt","llmsFull":"https://zod.dev/llms-full.txt","mcpServer":"https://mcp.inkeep.com/zod/mcp","funding":"https://github.com/sponsors/colinhacks","sideEffects":false,"files":["src","**/*.js","**/*.mjs","**/*.cjs","**/*.d.ts","**/*.d.mts","**/*.d.cts","**/package.json"],"keywords":["typescript","schema","validation","type","inference"],"main":"./index.cjs","types":"./index.d.cts","module":"./index.js","zshy":{"exports":{"./package.json":"./package.json",".":"./src/index.ts","./mini":"./src/mini/index.ts","./locales":"./src/locales/index.ts","./v3":"./src/v3/index.ts","./v4":"./src/v4/index.ts","./v4-mini":"./src/v4-mini/index.ts","./v4/mini":"./src/v4/mini/index.ts","./v4/core":"./src/v4/core/index.ts","./v4/locales":"./src/v4/locales/index.ts","./v4/locales/*":"./src/v4/locales/*"},"conditions":{"@zod/source":"src"}},"exports":{"./package.json":"./package.json",".":{"@zod/source":"./src/index.ts","types":"./index.d.cts","import":"./index.js","require":"./index.cjs"},"./mini":{"@zod/source":"./src/mini/index.ts","types":"./mini/index.d.cts","import":"./mini/index.js","require":"./mini/index.cjs"},"./locales":{"@zod/source":"./src/locales/index.ts","types":"./locales/index.d.cts","import":"./locales/index.js","require":"./locales/index.cjs"},"./v3":{"@zod/source":"./src/v3/index.ts","types":"./v3/index.d.cts","import":"./v3/index.js","require":"./v3/index.cjs"},"./v4":{"@zod/source":"./src/v4/index.ts","types":"./v4/index.d.cts","import":"./v4/index.js","require":"./v4/index.cjs"},"./v4-mini":{"@zod/source":"./src/v4-mini/index.ts","types":"./v4-mini/index.d.cts","import":"./v4-mini/index.js","require":"./v4-mini/index.cjs"},"./v4/mini":{"@zod/source":"./src/v4/mini/index.ts","types":"./v4/mini/index.d.cts","import":"./v4/mini/index.js","require":"./v4/mini/index.cjs"},"./v4/core":{"@zod/source":"./src/v4/core/index.ts","types":"./v4/core/index.d.cts","import":"./v4/core/index.js","require":"./v4/core/index.cjs"},"./v4/locales":{"@zod/source":"./src/v4/locales/index.ts","types":"./v4/locales/index.d.cts","import":"./v4/locales/index.js","require":"./v4/locales/index.cjs"},"./v4/locales/*":{"@zod/source":"./src/v4/locales/*","types":"./v4/locales/*","import":"./v4/locales/*","require":"./v4/locales/*"}},"repository":{"type":"git","url":"git+https://github.com/colinhacks/zod.git"},"bugs":{"url":"https://github.com/colinhacks/zod/issues"},"support":{"backing":{"npm-funding":true}},"scripts":{"clean":"git clean -xdf . -e node_modules","build":"zshy --project tsconfig.build.json","postbuild":"tsx ../../scripts/write-stub-package-jsons.ts && pnpm biome check --write .","test:watch":"pnpm vitest","test":"pnpm vitest run","prepublishOnly":"tsx ../../scripts/check-versions.ts"},"_lastModified":"2026-
|
|
1
|
+
{"name":"zod","version":"4.3.5","type":"module","license":"MIT","author":"Colin McDonnell <zod@colinhacks.com>","description":"TypeScript-first schema declaration and validation library with static type inference","homepage":"https://zod.dev","llms":"https://zod.dev/llms.txt","llmsFull":"https://zod.dev/llms-full.txt","mcpServer":"https://mcp.inkeep.com/zod/mcp","funding":"https://github.com/sponsors/colinhacks","sideEffects":false,"files":["src","**/*.js","**/*.mjs","**/*.cjs","**/*.d.ts","**/*.d.mts","**/*.d.cts","**/package.json"],"keywords":["typescript","schema","validation","type","inference"],"main":"./index.cjs","types":"./index.d.cts","module":"./index.js","zshy":{"exports":{"./package.json":"./package.json",".":"./src/index.ts","./mini":"./src/mini/index.ts","./locales":"./src/locales/index.ts","./v3":"./src/v3/index.ts","./v4":"./src/v4/index.ts","./v4-mini":"./src/v4-mini/index.ts","./v4/mini":"./src/v4/mini/index.ts","./v4/core":"./src/v4/core/index.ts","./v4/locales":"./src/v4/locales/index.ts","./v4/locales/*":"./src/v4/locales/*"},"conditions":{"@zod/source":"src"}},"exports":{"./package.json":"./package.json",".":{"@zod/source":"./src/index.ts","types":"./index.d.cts","import":"./index.js","require":"./index.cjs"},"./mini":{"@zod/source":"./src/mini/index.ts","types":"./mini/index.d.cts","import":"./mini/index.js","require":"./mini/index.cjs"},"./locales":{"@zod/source":"./src/locales/index.ts","types":"./locales/index.d.cts","import":"./locales/index.js","require":"./locales/index.cjs"},"./v3":{"@zod/source":"./src/v3/index.ts","types":"./v3/index.d.cts","import":"./v3/index.js","require":"./v3/index.cjs"},"./v4":{"@zod/source":"./src/v4/index.ts","types":"./v4/index.d.cts","import":"./v4/index.js","require":"./v4/index.cjs"},"./v4-mini":{"@zod/source":"./src/v4-mini/index.ts","types":"./v4-mini/index.d.cts","import":"./v4-mini/index.js","require":"./v4-mini/index.cjs"},"./v4/mini":{"@zod/source":"./src/v4/mini/index.ts","types":"./v4/mini/index.d.cts","import":"./v4/mini/index.js","require":"./v4/mini/index.cjs"},"./v4/core":{"@zod/source":"./src/v4/core/index.ts","types":"./v4/core/index.d.cts","import":"./v4/core/index.js","require":"./v4/core/index.cjs"},"./v4/locales":{"@zod/source":"./src/v4/locales/index.ts","types":"./v4/locales/index.d.cts","import":"./v4/locales/index.js","require":"./v4/locales/index.cjs"},"./v4/locales/*":{"@zod/source":"./src/v4/locales/*","types":"./v4/locales/*","import":"./v4/locales/*","require":"./v4/locales/*"}},"repository":{"type":"git","url":"git+https://github.com/colinhacks/zod.git"},"bugs":{"url":"https://github.com/colinhacks/zod/issues"},"support":{"backing":{"npm-funding":true}},"scripts":{"clean":"git clean -xdf . -e node_modules","build":"zshy --project tsconfig.build.json","postbuild":"tsx ../../scripts/write-stub-package-jsons.ts && pnpm biome check --write .","test:watch":"pnpm vitest","test":"pnpm vitest run","prepublishOnly":"tsx ../../scripts/check-versions.ts"},"_lastModified":"2026-06-10T17:41:35.192Z"}
|
|
@@ -25,6 +25,12 @@ export interface FlowModelAttachOptions {
|
|
|
25
25
|
subType: 'array' | 'object';
|
|
26
26
|
position?: FlowModelAttachPosition;
|
|
27
27
|
}
|
|
28
|
+
type FlowModelMovePosition = 'before' | 'after';
|
|
29
|
+
interface FlowModelMoveOptions {
|
|
30
|
+
sourceId: string;
|
|
31
|
+
targetId: string;
|
|
32
|
+
position?: FlowModelMovePosition;
|
|
33
|
+
}
|
|
28
34
|
type BreakRemoveOnType = {
|
|
29
35
|
[key: string]: any;
|
|
30
36
|
};
|
|
@@ -59,6 +65,8 @@ export declare class FlowModelRepository extends Repository {
|
|
|
59
65
|
getParentProperty(uid: string, options?: GetPropertiesOptions): Promise<any>;
|
|
60
66
|
getJsonSchema(uid: string, options?: GetJsonSchemaOptions): Promise<any>;
|
|
61
67
|
static optionsToJson(options: any): any;
|
|
68
|
+
private static getSortNumber;
|
|
69
|
+
private static compareBySortAndUid;
|
|
62
70
|
nodesToSchema(nodes: any, rootUid: any): {
|
|
63
71
|
uid: any;
|
|
64
72
|
"x-async": boolean;
|
|
@@ -90,6 +98,12 @@ export declare class FlowModelRepository extends Repository {
|
|
|
90
98
|
protected childrenCount(uid: any, transaction: any): Promise<number>;
|
|
91
99
|
protected isLeafNode(uid: any, transaction: any): Promise<boolean>;
|
|
92
100
|
protected findParentUid(uid: any, transaction?: any): Promise<string>;
|
|
101
|
+
private findSiblingInfo;
|
|
102
|
+
private findSiblingSortRows;
|
|
103
|
+
private writeSiblingSorts;
|
|
104
|
+
private normalizeSiblingSorts;
|
|
105
|
+
private isAncestorOf;
|
|
106
|
+
private updateModelParentOptions;
|
|
93
107
|
protected findNodeSchemaWithParent(uid: any, transaction: any): Promise<{
|
|
94
108
|
parentUid: string;
|
|
95
109
|
schema: any;
|
|
@@ -122,6 +136,6 @@ export declare class FlowModelRepository extends Repository {
|
|
|
122
136
|
subKey?: string;
|
|
123
137
|
}): Promise<any>;
|
|
124
138
|
attach(uid: string, attachOptions: FlowModelAttachOptions, options?: Transactionable): Promise<any>;
|
|
125
|
-
move(options:
|
|
139
|
+
move(options: FlowModelMoveOptions, transactionOptions?: Transactionable): Promise<any>;
|
|
126
140
|
}
|
|
127
141
|
export default FlowModelRepository;
|
|
@@ -207,6 +207,32 @@ const _FlowModelRepository = class _FlowModelRepository extends import_database.
|
|
|
207
207
|
static optionsToJson(options) {
|
|
208
208
|
return import_lodash.default.isPlainObject(options) ? options : JSON.parse(options);
|
|
209
209
|
}
|
|
210
|
+
static getSortNumber(value) {
|
|
211
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
212
|
+
return value;
|
|
213
|
+
}
|
|
214
|
+
if (typeof value === "string" && value.trim()) {
|
|
215
|
+
const parsed = Number(value);
|
|
216
|
+
if (Number.isFinite(parsed)) {
|
|
217
|
+
return parsed;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
static compareBySortAndUid(a, b) {
|
|
223
|
+
const aSort = _FlowModelRepository.getSortNumber(a.sort);
|
|
224
|
+
const bSort = _FlowModelRepository.getSortNumber(b.sort);
|
|
225
|
+
if (aSort !== null && bSort !== null && aSort !== bSort) {
|
|
226
|
+
return aSort - bSort;
|
|
227
|
+
}
|
|
228
|
+
if (aSort !== null && bSort === null) {
|
|
229
|
+
return -1;
|
|
230
|
+
}
|
|
231
|
+
if (aSort === null && bSort !== null) {
|
|
232
|
+
return 1;
|
|
233
|
+
}
|
|
234
|
+
return String(a.uid || "").localeCompare(String(b.uid || ""));
|
|
235
|
+
}
|
|
210
236
|
nodesToSchema(nodes, rootUid) {
|
|
211
237
|
const nodeAttributeSanitize = (node) => {
|
|
212
238
|
const schema = {
|
|
@@ -215,8 +241,9 @@ const _FlowModelRepository = class _FlowModelRepository extends import_database.
|
|
|
215
241
|
["uid"]: node["uid"],
|
|
216
242
|
["x-async"]: !!node.async
|
|
217
243
|
};
|
|
218
|
-
|
|
219
|
-
|
|
244
|
+
const sort = _FlowModelRepository.getSortNumber(node.sort);
|
|
245
|
+
if (sort !== null) {
|
|
246
|
+
schema["x-index"] = sort;
|
|
220
247
|
}
|
|
221
248
|
return schema;
|
|
222
249
|
};
|
|
@@ -228,7 +255,12 @@ const _FlowModelRepository = class _FlowModelRepository extends import_database.
|
|
|
228
255
|
if (children.length > 0) {
|
|
229
256
|
const childrenGroupByType = import_lodash.default.groupBy(children, "type");
|
|
230
257
|
for (const childType of Object.keys(childrenGroupByType)) {
|
|
231
|
-
const properties = childrenGroupByType[childType].map((child) => buildTree(child)).sort(
|
|
258
|
+
const properties = childrenGroupByType[childType].map((child) => buildTree(child)).sort(
|
|
259
|
+
(a, b) => _FlowModelRepository.compareBySortAndUid(
|
|
260
|
+
{ sort: a["x-index"], uid: a.uid },
|
|
261
|
+
{ sort: b["x-index"], uid: b.uid }
|
|
262
|
+
)
|
|
263
|
+
);
|
|
232
264
|
rootNode[childType] = childType == "items" ? properties.length == 1 ? properties[0] : properties : properties.reduce((carry, item) => {
|
|
233
265
|
carry[item.name] = item;
|
|
234
266
|
delete item["name"];
|
|
@@ -289,7 +321,10 @@ const _FlowModelRepository = class _FlowModelRepository extends import_database.
|
|
|
289
321
|
await this.clearXUidPathCache(rootUid, transaction2);
|
|
290
322
|
if (!newSchema["properties"]) {
|
|
291
323
|
const s = await this.model.findByPk(rootUid, { transaction: transaction2 });
|
|
292
|
-
s.set("options", {
|
|
324
|
+
s.set("options", {
|
|
325
|
+
...import_lodash.default.omit(_FlowModelRepository.optionsToJson(s.get("options") || {}), ["uid"]),
|
|
326
|
+
...import_lodash.default.omit(newSchema, ["uid", "name", "options"])
|
|
327
|
+
});
|
|
293
328
|
await s.save({ transaction: transaction2, hooks: false });
|
|
294
329
|
await this.emitAfterSaveEvent(s, options);
|
|
295
330
|
if (newSchema["x-server-hooks"]) {
|
|
@@ -478,17 +513,25 @@ const _FlowModelRepository = class _FlowModelRepository extends import_database.
|
|
|
478
513
|
const oldParentUid = n["parent"];
|
|
479
514
|
const newParentUid = uidMap[oldParentUid] ?? null;
|
|
480
515
|
const optionsObj = this.replaceStepParamsModelUids(
|
|
481
|
-
import_lodash.default.
|
|
516
|
+
import_lodash.default.cloneDeep(_FlowModelRepository.optionsToJson(n.options)),
|
|
482
517
|
uidMap
|
|
483
518
|
);
|
|
519
|
+
delete optionsObj.uid;
|
|
520
|
+
delete optionsObj.name;
|
|
521
|
+
delete optionsObj.childOptions;
|
|
522
|
+
delete optionsObj["x-async"];
|
|
484
523
|
if (newParentUid) {
|
|
485
524
|
optionsObj.parent = newParentUid;
|
|
486
525
|
optionsObj.parentId = newParentUid;
|
|
526
|
+
} else {
|
|
527
|
+
delete optionsObj.parent;
|
|
528
|
+
delete optionsObj.parentId;
|
|
487
529
|
}
|
|
488
530
|
const schemaNode = {
|
|
531
|
+
...optionsObj,
|
|
489
532
|
uid: newUid,
|
|
490
|
-
|
|
491
|
-
|
|
533
|
+
name: newUid,
|
|
534
|
+
["x-async"]: !!n.async
|
|
492
535
|
};
|
|
493
536
|
if (newParentUid) {
|
|
494
537
|
schemaNode.childOptions = {
|
|
@@ -847,7 +890,7 @@ WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and TreeTable.sort
|
|
|
847
890
|
await nodeModel.update(
|
|
848
891
|
{
|
|
849
892
|
options: {
|
|
850
|
-
...nodeModel.get("options"),
|
|
893
|
+
...import_lodash.default.omit(_FlowModelRepository.optionsToJson(nodeModel.get("options") || {}), ["uid"]),
|
|
851
894
|
...import_lodash.default.omit(schema, ["x-async", "name", "uid", "properties"])
|
|
852
895
|
}
|
|
853
896
|
},
|
|
@@ -889,6 +932,115 @@ WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and TreeTable.sort
|
|
|
889
932
|
});
|
|
890
933
|
return parent ? parent.get("ancestor") : null;
|
|
891
934
|
}
|
|
935
|
+
async findSiblingInfo(uid2, transaction2) {
|
|
936
|
+
const rows = await this.database.sequelize.query(
|
|
937
|
+
this.sqlAdapter(`SELECT ParentPath.ancestor as parent, NodeInfo.type as type
|
|
938
|
+
FROM ${this.flowModelTreePathTableName} as ParentPath
|
|
939
|
+
LEFT JOIN ${this.flowModelTreePathTableName} as NodeInfo
|
|
940
|
+
ON NodeInfo.ancestor = ParentPath.descendant
|
|
941
|
+
AND NodeInfo.descendant = ParentPath.descendant
|
|
942
|
+
AND NodeInfo.depth = 0
|
|
943
|
+
WHERE ParentPath.descendant = :uid AND ParentPath.depth = 1`),
|
|
944
|
+
{
|
|
945
|
+
type: "SELECT",
|
|
946
|
+
replacements: { uid: uid2 },
|
|
947
|
+
transaction: transaction2
|
|
948
|
+
}
|
|
949
|
+
);
|
|
950
|
+
const row = rows[0];
|
|
951
|
+
if (!(row == null ? void 0 : row.parent) || !(row == null ? void 0 : row.type)) {
|
|
952
|
+
return null;
|
|
953
|
+
}
|
|
954
|
+
return {
|
|
955
|
+
parentUid: row.parent,
|
|
956
|
+
type: row.type
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
async findSiblingSortRows(parentUid, type, transaction2) {
|
|
960
|
+
const treeTable = this.flowModelTreePathTableName;
|
|
961
|
+
const rows = await this.database.sequelize.query(
|
|
962
|
+
this.sqlAdapter(`SELECT ChildPath.descendant as uid, ChildPath.sort as sort
|
|
963
|
+
FROM ${treeTable} as ChildPath
|
|
964
|
+
LEFT JOIN ${treeTable} as NodeInfo
|
|
965
|
+
ON NodeInfo.ancestor = ChildPath.descendant
|
|
966
|
+
AND NodeInfo.descendant = ChildPath.descendant
|
|
967
|
+
AND NodeInfo.depth = 0
|
|
968
|
+
WHERE ChildPath.ancestor = :parentUid
|
|
969
|
+
AND ChildPath.depth = 1
|
|
970
|
+
AND NodeInfo.type = :type`),
|
|
971
|
+
{
|
|
972
|
+
type: "SELECT",
|
|
973
|
+
replacements: { parentUid, type },
|
|
974
|
+
transaction: transaction2
|
|
975
|
+
}
|
|
976
|
+
);
|
|
977
|
+
return rows.sort((a, b) => _FlowModelRepository.compareBySortAndUid(a, b));
|
|
978
|
+
}
|
|
979
|
+
async writeSiblingSorts(parentUid, orderedUids, transaction2) {
|
|
980
|
+
const treeTable = this.flowModelTreePathTableName;
|
|
981
|
+
for (const [index, uid2] of orderedUids.entries()) {
|
|
982
|
+
await this.database.sequelize.query(
|
|
983
|
+
this.sqlAdapter(
|
|
984
|
+
`UPDATE ${treeTable} SET sort = :sort WHERE ancestor = :parentUid AND descendant = :uid AND depth = 1`
|
|
985
|
+
),
|
|
986
|
+
{
|
|
987
|
+
type: "UPDATE",
|
|
988
|
+
replacements: {
|
|
989
|
+
parentUid,
|
|
990
|
+
uid: uid2,
|
|
991
|
+
sort: index + 1
|
|
992
|
+
},
|
|
993
|
+
transaction: transaction2
|
|
994
|
+
}
|
|
995
|
+
);
|
|
996
|
+
}
|
|
997
|
+
await this.clearXUidPathCache(parentUid, transaction2);
|
|
998
|
+
}
|
|
999
|
+
async normalizeSiblingSorts(info, transaction2) {
|
|
1000
|
+
if (!info) {
|
|
1001
|
+
return;
|
|
1002
|
+
}
|
|
1003
|
+
const siblingRows = await this.findSiblingSortRows(info.parentUid, info.type, transaction2);
|
|
1004
|
+
await this.writeSiblingSorts(
|
|
1005
|
+
info.parentUid,
|
|
1006
|
+
siblingRows.map((row) => row.uid),
|
|
1007
|
+
transaction2
|
|
1008
|
+
);
|
|
1009
|
+
}
|
|
1010
|
+
async isAncestorOf(ancestorUid, descendantUid, transaction2) {
|
|
1011
|
+
const rows = await this.database.sequelize.query(
|
|
1012
|
+
this.sqlAdapter(`SELECT 1 as v
|
|
1013
|
+
FROM ${this.flowModelTreePathTableName}
|
|
1014
|
+
WHERE ancestor = :ancestorUid
|
|
1015
|
+
AND descendant = :descendantUid
|
|
1016
|
+
AND depth > 0
|
|
1017
|
+
LIMIT 1`),
|
|
1018
|
+
{
|
|
1019
|
+
type: "SELECT",
|
|
1020
|
+
replacements: { ancestorUid, descendantUid },
|
|
1021
|
+
transaction: transaction2
|
|
1022
|
+
}
|
|
1023
|
+
);
|
|
1024
|
+
return rows.length > 0;
|
|
1025
|
+
}
|
|
1026
|
+
async updateModelParentOptions(uid2, parentId, subKey, subType, transaction2) {
|
|
1027
|
+
const modelInstance = await this.model.findByPk(uid2, { transaction: transaction2 });
|
|
1028
|
+
if (!modelInstance) {
|
|
1029
|
+
throw new Error(`flowModels:move sourceId '${uid2}' not found`);
|
|
1030
|
+
}
|
|
1031
|
+
await modelInstance.update(
|
|
1032
|
+
{
|
|
1033
|
+
options: {
|
|
1034
|
+
...import_lodash.default.omit(_FlowModelRepository.optionsToJson(modelInstance.get("options") || {}), ["uid"]),
|
|
1035
|
+
parentId,
|
|
1036
|
+
parent: parentId,
|
|
1037
|
+
subKey,
|
|
1038
|
+
subType
|
|
1039
|
+
}
|
|
1040
|
+
},
|
|
1041
|
+
{ transaction: transaction2, hooks: false }
|
|
1042
|
+
);
|
|
1043
|
+
}
|
|
892
1044
|
async findNodeSchemaWithParent(uid2, transaction2) {
|
|
893
1045
|
const schema = await this.database.getRepository("flowModels").findOne({
|
|
894
1046
|
filter: {
|
|
@@ -1155,22 +1307,30 @@ WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and TreeTable.sort
|
|
|
1155
1307
|
for (const child of children) {
|
|
1156
1308
|
const { subKey, subType } = this.optionsToJson(child.options);
|
|
1157
1309
|
if (!subKey) continue;
|
|
1158
|
-
const
|
|
1159
|
-
uid: child["uid"],
|
|
1310
|
+
const model2 = _FlowModelRepository.nodesToModel(nodes, child["uid"]) || {
|
|
1160
1311
|
...this.optionsToJson(child.options),
|
|
1312
|
+
uid: child["uid"],
|
|
1161
1313
|
sortIndex: child.sort
|
|
1162
1314
|
};
|
|
1163
|
-
|
|
1315
|
+
model2.sortIndex = child.sort;
|
|
1164
1316
|
if (subType === "array") {
|
|
1165
1317
|
if (!subModels[subKey]) subModels[subKey] = [];
|
|
1166
|
-
subModels[subKey].push(
|
|
1318
|
+
subModels[subKey].push(model2);
|
|
1167
1319
|
} else {
|
|
1168
|
-
subModels[subKey] =
|
|
1320
|
+
subModels[subKey] = model2;
|
|
1169
1321
|
}
|
|
1170
1322
|
}
|
|
1171
1323
|
for (const key in subModels) {
|
|
1172
1324
|
if (Array.isArray(subModels[key])) {
|
|
1173
|
-
subModels[key]
|
|
1325
|
+
subModels[key] = subModels[key].sort(
|
|
1326
|
+
(a, b) => _FlowModelRepository.compareBySortAndUid(
|
|
1327
|
+
{ sort: a.sortIndex, uid: a.uid },
|
|
1328
|
+
{ sort: b.sortIndex, uid: b.uid }
|
|
1329
|
+
)
|
|
1330
|
+
).map((item, index) => {
|
|
1331
|
+
item.sortIndex = index + 1;
|
|
1332
|
+
return item;
|
|
1333
|
+
});
|
|
1174
1334
|
}
|
|
1175
1335
|
}
|
|
1176
1336
|
const filteredSubModels = {};
|
|
@@ -1181,11 +1341,19 @@ WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and TreeTable.sort
|
|
|
1181
1341
|
continue;
|
|
1182
1342
|
filteredSubModels[key] = value;
|
|
1183
1343
|
}
|
|
1184
|
-
|
|
1185
|
-
uid: rootNode["uid"],
|
|
1344
|
+
const model = {
|
|
1186
1345
|
...this.optionsToJson(rootNode.options),
|
|
1346
|
+
uid: rootNode["uid"],
|
|
1187
1347
|
...Object.keys(filteredSubModels).length > 0 ? { subModels: filteredSubModels } : {}
|
|
1188
1348
|
};
|
|
1349
|
+
if (rootNode.parent) {
|
|
1350
|
+
model.parent = rootNode.parent;
|
|
1351
|
+
model.parentId = rootNode.parent;
|
|
1352
|
+
} else {
|
|
1353
|
+
delete model.parent;
|
|
1354
|
+
delete model.parentId;
|
|
1355
|
+
}
|
|
1356
|
+
return model;
|
|
1189
1357
|
}
|
|
1190
1358
|
async insertModel(model, options) {
|
|
1191
1359
|
const nodes = _FlowModelRepository.modelToSingleNodes(model);
|
|
@@ -1194,6 +1362,7 @@ WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and TreeTable.sort
|
|
|
1194
1362
|
return await this.findModelById(rootUid, options);
|
|
1195
1363
|
}
|
|
1196
1364
|
async updateSingleNode(node, options) {
|
|
1365
|
+
var _a;
|
|
1197
1366
|
const instance = await this.model.findByPk(node["uid"], {
|
|
1198
1367
|
transaction: options == null ? void 0 : options.transaction
|
|
1199
1368
|
});
|
|
@@ -1201,8 +1370,12 @@ WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and TreeTable.sort
|
|
|
1201
1370
|
await instance.update(
|
|
1202
1371
|
{
|
|
1203
1372
|
options: {
|
|
1204
|
-
...instance.get("options"),
|
|
1205
|
-
...import_lodash.default.omit(node, ["x-async", "name", "uid", "childOptions"])
|
|
1373
|
+
...import_lodash.default.omit(instance.get("options"), ["uid"]),
|
|
1374
|
+
...import_lodash.default.omit(node, ["x-async", "name", "uid", "childOptions"]),
|
|
1375
|
+
...((_a = node.childOptions) == null ? void 0 : _a.parentUid) ? {
|
|
1376
|
+
parent: node.childOptions.parentUid,
|
|
1377
|
+
parentId: node.childOptions.parentUid
|
|
1378
|
+
} : {}
|
|
1206
1379
|
}
|
|
1207
1380
|
},
|
|
1208
1381
|
{
|
|
@@ -1376,7 +1549,7 @@ WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and TreeTable.sort
|
|
|
1376
1549
|
await modelInstance.update(
|
|
1377
1550
|
{
|
|
1378
1551
|
options: {
|
|
1379
|
-
...modelInstance.get("options"),
|
|
1552
|
+
...import_lodash.default.omit(modelInstance.get("options"), ["uid"]),
|
|
1380
1553
|
parentId,
|
|
1381
1554
|
parent: parentId,
|
|
1382
1555
|
subKey,
|
|
@@ -1399,11 +1572,74 @@ WHERE TreeTable.depth = 1 AND TreeTable.ancestor = :ancestor and TreeTable.sort
|
|
|
1399
1572
|
);
|
|
1400
1573
|
return await this.findModelById(modelUid, { transaction: transaction2, includeAsyncNode: true });
|
|
1401
1574
|
}
|
|
1402
|
-
async move(options) {
|
|
1575
|
+
async move(options, transactionOptions) {
|
|
1403
1576
|
const { sourceId, targetId, position } = options;
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1577
|
+
const sourceUid = String(sourceId || "").trim();
|
|
1578
|
+
const targetUid = String(targetId || "").trim();
|
|
1579
|
+
if (!sourceUid || !targetUid) {
|
|
1580
|
+
throw new Error("flowModels:move missing required params");
|
|
1581
|
+
}
|
|
1582
|
+
if (position !== "before" && position !== "after") {
|
|
1583
|
+
throw new Error("flowModels:move invalid position");
|
|
1584
|
+
}
|
|
1585
|
+
const transaction2 = transactionOptions == null ? void 0 : transactionOptions.transaction;
|
|
1586
|
+
const sourceInstance = await this.model.findByPk(sourceUid, { transaction: transaction2 });
|
|
1587
|
+
if (!sourceInstance) {
|
|
1588
|
+
throw new Error(`flowModels:move sourceId '${sourceUid}' not found`);
|
|
1589
|
+
}
|
|
1590
|
+
if (sourceUid === targetUid) {
|
|
1591
|
+
await this.normalizeSiblingSorts(await this.findSiblingInfo(sourceUid, transaction2), transaction2);
|
|
1592
|
+
return null;
|
|
1593
|
+
}
|
|
1594
|
+
const sourceInfo = await this.findSiblingInfo(sourceUid, transaction2);
|
|
1595
|
+
const targetInfo = await this.findSiblingInfo(targetUid, transaction2);
|
|
1596
|
+
if (!targetInfo) {
|
|
1597
|
+
throw new Error("flowModels:move target is not attached to a parent");
|
|
1598
|
+
}
|
|
1599
|
+
const targetInstance = await this.model.findByPk(targetUid, { transaction: transaction2 });
|
|
1600
|
+
const targetOptions = _FlowModelRepository.optionsToJson((targetInstance == null ? void 0 : targetInstance.get("options")) || {});
|
|
1601
|
+
const targetSubType = targetOptions.subType === "object" ? "object" : "array";
|
|
1602
|
+
if (targetInfo.parentUid === sourceUid || await this.isAncestorOf(sourceUid, targetInfo.parentUid, transaction2)) {
|
|
1603
|
+
throw new Error("flowModels:move cycle detected");
|
|
1604
|
+
}
|
|
1605
|
+
if ((sourceInfo == null ? void 0 : sourceInfo.parentUid) === targetInfo.parentUid && sourceInfo.type === targetInfo.type) {
|
|
1606
|
+
const siblingRows = await this.findSiblingSortRows(sourceInfo.parentUid, sourceInfo.type, transaction2);
|
|
1607
|
+
const sourceRow = siblingRows.find((row) => row.uid === sourceUid);
|
|
1608
|
+
const targetIndex = siblingRows.findIndex((row) => row.uid === targetUid);
|
|
1609
|
+
if (!sourceRow || targetIndex === -1) {
|
|
1610
|
+
throw new Error("flowModels:move source and target must be sibling nodes under the same parent/subKey");
|
|
1611
|
+
}
|
|
1612
|
+
const rowsWithoutSource = siblingRows.filter((row) => row.uid !== sourceUid);
|
|
1613
|
+
const insertIndex = rowsWithoutSource.findIndex((row) => row.uid === targetUid);
|
|
1614
|
+
rowsWithoutSource.splice(position === "after" ? insertIndex + 1 : insertIndex, 0, sourceRow);
|
|
1615
|
+
await this.writeSiblingSorts(
|
|
1616
|
+
sourceInfo.parentUid,
|
|
1617
|
+
rowsWithoutSource.map((row) => row.uid),
|
|
1618
|
+
transaction2
|
|
1619
|
+
);
|
|
1620
|
+
return await this.findModelById(sourceUid, { transaction: transaction2 });
|
|
1621
|
+
}
|
|
1622
|
+
await this.normalizeSiblingSorts(sourceInfo, transaction2);
|
|
1623
|
+
await this.normalizeSiblingSorts(targetInfo, transaction2);
|
|
1624
|
+
await this.updateModelParentOptions(sourceUid, targetInfo.parentUid, targetInfo.type, targetSubType, transaction2);
|
|
1625
|
+
await this.insertSingleNode(
|
|
1626
|
+
{
|
|
1627
|
+
uid: sourceUid,
|
|
1628
|
+
name: sourceUid,
|
|
1629
|
+
childOptions: {
|
|
1630
|
+
parentUid: targetInfo.parentUid,
|
|
1631
|
+
type: targetInfo.type,
|
|
1632
|
+
position: {
|
|
1633
|
+
type: position,
|
|
1634
|
+
target: targetUid
|
|
1635
|
+
}
|
|
1636
|
+
}
|
|
1637
|
+
},
|
|
1638
|
+
{ transaction: transaction2, removeParentsIfNoChildren: false }
|
|
1639
|
+
);
|
|
1640
|
+
await this.normalizeSiblingSorts(sourceInfo, transaction2);
|
|
1641
|
+
await this.normalizeSiblingSorts(await this.findSiblingInfo(sourceUid, transaction2), transaction2);
|
|
1642
|
+
return await this.findModelById(sourceUid, { transaction: transaction2 });
|
|
1407
1643
|
}
|
|
1408
1644
|
};
|
|
1409
1645
|
__decorateClass([
|
|
@@ -1466,6 +1702,9 @@ __decorateClass([
|
|
|
1466
1702
|
__decorateClass([
|
|
1467
1703
|
transaction()
|
|
1468
1704
|
], _FlowModelRepository.prototype, "attach", 1);
|
|
1705
|
+
__decorateClass([
|
|
1706
|
+
transaction()
|
|
1707
|
+
], _FlowModelRepository.prototype, "move", 1);
|
|
1469
1708
|
let FlowModelRepository = _FlowModelRepository;
|
|
1470
1709
|
var repository_default = FlowModelRepository;
|
|
1471
1710
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -50,6 +50,8 @@ export declare class ServerBaseContext {
|
|
|
50
50
|
delegate(ctx: ServerBaseContext): void;
|
|
51
51
|
/** 清空所有委托 */
|
|
52
52
|
clearDelegates(): void;
|
|
53
|
+
getSandboxKeys(): string[];
|
|
54
|
+
getSandboxValue(key: string, current?: ServerBaseContext): any;
|
|
53
55
|
/** 创建并返回代理对象(同一实例下保持稳定引用) */
|
|
54
56
|
createProxy(): any;
|
|
55
57
|
}
|
|
@@ -42,6 +42,10 @@ __export(contexts_exports, {
|
|
|
42
42
|
});
|
|
43
43
|
module.exports = __toCommonJS(contexts_exports);
|
|
44
44
|
var import_lodash = __toESM(require("lodash"));
|
|
45
|
+
const BLOCKED_SANDBOX_KEYS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor", "then"]);
|
|
46
|
+
function isBlockedSandboxKey(key) {
|
|
47
|
+
return BLOCKED_SANDBOX_KEYS.has(key);
|
|
48
|
+
}
|
|
45
49
|
class ServerBaseContext {
|
|
46
50
|
_props = {};
|
|
47
51
|
_methods = {};
|
|
@@ -106,6 +110,36 @@ class ServerBaseContext {
|
|
|
106
110
|
clearDelegates() {
|
|
107
111
|
this._delegates = [];
|
|
108
112
|
}
|
|
113
|
+
getSandboxKeys() {
|
|
114
|
+
const keys = /* @__PURE__ */ new Set();
|
|
115
|
+
for (const key of Object.keys(this._props)) {
|
|
116
|
+
if (!isBlockedSandboxKey(key)) keys.add(key);
|
|
117
|
+
}
|
|
118
|
+
for (const key of Object.keys(this._methods)) {
|
|
119
|
+
if (!isBlockedSandboxKey(key)) keys.add(key);
|
|
120
|
+
}
|
|
121
|
+
for (const d of this._delegates) {
|
|
122
|
+
for (const key of d.getSandboxKeys()) {
|
|
123
|
+
if (!isBlockedSandboxKey(key)) keys.add(key);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return Array.from(keys);
|
|
127
|
+
}
|
|
128
|
+
getSandboxValue(key, current = this.createProxy()) {
|
|
129
|
+
if (isBlockedSandboxKey(key)) return void 0;
|
|
130
|
+
if (Object.prototype.hasOwnProperty.call(this._props, key)) {
|
|
131
|
+
return this._getOwn(key, current);
|
|
132
|
+
}
|
|
133
|
+
if (Object.prototype.hasOwnProperty.call(this._methods, key)) {
|
|
134
|
+
const fn = this._methods[key];
|
|
135
|
+
return typeof fn === "function" ? fn.bind(this) : fn;
|
|
136
|
+
}
|
|
137
|
+
for (const d of this._delegates) {
|
|
138
|
+
if (!d.getSandboxKeys().includes(key)) continue;
|
|
139
|
+
return d.getSandboxValue(key, current);
|
|
140
|
+
}
|
|
141
|
+
return void 0;
|
|
142
|
+
}
|
|
109
143
|
/** 创建并返回代理对象(同一实例下保持稳定引用) */
|
|
110
144
|
createProxy() {
|
|
111
145
|
if (this._proxy) return this._proxy;
|
|
@@ -42,6 +42,16 @@ __export(resolver_exports, {
|
|
|
42
42
|
module.exports = __toCommonJS(resolver_exports);
|
|
43
43
|
var import_ses = require("ses");
|
|
44
44
|
var import_lodash = __toESM(require("lodash"));
|
|
45
|
+
var import_utils = require("@nocobase/utils");
|
|
46
|
+
var import_contexts = require("./contexts");
|
|
47
|
+
const BLOCKED_SANDBOX_KEYS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
|
|
48
|
+
const sandboxProxyCache = /* @__PURE__ */ new WeakMap();
|
|
49
|
+
const sandboxProxyMeta = /* @__PURE__ */ new WeakMap();
|
|
50
|
+
const EMPTY_SANDBOX_CONTEXT = {
|
|
51
|
+
getSandboxKeys: () => [],
|
|
52
|
+
getSandboxValue: () => void 0
|
|
53
|
+
};
|
|
54
|
+
let resolverLockdownReady = false;
|
|
45
55
|
async function resolveJsonTemplate(template, ctx) {
|
|
46
56
|
const compile = async (source) => {
|
|
47
57
|
if (typeof source === "string" && /\{\{.*?\}\}/.test(source)) {
|
|
@@ -75,6 +85,210 @@ async function replacePlaceholders(input, ctx) {
|
|
|
75
85
|
}
|
|
76
86
|
return result;
|
|
77
87
|
}
|
|
88
|
+
function isObjectLike(value) {
|
|
89
|
+
return value !== null && (typeof value === "object" || typeof value === "function");
|
|
90
|
+
}
|
|
91
|
+
function isTrustedPromise(value) {
|
|
92
|
+
return value instanceof Promise;
|
|
93
|
+
}
|
|
94
|
+
function isBlockedSandboxKey(key) {
|
|
95
|
+
return typeof key === "string" && BLOCKED_SANDBOX_KEYS.has(key);
|
|
96
|
+
}
|
|
97
|
+
function getSandboxDataDescriptor(source, key) {
|
|
98
|
+
if (isBlockedSandboxKey(key) || typeof key === "symbol") return void 0;
|
|
99
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(source, key);
|
|
100
|
+
if (!descriptor || !("value" in descriptor)) return void 0;
|
|
101
|
+
if (key === "then" && typeof descriptor.value === "function") return void 0;
|
|
102
|
+
return descriptor;
|
|
103
|
+
}
|
|
104
|
+
function getPrimitiveDataDescriptor(source, key) {
|
|
105
|
+
if (source == null || isObjectLike(source)) return void 0;
|
|
106
|
+
return getSandboxDataDescriptor(Object(source), key);
|
|
107
|
+
}
|
|
108
|
+
function isSandboxContextSource(value) {
|
|
109
|
+
return value === EMPTY_SANDBOX_CONTEXT || value instanceof import_contexts.ServerBaseContext;
|
|
110
|
+
}
|
|
111
|
+
function wrapSandboxValue(value) {
|
|
112
|
+
if (isTrustedPromise(value)) {
|
|
113
|
+
return Promise.prototype.then.call(value, (resolved) => wrapSandboxValue(resolved));
|
|
114
|
+
}
|
|
115
|
+
if (!isObjectLike(value)) return value;
|
|
116
|
+
if (sandboxProxyMeta.has(value)) return value;
|
|
117
|
+
const cached = sandboxProxyCache.get(value);
|
|
118
|
+
if (cached) return cached;
|
|
119
|
+
const kind = isSandboxContextSource(value) ? "context" : typeof value === "function" ? "function" : "data";
|
|
120
|
+
const proxy = kind === "context" ? createSandboxContextProxy(value) : kind === "function" ? createSandboxFunctionProxy(value) : createSandboxDataProxy(value);
|
|
121
|
+
sandboxProxyCache.set(value, proxy);
|
|
122
|
+
sandboxProxyMeta.set(proxy, { kind, source: value });
|
|
123
|
+
return proxy;
|
|
124
|
+
}
|
|
125
|
+
function wrapRootSandboxContext(ctx) {
|
|
126
|
+
return wrapSandboxValue(isSandboxContextSource(ctx) ? ctx : EMPTY_SANDBOX_CONTEXT);
|
|
127
|
+
}
|
|
128
|
+
function ensureResolverLockdown() {
|
|
129
|
+
if (resolverLockdownReady) return;
|
|
130
|
+
(0, import_utils.lockdownSes)({
|
|
131
|
+
consoleTaming: "unsafe",
|
|
132
|
+
errorTaming: "unsafe",
|
|
133
|
+
overrideTaming: "moderate",
|
|
134
|
+
stackFiltering: "verbose"
|
|
135
|
+
});
|
|
136
|
+
resolverLockdownReady = true;
|
|
137
|
+
}
|
|
138
|
+
function createSandboxContextProxy(source) {
|
|
139
|
+
return new Proxy(/* @__PURE__ */ Object.create(null), {
|
|
140
|
+
get: (_target, key) => {
|
|
141
|
+
if (isBlockedSandboxKey(key) || typeof key !== "string") return void 0;
|
|
142
|
+
if (!source.getSandboxKeys().includes(key)) return void 0;
|
|
143
|
+
return wrapSandboxValue(source.getSandboxValue(key));
|
|
144
|
+
},
|
|
145
|
+
has: (_target, key) => typeof key === "string" && source.getSandboxKeys().includes(key),
|
|
146
|
+
ownKeys: () => source.getSandboxKeys(),
|
|
147
|
+
getOwnPropertyDescriptor: (_target, key) => {
|
|
148
|
+
if (isBlockedSandboxKey(key) || typeof key !== "string" || !source.getSandboxKeys().includes(key)) {
|
|
149
|
+
return void 0;
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
configurable: true,
|
|
153
|
+
enumerable: true,
|
|
154
|
+
value: wrapSandboxValue(source.getSandboxValue(key))
|
|
155
|
+
};
|
|
156
|
+
},
|
|
157
|
+
getPrototypeOf: () => null,
|
|
158
|
+
set: () => false,
|
|
159
|
+
defineProperty: () => false,
|
|
160
|
+
deleteProperty: () => false
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
function createSandboxFunctionProxy(source) {
|
|
164
|
+
const callable = (...args) => Reflect.apply(source, void 0, args);
|
|
165
|
+
return new Proxy(callable, {
|
|
166
|
+
apply: (_target, _thisArg, argArray) => wrapSandboxValue(Reflect.apply(source, void 0, argArray)),
|
|
167
|
+
get: (_target, key) => {
|
|
168
|
+
if (key === "length" || key === "name") return Reflect.get(source, key);
|
|
169
|
+
return void 0;
|
|
170
|
+
},
|
|
171
|
+
has: (_target, key) => key === "length" || key === "name",
|
|
172
|
+
ownKeys: () => [],
|
|
173
|
+
getOwnPropertyDescriptor: () => void 0,
|
|
174
|
+
getPrototypeOf: () => null,
|
|
175
|
+
set: () => false,
|
|
176
|
+
defineProperty: () => false,
|
|
177
|
+
deleteProperty: () => false
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
function createSandboxDataProxy(source) {
|
|
181
|
+
const target = Array.isArray(source) ? new Array(source.length) : /* @__PURE__ */ Object.create(null);
|
|
182
|
+
return new Proxy(target, {
|
|
183
|
+
get: (_target, key) => {
|
|
184
|
+
const descriptor = getSandboxDataDescriptor(source, key);
|
|
185
|
+
if (!descriptor) return void 0;
|
|
186
|
+
const value = descriptor.value;
|
|
187
|
+
return typeof value === "function" ? wrapSandboxValue(value.bind(source)) : wrapSandboxValue(value);
|
|
188
|
+
},
|
|
189
|
+
has: (_target, key) => {
|
|
190
|
+
if (isBlockedSandboxKey(key) || typeof key !== "string") return false;
|
|
191
|
+
return !!getSandboxDataDescriptor(source, key);
|
|
192
|
+
},
|
|
193
|
+
ownKeys: () => {
|
|
194
|
+
const keys = Reflect.ownKeys(source).filter((key) => {
|
|
195
|
+
if (typeof key !== "string" || isBlockedSandboxKey(key)) return false;
|
|
196
|
+
return !!getSandboxDataDescriptor(source, key);
|
|
197
|
+
});
|
|
198
|
+
if (Array.isArray(source) && !keys.includes("length")) keys.push("length");
|
|
199
|
+
return keys;
|
|
200
|
+
},
|
|
201
|
+
getOwnPropertyDescriptor: (proxyTarget, key) => {
|
|
202
|
+
if (isBlockedSandboxKey(key) || typeof key === "symbol") return void 0;
|
|
203
|
+
if (Array.isArray(source) && key === "length") {
|
|
204
|
+
return Reflect.getOwnPropertyDescriptor(proxyTarget, key);
|
|
205
|
+
}
|
|
206
|
+
const descriptor = getSandboxDataDescriptor(source, key);
|
|
207
|
+
if (!descriptor) return void 0;
|
|
208
|
+
return {
|
|
209
|
+
configurable: true,
|
|
210
|
+
enumerable: descriptor.enumerable,
|
|
211
|
+
writable: false,
|
|
212
|
+
value: wrapSandboxValue(descriptor.value)
|
|
213
|
+
};
|
|
214
|
+
},
|
|
215
|
+
getPrototypeOf: () => null,
|
|
216
|
+
set: () => false,
|
|
217
|
+
defineProperty: () => false,
|
|
218
|
+
deleteProperty: () => false
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
async function unwrapSandboxValue(value, seen = /* @__PURE__ */ new WeakMap()) {
|
|
222
|
+
const resolved = isTrustedPromise(value) ? await value : value;
|
|
223
|
+
if (!isObjectLike(resolved)) return resolved;
|
|
224
|
+
const meta = sandboxProxyMeta.get(resolved);
|
|
225
|
+
if ((meta == null ? void 0 : meta.kind) === "function" || typeof resolved === "function") return void 0;
|
|
226
|
+
const source = (meta == null ? void 0 : meta.source) ?? resolved;
|
|
227
|
+
if (!isObjectLike(source)) return source;
|
|
228
|
+
if (seen.has(source)) return seen.get(source);
|
|
229
|
+
if (isSandboxContextSource(source)) {
|
|
230
|
+
const out2 = {};
|
|
231
|
+
seen.set(source, out2);
|
|
232
|
+
for (const key of source.getSandboxKeys()) {
|
|
233
|
+
if (BLOCKED_SANDBOX_KEYS.has(key)) continue;
|
|
234
|
+
out2[key] = await unwrapSandboxValue(wrapSandboxValue(source.getSandboxValue(key)), seen);
|
|
235
|
+
}
|
|
236
|
+
return out2;
|
|
237
|
+
}
|
|
238
|
+
if (Array.isArray(source)) {
|
|
239
|
+
const out2 = [];
|
|
240
|
+
seen.set(source, out2);
|
|
241
|
+
const lengthDescriptor = Reflect.getOwnPropertyDescriptor(source, "length");
|
|
242
|
+
const length = typeof (lengthDescriptor == null ? void 0 : lengthDescriptor.value) === "number" ? lengthDescriptor.value : 0;
|
|
243
|
+
for (let index = 0; index < length; index++) {
|
|
244
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(source, String(index));
|
|
245
|
+
if (!descriptor || !("value" in descriptor)) continue;
|
|
246
|
+
out2.push(await unwrapSandboxValue(descriptor.value, seen));
|
|
247
|
+
}
|
|
248
|
+
return out2;
|
|
249
|
+
}
|
|
250
|
+
if (source instanceof Date) return source;
|
|
251
|
+
const out = {};
|
|
252
|
+
seen.set(source, out);
|
|
253
|
+
for (const key of Object.keys(source)) {
|
|
254
|
+
if (BLOCKED_SANDBOX_KEYS.has(key)) continue;
|
|
255
|
+
const descriptor = getSandboxDataDescriptor(source, key);
|
|
256
|
+
if (!descriptor) continue;
|
|
257
|
+
out[key] = await unwrapSandboxValue(descriptor.value, seen);
|
|
258
|
+
}
|
|
259
|
+
return out;
|
|
260
|
+
}
|
|
261
|
+
function getRootSandboxValue(ctx, key) {
|
|
262
|
+
if (BLOCKED_SANDBOX_KEYS.has(key)) return void 0;
|
|
263
|
+
if (isSandboxContextSource(ctx)) {
|
|
264
|
+
if (!ctx.getSandboxKeys().includes(key)) return void 0;
|
|
265
|
+
return wrapSandboxValue(ctx.getSandboxValue(key));
|
|
266
|
+
}
|
|
267
|
+
return void 0;
|
|
268
|
+
}
|
|
269
|
+
async function getSandboxProperty(value, key) {
|
|
270
|
+
if (BLOCKED_SANDBOX_KEYS.has(key)) return void 0;
|
|
271
|
+
const resolved = isTrustedPromise(value) ? await value : value;
|
|
272
|
+
if (resolved == null) return void 0;
|
|
273
|
+
const meta = isObjectLike(resolved) ? sandboxProxyMeta.get(resolved) : void 0;
|
|
274
|
+
const source = (meta == null ? void 0 : meta.source) ?? resolved;
|
|
275
|
+
if (isSandboxContextSource(source)) {
|
|
276
|
+
if (!source.getSandboxKeys().includes(key)) return void 0;
|
|
277
|
+
return wrapSandboxValue(source.getSandboxValue(key));
|
|
278
|
+
}
|
|
279
|
+
if (typeof source === "function") {
|
|
280
|
+
return key === "length" || key === "name" ? Reflect.get(source, key) : void 0;
|
|
281
|
+
}
|
|
282
|
+
if (!isObjectLike(source)) {
|
|
283
|
+
const descriptor2 = getPrimitiveDataDescriptor(source, key);
|
|
284
|
+
if (!descriptor2 || typeof descriptor2.value === "function") return void 0;
|
|
285
|
+
return wrapSandboxValue(descriptor2.value);
|
|
286
|
+
}
|
|
287
|
+
const descriptor = getSandboxDataDescriptor(source, key);
|
|
288
|
+
if (!descriptor) return void 0;
|
|
289
|
+
const current = descriptor.value;
|
|
290
|
+
return typeof current === "function" ? wrapSandboxValue(current.bind(source)) : wrapSandboxValue(current);
|
|
291
|
+
}
|
|
78
292
|
async function evaluate(expr, ctx) {
|
|
79
293
|
try {
|
|
80
294
|
const raw = expr.trim();
|
|
@@ -84,40 +298,36 @@ async function evaluate(expr, ctx) {
|
|
|
84
298
|
if (dotOnly) {
|
|
85
299
|
const first = dotOnly[1];
|
|
86
300
|
const rest = dotOnly[2];
|
|
87
|
-
const base =
|
|
88
|
-
if (!rest) return base;
|
|
301
|
+
const base = getRootSandboxValue(ctx, first);
|
|
302
|
+
if (!rest) return await unwrapSandboxValue(wrapSandboxValue(base));
|
|
89
303
|
const resolved = await asyncGetValuesByPath(base, rest);
|
|
90
304
|
if (typeof resolved !== "undefined" || !rest.includes("-")) {
|
|
91
|
-
return resolved;
|
|
305
|
+
return await unwrapSandboxValue(resolved);
|
|
92
306
|
}
|
|
93
307
|
}
|
|
94
308
|
const transformed = preprocessExpression(raw);
|
|
309
|
+
ensureResolverLockdown();
|
|
95
310
|
const compartment = new Compartment({
|
|
96
|
-
ctx,
|
|
97
|
-
__get: (varName, path) => getAtPath(ctx, varName, path)
|
|
98
|
-
console
|
|
311
|
+
ctx: wrapRootSandboxContext(ctx),
|
|
312
|
+
__get: wrapSandboxValue((varName, path) => getAtPath(ctx, varName, path))
|
|
99
313
|
});
|
|
100
314
|
const wrapped = `(async () => { try { return ${transformed}; } catch (e) { return undefined; } })()`;
|
|
101
|
-
return await compartment.evaluate(wrapped);
|
|
315
|
+
return await unwrapSandboxValue(await compartment.evaluate(wrapped));
|
|
102
316
|
} catch (_2) {
|
|
103
317
|
return void 0;
|
|
104
318
|
}
|
|
105
319
|
}
|
|
106
320
|
async function getAtPath(ctx, varName, path) {
|
|
107
321
|
try {
|
|
108
|
-
let current =
|
|
322
|
+
let current = getRootSandboxValue(ctx, varName);
|
|
109
323
|
if (!path) return current;
|
|
110
324
|
const norm = String(path || "").replace(/^\./, "");
|
|
111
325
|
const segments = import_lodash.default.toPath(norm);
|
|
112
326
|
for (const seg of segments) {
|
|
113
327
|
if (current == null) return void 0;
|
|
114
|
-
|
|
115
|
-
if (val && typeof val["then"] === "function") {
|
|
116
|
-
val = await val;
|
|
117
|
-
}
|
|
118
|
-
current = val;
|
|
328
|
+
current = await getSandboxProperty(current, seg);
|
|
119
329
|
}
|
|
120
|
-
return current;
|
|
330
|
+
return wrapSandboxValue(current);
|
|
121
331
|
} catch (_2) {
|
|
122
332
|
return void 0;
|
|
123
333
|
}
|
|
@@ -134,18 +344,19 @@ async function asyncGetValuesByPath(obj, path, defaultValue) {
|
|
|
134
344
|
if (Array.isArray(currentValue)) {
|
|
135
345
|
shouldReturnArray = true;
|
|
136
346
|
const rest = keys.slice(i).join(".");
|
|
137
|
-
const parts = await Promise.all(
|
|
347
|
+
const parts = await Promise.all(
|
|
348
|
+
Array.prototype.map.call(currentValue, (el) => asyncGetValuesByPath(el, rest, defaultValue))
|
|
349
|
+
);
|
|
138
350
|
for (const p of parts) {
|
|
139
|
-
if (Array.isArray(p))
|
|
140
|
-
|
|
351
|
+
if (Array.isArray(p)) {
|
|
352
|
+
for (let index = 0; index < p.length; index++) {
|
|
353
|
+
if (typeof p[index] !== "undefined") result.push(p[index]);
|
|
354
|
+
}
|
|
355
|
+
} else if (typeof p !== "undefined") result.push(p);
|
|
141
356
|
}
|
|
142
357
|
break;
|
|
143
358
|
}
|
|
144
|
-
|
|
145
|
-
if (val && typeof val.then === "function") {
|
|
146
|
-
val = await val;
|
|
147
|
-
}
|
|
148
|
-
currentValue = val;
|
|
359
|
+
currentValue = await getSandboxProperty(currentValue, key);
|
|
149
360
|
if (i === keys.length - 1) {
|
|
150
361
|
result.push(currentValue);
|
|
151
362
|
}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"displayName.zh-CN": "前端流引擎",
|
|
5
5
|
"description": "",
|
|
6
6
|
"description.zh-CN": "",
|
|
7
|
-
"version": "2.0.
|
|
7
|
+
"version": "2.0.62",
|
|
8
8
|
"main": "./dist/server/index.js",
|
|
9
9
|
"license": "Apache-2.0",
|
|
10
10
|
"devDependencies": {
|
|
@@ -24,5 +24,5 @@
|
|
|
24
24
|
"@nocobase/test": "2.x",
|
|
25
25
|
"@nocobase/utils": "2.x"
|
|
26
26
|
},
|
|
27
|
-
"gitHead": "
|
|
27
|
+
"gitHead": "b21b0a5111d188ba495eb579fdae674c5680fff2"
|
|
28
28
|
}
|