@nocobase/plugin-flow-engine 2.2.0-beta.2 → 2.2.0-beta.3

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 (45) hide show
  1. package/dist/externalVersion.js +9 -9
  2. package/dist/node_modules/@ant-design/icons-svg/package.json +1 -1
  3. package/dist/node_modules/acorn/package.json +1 -1
  4. package/dist/node_modules/acorn-jsx/package.json +1 -1
  5. package/dist/node_modules/acorn-walk/package.json +1 -1
  6. package/dist/node_modules/ses/package.json +1 -1
  7. package/dist/node_modules/zod/package.json +1 -1
  8. package/dist/server/flow-surfaces/approval/authoring-validation.d.ts +9 -0
  9. package/dist/server/flow-surfaces/approval/authoring-validation.js +1151 -0
  10. package/dist/server/flow-surfaces/approval/blueprint-service.js +2 -0
  11. package/dist/server/flow-surfaces/authoring-validation.js +372 -32
  12. package/dist/server/flow-surfaces/blueprint/export-document.d.ts +50 -0
  13. package/dist/server/flow-surfaces/blueprint/export-document.js +2503 -0
  14. package/dist/server/flow-surfaces/constants.d.ts +9 -2
  15. package/dist/server/flow-surfaces/constants.js +1 -0
  16. package/dist/server/flow-surfaces/default-action-popup.d.ts +2 -0
  17. package/dist/server/flow-surfaces/default-action-popup.js +27 -13
  18. package/dist/server/flow-surfaces/filter-group.d.ts +19 -2
  19. package/dist/server/flow-surfaces/filter-group.js +232 -3
  20. package/dist/server/flow-surfaces/planning/compiler.d.ts +1 -0
  21. package/dist/server/flow-surfaces/planning/compiler.js +205 -82
  22. package/dist/server/flow-surfaces/planning/runtime.js +1 -0
  23. package/dist/server/flow-surfaces/planning/step-link.d.ts +1 -1
  24. package/dist/server/flow-surfaces/planning/step-link.js +22 -3
  25. package/dist/server/flow-surfaces/public-data-surface-default-filter.js +0 -9
  26. package/dist/server/flow-surfaces/reaction/field-value.d.ts +9 -0
  27. package/dist/server/flow-surfaces/reaction/field-value.js +51 -2
  28. package/dist/server/flow-surfaces/reaction/linkage.d.ts +6 -1
  29. package/dist/server/flow-surfaces/reaction/linkage.js +18 -3
  30. package/dist/server/flow-surfaces/reaction/meta.js +19 -1
  31. package/dist/server/flow-surfaces/reaction/types.d.ts +19 -0
  32. package/dist/server/flow-surfaces/relation-backing-foreign-key.d.ts +10 -0
  33. package/dist/server/flow-surfaces/relation-backing-foreign-key.js +79 -0
  34. package/dist/server/flow-surfaces/runjs-authoring/ast/source.d.ts +1 -0
  35. package/dist/server/flow-surfaces/runjs-authoring/ast/source.js +20 -0
  36. package/dist/server/flow-surfaces/runjs-authoring/scan/filter.js +12 -2
  37. package/dist/server/flow-surfaces/runjs-authoring/scan/index.js +9 -1
  38. package/dist/server/flow-surfaces/service.d.ts +19 -0
  39. package/dist/server/flow-surfaces/service.js +189 -20
  40. package/dist/swagger/flow-surfaces.d.ts +180 -0
  41. package/dist/swagger/flow-surfaces.examples.d.ts +8 -0
  42. package/dist/swagger/flow-surfaces.examples.js +8 -0
  43. package/dist/swagger/flow-surfaces.js +160 -4
  44. package/dist/swagger/index.d.ts +180 -0
  45. package/package.json +2 -2
