@nocobase/plugin-flow-engine 2.3.0-alpha.1 → 2.3.0-beta.2

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.
Files changed (59) hide show
  1. package/dist/ai/ai-employees/nathan/prompt.md +2 -0
  2. package/dist/ai/ai-employees/nathan/skills/frontend-developer/SKILLS.md +1 -0
  3. package/dist/ai/ai-employees/nathan/skills/frontend-developer/tools/patchJSCode.js +2 -2
  4. package/dist/ai/docs/runjs/context/ai.md +194 -4
  5. package/dist/externalVersion.js +9 -9
  6. package/dist/locale/en-US.json +2 -0
  7. package/dist/locale/index.d.ts +4 -0
  8. package/dist/locale/zh-CN.json +2 -0
  9. package/dist/node_modules/@ant-design/icons-svg/package.json +1 -1
  10. package/dist/node_modules/acorn/package.json +1 -1
  11. package/dist/node_modules/acorn-jsx/package.json +1 -1
  12. package/dist/node_modules/acorn-walk/package.json +1 -1
  13. package/dist/node_modules/ses/package.json +1 -1
  14. package/dist/node_modules/zod/package.json +1 -1
  15. package/dist/server/flow-surfaces/builder.js +5 -0
  16. package/dist/server/flow-surfaces/catalog.js +27 -8
  17. package/dist/server/flow-surfaces/configure-options.js +17 -1
  18. package/dist/server/flow-surfaces/field-binding-registry.js +9 -8
  19. package/dist/server/flow-surfaces/service-utils.d.ts +1 -0
  20. package/dist/server/flow-surfaces/service-utils.js +17 -0
  21. package/dist/server/flow-surfaces/service.js +9 -0
  22. package/dist/server/index.d.ts +2 -0
  23. package/dist/server/index.js +7 -0
  24. package/dist/server/plugin.d.ts +13 -0
  25. package/dist/server/plugin.js +90 -3
  26. package/dist/server/repository.d.ts +12 -0
  27. package/dist/server/repository.js +39 -2
  28. package/dist/server/template/context-keys.d.ts +14 -0
  29. package/dist/server/template/context-keys.js +86 -0
  30. package/dist/server/template/contexts.d.ts +5 -8
  31. package/dist/server/template/contexts.js +43 -51
  32. package/dist/server/template/resolver.d.ts +5 -13
  33. package/dist/server/template/resolver.js +188 -257
  34. package/dist/server/template/variable-expression.d.ts +72 -0
  35. package/dist/server/template/variable-expression.js +597 -0
  36. package/dist/server/variables/allow-list.d.ts +49 -0
  37. package/dist/server/variables/allow-list.js +492 -0
  38. package/dist/server/variables/form-item-record-slot-resolvers.d.ts +10 -0
  39. package/dist/server/variables/form-item-record-slot-resolvers.js +280 -0
  40. package/dist/server/variables/record-bindings.d.ts +42 -0
  41. package/dist/server/variables/record-bindings.js +196 -0
  42. package/dist/server/variables/record-projection.d.ts +10 -0
  43. package/dist/server/variables/record-projection.js +140 -0
  44. package/dist/server/variables/record-slot-policy.d.ts +23 -0
  45. package/dist/server/variables/record-slot-policy.js +100 -0
  46. package/dist/server/variables/record-slot-resolvers.d.ts +46 -0
  47. package/dist/server/variables/record-slot-resolvers.js +115 -0
  48. package/dist/server/variables/records.d.ts +49 -2
  49. package/dist/server/variables/records.js +309 -18
  50. package/dist/server/variables/registry.d.ts +33 -10
  51. package/dist/server/variables/registry.js +197 -362
  52. package/dist/server/variables/resolve.d.ts +20 -2
  53. package/dist/server/variables/resolve.js +85 -13
  54. package/dist/server/variables/runjs-variable-dependencies.d.ts +23 -0
  55. package/dist/server/variables/runjs-variable-dependencies.js +407 -0
  56. package/dist/server/variables/selects.js +6 -3
  57. package/dist/server/variables/utils.d.ts +3 -6
  58. package/dist/server/variables/utils.js +50 -111
  59. package/package.json +2 -2
