@nocobase/plugin-flow-engine 2.1.0-beta.43 → 2.1.0-beta.45

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 (90) hide show
  1. package/dist/client/index.js +1 -1
  2. package/dist/externalVersion.js +9 -9
  3. package/dist/node_modules/@ant-design/icons-svg/package.json +1 -1
  4. package/dist/node_modules/acorn/package.json +1 -1
  5. package/dist/node_modules/acorn-jsx/package.json +1 -1
  6. package/dist/node_modules/acorn-walk/package.json +1 -1
  7. package/dist/node_modules/ses/package.json +1 -1
  8. package/dist/node_modules/zod/package.json +1 -1
  9. package/dist/server/flow-surfaces/authoring-validation.js +160 -21
  10. package/dist/server/flow-surfaces/catalog.js +9 -5
  11. package/dist/server/flow-surfaces/chart-config.js +29 -6
  12. package/dist/server/flow-surfaces/contract-guard.js +39 -5
  13. package/dist/server/flow-surfaces/default-block-actions.js +2 -0
  14. package/dist/server/flow-surfaces/errors.d.ts +15 -0
  15. package/dist/server/flow-surfaces/errors.js +49 -3
  16. package/dist/server/flow-surfaces/filter-group.d.ts +7 -1
  17. package/dist/server/flow-surfaces/filter-group.js +175 -71
  18. package/dist/server/flow-surfaces/public-data-surface-default-filter.js +2 -1
  19. package/dist/server/flow-surfaces/runjs-authoring/ast/bindings.d.ts +66 -0
  20. package/dist/server/flow-surfaces/runjs-authoring/ast/bindings.js +661 -0
  21. package/dist/server/flow-surfaces/runjs-authoring/ast/execution.d.ts +20 -0
  22. package/dist/server/flow-surfaces/runjs-authoring/ast/execution.js +275 -0
  23. package/dist/server/flow-surfaces/runjs-authoring/ast/parser.d.ts +16 -0
  24. package/dist/server/flow-surfaces/runjs-authoring/ast/parser.js +130 -0
  25. package/dist/server/flow-surfaces/runjs-authoring/ast/react-values.d.ts +20 -0
  26. package/dist/server/flow-surfaces/runjs-authoring/ast/react-values.js +401 -0
  27. package/dist/server/flow-surfaces/runjs-authoring/ast/request-config.d.ts +21 -0
  28. package/dist/server/flow-surfaces/runjs-authoring/ast/request-config.js +199 -0
  29. package/dist/server/flow-surfaces/runjs-authoring/ast/source.d.ts +70 -0
  30. package/dist/server/flow-surfaces/runjs-authoring/ast/source.js +895 -0
  31. package/dist/server/flow-surfaces/runjs-authoring/ast/static-bindings.d.ts +23 -0
  32. package/dist/server/flow-surfaces/runjs-authoring/ast/static-bindings.js +618 -0
  33. package/dist/server/flow-surfaces/runjs-authoring/ast/static-values.d.ts +196 -0
  34. package/dist/server/flow-surfaces/runjs-authoring/ast/static-values.js +1777 -0
  35. package/dist/server/flow-surfaces/runjs-authoring/ast/walk.d.ts +10 -0
  36. package/dist/server/flow-surfaces/runjs-authoring/ast/walk.js +55 -0
  37. package/dist/server/flow-surfaces/runjs-authoring/collectors.d.ts +12 -0
  38. package/dist/server/flow-surfaces/runjs-authoring/collectors.js +589 -0
  39. package/dist/server/flow-surfaces/runjs-authoring/index.d.ts +2 -25
  40. package/dist/server/flow-surfaces/runjs-authoring/index.js +5 -11138
  41. package/dist/server/flow-surfaces/runjs-authoring/inspect.d.ts +13 -0
  42. package/dist/server/flow-surfaces/runjs-authoring/inspect.js +149 -0
  43. package/dist/server/flow-surfaces/runjs-authoring/internal-types.d.ts +333 -0
  44. package/dist/server/flow-surfaces/runjs-authoring/internal-types.js +36 -0
  45. package/dist/server/flow-surfaces/runjs-authoring/rules.js +2 -0
  46. package/dist/server/flow-surfaces/runjs-authoring/runtime/constants.d.ts +67 -0
  47. package/dist/server/flow-surfaces/runjs-authoring/runtime/constants.js +757 -0
  48. package/dist/server/flow-surfaces/runjs-authoring/runtime/errors.d.ts +22 -0
  49. package/dist/server/flow-surfaces/runjs-authoring/runtime/errors.js +91 -0
  50. package/dist/server/flow-surfaces/runjs-authoring/runtime/source-budget.d.ts +16 -0
  51. package/dist/server/flow-surfaces/runjs-authoring/runtime/source-budget.js +115 -0
  52. package/dist/server/flow-surfaces/runjs-authoring/runtime/surface.d.ts +19 -0
  53. package/dist/server/flow-surfaces/runjs-authoring/runtime/surface.js +140 -0
  54. package/dist/server/flow-surfaces/runjs-authoring/runtime/types.d.ts +91 -0
  55. package/dist/server/flow-surfaces/runjs-authoring/runtime/types.js +24 -0
  56. package/dist/server/flow-surfaces/runjs-authoring/scan/ctx-api.d.ts +138 -0
  57. package/dist/server/flow-surfaces/runjs-authoring/scan/ctx-api.js +1779 -0
  58. package/dist/server/flow-surfaces/runjs-authoring/scan/filter.d.ts +10 -0
  59. package/dist/server/flow-surfaces/runjs-authoring/scan/filter.js +1583 -0
  60. package/dist/server/flow-surfaces/runjs-authoring/scan/index.d.ts +195 -0
  61. package/dist/server/flow-surfaces/runjs-authoring/scan/index.js +463 -0
  62. package/dist/server/flow-surfaces/runjs-authoring/scan/react-render.d.ts +48 -0
  63. package/dist/server/flow-surfaces/runjs-authoring/scan/react-render.js +379 -0
  64. package/dist/server/flow-surfaces/runjs-authoring/scan/react.d.ts +26 -0
  65. package/dist/server/flow-surfaces/runjs-authoring/scan/react.js +1441 -0
  66. package/dist/server/flow-surfaces/runjs-authoring/scan/resource.d.ts +23 -0
  67. package/dist/server/flow-surfaces/runjs-authoring/scan/resource.js +1427 -0
  68. package/dist/server/flow-surfaces/runjs-authoring/scan/source-patterns.d.ts +91 -0
  69. package/dist/server/flow-surfaces/runjs-authoring/scan/source-patterns.js +889 -0
  70. package/dist/server/flow-surfaces/runjs-authoring/types.d.ts +1 -1
  71. package/dist/server/flow-surfaces/runjs-authoring/unknown-global-stop/index.d.ts +10 -0
  72. package/dist/server/flow-surfaces/runjs-authoring/unknown-global-stop/index.js +40 -0
  73. package/dist/server/flow-surfaces/runjs-authoring/validators/index.d.ts +12 -0
  74. package/dist/server/flow-surfaces/runjs-authoring/validators/index.js +887 -0
  75. package/dist/server/flow-surfaces/service-helpers.d.ts +29 -0
  76. package/dist/server/flow-surfaces/service-helpers.js +105 -0
  77. package/dist/server/flow-surfaces/service-utils.d.ts +15 -3
  78. package/dist/server/flow-surfaces/service-utils.js +5 -4
  79. package/dist/server/flow-surfaces/service.d.ts +4 -0
  80. package/dist/server/flow-surfaces/service.js +360 -30
  81. package/dist/server/flow-surfaces/types.d.ts +3 -0
  82. package/dist/server/repository.d.ts +15 -1
  83. package/dist/server/repository.js +262 -23
  84. package/dist/server/template/contexts.d.ts +2 -0
  85. package/dist/server/template/contexts.js +34 -0
  86. package/dist/server/template/resolver.js +233 -22
  87. package/dist/swagger/flow-surfaces.d.ts +175 -0
  88. package/dist/swagger/flow-surfaces.js +130 -51
  89. package/dist/swagger/index.d.ts +175 -0
  90. package/package.json +2 -2