@@ -180,6 +180,8 @@ async function resolvePlanSelectorInContext(actionName, selector, context, deps,
180
180
  uid: resolved.uid,
181
181
  source: "system",
182
182
  kind: deps.buildPlanKeyKind(node, resolved.kind),
183
+ node: node || resolved.node,
184
+ resolved,
183
185
  locator: (0, import_service_utils.buildDefinedPayload)({
184
186
  uid: normalizedSelector.locator.uid,
185
187
  pageSchemaUid: normalizedSelector.locator.pageSchemaUid,
@@ -217,51 +219,146 @@ function buildSelectorRuntimeValue(selector) {
217
219
  }
218
220
  return selector.uid;
219
221
  }
222
+ function getResolvedSelectorUid(selector) {
223
+ if (!selector || "summary" in selector) {
224
+ return void 0;
225
+ }
226
+ return selector.uid;
227
+ }
228
+ function isReplaceComposeStep(step) {
229
+ var _a;
230
+ return step.action === "compose" && String(((_a = step.values) == null ? void 0 : _a.mode) || "").trim() === "replace";
231
+ }
232
+ function assertReplaceComposeTargetSupportsScopeResolution(actionName, index, step, target) {
233
+ if (!isReplaceComposeStep(step) || !target || !("summary" in target) || target.summary.source !== "step") {
234
+ return;
235
+ }
236
+ (0, import_errors.throwBadRequest)(
237
+ `flowSurfaces ${actionName} plan.steps[${index}] compose replace does not support selectors.target.step; use a concrete locator or key for the existing replace target`
238
+ );
239
+ }
240
+ function collectDescendantUids(node, carry = /* @__PURE__ */ new Set()) {
241
+ if (!node || typeof node !== "object") {
242
+ return carry;
243
+ }
244
+ for (const value of Object.values(node.subModels || {})) {
245
+ for (const child of import_lodash.default.castArray(value)) {
246
+ if (child == null ? void 0 : child.uid) {
247
+ carry.add(child.uid);
248
+ }
249
+ collectDescendantUids(child, carry);
250
+ }
251
+ }
252
+ return carry;
253
+ }
254
+ function collectNodeAndDescendantUids(node, carry = /* @__PURE__ */ new Set()) {
255
+ if (!node || typeof node !== "object") {
256
+ return carry;
257
+ }
258
+ if (node.uid) {
259
+ carry.add(node.uid);
260
+ }
261
+ return collectDescendantUids(node, carry);
262
+ }
263
+ function findNodeInTreeByUid(node, uid) {
264
+ if (!node || typeof node !== "object" || !uid) {
265
+ return void 0;
266
+ }
267
+ if (node.uid === uid) {
268
+ return node;
269
+ }
270
+ for (const value of Object.values(node.subModels || {})) {
271
+ for (const child of import_lodash.default.castArray(value)) {
272
+ const matched = findNodeInTreeByUid(child, uid);
273
+ if (matched) {
274
+ return matched;
275
+ }
276
+ }
277
+ }
278
+ return void 0;
279
+ }
280
+ function getContextNodeByUid(context, uid) {
281
+ if (!uid) {
282
+ return void 0;
283
+ }
284
+ return findNodeInTreeByUid(context.publicTree, uid) || findNodeInTreeByUid(context.rawTree, uid);
285
+ }
286
+ function getSingleSubModel(node, key) {
287
+ var _a;
288
+ const value = (_a = node == null ? void 0 : node.subModels) == null ? void 0 : _a[key];
289
+ return Array.isArray(value) ? value[0] : value;
290
+ }
291
+ function getSubModelList(node, key) {
292
+ var _a;
293
+ return import_lodash.default.castArray(((_a = node == null ? void 0 : node.subModels) == null ? void 0 : _a[key]) || []).filter((item) => item && typeof item === "object");
294
+ }
295
+ function isGridNode(node) {
296
+ return typeof (node == null ? void 0 : node.use) === "string" && node.use.endsWith("GridModel");
297
+ }
298
+ function resolveReplaceComposeGridNode(targetNode) {
299
+ if (!targetNode || typeof targetNode !== "object") {
300
+ return void 0;
301
+ }
302
+ if (isGridNode(targetNode)) {
303
+ return targetNode;
304
+ }
305
+ const directGrid = getSingleSubModel(targetNode, "grid");
306
+ if (directGrid) {
307
+ return directGrid;
308
+ }
309
+ const firstTab = getSubModelList(targetNode, "tabs")[0];
310
+ const firstTabGrid = getSingleSubModel(firstTab, "grid");
311
+ if (firstTabGrid) {
312
+ return firstTabGrid;
313
+ }
314
+ const popupPage = getSingleSubModel(targetNode, "page");
315
+ const firstPopupTab = getSubModelList(popupPage, "tabs")[0];
316
+ return getSingleSubModel(firstPopupTab, "grid");
317
+ }
318
+ async function collectReplaceScopeExistingKeys(step, context, target, deps, options = {}) {
319
+ if (!isReplaceComposeStep(step)) {
320
+ return /* @__PURE__ */ new Set();
321
+ }
322
+ let targetNode = getContextNodeByUid(context, getResolvedSelectorUid(target)) || (!target || "summary" in target ? void 0 : target.node);
323
+ if (!targetNode && target && !("summary" in target) && target.resolved && deps.loadResolvedSurfaceTree) {
324
+ targetNode = await deps.loadResolvedSurfaceTree(target.resolved, options.transaction);
325
+ }
326
+ if (!targetNode) {
327
+ return /* @__PURE__ */ new Set();
328
+ }
329
+ const gridNode = resolveReplaceComposeGridNode(targetNode);
330
+ if (!gridNode) {
331
+ return /* @__PURE__ */ new Set();
332
+ }
333
+ const replacedUids = /* @__PURE__ */ new Set();
334
+ for (const item of getSubModelList(gridNode, "items")) {
335
+ collectNodeAndDescendantUids(item, replacedUids);
336
+ }
337
+ const keys = /* @__PURE__ */ new Set();
338
+ context.keyMap.forEach((info, key) => {
339
+ if (replacedUids.has(info.uid)) {
340
+ keys.add(key);
341
+ }
342
+ });
343
+ return keys;
344
+ }
345
+ function buildExistingKeysForConflict(context, priorCreatedKeys, allowedExistingKeys) {
346
+ const existing = /* @__PURE__ */ new Set();
347
+ context.keyMap.forEach((_info, key) => {
348
+ if (!allowedExistingKeys.has(key)) {
349
+ existing.add(key);
350
+ }
351
+ });
352
+ priorCreatedKeys.forEach((key) => existing.add(key));
353
+ return existing;
354
+ }
220
355
  async function compilePlanStep(actionName, step, index, context, deps, priorStepIds, priorCreatedKeys, options = {}) {
221
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
356
+ var _a, _b, _c, _d, _e, _f, _g;
222
357
  const runtimeValues = step.action === "compose" ? (0, import_created_keys.normalizeComposeInlineKeysForPlan)(step.values || {}, `plan.steps[${index}].values`) : import_lodash.default.cloneDeep(step.values || {});
223
- const payload = (0, import_step_link.replaceFlowSurfacePlanStepLinks)(
224
- actionName,
225
- runtimeValues,
226
- `plan.steps[${index}].values`,
227
- priorStepIds,
228
- /* @__PURE__ */ new Set([...context.keyMap.keys(), ...priorCreatedKeys])
229
- );
230
358
  const targetSelectorKey = (0, import_created_keys.isFlowSurfacePureKeyObject)((_a = step.selectors) == null ? void 0 : _a.target) ? String(step.selectors.target.key || "").trim() : void 0;
231
359
  const createdKeys = (0, import_created_keys.collectFlowSurfaceCreatedKeys)(step.action, step.values || {}, {
232
360
  targetSelectorKey
233
361
  });
234
- (0, import_created_keys.assertNoDuplicateFlowSurfaceCreatedKeys)(createdKeys, `flowSurfaces ${actionName} plan.steps[${index}]`, {
235
- existingKeys: [...context.keyMap.keys(), ...priorCreatedKeys],
236
- reservedNames: [...priorStepIds, ...step.id ? [step.id] : []]
237
- });
238
- const compiled = {
239
- index,
240
- ...step.id ? { id: step.id } : {},
241
- action: step.action,
242
- payload,
243
- resolvedSelectors: {},
244
- usedKeys: [],
245
- usedStepLinks: [],
246
- createdKeys
247
- };
248
- const addUsedKey = (selector) => {
249
- if ("summary" in selector) {
250
- if (isFlowSurfaceResolvedStepLink(selector)) {
251
- compiled.usedStepLinks.push(selector);
252
- }
253
- return selector.summary;
254
- }
255
- if (selector.source === "request" || selector.source === "declared") {
256
- compiled.usedKeys.push(selector);
257
- }
258
- return {
259
- uid: selector.uid,
260
- kind: selector.kind,
261
- ...selector.key ? { key: selector.key } : {},
262
- source: selector.source
263
- };
264
- };
265
362
  const spec = (0, import_action_specs.getFlowSurfacePlanActionSpec)(step.action);
266
363
  if (!spec) {
267
364
  (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} plan.steps[${index}].action '${step.action}' is not supported`);
@@ -283,14 +380,14 @@ async function compilePlanStep(actionName, step, index, context, deps, priorStep
283
380
  `flowSurfaces ${actionName} plan.steps[${index}] action '${step.action}' does not support selectors.source`
284
381
  );
285
382
  }
286
- if (spec.selectorMode === "none") {
287
- compiled.payload = payload;
288
- } else if (spec.selectorMode === "target") {
383
+ let resolvedTarget;
384
+ let resolvedSource;
385
+ if (selectorRequirements.requiresTarget) {
289
386
  const targetSelector = (_f = step.selectors) == null ? void 0 : _f.target;
290
387
  if (!targetSelector) {
291
388
  (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} plan.steps[${index}] requires selectors.target`);
292
389
  }
293
- const target = await resolvePlanSelectorInContext(
390
+ resolvedTarget = await resolvePlanSelectorInContext(
294
391
  actionName,
295
392
  targetSelector,
296
393
  context,
@@ -300,59 +397,85 @@ async function compilePlanStep(actionName, step, index, context, deps, priorStep
300
397
  priorCreatedKeys,
301
398
  options
302
399
  );
303
- compiled.payload = {
304
- ...payload,
305
- target: {
306
- uid: buildSelectorRuntimeValue(target)
307
- }
308
- };
309
- compiled.resolvedSelectors.target = addUsedKey(target);
310
- } else if (spec.selectorMode === "rootUidTarget") {
311
- const targetSelector = (_g = step.selectors) == null ? void 0 : _g.target;
312
- if (!targetSelector) {
313
- (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} plan.steps[${index}] requires selectors.target`);
400
+ }
401
+ if (selectorRequirements.requiresSource) {
402
+ const sourceSelector = (_g = step.selectors) == null ? void 0 : _g.source;
403
+ if (!sourceSelector) {
404
+ (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} plan.steps[${index}] requires selectors.source`);
314
405
  }
315
- const target = await resolvePlanSelectorInContext(
406
+ resolvedSource = await resolvePlanSelectorInContext(
316
407
  actionName,
317
- targetSelector,
408
+ sourceSelector,
318
409
  context,
319
410
  deps,
320
- `plan.steps[${index}].selectors.target`,
411
+ `plan.steps[${index}].selectors.source`,
321
412
  priorStepIds,
322
413
  priorCreatedKeys,
323
414
  options
324
415
  );
416
+ }
417
+ assertReplaceComposeTargetSupportsScopeResolution(actionName, index, step, resolvedTarget);
418
+ const allowedExistingKeys = await collectReplaceScopeExistingKeys(step, context, resolvedTarget, deps, options);
419
+ (0, import_created_keys.assertNoDuplicateFlowSurfaceCreatedKeys)(createdKeys, `flowSurfaces ${actionName} plan.steps[${index}]`, {
420
+ existingKeys: buildExistingKeysForConflict(context, priorCreatedKeys, allowedExistingKeys),
421
+ reservedNames: [...priorStepIds, ...step.id ? [step.id] : []]
422
+ });
423
+ const payload = (0, import_step_link.replaceFlowSurfacePlanStepLinks)(
424
+ actionName,
425
+ runtimeValues,
426
+ `plan.steps[${index}].values`,
427
+ priorStepIds,
428
+ /* @__PURE__ */ new Set([...context.keyMap.keys(), ...priorCreatedKeys]),
429
+ allowedExistingKeys
430
+ );
431
+ const compiled = {
432
+ index,
433
+ ...step.id ? { id: step.id } : {},
434
+ action: step.action,
435
+ payload,
436
+ resolvedSelectors: {},
437
+ usedKeys: [],
438
+ usedStepLinks: [],
439
+ createdKeys
440
+ };
441
+ const addUsedKey = (selector) => {
442
+ if ("summary" in selector) {
443
+ if (isFlowSurfaceResolvedStepLink(selector)) {
444
+ compiled.usedStepLinks.push(selector);
445
+ }
446
+ return selector.summary;
447
+ }
448
+ if (selector.source === "request" || selector.source === "declared") {
449
+ compiled.usedKeys.push(selector);
450
+ }
451
+ return {
452
+ uid: selector.uid,
453
+ kind: selector.kind,
454
+ ...selector.key ? { key: selector.key } : {},
455
+ source: selector.source
456
+ };
457
+ };
458
+ if (spec.selectorMode === "none") {
459
+ compiled.payload = payload;
460
+ } else if (spec.selectorMode === "target") {
461
+ const target = resolvedTarget;
462
+ compiled.payload = {
463
+ ...payload,
464
+ target: {
465
+ uid: buildSelectorRuntimeValue(target)
466
+ }
467
+ };
468
+ compiled.resolvedSelectors.target = addUsedKey(target);
469
+ } else if (spec.selectorMode === "rootUidTarget") {
470
+ const target = resolvedTarget;
325
471
  compiled.payload = {
326
472
  ...payload,
327
473
  uid: buildSelectorRuntimeValue(target)
328
474
  };
329
475
  compiled.resolvedSelectors.target = addUsedKey(target);
330
476
  } else if (spec.selectorMode === "sourceTarget") {
331
- const sourceSelector = (_h = step.selectors) == null ? void 0 : _h.source;
332
- const targetSelector = (_i = step.selectors) == null ? void 0 : _i.target;
333
- if (!sourceSelector || !targetSelector) {
334
- (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} plan.steps[${index}] requires selectors.source and selectors.target`);
335
- }
336
- const source = await resolvePlanSelectorInContext(
337
- actionName,
338
- sourceSelector,
339
- context,
340
- deps,
341
- `plan.steps[${index}].selectors.source`,
342
- priorStepIds,
343
- priorCreatedKeys,
344
- options
345
- );
346
- const target = await resolvePlanSelectorInContext(
347
- actionName,
348
- targetSelector,
349
- context,
350
- deps,
351
- `plan.steps[${index}].selectors.target`,
352
- priorStepIds,
353
- priorCreatedKeys,
354
- options
355
- );
477
+ const source = resolvedSource;
478
+ const target = resolvedTarget;
356
479
  compiled.payload = {
357
480
  ...payload,
358
481
  sourceUid: buildSelectorRuntimeValue(source),
@@ -152,6 +152,7 @@ async function compilePlanStep(actionName, step, index, context, deps, priorStep
152
152
  {
153
153
  normalizeGetTarget: deps.normalizeGetTarget,
154
154
  resolveLocator: deps.resolveLocator,
155
+ loadResolvedSurfaceTree: deps.loadResolvedSurfaceTree,
155
156
  buildPlanKeyKind: import_key_kind.buildPlanKeyKind
156
157
  },
157
158
  priorStepIds,
@@ -11,4 +11,4 @@ import type { FlowSurfacePlanStepLink } from '../types';
11
11
  export declare const isFlowSurfacePlanStepLink: typeof isFlowSurfacePlanStepValue;
12
12
  export declare function normalizeFlowSurfacePlanStepLink(actionName: string, input: any, fieldName: string): FlowSurfacePlanStepLink;
13
13
  export declare function assertFlowSurfaceKnownPlanStepLink(actionName: string, stepLink: FlowSurfacePlanStepLink, fieldName: string, knownStepIds?: Set<string>): void;
14
- export declare function replaceFlowSurfacePlanStepLinks(actionName: string, input: any, path: string, knownStepIds?: Set<string>, knownRuntimeKeys?: Set<string>): any;
14
+ export declare function replaceFlowSurfacePlanStepLinks(actionName: string, input: any, path: string, knownStepIds?: Set<string>, knownRuntimeKeys?: Set<string>, blockedRuntimeKeys?: Set<string>): any;
@@ -56,10 +56,17 @@ function assertFlowSurfaceKnownPlanStepLink(actionName, stepLink, fieldName, kno
56
56
  }
57
57
  (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${fieldName}.step '${stepLink.step}' is not a previous step id`);
58
58
  }
59
- function replaceFlowSurfacePlanStepLinks(actionName, input, path, knownStepIds, knownRuntimeKeys) {
59
+ function replaceFlowSurfacePlanStepLinks(actionName, input, path, knownStepIds, knownRuntimeKeys, blockedRuntimeKeys) {
60
60
  if (Array.isArray(input)) {
61
61
  return input.map(
62
- (item, index) => replaceFlowSurfacePlanStepLinks(actionName, item, `${path}[${index}]`, knownStepIds, knownRuntimeKeys)
62
+ (item, index) => replaceFlowSurfacePlanStepLinks(
63
+ actionName,
64
+ item,
65
+ `${path}[${index}]`,
66
+ knownStepIds,
67
+ knownRuntimeKeys,
68
+ blockedRuntimeKeys
69
+ )
63
70
  );
64
71
  }
65
72
  if (!import_lodash.default.isPlainObject(input)) {
@@ -81,6 +88,11 @@ function replaceFlowSurfacePlanStepLinks(actionName, input, path, knownStepIds,
81
88
  if (!runtimeKey) {
82
89
  (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.key cannot be empty`);
83
90
  }
91
+ if (blockedRuntimeKeys == null ? void 0 : blockedRuntimeKeys.has(runtimeKey)) {
92
+ (0, import_errors.throwBadRequest)(
93
+ `flowSurfaces ${actionName} ${path}.key '${runtimeKey}' belongs to the current replace scope; replace-step key links cannot resolve to old replace subtree nodes`
94
+ );
95
+ }
84
96
  if (!(knownRuntimeKeys == null ? void 0 : knownRuntimeKeys.has(runtimeKey))) {
85
97
  (0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} ${path}.key '${runtimeKey}' is not defined`);
86
98
  }
@@ -91,7 +103,14 @@ function replaceFlowSurfacePlanStepLinks(actionName, input, path, knownStepIds,
91
103
  return Object.fromEntries(
92
104
  Object.entries(input).map(([key, value]) => [
93
105
  key,
94
- replaceFlowSurfacePlanStepLinks(actionName, value, `${path}.${key}`, knownStepIds, knownRuntimeKeys)
106
+ replaceFlowSurfacePlanStepLinks(
107
+ actionName,
108
+ value,
109
+ `${path}.${key}`,
110
+ knownStepIds,
111
+ knownRuntimeKeys,
112
+ blockedRuntimeKeys
113
+ )
95
114
  ])
96
115
  );
97
116
  }
@@ -299,9 +299,7 @@ function backfillFlowSurfaceDefaultFilterSetting(settings, defaultFilter) {
299
299
  if (import_lodash.default.isUndefined(defaultFilter)) {
300
300
  return settings;
301
301
  }
302
- const filterableFieldNames = resolveFlowSurfaceDefaultFilterFieldNames(defaultFilter);
303
302
  const defaults = {
304
- ...filterableFieldNames.length ? { filterableFieldNames } : {},
305
303
  defaultFilter: import_lodash.default.cloneDeep(defaultFilter)
306
304
  };
307
305
  if (import_lodash.default.isUndefined(settings)) {
@@ -311,13 +309,6 @@ function backfillFlowSurfaceDefaultFilterSetting(settings, defaultFilter) {
311
309
  return settings;
312
310
  }
313
311
  if (Object.prototype.hasOwnProperty.call(settings, "defaultFilter")) {
314
- const explicitFilterableFieldNames = resolveFlowSurfaceDefaultFilterFieldNames(settings.defaultFilter);
315
- if (!Object.prototype.hasOwnProperty.call(settings, "filterableFieldNames") && explicitFilterableFieldNames.length) {
316
- return {
317
- ...import_lodash.default.cloneDeep(settings),
318
- filterableFieldNames: explicitFilterableFieldNames
319
- };
320
- }
321
312
  return settings;
322
313
  }
323
314
  return {
@@ -17,6 +17,15 @@ export type FlowSurfaceFieldValueCompileResult = FlowSurfaceReactionWriteResult<
17
17
  export declare function isFieldValueTargetUseSupported(use?: string | null): boolean;
18
18
  export declare function assertFieldValueTargetSupported(target: FlowSurfaceFieldValueTarget): void;
19
19
  export declare function normalizeFieldValueRules(rules: FlowSurfaceFieldValueRule[] | undefined): FlowSurfaceFieldValueRule[];
20
+ export declare function validateFieldValueRulesAgainstCapability(rules: FlowSurfaceFieldValueRule[], capability: {
21
+ conditionMeta: {
22
+ operatorsByPath: Record<string, string[]>;
23
+ fieldMetaByPath?: Record<string, {
24
+ type?: string;
25
+ interface?: string;
26
+ }>;
27
+ };
28
+ }): void;
20
29
  export declare function compileFieldValueRulesToCanonical(rules: FlowSurfaceFieldValueRule[] | undefined): {
21
30
  key: string;
22
31
  enable: boolean;
@@ -41,11 +41,13 @@ __export(field_value_exports, {
41
41
  collectUpdateAssociationValuesFromFieldValueRules: () => collectUpdateAssociationValuesFromFieldValueRules,
42
42
  compileFieldValueRulesToCanonical: () => compileFieldValueRulesToCanonical,
43
43
  isFieldValueTargetUseSupported: () => isFieldValueTargetUseSupported,
44
- normalizeFieldValueRules: () => normalizeFieldValueRules
44
+ normalizeFieldValueRules: () => normalizeFieldValueRules,
45
+ validateFieldValueRulesAgainstCapability: () => validateFieldValueRulesAgainstCapability
45
46
  });
46
47
  module.exports = __toCommonJS(field_value_exports);
47
48
  var import_lodash = __toESM(require("lodash"));
48
49
  var import_errors = require("../errors");
50
+ var import_filter_group = require("../filter-group");
49
51
  var import_errors2 = require("./errors");
50
52
  var import_fingerprint = require("./fingerprint");
51
53
  var import_registry = require("./registry");
@@ -85,6 +87,52 @@ function normalizeFieldValueRules(rules) {
85
87
  const list = Array.isArray(rules) ? rules : [];
86
88
  return list.map((rule, index) => normalizeFieldValueRule(rule, index));
87
89
  }
90
+ function validateFieldValueRulesAgainstCapability(rules, capability) {
91
+ for (const [ruleIndex, rule] of (rules || []).entries()) {
92
+ validateFieldValueDateConditionFilter(rule.when, capability, `rules[${ruleIndex}].when`);
93
+ }
94
+ }
95
+ function validateFieldValueDateConditionFilter(filter, capability, prefix) {
96
+ const visit = (node, currentPrefix) => {
97
+ var _a;
98
+ if (!import_lodash.default.isPlainObject(node)) {
99
+ return;
100
+ }
101
+ if (Array.isArray(node.items)) {
102
+ node.items.forEach((item, index) => visit(item, `${currentPrefix}.items[${index}]`));
103
+ return;
104
+ }
105
+ const operator = typeof node.operator === "string" ? node.operator.trim() : "";
106
+ const path = typeof node.path === "string" ? node.path.trim() : "";
107
+ if (!operator || !path || !Object.prototype.hasOwnProperty.call(node, "value")) {
108
+ return;
109
+ }
110
+ const fieldMeta = resolveFieldValueConditionFieldMeta(path, (_a = capability.conditionMeta) == null ? void 0 : _a.fieldMetaByPath);
111
+ if (!import_filter_group.FLOW_SURFACE_DATE_FILTER_OPERATORS.has(operator) && !(0, import_filter_group.isFlowSurfaceDateLikeFieldMeta)(fieldMeta)) {
112
+ return;
113
+ }
114
+ (0, import_filter_group.normalizeFlowSurfaceDateConditionValue)(operator, node.value, `${currentPrefix}.value`, {
115
+ fieldPath: path,
116
+ fieldType: fieldMeta == null ? void 0 : fieldMeta.type,
117
+ fieldInterface: fieldMeta == null ? void 0 : fieldMeta.interface,
118
+ allowContextPathValue: true
119
+ });
120
+ };
121
+ visit(filter, prefix);
122
+ }
123
+ function resolveFieldValueConditionFieldMeta(path, fieldMetaByPath) {
124
+ if (!fieldMetaByPath) {
125
+ return void 0;
126
+ }
127
+ if (fieldMetaByPath[path]) {
128
+ return fieldMetaByPath[path];
129
+ }
130
+ const wildcardPath = Object.keys(fieldMetaByPath).filter((candidate) => candidate.endsWith(".*")).sort((a, b) => b.length - a.length).find((candidate) => {
131
+ const prefix = candidate.slice(0, -2);
132
+ return path.startsWith(`${prefix}.`) && path.length > prefix.length + 1;
133
+ });
134
+ return wildcardPath ? fieldMetaByPath[wildcardPath] : void 0;
135
+ }
88
136
  function compileFieldValueRulesToCanonical(rules) {
89
137
  return normalizeFieldValueRules(rules).map((rule) => ({
90
138
  key: rule.key,
@@ -177,5 +225,6 @@ function buildFieldValueWriteResult(params) {
177
225
  collectUpdateAssociationValuesFromFieldValueRules,
178
226
  compileFieldValueRulesToCanonical,
179
227
  isFieldValueTargetUseSupported,
180
- normalizeFieldValueRules
228
+ normalizeFieldValueRules,
229
+ validateFieldValueRulesAgainstCapability
181
230
  });
@@ -6,7 +6,7 @@
6
6
  * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
- import type { FlowSurfaceActionLinkageRule, FlowSurfaceFieldLinkageRule, FlowSurfaceFieldLinkageScene, FlowSurfaceFieldOption, FlowSurfaceFieldPathToUidResolver, FlowSurfaceFieldUidToPathResolver, FlowSurfaceBlockLinkageRule } from './types';
9
+ import type { FlowSurfaceActionLinkageRule, FlowSurfaceFieldLinkageRule, FlowSurfaceFieldLinkageScene, FlowSurfaceFieldOption, FlowSurfaceFieldPathToUidResolver, FlowSurfaceFieldUidToPathResolver, FlowSurfaceReactionFilter, FlowSurfaceBlockLinkageRule } from './types';
10
10
  type NormalizeFieldRuleOptions = {
11
11
  scene: FlowSurfaceFieldLinkageScene;
12
12
  resolveFieldPath?: FlowSurfaceFieldUidToPathResolver;
@@ -18,6 +18,10 @@ type CompileFieldRuleOptions = {
18
18
  type FlowSurfaceLinkageValidationCapability = {
19
19
  conditionMeta: {
20
20
  operatorsByPath: Record<string, string[]>;
21
+ fieldMetaByPath?: Record<string, {
22
+ type?: string;
23
+ interface?: string;
24
+ }>;
21
25
  };
22
26
  };
23
27
  type FlowSurfaceFieldLinkageValidationCapability = FlowSurfaceLinkageValidationCapability & {
@@ -26,6 +30,7 @@ type FlowSurfaceFieldLinkageValidationCapability = FlowSurfaceLinkageValidationC
26
30
  supportedSources: Array<'literal' | 'path' | 'runjs'>;
27
31
  };
28
32
  };
33
+ export declare function validateReactionFilterAgainstCapability(filter: FlowSurfaceReactionFilter | undefined, capability: FlowSurfaceLinkageValidationCapability, prefix: string): void;
29
34
  export declare function buildReactionFingerprint(value: any): string;
30
35
  export declare function normalizeBlockLinkageRules(rawRules: unknown): FlowSurfaceBlockLinkageRule[];
31
36
  export declare function normalizeActionLinkageRules(rawRules: unknown): FlowSurfaceActionLinkageRule[];
@@ -48,7 +48,8 @@ __export(linkage_exports, {
48
48
  validateBlockLinkageRulesAgainstCapability: () => validateBlockLinkageRulesAgainstCapability,
49
49
  validateBlockLinkageSceneSupport: () => validateBlockLinkageSceneSupport,
50
50
  validateFieldLinkageRulesAgainstCapability: () => validateFieldLinkageRulesAgainstCapability,
51
- validateFieldLinkageSceneSupport: () => validateFieldLinkageSceneSupport
51
+ validateFieldLinkageSceneSupport: () => validateFieldLinkageSceneSupport,
52
+ validateReactionFilterAgainstCapability: () => validateReactionFilterAgainstCapability
52
53
  });
53
54
  module.exports = __toCommonJS(linkage_exports);
54
55
  var import_node_crypto = require("node:crypto");
@@ -148,7 +149,10 @@ function normalizeReactionFilter(rawFilter) {
148
149
  }
149
150
  const normalizedFilter = (0, import_filter_group.normalizeFlowSurfaceCompatibleFilterGroupValue)(
150
151
  rawFilter,
151
- "flowSurfaces linkage rule condition"
152
+ "flowSurfaces linkage rule condition",
153
+ {
154
+ allowContextPathValue: true
155
+ }
152
156
  );
153
157
  const visit = (node) => {
154
158
  if (!import_lodash.default.isPlainObject(node)) {
@@ -639,6 +643,7 @@ function validateReactionFilterAgainstCapability(filter, capability, prefix) {
639
643
  var _a;
640
644
  const operatorsByPath = ((_a = capability.conditionMeta) == null ? void 0 : _a.operatorsByPath) || {};
641
645
  const visit = (node, currentPrefix) => {
646
+ var _a2, _b;
642
647
  if (!import_lodash.default.isPlainObject(node)) {
643
648
  return;
644
649
  }
@@ -683,6 +688,15 @@ function validateReactionFilterAgainstCapability(filter, capability, prefix) {
683
688
  );
684
689
  }
685
690
  if (hasValue) {
691
+ const fieldMeta = (_b = (_a2 = capability.conditionMeta) == null ? void 0 : _a2.fieldMetaByPath) == null ? void 0 : _b[operatorPath];
692
+ if (import_filter_group.FLOW_SURFACE_DATE_FILTER_OPERATORS.has(operator) || (0, import_filter_group.isFlowSurfaceDateLikeFieldMeta)(fieldMeta)) {
693
+ (0, import_filter_group.normalizeFlowSurfaceDateConditionValue)(operator, node.value, `${currentPrefix}.value`, {
694
+ fieldPath: path,
695
+ fieldType: fieldMeta == null ? void 0 : fieldMeta.type,
696
+ fieldInterface: fieldMeta == null ? void 0 : fieldMeta.interface,
697
+ allowContextPathValue: true
698
+ });
699
+ }
686
700
  validateContextBoundValue(node.value, capability, `${currentPrefix}.value`);
687
701
  }
688
702
  };
@@ -895,5 +909,6 @@ function compileFieldLinkageCanonicalRules(rules, options) {
895
909
  validateBlockLinkageRulesAgainstCapability,
896
910
  validateBlockLinkageSceneSupport,
897
911
  validateFieldLinkageRulesAgainstCapability,
898
- validateFieldLinkageSceneSupport
912
+ validateFieldLinkageSceneSupport,
913
+ validateReactionFilterAgainstCapability
899
914
  });
@@ -114,6 +114,19 @@ function buildConditionOperatorsByPath(context) {
114
114
  }
115
115
  return operatorsByPath;
116
116
  }
117
+ function buildConditionFieldMetaByPath(context) {
118
+ const fieldMetaByPath = {};
119
+ for (const [path, info] of collectContextPathEntries(context)) {
120
+ if (!isAuthorableLinkageContextPath(path)) {
121
+ continue;
122
+ }
123
+ fieldMetaByPath[path] = {
124
+ ...(info == null ? void 0 : info.type) ? { type: info.type } : {},
125
+ ...(info == null ? void 0 : info.interface) ? { interface: info.interface } : {}
126
+ };
127
+ }
128
+ return fieldMetaByPath;
129
+ }
117
130
  function isAuthorableLinkageContextPath(path) {
118
131
  const segments = String(path || "").split(".").filter(Boolean);
119
132
  const root = segments[0];
@@ -395,6 +408,10 @@ function buildFieldValueCapability(input, capability) {
395
408
  canonicalRules,
396
409
  context: input.context,
397
410
  targetFields: collectFieldOptions(input.resolvedTarget.node, input.context, capability.resolvedScene),
411
+ conditionMeta: {
412
+ operatorsByPath: buildConditionOperatorsByPath(input.context),
413
+ fieldMetaByPath: buildConditionFieldMetaByPath(input.context)
414
+ },
398
415
  valueExprMeta: {
399
416
  supportedSources: ["literal", "path", "runjs"],
400
417
  runjsScene: "fieldValue"
@@ -412,7 +429,8 @@ function buildLinkageCapability(input, capability) {
412
429
  context: input.context,
413
430
  supportedActions: buildSupportedActions(capability),
414
431
  conditionMeta: {
415
- operatorsByPath: buildConditionOperatorsByPath(input.context)
432
+ operatorsByPath: buildConditionOperatorsByPath(input.context),
433
+ fieldMetaByPath: buildConditionFieldMetaByPath(input.context)
416
434
  }
417
435
  };
418
436
  if (capability.kind === "fieldLinkage") {