@@ -7,11 +7,9 @@
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
9
 
10
- var __create = Object.create;
11
10
  var __defProp = Object.defineProperty;
12
11
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
12
  var __getOwnPropNames = Object.getOwnPropertyNames;
14
- var __getProtoOf = Object.getPrototypeOf;
15
13
  var __hasOwnProp = Object.prototype.hasOwnProperty;
16
14
  var __export = (target, all) => {
17
15
  for (var name in all)
@@ -25,65 +23,68 @@ var __copyProps = (to, from, except, desc) => {
25
23
  }
26
24
  return to;
27
25
  };
28
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
29
- // If the importer is in node compatibility mode or this is not an ESM
30
- // file that has been converted to a CommonJS file using a Babel-
31
- // compatible transform (i.e. "__esModule" has not been set), then set
32
- // "default" to the CommonJS "module.exports" for node compatibility.
33
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
- mod
35
- ));
36
26
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
37
27
  var resolver_exports = {};
38
28
  __export(resolver_exports, {
39
- preprocessExpression: () => preprocessExpression,
29
+ resolveAnalyzedJsonTemplate: () => resolveAnalyzedJsonTemplate,
40
30
  resolveJsonTemplate: () => resolveJsonTemplate
41
31
  });
42
32
  module.exports = __toCommonJS(resolver_exports);
43
33
  var import_ses = require("ses");
44
- var import_lodash = __toESM(require("lodash"));
45
34
  var import_utils = require("@nocobase/utils");
46
35
  var import_contexts = require("./contexts");
36
+ var import_variable_expression = require("./variable-expression");
47
37
  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
38
  let resolverLockdownReady = false;
55
39
  async function resolveJsonTemplate(template, ctx) {
56
- const compile = async (source) => {
57
- if (typeof source === "string" && /\{\{.*?\}\}/.test(source)) {
58
- return await replacePlaceholders(source, ctx);
59
- }
60
- if (Array.isArray(source)) return Promise.all(source.map(compile));
61
- if (source && typeof source === "object") {
62
- const out = {};
63
- for (const [k, v] of Object.entries(source)) out[k] = await compile(v);
64
- return out;
65
- }
66
- return source;
67
- };
68
- return compile(template);
40
+ const analysis = (0, import_variable_expression.analyzeVariableTemplate)(template);
41
+ return resolveAnalyzedJsonTemplate(analysis, ctx, {
42
+ allowAll: true,
43
+ allowedPaths: /* @__PURE__ */ new Set(),
44
+ unrestrictedVariables: /* @__PURE__ */ new Set()
45
+ });
46
+ }
47
+ async function resolveAnalyzedJsonTemplate(analysis, ctx, policy) {
48
+ const policySnapshot = Object.freeze({
49
+ allowAll: policy.allowAll,
50
+ allowedPaths: new Set(policy.allowedPaths),
51
+ unrestrictedVariables: new Set(policy.unrestrictedVariables)
52
+ });
53
+ return resolveAnalyzedNode(analysis.value, ctx, policySnapshot);
54
+ }
55
+ async function resolveAnalyzedNode(node, ctx, policy) {
56
+ if (node.kind === "value") return node.value;
57
+ if (node.kind === "string") return replaceAnalyzedPlaceholders(node, ctx, policy);
58
+ if (node.kind === "array") return Promise.all(node.items.map((item) => resolveAnalyzedNode(item, ctx, policy)));
59
+ const out = {};
60
+ for (const [key, value] of Object.entries(node.entries)) {
61
+ out[key] = await resolveAnalyzedNode(value, ctx, policy);
62
+ }
63
+ return out;
69
64
  }