@@ -349,33 +349,67 @@ function collectSchemaValueErrors(value, schema, path) {
349
349
  function normalizeDomainValue(value, contract, context) {
350
350
  const normalized = import_lodash.default.cloneDeep(value);
351
351
  Object.entries(contract.pathSchemas || {}).forEach(([path, schema]) => {
352
- if (!import_lodash.default.has(normalized, path) || !isFilterGroupSchema(schema)) {
352
+ if (!import_lodash.default.has(normalized, path)) {
353
353
  return;
354
354
  }
355
- import_lodash.default.set(normalized, path, normalizeFilterGroupValue(import_lodash.default.get(normalized, path), context, path));
355
+ if (isFilterGroupSchema(schema)) {
356
+ import_lodash.default.set(normalized, path, normalizeFilterGroupValue(import_lodash.default.get(normalized, path), context, path));
357
+ } else if (isLinkageRulesSchema(schema)) {
358
+ import_lodash.default.set(normalized, path, normalizeLinkageRulesValue(import_lodash.default.get(normalized, path), context, path));
359
+ }
356
360
  });
357
361
  return normalized;
358
362
  }
359
363
  function normalizeGroupValue(value, groupContract, context) {
360
364
  const normalized = import_lodash.default.cloneDeep(value);
361
365
  Object.entries(groupContract.pathSchemas || {}).forEach(([path, schema]) => {
362
- if (!import_lodash.default.has(normalized, path) || !isFilterGroupSchema(schema)) {
366
+ if (!import_lodash.default.has(normalized, path)) {
363
367
  return;
364
368
  }
365
- import_lodash.default.set(normalized, path, normalizeFilterGroupValue(import_lodash.default.get(normalized, path), context, path));
369
+ if (isFilterGroupSchema(schema)) {
370
+ import_lodash.default.set(normalized, path, normalizeFilterGroupValue(import_lodash.default.get(normalized, path), context, path));
371
+ } else if (isLinkageRulesSchema(schema)) {
372
+ import_lodash.default.set(normalized, path, normalizeLinkageRulesValue(import_lodash.default.get(normalized, path), context, path));
373
+ }
366
374
  });
367
375
  return normalized;
368
376
  }
369
377
  function isFilterGroupSchema(schema) {
370
378
  return (schema == null ? void 0 : schema["x-flowSurfaceFormat"]) === "filter-group";
371
379
  }
380
+ function isLinkageRulesSchema(schema) {
381
+ return (schema == null ? void 0 : schema["x-flowSurfaceFormat"]) === "linkage-rules";
382
+ }
372
383
  function normalizeFilterGroupValue(value, context, path) {
373
384
  const domainPath = context.groupKey ? `${context.domain}.${context.groupKey}.${path}` : `${context.domain}.${path}`;
374
385
  return (0, import_filter_group.normalizeFlowSurfaceFilterGroupValue)(
375
386
  value,
376
- `flowSurfaces updateSettings domain '${domainPath}' on '${context.use}' expects FilterGroup like ${import_filter_group.FLOW_SURFACE_FILTER_GROUP_EXAMPLE}`
387
+ `flowSurfaces updateSettings domain '${domainPath}' on '${context.use}' expects FilterGroup like ${import_filter_group.FLOW_SURFACE_FILTER_GROUP_EXAMPLE}`,
388
+ { strictDateValues: true }
377
389
  );
378
390
  }
391
+ function normalizeLinkageRulesValue(value, context, path) {
392
+ if (!Array.isArray(value)) {
393
+ return value;
394
+ }
395
+ return value.map((rule, index) => {
396
+ if (!import_lodash.default.isPlainObject(rule) || !import_lodash.default.has(rule, "condition")) {
397
+ return rule;
398
+ }
399
+ const normalizedRule = import_lodash.default.cloneDeep(rule);
400
+ const domainPath = context.groupKey ? `${context.domain}.${context.groupKey}.${path}[${index}].condition` : `${context.domain}.${path}[${index}].condition`;
401
+ import_lodash.default.set(
402
+ normalizedRule,
403
+ "condition",
404
+ (0, import_filter_group.normalizeFlowSurfaceCompatibleFilterGroupValue)(
405
+ import_lodash.default.get(normalizedRule, "condition"),
406
+ `flowSurfaces updateSettings domain '${domainPath}' on '${context.use}' expects FilterGroup or backend query filter like ${import_filter_group.FLOW_SURFACE_FILTER_GROUP_EXAMPLE}`,
407
+ { strictDateValues: true }
408
+ )
409
+ );
410
+ return normalizedRule;
411
+ });
412
+ }
379
413
  function isContractDefinedFlowGroup(groupContract) {
380
414
  if (!groupContract) {
381
415
  return false;
@@ -104,6 +104,8 @@ const FLOW_SURFACE_DEFAULT_BLOCK_ACTIONS = {
104
104
  ],
105
105
  calendar: [
106
106
  { type: "filter", scope: "actions" },
107
+ { type: "turnPages", scope: "actions" },
108
+ { type: "selectView", scope: "actions" },
107
109
  { type: "refresh", scope: "actions" },
108
110
  {
109
111
  type: "addNew",
@@ -8,6 +8,7 @@
8
8
  */
9
9
  export type FlowSurfaceErrorType = 'bad_request' | 'forbidden' | 'conflict' | 'internal_error';
10
10
  export interface FlowSurfaceErrorItem {
11
+ index?: number;
11
12
  message: string;
12
13
  type: FlowSurfaceErrorType;
13
14
  code: string;
@@ -48,6 +49,20 @@ export declare class FlowSurfaceAggregateError extends FlowSurfaceError {
48
49
  readonly errors: FlowSurfaceErrorItem[];
49
50
  constructor(errors: FlowSurfaceErrorItemInput[], message?: string);
50
51
  toResponseBody(): {
52
+ message: string;
53
+ errorCount: number;
54
+ details: {
55
+ requiredBlockPolicy?: {
56
+ requiredBlockTypes: string[];
57
+ fixStrategy: string;
58
+ doNotReplaceOrDrop: boolean;
59
+ };
60
+ errorCount: number;
61
+ mustFixAllErrorsBeforeRetry: boolean;
62
+ retryPolicy: string;
63
+ sameWriteRetryRequired: boolean;
64
+ agentInstruction: string;
65
+ };
51
66
  errors: FlowSurfaceErrorItem[];
52
67
  };
53
68
  }
@@ -88,14 +88,27 @@ class FlowSurfaceInternalError extends FlowSurfaceError {
88
88
  }
89
89
  class FlowSurfaceAggregateError extends FlowSurfaceError {
90
90
  errors;
91
- constructor(errors, message = "flowSurfaces authoring validation failed") {
92
- const normalizedErrors = errors.map((error) => normalizeFlowSurfaceErrorItemInput(error));
93
- super(message, 400, "bad_request", "FLOW_SURFACE_AUTHORING_VALIDATION_FAILED");
91
+ constructor(errors, message) {
92
+ const normalizedErrors = errors.map(
93
+ (error, index) => normalizeFlowSurfaceErrorItemInput({
94
+ ...error,
95
+ index: index + 1
96
+ })
97
+ );
98
+ super(
99
+ message || buildAggregateBadRequestMessage(normalizedErrors.length),
100
+ 400,
101
+ "bad_request",
102
+ "FLOW_SURFACE_AUTHORING_VALIDATION_FAILED"
103
+ );
94
104
  this.name = "FlowSurfaceAggregateError";
95
105
  this.errors = normalizedErrors;
96
106
  }
97
107
  toResponseBody() {
98
108
  return {
109
+ message: this.message,
110
+ errorCount: this.errors.length,
111
+ details: buildAggregateBadRequestDetails(this.errors),
99
112
  errors: this.errors
100
113
  };
101
114
  }
@@ -162,6 +175,9 @@ function buildDefinedErrorItem(input) {
162
175
  code: input.code,
163
176
  status: input.status
164
177
  };
178
+ if (typeof input.index !== "undefined") {
179
+ output.index = input.index;
180
+ }
165
181
  if (typeof input.path !== "undefined") {
166
182
  output.path = input.path;
167
183
  }
@@ -176,6 +192,7 @@ function buildDefinedErrorItem(input) {
176
192
  function normalizeFlowSurfaceErrorItemInput(input) {
177
193
  return buildDefinedErrorItem({
178
194
  message: input.message,
195
+ index: input.index,
179
196
  type: input.type || "bad_request",
180
197
  code: input.code || "FLOW_SURFACE_AUTHORING_VALIDATION_ERROR",
181
198
  status: input.status || 400,
@@ -184,6 +201,35 @@ function normalizeFlowSurfaceErrorItemInput(input) {
184
201
  details: input.details
185
202
  });
186
203
  }
204
+ function buildAggregateBadRequestMessage(errorCount) {
205
+ return `flowSurfaces authoring validation failed with ${errorCount} error(s); fix all errors before retrying the same write`;
206
+ }
207
+ function buildAggregateBadRequestDetails(errors) {
208
+ const requiredBlockTypes = Array.from(
209
+ new Set(
210
+ errors.map((error) => {
211
+ var _a;
212
+ return (_a = error.details) == null ? void 0 : _a.requiredBlockType;
213
+ }).filter(
214
+ (requiredBlockType) => typeof requiredBlockType === "string" && !!requiredBlockType
215
+ )
216
+ )
217
+ );
218
+ return {
219
+ errorCount: errors.length,
220
+ mustFixAllErrorsBeforeRetry: true,
221
+ retryPolicy: "fix_all_errors_before_retry_same_write",
222
+ sameWriteRetryRequired: true,
223
+ agentInstruction: "Read the complete errors[] array. Fix every listed error in one payload revision before retrying the same write. Do not fix only the first error and immediately retry. Do not drop, defer, or replace required chart, jsBlock, or JS/RunJS work to bypass validation.",
224
+ ...requiredBlockTypes.length ? {
225
+ requiredBlockPolicy: {
226
+ requiredBlockTypes,
227
+ fixStrategy: "repair_same_block_type",
228
+ doNotReplaceOrDrop: true
229
+ }
230
+ } : {}
231
+ };
232
+ }
187
233
  // Annotate the CommonJS export names for ESM import in node:
188
234
  0 && (module.exports = {
189
235
  FlowSurfaceAggregateError,
@@ -13,5 +13,11 @@ export declare const FLOW_SURFACE_EMPTY_FILTER_GROUP: {
13
13
  export declare const FLOW_SURFACE_FILTER_GROUP_EXAMPLE: string;
14
14
  export declare function assertFlowSurfaceFilterOperator(operator: unknown, path: string): void;
15
15
  export declare function normalizeFlowSurfaceFilterDateValue(operator: unknown, value: unknown, path: string): unknown;
16
- export declare function normalizeFlowSurfaceFilterGroupValue(value: any, errorPrefix: string): any;
16
+ export declare function normalizeFlowSurfaceStrictFilterDateValue(operator: unknown, value: unknown, path: string): unknown;
17
+ export declare function normalizeFlowSurfaceFilterGroupValue(value: any, errorPrefix: string, options?: {
18
+ strictDateValues?: boolean;
19
+ }): any;
20
+ export declare function normalizeFlowSurfaceCompatibleFilterGroupValue(value: unknown, errorPrefix: string, options?: {
21
+ strictDateValues?: boolean;
22
+ }): any;
17
23
  export declare function assertFlowSurfaceFilterGroupShape(filter: any): void;
@@ -40,8 +40,10 @@ __export(filter_group_exports, {
40
40
  FLOW_SURFACE_FILTER_GROUP_EXAMPLE: () => FLOW_SURFACE_FILTER_GROUP_EXAMPLE,
41
41
  assertFlowSurfaceFilterGroupShape: () => assertFlowSurfaceFilterGroupShape,
42
42
  assertFlowSurfaceFilterOperator: () => assertFlowSurfaceFilterOperator,
43
+ normalizeFlowSurfaceCompatibleFilterGroupValue: () => normalizeFlowSurfaceCompatibleFilterGroupValue,
43
44
  normalizeFlowSurfaceFilterDateValue: () => normalizeFlowSurfaceFilterDateValue,
44
- normalizeFlowSurfaceFilterGroupValue: () => normalizeFlowSurfaceFilterGroupValue
45
+ normalizeFlowSurfaceFilterGroupValue: () => normalizeFlowSurfaceFilterGroupValue,
46
+ normalizeFlowSurfaceStrictFilterDateValue: () => normalizeFlowSurfaceStrictFilterDateValue
45
47
  });
46
48
  module.exports = __toCommonJS(filter_group_exports);
47
49
  var import_database = require("@nocobase/database");
@@ -94,7 +96,9 @@ const FLOW_SURFACE_DATE_RANGE_TYPES = /* @__PURE__ */ new Set([
94
96
  "next"
95
97
  ]);
96
98
  const FLOW_SURFACE_DATE_RANGE_UNITS = /* @__PURE__ */ new Set(["day", "week", "month", "year"]);
97
- const FLOW_SURFACE_DATE_VALUE_REPAIR_HINT = 'Date filter values must use NocoBase-supported date values such as "2026-05-17", ["2026-05-01","2026-05-31"], or UI relative date descriptors like {"type":"past","number":14,"unit":"day"}.';
99
+ const FLOW_SURFACE_RELATIVE_DATE_DESCRIPTOR_KEYS = /* @__PURE__ */ new Set(["type", "number", "unit"]);
100
+ const FLOW_SURFACE_EXACT_DATE_VALUE_FORMATS = ["YYYY-MM-DD", "YYYY-MM", "YYYY", "YYYY[Q]Q", "YYYY-[Q]Q"];
101
+ const FLOW_SURFACE_DATE_VALUE_REPAIR_HINT = 'Date filter values must match the NocoBase filter UI contract: exact values like "2026-05-17", "2026-05", "2026", "2026-Q2", ranges like ["2026-05-01","2026-05-31"], or relative date descriptors like {"type":"past","number":14,"unit":"day"} and {"type":"thisWeek"}.';
98
102
  const FLOW_SURFACE_DATE_VALUE_REPAIR_EXAMPLE = {
99
103
  logic: "$and",
100
104
  items: [
@@ -158,12 +162,23 @@ function normalizeFlowSurfaceFilterDateValue(operator, value, path) {
158
162
  }
159
163
  return normalizeFlowSurfaceDateValue(value, path);
160
164
  }
161
- function normalizeFlowSurfaceFilterGroupValue(value, errorPrefix) {
165
+ function normalizeFlowSurfaceStrictFilterDateValue(operator, value, path) {
166
+ if (typeof operator !== "string" || !FLOW_SURFACE_DATE_FILTER_OPERATORS.has(operator)) {
167
+ return value;
168
+ }
169
+ if (import_lodash.default.isNil(value) || value === "") {
170
+ throwInvalidFlowSurfaceDateValue(path, value, {
171
+ invalidReason: "date filter value is required"
172
+ });
173
+ }
174
+ return normalizeFlowSurfaceDateValue(value, path);
175
+ }
176
+ function normalizeFlowSurfaceFilterGroupValue(value, errorPrefix, options = {}) {
162
177
  const normalized = value === null || import_lodash.default.isPlainObject(value) && !Object.keys(value).length ? import_lodash.default.cloneDeep(FLOW_SURFACE_EMPTY_FILTER_GROUP) : import_lodash.default.cloneDeep(value);
163
178
  try {
164
179
  assertFlowSurfaceFilterGroupShape(normalized);
165
180
  assertFlowSurfaceFilterGroupOperators(normalized, errorPrefix);
166
- normalizeFlowSurfaceFilterGroupDateValues(normalized, errorPrefix);
181
+ normalizeFlowSurfaceFilterGroupDateValues(normalized, errorPrefix, options);
167
182
  (0, import_utils.transformFilter)(normalized);
168
183
  return normalized;
169
184
  } catch (error) {
@@ -174,10 +189,30 @@ function normalizeFlowSurfaceFilterGroupValue(value, errorPrefix) {
174
189
  (0, import_errors.throwBadRequest)(`${errorPrefix}: ${reason}`);
175
190
  }
176
191
  }
192
+ function normalizeFlowSurfaceCompatibleFilterGroupValue(value, errorPrefix, options = {}) {
193
+ const input = value === null || import_lodash.default.isPlainObject(value) && !Object.keys(value).length ? import_lodash.default.cloneDeep(FLOW_SURFACE_EMPTY_FILTER_GROUP) : import_lodash.default.cloneDeep(value);
194
+ if (isFlowSurfaceFilterGroupLike(input)) {
195
+ return normalizeFlowSurfaceFilterGroupValue(input, errorPrefix, options);
196
+ }
197
+ try {
198
+ const converted = convertBackendQueryFilterToFlowSurfaceFilterGroup(input, errorPrefix);
199
+ return normalizeFlowSurfaceFilterGroupValue(converted, errorPrefix, options);
200
+ } catch (error) {
201
+ if (error instanceof import_errors.FlowSurfaceBadRequestError) {
202
+ throw error;
203
+ }
204
+ const reason = error instanceof Error ? error.message : String(error);
205
+ (0, import_errors.throwBadRequest)(`${errorPrefix}: ${reason}`);
206
+ }
207
+ }
177
208
  function assertFlowSurfaceFilterGroupShape(filter) {
178
209
  if (!import_lodash.default.isPlainObject(filter)) {
179
210
  throw new Error("Invalid filter: filter must be an object");
180
211
  }
212
+ const unsupportedKeys = Object.keys(filter).filter((key) => key !== "logic" && key !== "items");
213
+ if (unsupportedKeys.length) {
214
+ throw new Error(`Invalid filter: filter group does not support: ${unsupportedKeys.join(", ")}`);
215
+ }
181
216
  if (!("logic" in filter) || !("items" in filter)) {
182
217
  throw new Error("Invalid filter: filter must have logic and items properties");
183
218
  }
@@ -198,6 +233,88 @@ function assertFlowSurfaceFilterGroupShape(filter) {
198
233
  throw new Error("Invalid filter item type");
199
234
  });
200
235
  }
236
+ function isFlowSurfaceFilterGroupLike(value) {
237
+ if (!import_lodash.default.isPlainObject(value)) {
238
+ return false;
239
+ }
240
+ const filter = value;
241
+ return "logic" in filter && "items" in filter;
242
+ }
243
+ function isBackendQueryLogicKey(key) {
244
+ return key === "$and" || key === "$or";
245
+ }
246
+ function convertBackendQueryFilterToFlowSurfaceFilterGroup(input, label) {
247
+ if (!import_lodash.default.isPlainObject(input)) {
248
+ throw new Error("Invalid filter: filter must be an object");
249
+ }
250
+ const keys = Object.keys(input);
251
+ const logicKeys = keys.filter(isBackendQueryLogicKey);
252
+ if (logicKeys.length > 1 || logicKeys.length === 1 && keys.length > 1) {
253
+ throw new Error("cannot convert backend query filter with mixed logical and field conditions");
254
+ }
255
+ if (logicKeys.length === 1) {
256
+ const logic = logicKeys[0];
257
+ const operands = input[logic];
258
+ if (!Array.isArray(operands)) {
259
+ throw new Error(`${logic}: backend query filter operands must be an array`);
260
+ }
261
+ return {
262
+ logic,
263
+ items: operands.map((operand, index) => convertBackendQueryOperandToFlowSurfaceFilterItem(operand, label, index))
264
+ };
265
+ }
266
+ if (keys.some((key) => key.startsWith("$"))) {
267
+ throw new Error("cannot convert backend query filter with unsupported logical operator");
268
+ }
269
+ return {
270
+ logic: "$and",
271
+ items: Object.entries(input).flatMap(
272
+ ([field, condition]) => convertBackendFieldConditionToFlowSurfaceFilterItems(field, condition, label)
273
+ )
274
+ };
275
+ }
276
+ function convertBackendQueryOperandToFlowSurfaceFilterItem(input, label, index) {
277
+ if (isFlowSurfaceFilterGroupLike(input)) {
278
+ throw new Error(`${label}.$operand[${index}]: cannot mix filter groups with backend query filters`);
279
+ }
280
+ const group = convertBackendQueryFilterToFlowSurfaceFilterGroup(input, `${label}.$operand[${index}]`);
281
+ if (group.logic === "$and" && group.items.length === 1) {
282
+ return group.items[0];
283
+ }
284
+ return group;
285
+ }
286
+ function convertBackendFieldConditionToFlowSurfaceFilterItems(field, condition, label) {
287
+ if (!field.trim() || field.startsWith("$")) {
288
+ throw new Error(`cannot convert backend query filter field "${field}"`);
289
+ }
290
+ if (!import_lodash.default.isPlainObject(condition)) {
291
+ throw new Error(`${field}: backend query filter condition must be an object`);
292
+ }
293
+ const keys = Object.keys(condition);
294
+ if (!keys.length) {
295
+ throw new Error(`${field}: backend query filter condition cannot be empty`);
296
+ }
297
+ const operatorKeys = keys.filter((key) => key.startsWith("$"));
298
+ if (operatorKeys.length) {
299
+ if (operatorKeys.length !== keys.length) {
300
+ throw new Error(`${field}: cannot mix backend query operators with nested field conditions`);
301
+ }
302
+ return operatorKeys.map((operator) => {
303
+ if (isBackendQueryLogicKey(operator)) {
304
+ throw new Error(`${field}: cannot convert backend query filter operator "${operator}"`);
305
+ }
306
+ assertFlowSurfaceFilterOperator(operator, `${label}.${field}.${operator}`);
307
+ return {
308
+ path: field,
309
+ operator,
310
+ value: import_lodash.default.cloneDeep(import_lodash.default.get(condition, operator))
311
+ };
312
+ });
313
+ }
314
+ return Object.entries(condition).flatMap(
315
+ ([nestedField, nestedCondition]) => convertBackendFieldConditionToFlowSurfaceFilterItems(`${field}.${nestedField}`, nestedCondition, label)
316
+ );
317
+ }
201
318
  function assertFlowSurfaceFilterGroupOperators(filter, errorPrefix) {
202
319
  filter.items.forEach((item, index) => {
203
320
  const itemPath = `${errorPrefix}.items[${index}]`;
@@ -208,14 +325,14 @@ function assertFlowSurfaceFilterGroupOperators(filter, errorPrefix) {
208
325
  assertFlowSurfaceFilterOperator(item.operator, `${itemPath}.operator`);
209
326
  });
210
327
  }
211
- function normalizeFlowSurfaceFilterGroupDateValues(filter, errorPrefix) {
328
+ function normalizeFlowSurfaceFilterGroupDateValues(filter, errorPrefix, options) {
212
329
  filter.items.forEach((item, index) => {
213
330
  const itemPath = `${errorPrefix}.items[${index}]`;
214
331
  if (import_lodash.default.isPlainObject(item) && "logic" in item && "items" in item) {
215
- normalizeFlowSurfaceFilterGroupDateValues(item, itemPath);
332
+ normalizeFlowSurfaceFilterGroupDateValues(item, itemPath, options);
216
333
  return;
217
334
  }
218
- item.value = normalizeFlowSurfaceFilterDateValue(item.operator, item.value, `${itemPath}.value`);
335
+ item.value = options.strictDateValues ? normalizeFlowSurfaceStrictFilterDateValue(item.operator, item.value, `${itemPath}.value`) : normalizeFlowSurfaceFilterDateValue(item.operator, item.value, `${itemPath}.value`);
219
336
  });
220
337
  }
221
338
  function normalizeFlowSurfaceDateValue(value, path) {
@@ -223,17 +340,9 @@ function normalizeFlowSurfaceDateValue(value, path) {
223
340
  return value;
224
341
  }
225
342
  if (Array.isArray(value)) {
226
- const normalized2 = normalizeFlowSurfaceDateArrayValue(value, path);
227
- if (!hasTemplateDateValue(normalized2)) {
228
- assertFlowSurfaceDateValueParsable(normalized2, path);
229
- }
230
- return normalized2;
343
+ return normalizeFlowSurfaceDateArrayValue(value, path);
231
344
  }
232
- const normalized = normalizeFlowSurfaceDateValuePart(value, path);
233
- if (!hasTemplateDateValue(normalized)) {
234
- assertFlowSurfaceDateValueParsable(normalized, path);
235
- }
236
- return normalized;
345
+ return normalizeFlowSurfaceDateValuePart(value, path);
237
346
  }
238
347
  function normalizeFlowSurfaceDateArrayValue(value, path) {
239
348
  if (value.length !== 2) {
@@ -241,41 +350,49 @@ function normalizeFlowSurfaceDateArrayValue(value, path) {
241
350
  invalidReason: "date range arrays must contain exactly start and end values"
242
351
  });
243
352
  }
244
- return value.map((item, index) => normalizeFlowSurfaceDateValuePart(item, `${path}[${index}]`));
353
+ return value.map((item, index) => normalizeFlowSurfaceExactDateValuePart(item, `${path}[${index}]`));
245
354
  }
246
355
  function normalizeFlowSurfaceDateValuePart(value, path) {
247
- if (import_lodash.default.isNil(value) || value === "" || isTemplateDateString(value) || value instanceof Date) {
356
+ if (import_lodash.default.isNil(value) || value === "" || isTemplateDateString(value)) {
248
357
  return value;
249
358
  }
250
359
  if (typeof value === "string") {
251
- const relative = normalizeRelativeDateShorthand(value, path);
252
- if (relative) {
253
- return relative;
254
- }
255
- assertFlowSurfaceDateValueParsable(value, path);
256
- return value;
360
+ return normalizeFlowSurfaceExactDateValuePart(value, path);
257
361
  }
258
362
  if (import_lodash.default.isPlainObject(value)) {
259
363
  return normalizeRelativeDateDescriptor(value, path);
260
364
  }
261
- assertFlowSurfaceDateValueParsable(value, path);
262
- return value;
365
+ throwInvalidFlowSurfaceDateValue(path, value, {
366
+ invalidReason: "date filter value must be an exact date string, date range array, or relative date descriptor"
367
+ });
263
368
  }
264
- function normalizeRelativeDateShorthand(value, path) {
265
- const match = /^\s*([+-])(\d+)d\s*$/i.exec(value);
266
- if (!match) {
267
- return void 0;
369
+ function normalizeFlowSurfaceExactDateValuePart(value, path) {
370
+ if (isTemplateDateString(value)) {
371
+ return value;
268
372
  }
269
- return normalizeRelativeDateDescriptor(
270
- {
271
- type: match[1] === "-" ? "past" : "next",
272
- number: Number(match[2]),
273
- unit: "day"
274
- },
275
- path
276
- );
373
+ if (typeof value === "string") {
374
+ const normalized = value.trim();
375
+ if (isFlowSurfaceExactDateValue(normalized)) {
376
+ return normalized;
377
+ }
378
+ }
379
+ throwInvalidFlowSurfaceDateValue(path, value, {
380
+ invalidReason: "date filter strings must use UI exact date formats YYYY-MM-DD, YYYY-MM, YYYY, YYYYQn, or YYYY-Qn"
381
+ });
382
+ }
383
+ function isFlowSurfaceExactDateValue(value) {
384
+ return FLOW_SURFACE_EXACT_DATE_VALUE_FORMATS.some((format) => {
385
+ const parsed = (0, import_utils.dayjs)(value, format, true);
386
+ return parsed.isValid() && parsed.format(format) === value;
387
+ });
277
388
  }
278
389
  function normalizeRelativeDateDescriptor(value, path) {
390
+ const invalidKeys = Object.keys(value).filter((key) => !FLOW_SURFACE_RELATIVE_DATE_DESCRIPTOR_KEYS.has(key));
391
+ if (invalidKeys.length) {
392
+ throwInvalidFlowSurfaceDateValue(path, value, {
393
+ invalidReason: `relative date descriptor contains unsupported keys: ${invalidKeys.join(", ")}`
394
+ });
395
+ }
279
396
  const rawType = value.type;
280
397
  const type = typeof rawType === "string" ? rawType.trim() : "";
281
398
  if (!isTemplateDateString(rawType) && !FLOW_SURFACE_DATE_RANGE_TYPES.has(type)) {
@@ -289,18 +406,21 @@ function normalizeRelativeDateDescriptor(value, path) {
289
406
  };
290
407
  if (type === "past" || type === "next") {
291
408
  if (import_lodash.default.isUndefined(value.number)) {
292
- normalized.number = 1;
409
+ throwInvalidFlowSurfaceDateValue(path, value, {
410
+ invalidReason: "past/next relative date descriptor must include number"
411
+ });
293
412
  } else if (!isTemplateDateString(value.number)) {
294
- const number = Number(value.number);
295
- if (!Number.isFinite(number) || number <= 0) {
413
+ if (typeof value.number !== "number" || !Number.isFinite(value.number) || value.number <= 0) {
296
414
  throwInvalidFlowSurfaceDateValue(path, value, {
297
415
  invalidReason: "past/next relative date descriptor number must be greater than 0"
298
416
  });
299
417
  }
300
- normalized.number = number;
418
+ normalized.number = value.number;
301
419
  }
302
420
  if (import_lodash.default.isUndefined(value.unit)) {
303
- normalized.unit = "day";
421
+ throwInvalidFlowSurfaceDateValue(path, value, {
422
+ invalidReason: "past/next relative date descriptor must include unit"
423
+ });
304
424
  } else if (!isTemplateDateString(value.unit)) {
305
425
  const unit = typeof value.unit === "string" ? value.unit.trim() : "";
306
426
  if (!FLOW_SURFACE_DATE_RANGE_UNITS.has(unit)) {
@@ -311,23 +431,15 @@ function normalizeRelativeDateDescriptor(value, path) {
311
431
  normalized.unit = unit;
312
432
  }
313
433
  } else {
314
- if (!import_lodash.default.isUndefined(value.number) && !isTemplateDateString(value.number)) {
315
- const number = Number(value.number);
316
- if (!Number.isFinite(number) || number <= 0) {
317
- throwInvalidFlowSurfaceDateValue(path, value, {
318
- invalidReason: "relative date descriptor number must be greater than 0"
319
- });
320
- }
321
- normalized.number = number;
434
+ if (!import_lodash.default.isUndefined(value.number)) {
435
+ throwInvalidFlowSurfaceDateValue(path, value, {
436
+ invalidReason: `relative date descriptor type "${type}" must not include number`
437
+ });
322
438
  }
323
- if (!import_lodash.default.isUndefined(value.unit) && !isTemplateDateString(value.unit)) {
324
- const unit = typeof value.unit === "string" ? value.unit.trim() : "";
325
- if (!FLOW_SURFACE_DATE_RANGE_UNITS.has(unit)) {
326
- throwInvalidFlowSurfaceDateValue(path, value, {
327
- invalidReason: `unsupported relative date unit "${unit}"`
328
- });
329
- }
330
- normalized.unit = unit;
439
+ if (!import_lodash.default.isUndefined(value.unit)) {
440
+ throwInvalidFlowSurfaceDateValue(path, value, {
441
+ invalidReason: `relative date descriptor type "${type}" must not include unit`
442
+ });
331
443
  }
332
444
  }
333
445
  if (!hasTemplateDateValue(normalized)) {
@@ -356,16 +468,6 @@ function hasTemplateDateValue(value) {
356
468
  }
357
469
  return false;
358
470
  }
359
- function assertFlowSurfaceDateValueParsable(value, path) {
360
- try {
361
- const parsed = (0, import_utils.parseDate)(value);
362
- if (parsed) {
363
- return;
364
- }
365
- } catch {
366
- }
367
- throwInvalidFlowSurfaceDateValue(path, value);
368
- }
369
471
  function throwInvalidFlowSurfaceDateValue(path, value, details = {}) {
370
472
  (0, import_errors.throwBadRequest)(`${path} must be a valid date filter value`, {
371
473
  path,
@@ -384,6 +486,8 @@ function throwInvalidFlowSurfaceDateValue(path, value, details = {}) {
384
486
  FLOW_SURFACE_FILTER_GROUP_EXAMPLE,
385
487
  assertFlowSurfaceFilterGroupShape,
386
488
  assertFlowSurfaceFilterOperator,
489
+ normalizeFlowSurfaceCompatibleFilterGroupValue,
387
490
  normalizeFlowSurfaceFilterDateValue,
388
- normalizeFlowSurfaceFilterGroupValue
491
+ normalizeFlowSurfaceFilterGroupValue,
492
+ normalizeFlowSurfaceStrictFilterDateValue
389
493
  });
@@ -263,7 +263,8 @@ function normalizeFlowSurfacePublicBlockDefaultFilter(actionName, defaultFilter,
263
263
  }
264
264
  const normalized = (0, import_filter_group.normalizeFlowSurfaceFilterGroupValue)(
265
265
  defaultFilter,
266
- `flowSurfaces ${actionName} ${fieldPath} expects FilterGroup like ${import_filter_group.FLOW_SURFACE_FILTER_GROUP_EXAMPLE}`
266
+ `flowSurfaces ${actionName} ${fieldPath} expects FilterGroup like ${import_filter_group.FLOW_SURFACE_FILTER_GROUP_EXAMPLE}`,
267
+ { strictDateValues: true }
267
268
  );
268
269
  return normalized;
269
270
  }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import type { SourceBinding, SourceRange, StringLiteralBinding } from '../internal-types';
10
+ export declare function collectSourceBindings(masked: string, functionRanges: SourceRange[], blockRanges: SourceRange[], staticBlockRanges: SourceRange[]): SourceBinding[];
11
+ export declare function collectStringLiteralBindings(source: string, masked: string, bindings: SourceBinding[]): StringLiteralBinding[];
12
+ export declare function isNamedFunctionOrClassExpression(masked: string, keywordIndex: number, kind: string): boolean;
13
+ export declare function isExpressionPrefixToken(token: string): boolean;
14
+ export declare function findNamedFunctionOrClassExpressionRange(masked: string, keywordIndex: number, kind: string): {
15
+ start: number;
16
+ end: number;
17
+ };
18
+ export declare function addSourceBinding(bindings: SourceBinding[], functionRanges: SourceRange[], blockRanges: SourceRange[], staticBlockRanges: SourceRange[], masked: string, name: string, start: number, sourceEnd: number, kind: string): void;
19
+ export declare function resolveBindingScope(masked: string, sourceEnd: number, start: number, kind: string, functionRanges: SourceRange[], blockRanges: SourceRange[], staticBlockRanges: SourceRange[]): SourceRange;
20
+ export declare function findForScopeForDeclaration(masked: string, start: number, blockRanges: SourceRange[]): {
21
+ start: number;
22
+ end: number;
23
+ };
24
+ export declare function findForHeaderRangeContaining(masked: string, start: number): {
25
+ start: number;
26
+ end: number;
27
+ };
28
+ export declare function findFollowingBraceRange(masked: string, afterIndex: number, blockRanges: SourceRange[]): SourceRange;
29
+ export declare function findFollowingStatementRange(masked: string, afterIndex: number, blockRanges: SourceRange[]): SourceRange;
30
+ export declare function findSingleStatementEnd(masked: string, start: number): number;
31
+ export declare function collectDestructuredVariableBindingNames(masked: string, functionRanges: SourceRange[], blockRanges: SourceRange[], staticBlockRanges: SourceRange[], bindings: SourceBinding[]): void;
32
+ export declare function collectParameterBindingNames(masked: string, bindings: SourceBinding[]): void;
33
+ export declare function collectArrowParameterBindingNames(masked: string, bindings: SourceBinding[]): void;
34
+ export declare function collectMethodParameterBindingNames(masked: string, bindings: SourceBinding[]): void;
35
+ export declare function findBraceBodyAfter(masked: string, afterIndex: number): SourceRange | undefined;
36
+ export declare function findArrowBodyRange(masked: string, afterArrowIndex: number): SourceRange | undefined;
37
+ export declare function addParameterBindings(bindings: SourceBinding[], params: string, range: SourceRange): void;
38
+ export declare function extractBindingPatternNames(pattern: string): string[];
39
+ export declare function collectBindingPatternNames(pattern: string, names: Set<string>): void;
40
+ export declare function collectObjectBindingPatternNames(pattern: string, names: Set<string>): void;
41
+ export declare function collectArrayBindingPatternNames(pattern: string, names: Set<string>): void;
42
+ export declare function findInnermostRange(index: number, ranges: SourceRange[]): SourceRange;
43
+ export declare function isNameBoundAtIndex(bindings: SourceBinding[], name: string, index: number): boolean;
44
+ export declare function findSourceBindingByDeclaration(bindings: SourceBinding[], name: string, declarationStart: number): SourceBinding;
45
+ export declare function isSameAstRange(left: SourceRange, right: SourceRange): boolean;
46
+ export declare function isSourceAliasShadowedAtIndex(alias: SourceRange & {
47
+ declarationStart?: number;
48
+ name: string;
49
+ }, bindings: SourceBinding[], index: number): boolean;
50
+ export declare function isAstDefinitelyNonEmptyForInSource(node: any): any;
51
+ export declare function isAstDefinitelyNonEmptyForOfSource(node: any): any;
52
+ export declare function isAstDefinitelyNonEmptyArrayElement(element: any): boolean;
53
+ export declare function isAstDefinitelyEnumerableObjectProperty(property: any): boolean;
54
+ export declare function isAstDefinitelyEnumerableComputedObjectKey(key: any): boolean;
55
+ export declare function findAstAncestor(ancestors: any[], type: string): any;
56
+ export declare function getAstExecutionScopeRange(ancestors: any[], sourceLength: number): SourceRange;
57
+ export declare function isAstAlwaysExecutedInCurrentExecutionScope(ancestors: any[]): boolean;
58
+ export declare function getAstBindingScopeRange(ancestors: any[], sourceLength: number, functionScoped?: boolean): SourceRange;
59
+ export declare function isAstFunctionLike(node: any): boolean;
60
+ export declare function dedupeIndexedEntries<T extends {
61
+ index: number;
62
+ match?: string;
63
+ capability?: string;
64
+ component?: string;
65
+ }>(entries: T[]): T[];
66
+ export declare function unwrapAstChainExpression(node: any): any;