70
- async function replacePlaceholders(input, ctx) {
71
- const single = input.match(/^\{\{\s*(.+)\s*\}\}$/);
72
- if (single) {
73
- const val = await evaluate(single[1], ctx);
74
- return typeof val === "undefined" ? input : val;
65
+ async function replaceAnalyzedPlaceholders(node, ctx, policy) {
66
+ const single = node.expressions.length === 1 && node.expressions[0].placeholderSpan.start === 0;
67
+ if (single && node.expressions[0].placeholderSpan.end === node.source.length) {
68
+ const value = await evaluateAnalyzedExpression(node.expressions[0], ctx, policy);
69
+ return typeof value === "undefined" ? node.source : value;
75
70
  }
76
- const regex = /\{\{\s*(.+?)\s*\}\}/g;
77
- let result = input;
78
- const matches = [...input.matchAll(regex)];
79
- for (const [full, inner] of matches) {
80
- const value = await evaluate(inner, ctx);
81
- if (typeof value !== "undefined") {
82
- const replacement = typeof value === "object" && value !== null ? JSON.stringify(value) : String(value);
83
- result = result.replace(full, replacement);
71
+ let result = "";
72
+ let cursor = 0;
73
+ for (const expression of node.expressions) {
74
+ result += node.source.slice(cursor, expression.placeholderSpan.start);
75
+ const placeholder = node.source.slice(expression.placeholderSpan.start, expression.placeholderSpan.end);
76
+ const value = await evaluateAnalyzedExpression(expression, ctx, policy);
77
+ if (typeof value === "undefined") {
78
+ result += placeholder;
79
+ } else {
80
+ result += typeof value === "object" && value !== null ? JSON.stringify(value) : String(value);
84
81
  }
82
+ cursor = expression.placeholderSpan.end;
85
83
  }
86
- return result;
84
+ return result + node.source.slice(cursor);
85
+ }
86
+ function createSandboxScope() {
87
+ return { proxyCache: /* @__PURE__ */ new WeakMap(), proxyMeta: /* @__PURE__ */ new WeakMap() };
87
88
  }
88
89
  function isObjectLike(value) {
89
90
  return value !== null && (typeof value === "object" || typeof value === "function");
@@ -97,8 +98,7 @@ function isBlockedSandboxKey(key) {
97
98
  function getSandboxDataDescriptor(source, key) {
98
99
  if (isBlockedSandboxKey(key) || typeof key === "symbol") return void 0;
99
100
  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;
101
+ if (!descriptor || !("value" in descriptor) || typeof descriptor.value === "function") return void 0;
102
102
  return descriptor;
103
103
  }
104
104
  function getPrimitiveDataDescriptor(source, key) {
@@ -106,25 +106,22 @@ function getPrimitiveDataDescriptor(source, key) {
106
106
  return getSandboxDataDescriptor(Object(source), key);
107
107
  }
108
108
  function isSandboxContextSource(value) {
109
- return value === EMPTY_SANDBOX_CONTEXT || value instanceof import_contexts.ServerBaseContext;
109
+ return value instanceof import_contexts.ServerBaseContext;
110
110
  }
111
- function wrapSandboxValue(value) {
111
+ function wrapSandboxValue(scope, value) {
112
112
  if (isTrustedPromise(value)) {
113
- return Promise.prototype.then.call(value, (resolved) => wrapSandboxValue(resolved));
113
+ return Promise.prototype.then.call(value, (resolved) => wrapSandboxValue(scope, resolved));
114
114
  }
115
+ if (typeof value === "function") return void 0;
115
116
  if (!isObjectLike(value)) return value;
116
- if (sandboxProxyMeta.has(value)) return value;
117
- const cached = sandboxProxyCache.get(value);
117
+ if (scope.proxyMeta.has(value)) return value;
118
+ const cached = scope.proxyCache.get(value);
118
119
  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 });
120
+ const proxy = isSandboxContextSource(value) ? createSandboxContextProxy(scope, value) : createSandboxDataProxy(scope, value);
121
+ scope.proxyCache.set(value, proxy);
122
+ scope.proxyMeta.set(proxy, value);
123
123
  return proxy;
124
124
  }
125
- function wrapRootSandboxContext(ctx) {
126
- return wrapSandboxValue(isSandboxContextSource(ctx) ? ctx : EMPTY_SANDBOX_CONTEXT);
127
- }
128
125
  function ensureResolverLockdown() {
129
126
  if (resolverLockdownReady) return;
130
127
  (0, import_utils.lockdownSes)({
@@ -135,12 +132,13 @@ function ensureResolverLockdown() {
135
132
  });
136
133
  resolverLockdownReady = true;
137
134
  }
138
- function createSandboxContextProxy(source) {
135
+ function createSandboxContextProxy(scope, source) {
139
136
  return new Proxy(/* @__PURE__ */ Object.create(null), {
140
137
  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));
138
+ if (isBlockedSandboxKey(key) || typeof key !== "string" || !source.getSandboxKeys().includes(key)) {
139
+ return void 0;
140
+ }
141
+ return wrapSandboxValue(scope, source.getSandboxValue(key));
144
142
  },
145
143
  has: (_target, key) => typeof key === "string" && source.getSandboxKeys().includes(key),
146
144
  ownKeys: () => source.getSandboxKeys(),
@@ -151,55 +149,31 @@ function createSandboxContextProxy(source) {
151
149
  return {
152
150
  configurable: true,
153
151
  enumerable: true,
154
- value: wrapSandboxValue(source.getSandboxValue(key))
152
+ value: wrapSandboxValue(scope, source.getSandboxValue(key))
155
153
  };
156
154
  },
157
155
  getPrototypeOf: () => null,
156
+ setPrototypeOf: () => false,
157
+ preventExtensions: () => false,
158
158
  set: () => false,
159
159
  defineProperty: () => false,
160
160
  deleteProperty: () => false
161
161
  });
162
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) {
163
+ function createSandboxDataProxy(scope, source) {
181
164
  const target = Array.isArray(source) ? new Array(source.length) : /* @__PURE__ */ Object.create(null);
182
165
  return new Proxy(target, {
183
166
  get: (_target, key) => {
184
167
  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);
168
+ return descriptor ? wrapSandboxValue(scope, descriptor.value) : void 0;
192
169
  },
170
+ has: (_target, key) => !!getSandboxDataDescriptor(source, key),
193
171
  ownKeys: () => {
194
- const keys = Reflect.ownKeys(source).filter((key) => {
195
- if (typeof key !== "string" || isBlockedSandboxKey(key)) return false;
196
- return !!getSandboxDataDescriptor(source, key);
197
- });
172
+ const keys = Reflect.ownKeys(source).filter((key) => !!getSandboxDataDescriptor(source, key));
198
173
  if (Array.isArray(source) && !keys.includes("length")) keys.push("length");
199
174
  return keys;
200
175
  },
201
176
  getOwnPropertyDescriptor: (proxyTarget, key) => {
202
- if (isBlockedSandboxKey(key) || typeof key === "symbol") return void 0;
203
177
  if (Array.isArray(source) && key === "length") {
204
178
  return Reflect.getOwnPropertyDescriptor(proxyTarget, key);
205
179
  }
@@ -209,29 +183,32 @@ function createSandboxDataProxy(source) {
209
183
  configurable: true,
210
184
  enumerable: descriptor.enumerable,
211
185
  writable: false,
212
- value: wrapSandboxValue(descriptor.value)
186
+ value: wrapSandboxValue(scope, descriptor.value)
213
187
  };
214
188
  },
215
189
  getPrototypeOf: () => null,
190
+ setPrototypeOf: () => false,
191
+ preventExtensions: () => false,
216
192
  set: () => false,
217
193
  defineProperty: () => false,
218
194
  deleteProperty: () => false
219
195
  });
220
196
  }
221
- async function unwrapSandboxValue(value, seen = /* @__PURE__ */ new WeakMap()) {
197
+ async function unwrapSandboxValue(scope, value, seen = /* @__PURE__ */ new WeakMap()) {
222
198
  const resolved = isTrustedPromise(value) ? await value : value;
199
+ if (typeof resolved === "function") return void 0;
223
200
  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;
201
+ const meta = scope.proxyMeta.get(resolved);
202
+ const source = meta ?? resolved;
203
+ if (typeof source === "function") return void 0;
228
204
  if (seen.has(source)) return seen.get(source);
205
+ if (Buffer.isBuffer(source)) return Buffer.prototype.toJSON.call(source);
229
206
  if (isSandboxContextSource(source)) {
230
207
  const out2 = {};
231
208
  seen.set(source, out2);
232
209
  for (const key of source.getSandboxKeys()) {
233
210
  if (BLOCKED_SANDBOX_KEYS.has(key)) continue;
234
- out2[key] = await unwrapSandboxValue(wrapSandboxValue(source.getSandboxValue(key)), seen);
211
+ out2[key] = await unwrapSandboxValue(scope, wrapSandboxValue(scope, source.getSandboxValue(key)), seen);
235
212
  }
236
213
  return out2;
237
214
  }
@@ -241,9 +218,9 @@ async function unwrapSandboxValue(value, seen = /* @__PURE__ */ new WeakMap()) {
241
218
  const lengthDescriptor = Reflect.getOwnPropertyDescriptor(source, "length");
242
219
  const length = typeof (lengthDescriptor == null ? void 0 : lengthDescriptor.value) === "number" ? lengthDescriptor.value : 0;
243
220
  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));
221
+ const descriptor = getSandboxDataDescriptor(source, String(index));
222
+ if (!descriptor) continue;
223
+ out2.push(await unwrapSandboxValue(scope, descriptor.value, seen));
247
224
  }
248
225
  return out2;
249
226
  }
@@ -251,190 +228,144 @@ async function unwrapSandboxValue(value, seen = /* @__PURE__ */ new WeakMap()) {
251
228
  const out = {};
252
229
  seen.set(source, out);
253
230
  for (const key of Object.keys(source)) {
254
- if (BLOCKED_SANDBOX_KEYS.has(key)) continue;
255
231
  const descriptor = getSandboxDataDescriptor(source, key);
256
232
  if (!descriptor) continue;
257
- out[key] = await unwrapSandboxValue(descriptor.value, seen);
233
+ out[key] = await unwrapSandboxValue(scope, descriptor.value, seen);
258
234
  }
259
235
  return out;
260
236
  }
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));
237
+ function getRootSandboxValue(scope, ctx, key) {
238
+ if (BLOCKED_SANDBOX_KEYS.has(key) || !isSandboxContextSource(ctx) || !ctx.getSandboxKeys().includes(key)) {
239
+ return void 0;
266
240
  }
267
- return void 0;
241
+ return wrapSandboxValue(scope, ctx.getSandboxValue(key));
268
242
  }
269
- async function getSandboxProperty(value, key) {
243
+ async function getSandboxProperty(scope, value, key) {
270
244
  if (BLOCKED_SANDBOX_KEYS.has(key)) return void 0;
271
245
  const resolved = isTrustedPromise(value) ? await value : value;
272
246
  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;
247
+ const meta = isObjectLike(resolved) ? scope.proxyMeta.get(resolved) : void 0;
248
+ const source = meta ?? resolved;
275
249
  if (isSandboxContextSource(source)) {
276
250
  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;
251
+ return wrapSandboxValue(scope, source.getSandboxValue(key));
281
252
  }
253
+ if (typeof source === "function") return void 0;
282
254
  if (!isObjectLike(source)) {
283
255
  const descriptor2 = getPrimitiveDataDescriptor(source, key);
284
- if (!descriptor2 || typeof descriptor2.value === "function") return void 0;
285
- return wrapSandboxValue(descriptor2.value);
256
+ return descriptor2 ? wrapSandboxValue(scope, descriptor2.value) : void 0;
286
257
  }
287
258
  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);
259
+ return descriptor ? wrapSandboxValue(scope, descriptor.value) : void 0;
291
260
  }
292
- async function evaluate(expr, ctx) {
293
- try {
294
- const raw = expr.trim();
295
- const dotOnly = raw.match(
296
- /^ctx\.([a-zA-Z_$][a-zA-Z0-9_$]*)(?:\.([a-zA-Z_$][a-zA-Z0-9_$-]*(?:\.[a-zA-Z_$][a-zA-Z0-9_$-]*)*))?$/
297
- );
298
- if (dotOnly) {
299
- const first = dotOnly[1];
300
- const rest = dotOnly[2];
301
- const base = getRootSandboxValue(ctx, first);
302
- if (!rest) return await unwrapSandboxValue(wrapSandboxValue(base));
303
- const resolved = await asyncGetValuesByPath(base, rest);
304
- if (typeof resolved !== "undefined" || !rest.includes("-")) {
305
- return await unwrapSandboxValue(resolved);
306
- }
307
- }
308
- const transformed = preprocessExpression(raw);
309
- ensureResolverLockdown();
310
- const compartment = new Compartment({
311
- ctx: wrapRootSandboxContext(ctx),
312
- __get: wrapSandboxValue((varName, path) => getAtPath(ctx, varName, path))
313
- });
314
- const wrapped = `(async () => { try { return ${transformed}; } catch (e) { return undefined; } })()`;
315
- return await unwrapSandboxValue(await compartment.evaluate(wrapped));
316
- } catch (_2) {
261
+ function copyRuntimeSegments(segments) {
262
+ if (!Array.isArray(segments)) return void 0;
263
+ const copy = [];
264
+ for (const segment of segments) {
265
+ if (typeof segment !== "string" && typeof segment !== "number") return void 0;
266
+ copy.push(segment);
267
+ }
268
+ return copy;
269
+ }
270
+ function isPathAllowed(varName, segments, policy) {
271
+ if (typeof varName !== "string") return void 0;
272
+ const runtimeSegments = copyRuntimeSegments(segments);
273
+ if (!runtimeSegments) return void 0;
274
+ if (!policy.allowAll && !policy.unrestrictedVariables.has(varName) && !policy.allowedPaths.has((0, import_variable_expression.getVariableCanonicalKey)(varName, runtimeSegments))) {
317
275
  return void 0;
318
276
  }
277
+ return runtimeSegments;
319
278
  }
320
- async function getAtPath(ctx, varName, path) {
279
+ async function resolveGuardedPath(scope, ctx, policy, aggregateArrays, varName, segments) {
321
280
  try {
322
- let current = getRootSandboxValue(ctx, varName);
323
- if (!path) return current;
324
- const norm = String(path || "").replace(/^\./, "");
325
- const segments = import_lodash.default.toPath(norm);
326
- for (const seg of segments) {
327
- if (current == null) return void 0;
328
- current = await getSandboxProperty(current, seg);
329
- }
330
- return wrapSandboxValue(current);
331
- } catch (_2) {
281
+ const runtimeSegments = isPathAllowed(varName, segments, policy);
282
+ if (!runtimeSegments || typeof varName !== "string") return void 0;
283
+ const root = getRootSandboxValue(scope, ctx, varName);
284
+ return resolveSandboxSegments(scope, root, runtimeSegments, aggregateArrays);
285
+ } catch (_) {
332
286
  return void 0;
333
287
  }
334
288
  }
335
- async function asyncGetValuesByPath(obj, path, defaultValue) {
336
- try {
337
- let currentValue = await obj;
338
- if (!currentValue) return defaultValue;
339
- const keys = String(path || "").split(".");
340
- let result = [];
341
- let shouldReturnArray = false;
342
- for (let i = 0; i < keys.length; i++) {
343
- const key = keys[i];
344
- if (Array.isArray(currentValue)) {
345
- shouldReturnArray = true;
346
- const rest = keys.slice(i).join(".");
347
- const parts = await Promise.all(
348
- Array.prototype.map.call(currentValue, (el) => asyncGetValuesByPath(el, rest, defaultValue))
349
- );
350
- for (const p of parts) {
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);
356
- }
357
- break;
358
- }
359
- currentValue = await getSandboxProperty(currentValue, key);
360
- if (i === keys.length - 1) {
361
- result.push(currentValue);
362
- }
289
+ async function resolveSandboxSegments(scope, value, segments, aggregateArrays) {
290
+ var _a;
291
+ const resolved = isTrustedPromise(value) ? await value : value;
292
+ if (!segments.length || resolved == null) return resolved;
293
+ const [segment, ...rest] = segments;
294
+ const meta = isObjectLike(resolved) ? scope.proxyMeta.get(resolved) : void 0;
295
+ const source = meta ?? resolved;
296
+ const key = String(segment);
297
+ if (aggregateArrays && typeof segment === "string" && Array.isArray(source) && key !== "length") {
298
+ const result = [];
299
+ const length = (_a = Reflect.getOwnPropertyDescriptor(source, "length")) == null ? void 0 : _a.value;
300
+ for (let index = 0; index < (typeof length === "number" ? length : 0); index++) {
301
+ const descriptor = getSandboxDataDescriptor(source, String(index));
302
+ if (!descriptor) continue;
303
+ const part = await resolveSandboxSegments(scope, descriptor.value, segments, true);
304
+ await appendAggregatedValue(scope, result, part);
363
305
  }
364
- result = result.filter((item) => typeof item !== "undefined");
365
- if (result.length === 0) return defaultValue;
366
- if (shouldReturnArray) return result.filter((item) => item !== null);
367
- return result[0];
368
- } catch (_2) {
369
- return defaultValue;
306
+ return wrapSandboxValue(
307
+ scope,
308
+ result.filter((item) => item !== null)
309
+ );
370
310
  }
311
+ const next = await getSandboxProperty(scope, resolved, key);
312
+ return resolveSandboxSegments(scope, next, rest, aggregateArrays);
371
313
  }
372
- function preprocessExpression(expression) {
373
- let out = "";
374
- let i = 0;
375
- const n = expression.length;
376
- while (i < n) {
377
- const dotIdx = expression.indexOf("ctx.", i);
378
- const brkIdx = expression.indexOf("ctx[", i);
379
- let idx = -1;
380
- if (dotIdx === -1) idx = brkIdx;
381
- else if (brkIdx === -1) idx = dotIdx;
382
- else idx = Math.min(dotIdx, brkIdx);
383
- if (idx === -1) {
384
- out += expression.slice(i);
385
- break;
386
- }
387
- out += expression.slice(i, idx);
388
- let j = idx + 3;
389
- let varName = null;
390
- let pathStr = "";
391
- if (expression[j] === ".") {
392
- j += 1;
393
- const varMatch = /^[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(expression.slice(j));
394
- if (!varMatch) {
395
- out += "ctx.";
396
- i = j;
397
- continue;
398
- }
399
- varName = varMatch[0];
400
- j += varName.length;
401
- } else if (expression[j] === "[") {
402
- const m = /^\[("((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)')\]/.exec(expression.slice(j));
403
- if (!m) {
404
- out += "ctx[";
405
- i = j;
406
- continue;
407
- }
408
- varName = m[2] ?? m[3];
409
- j += m[0].length;
410
- } else {
411
- out += expression.slice(idx, idx + 3);
412
- i = idx + 3;
413
- continue;
414
- }
415
- while (j < n) {
416
- if (expression[j] === ".") {
417
- const m = /^\.[a-zA-Z_$][a-zA-Z0-9_$]*/.exec(expression.slice(j));
418
- if (!m) break;
419
- pathStr += m[0];
420
- j += m[0].length;
421
- } else if (expression[j] === "[") {
422
- const m = /^(\[(?:\d+|"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')\])/.exec(expression.slice(j));
423
- if (!m) break;
424
- pathStr += m[1];
425
- j += m[1].length;
426
- } else {
427
- break;
428
- }
429
- }
430
- const argPath = pathStr ? `, ${JSON.stringify(pathStr)}` : "";
431
- out += `(await __get(${JSON.stringify(varName)}${argPath}))`;
432
- i = j;
314
+ async function appendAggregatedValue(scope, result, value) {
315
+ var _a;
316
+ const resolved = isTrustedPromise(value) ? await value : value;
317
+ const meta = isObjectLike(resolved) ? scope.proxyMeta.get(resolved) : void 0;
318
+ const source = meta ?? resolved;
319
+ if (!Array.isArray(source)) {
320
+ if (typeof resolved !== "undefined") result.push(resolved);
321
+ return;
322
+ }
323
+ const length = (_a = Reflect.getOwnPropertyDescriptor(source, "length")) == null ? void 0 : _a.value;
324
+ for (let index = 0; index < (typeof length === "number" ? length : 0); index++) {
325
+ const descriptor = getSandboxDataDescriptor(source, String(index));
326
+ if (descriptor) result.push(wrapSandboxValue(scope, descriptor.value));
327
+ }
328
+ }
329
+ function isStandalonePath(expression) {
330
+ const path = expression.paths[0];
331
+ return !!path && expression.paths.length === 1 && !expression.source.slice(0, path.span.start - expression.expressionSpan.start).trim() && !expression.source.slice(path.span.end - expression.expressionSpan.start).trim();
332
+ }
333
+ function createGuardedCallable(source) {
334
+ const callable = (...args) => Reflect.apply(source, void 0, args);
335
+ return new Proxy(callable, {
336
+ apply: (_target, _thisArg, args) => Reflect.apply(source, void 0, args),
337
+ get: () => void 0,
338
+ has: () => false,
339
+ ownKeys: () => [],
340
+ getOwnPropertyDescriptor: () => void 0,
341
+ getPrototypeOf: () => null,
342
+ setPrototypeOf: () => false,
343
+ preventExtensions: () => false,
344
+ set: () => false,
345
+ defineProperty: () => false,
346
+ deleteProperty: () => false
347
+ });
348
+ }
349
+ async function evaluateAnalyzedExpression(expression, ctx, policy) {
350
+ if (!expression.supported) return void 0;
351
+ try {
352
+ const scope = createSandboxScope();
353
+ const aggregateArrays = isStandalonePath(expression);
354
+ const helper = createGuardedCallable(
355
+ (varName, segments) => resolveGuardedPath(scope, ctx, policy, aggregateArrays, varName, segments)
356
+ );
357
+ ensureResolverLockdown();
358
+ const compartment = new Compartment();
359
+ const factory = compartment.evaluate(
360
+ `async (${expression.helperIdentifier}) => { try { return ${expression.compiled}; } catch (_) { return undefined; } }`
361
+ );
362
+ return await unwrapSandboxValue(scope, await factory(helper));
363
+ } catch (_) {
364
+ return void 0;
433
365
  }
434
- return out;
435
366
  }
436
367
  // Annotate the CommonJS export names for ESM import in node:
437
368
  0 && (module.exports = {
438
- preprocessExpression,
369
+ resolveAnalyzedJsonTemplate,
439
370
  resolveJsonTemplate
440
371
  });