@nocobase/plugin-flow-engine 2.1.0-alpha.45 → 2.1.0-alpha.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/index.js +1 -1
- package/dist/externalVersion.js +9 -9
- package/dist/node_modules/@ant-design/icons-svg/package.json +1 -1
- package/dist/node_modules/acorn/package.json +1 -1
- package/dist/node_modules/acorn-jsx/package.json +1 -1
- package/dist/node_modules/acorn-walk/package.json +1 -1
- package/dist/node_modules/ses/package.json +1 -1
- package/dist/node_modules/zod/package.json +1 -1
- package/dist/server/flow-surfaces/apply/compiler.js +10 -11
- package/dist/server/flow-surfaces/authoring-validation.d.ts +1 -0
- package/dist/server/flow-surfaces/authoring-validation.js +773 -26
- package/dist/server/flow-surfaces/blueprint/normalize-document.js +5 -1
- package/dist/server/flow-surfaces/catalog.js +9 -5
- package/dist/server/flow-surfaces/chart-config.js +220 -16
- package/dist/server/flow-surfaces/contract-guard.js +40 -6
- package/dist/server/flow-surfaces/default-block-actions.js +2 -0
- package/dist/server/flow-surfaces/errors.d.ts +15 -0
- package/dist/server/flow-surfaces/errors.js +49 -3
- package/dist/server/flow-surfaces/event-flow-normalizer.d.ts +19 -0
- package/dist/server/flow-surfaces/event-flow-normalizer.js +128 -0
- package/dist/server/flow-surfaces/filter-group.d.ts +9 -1
- package/dist/server/flow-surfaces/filter-group.js +402 -3
- package/dist/server/flow-surfaces/public-data-surface-default-filter.js +2 -1
- package/dist/server/flow-surfaces/route-sync.js +19 -2
- package/dist/server/flow-surfaces/runjs-authoring/ast/bindings.d.ts +66 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/bindings.js +661 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/execution.d.ts +20 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/execution.js +275 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/parser.d.ts +16 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/parser.js +130 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/react-values.d.ts +20 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/react-values.js +401 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/request-config.d.ts +21 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/request-config.js +199 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/source.d.ts +70 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/source.js +895 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/static-bindings.d.ts +23 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/static-bindings.js +618 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/static-values.d.ts +196 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/static-values.js +1777 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/walk.d.ts +10 -0
- package/dist/server/flow-surfaces/runjs-authoring/ast/walk.js +55 -0
- package/dist/server/flow-surfaces/runjs-authoring/collectors.d.ts +12 -0
- package/dist/server/flow-surfaces/runjs-authoring/collectors.js +589 -0
- package/dist/server/flow-surfaces/runjs-authoring/index.d.ts +2 -25
- package/dist/server/flow-surfaces/runjs-authoring/index.js +5 -11138
- package/dist/server/flow-surfaces/runjs-authoring/inspect.d.ts +13 -0
- package/dist/server/flow-surfaces/runjs-authoring/inspect.js +149 -0
- package/dist/server/flow-surfaces/runjs-authoring/internal-types.d.ts +333 -0
- package/dist/server/flow-surfaces/runjs-authoring/internal-types.js +36 -0
- package/dist/server/flow-surfaces/runjs-authoring/rules.js +2 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/constants.d.ts +67 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/constants.js +757 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/errors.d.ts +22 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/errors.js +91 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/source-budget.d.ts +16 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/source-budget.js +115 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/surface.d.ts +19 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/surface.js +140 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/types.d.ts +91 -0
- package/dist/server/flow-surfaces/runjs-authoring/runtime/types.js +24 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/ctx-api.d.ts +138 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/ctx-api.js +1779 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/filter.d.ts +10 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/filter.js +1583 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/index.d.ts +195 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/index.js +463 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/react-render.d.ts +48 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/react-render.js +379 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/react.d.ts +26 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/react.js +1441 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/resource.d.ts +23 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/resource.js +1427 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/source-patterns.d.ts +91 -0
- package/dist/server/flow-surfaces/runjs-authoring/scan/source-patterns.js +889 -0
- package/dist/server/flow-surfaces/runjs-authoring/types.d.ts +1 -1
- package/dist/server/flow-surfaces/runjs-authoring/unknown-global-stop/index.d.ts +10 -0
- package/dist/server/flow-surfaces/runjs-authoring/unknown-global-stop/index.js +40 -0
- package/dist/server/flow-surfaces/runjs-authoring/validators/index.d.ts +12 -0
- package/dist/server/flow-surfaces/runjs-authoring/validators/index.js +887 -0
- package/dist/server/flow-surfaces/service-helpers.d.ts +29 -0
- package/dist/server/flow-surfaces/service-helpers.js +105 -0
- package/dist/server/flow-surfaces/service-utils.d.ts +15 -3
- package/dist/server/flow-surfaces/service-utils.js +6 -5
- package/dist/server/flow-surfaces/service.d.ts +7 -1
- package/dist/server/flow-surfaces/service.js +488 -94
- package/dist/server/flow-surfaces/types.d.ts +3 -0
- package/dist/server/repository.d.ts +12 -1
- package/dist/server/repository.js +195 -23
- package/dist/swagger/flow-surfaces.d.ts +175 -0
- package/dist/swagger/flow-surfaces.js +130 -51
- package/dist/swagger/index.d.ts +175 -0
- package/package.json +2 -2
|
@@ -0,0 +1,887 @@
|
|
|
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
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var validators_exports = {};
|
|
28
|
+
__export(validators_exports, {
|
|
29
|
+
RUNJS_INSPECTION_VALIDATORS: () => RUNJS_INSPECTION_VALIDATORS,
|
|
30
|
+
collectRunJsInspectionErrors: () => collectRunJsInspectionErrors
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(validators_exports);
|
|
33
|
+
var import_constants = require("../runtime/constants");
|
|
34
|
+
var import_errors = require("../runtime/errors");
|
|
35
|
+
var import_source_patterns = require("../scan/source-patterns");
|
|
36
|
+
function collectNestedRunJsErrors(path, source, scan, modelUse, surface, errors) {
|
|
37
|
+
scan.nestedRunjsCalls.forEach((entry) => {
|
|
38
|
+
errors.push(
|
|
39
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
40
|
+
path,
|
|
41
|
+
repairClass: "nested-runjs-stop",
|
|
42
|
+
ruleId: "runjs-nested-runjs-forbidden",
|
|
43
|
+
message: `flowSurfaces authoring ${path} cannot call ${entry.capability}(...) from authored RunJS`,
|
|
44
|
+
modelUse,
|
|
45
|
+
surface,
|
|
46
|
+
index: entry.index,
|
|
47
|
+
source,
|
|
48
|
+
details: {
|
|
49
|
+
capability: entry.capability
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function collectResourceApiErrors(path, source, scan, modelUse, surface, errors) {
|
|
56
|
+
if (!scan.nestedRunjsCalls.length) {
|
|
57
|
+
scan.ctxRunjsCalls.forEach((entry) => {
|
|
58
|
+
const endpoint = (0, import_source_patterns.getResourceLikeCtxRunjsEntrypoint)(source, scan.masked, entry.index);
|
|
59
|
+
if (!endpoint) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
errors.push(
|
|
63
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
64
|
+
path,
|
|
65
|
+
repairClass: "switch-to-resource-api",
|
|
66
|
+
message: `flowSurfaces authoring ${path} must use resource APIs for collection access; ctx.runjs(...) executes JavaScript strings, not resource endpoints`,
|
|
67
|
+
modelUse,
|
|
68
|
+
surface,
|
|
69
|
+
index: entry.index,
|
|
70
|
+
source,
|
|
71
|
+
details: {
|
|
72
|
+
capability: "ctx.runjs",
|
|
73
|
+
endpoint
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
scan.ctxRequestCalls.forEach((entry) => {
|
|
80
|
+
if (!(0, import_source_patterns.isResourceLikeCtxRequest)(source, scan.masked, entry.index)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
errors.push(
|
|
84
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
85
|
+
path,
|
|
86
|
+
repairClass: "switch-to-resource-api",
|
|
87
|
+
message: `flowSurfaces authoring ${path} must use resource APIs instead of ctx request APIs for collection access`,
|
|
88
|
+
modelUse,
|
|
89
|
+
surface,
|
|
90
|
+
index: entry.index,
|
|
91
|
+
source
|
|
92
|
+
})
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
scan.invalidApiResourceCalls.forEach((entry) => {
|
|
96
|
+
errors.push(
|
|
97
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
98
|
+
path,
|
|
99
|
+
repairClass: "switch-to-resource-api",
|
|
100
|
+
ruleId: "runjs-api-resource-call-invalid",
|
|
101
|
+
message: `flowSurfaces authoring ${path} cannot call ${entry.match}(...); use resource APIs or ctx.request(...) for collection access`,
|
|
102
|
+
modelUse,
|
|
103
|
+
surface,
|
|
104
|
+
index: entry.index,
|
|
105
|
+
source,
|
|
106
|
+
details: {
|
|
107
|
+
capability: entry.match,
|
|
108
|
+
method: entry.method
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
function collectResourceRuntimeErrors(path, source, scan, modelUse, surface, errors) {
|
|
115
|
+
if (modelUse === "JSBlockModel") {
|
|
116
|
+
scan.resourceCallsInReactHooks.forEach((entry) => {
|
|
117
|
+
errors.push(
|
|
118
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
119
|
+
path,
|
|
120
|
+
repairClass: "resource-runtime-contract-stop",
|
|
121
|
+
ruleId: "runjs-jsblock-resource-hook-forbidden",
|
|
122
|
+
message: `flowSurfaces authoring ${path} cannot use ${entry.capability} inside React Hook ${entry.hook}(...) in JSBlock render code; load resource data before ctx.render(...) and pass values into the rendered component`,
|
|
123
|
+
modelUse,
|
|
124
|
+
surface,
|
|
125
|
+
index: entry.index,
|
|
126
|
+
source,
|
|
127
|
+
details: {
|
|
128
|
+
capability: entry.capability,
|
|
129
|
+
hook: entry.hook
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
);
|
|
133
|
+
});
|
|
134
|
+
scan.sharedCtxResourceCallsInFunctions.forEach((entry) => {
|
|
135
|
+
const functionScope = entry.functionName ? ` inside function '${entry.functionName}'` : " inside a nested function";
|
|
136
|
+
errors.push(
|
|
137
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
138
|
+
path,
|
|
139
|
+
repairClass: "resource-runtime-contract-stop",
|
|
140
|
+
ruleId: "runjs-jsblock-shared-resource-helper-forbidden",
|
|
141
|
+
message: `flowSurfaces authoring ${path} cannot use ${entry.capability}${functionScope} in JSBlock render code; ctx.initResource reuses ctx.resource across calls and can retain stale request params. Use a local ctx.makeResource(...) resource inside the helper instead`,
|
|
142
|
+
modelUse,
|
|
143
|
+
surface,
|
|
144
|
+
index: entry.index,
|
|
145
|
+
source,
|
|
146
|
+
details: {
|
|
147
|
+
capability: entry.capability,
|
|
148
|
+
functionName: entry.functionName
|
|
149
|
+
}
|
|
150
|
+
})
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
scan.invalidResourceTypeCalls.forEach((entry) => {
|
|
155
|
+
const message = entry.ruleId === "runjs-make-resource-type-invalid" ? `flowSurfaces authoring ${path} ${entry.capability}(...) expects a FlowResource class name, not collection '${entry.resourceType}'` : `flowSurfaces authoring ${path} cannot validate dynamic ${entry.capability}(...) resource type '${entry.expression}'`;
|
|
156
|
+
errors.push(
|
|
157
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
158
|
+
path,
|
|
159
|
+
repairClass: "resource-runtime-contract-stop",
|
|
160
|
+
ruleId: entry.ruleId,
|
|
161
|
+
message,
|
|
162
|
+
modelUse,
|
|
163
|
+
surface,
|
|
164
|
+
index: entry.index,
|
|
165
|
+
source,
|
|
166
|
+
details: {
|
|
167
|
+
capability: entry.capability,
|
|
168
|
+
expression: entry.expression,
|
|
169
|
+
resourceType: entry.resourceType
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
);
|
|
173
|
+
});
|
|
174
|
+
scan.invalidFlowResourceMethodCalls.forEach((entry) => {
|
|
175
|
+
const suggestedMethod = entry.suggestedMethod ? `; use ${entry.suggestedMethod}(...) instead` : "";
|
|
176
|
+
errors.push(
|
|
177
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
178
|
+
path,
|
|
179
|
+
repairClass: "resource-runtime-contract-stop",
|
|
180
|
+
ruleId: "runjs-flow-resource-method-invalid",
|
|
181
|
+
message: `flowSurfaces authoring ${path} cannot call ${entry.capability}(...); FlowResource method '${entry.method}' is not supported${suggestedMethod}`,
|
|
182
|
+
modelUse,
|
|
183
|
+
surface,
|
|
184
|
+
index: entry.index,
|
|
185
|
+
source,
|
|
186
|
+
details: {
|
|
187
|
+
capability: entry.capability,
|
|
188
|
+
method: entry.method,
|
|
189
|
+
resourceType: entry.resourceType,
|
|
190
|
+
suggestedMethod: entry.suggestedMethod
|
|
191
|
+
}
|
|
192
|
+
})
|
|
193
|
+
);
|
|
194
|
+
});
|
|
195
|
+
scan.invalidFlowResourceListCalls.forEach((entry) => {
|
|
196
|
+
errors.push(
|
|
197
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
198
|
+
path,
|
|
199
|
+
repairClass: "resource-runtime-contract-stop",
|
|
200
|
+
ruleId: "runjs-flow-resource-list-method-invalid",
|
|
201
|
+
message: `flowSurfaces authoring ${path} cannot call ${entry.capability}; FlowResource instances fetch through refresh() and expose getData()/getMeta()`,
|
|
202
|
+
modelUse,
|
|
203
|
+
surface,
|
|
204
|
+
index: entry.index,
|
|
205
|
+
source,
|
|
206
|
+
details: {
|
|
207
|
+
capability: entry.capability,
|
|
208
|
+
method: "list"
|
|
209
|
+
}
|
|
210
|
+
})
|
|
211
|
+
);
|
|
212
|
+
});
|
|
213
|
+
scan.invalidResourceActionCalls.forEach((entry) => {
|
|
214
|
+
var _a;
|
|
215
|
+
const allowedActions = ((_a = entry.allowedActions) == null ? void 0 : _a.length) ? ` Allowed collection actions: ${entry.allowedActions.join(", ")}.` : "";
|
|
216
|
+
const suggestion = entry.actionName === "refresh" ? " Use resource.refresh() for UI resource refresh, or use list/get when making a backend resource action request." : entry.suggestedMethod ? ` Use ${entry.suggestedMethod}(...) instead.` : "";
|
|
217
|
+
errors.push(
|
|
218
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
219
|
+
path,
|
|
220
|
+
repairClass: "resource-runtime-contract-stop",
|
|
221
|
+
ruleId: "runjs-resource-action-invalid",
|
|
222
|
+
message: `flowSurfaces authoring ${path} cannot call ${entry.capability}; collection action '${entry.actionName}' is not supported.${allowedActions}${suggestion}`,
|
|
223
|
+
modelUse,
|
|
224
|
+
surface,
|
|
225
|
+
index: entry.index,
|
|
226
|
+
source,
|
|
227
|
+
details: {
|
|
228
|
+
actionName: entry.actionName,
|
|
229
|
+
allowedActions: entry.allowedActions,
|
|
230
|
+
capability: entry.capability,
|
|
231
|
+
collectionName: entry.collectionName,
|
|
232
|
+
dataSourceKey: entry.dataSourceKey,
|
|
233
|
+
endpoint: entry.endpoint,
|
|
234
|
+
invalidReason: entry.invalidReason,
|
|
235
|
+
resourceType: entry.resourceType,
|
|
236
|
+
suggestedMethod: entry.suggestedMethod
|
|
237
|
+
}
|
|
238
|
+
})
|
|
239
|
+
);
|
|
240
|
+
});
|
|
241
|
+
scan.invalidResourceFilterCalls.forEach((entry) => {
|
|
242
|
+
errors.push(
|
|
243
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
244
|
+
path,
|
|
245
|
+
repairClass: "resource-runtime-contract-stop",
|
|
246
|
+
ruleId: entry.ruleId,
|
|
247
|
+
message: entry.message,
|
|
248
|
+
modelUse,
|
|
249
|
+
surface,
|
|
250
|
+
index: entry.index,
|
|
251
|
+
source,
|
|
252
|
+
details: {
|
|
253
|
+
capability: entry.capability,
|
|
254
|
+
resourceType: entry.resourceType,
|
|
255
|
+
dataSourceKey: entry.dataSourceKey,
|
|
256
|
+
collectionName: entry.collectionName,
|
|
257
|
+
fieldInterface: entry.fieldInterface,
|
|
258
|
+
fieldPath: entry.fieldPath,
|
|
259
|
+
fieldType: entry.fieldType,
|
|
260
|
+
invalidShape: entry.invalidShape,
|
|
261
|
+
invalidReason: entry.invalidReason,
|
|
262
|
+
invalidValue: entry.invalidValue,
|
|
263
|
+
operator: entry.operator,
|
|
264
|
+
repairExample: entry.repairExample,
|
|
265
|
+
repairHint: entry.repairHint,
|
|
266
|
+
unsupportedKeys: entry.unsupportedKeys,
|
|
267
|
+
suggestedOperator: entry.suggestedOperator,
|
|
268
|
+
suggestedValue: entry.suggestedValue,
|
|
269
|
+
examples: entry.examples,
|
|
270
|
+
availableFields: entry.availableFields
|
|
271
|
+
}
|
|
272
|
+
})
|
|
273
|
+
);
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
function collectDirectDomErrors(path, source, scan, modelUse, surface, errors) {
|
|
277
|
+
scan.directDomAliases.forEach((entry) => {
|
|
278
|
+
errors.push(
|
|
279
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
280
|
+
path,
|
|
281
|
+
repairClass: "replace-innerhtml-with-render",
|
|
282
|
+
ruleId: "runjs-direct-dom-render-forbidden",
|
|
283
|
+
message: `flowSurfaces authoring ${path} cannot alias ctx.element in RunJS`,
|
|
284
|
+
modelUse,
|
|
285
|
+
surface,
|
|
286
|
+
index: entry.index,
|
|
287
|
+
source,
|
|
288
|
+
details: {
|
|
289
|
+
capability: "ctx.element",
|
|
290
|
+
alias: entry.alias
|
|
291
|
+
}
|
|
292
|
+
})
|
|
293
|
+
);
|
|
294
|
+
});
|
|
295
|
+
scan.directDomWrites.forEach((entry) => {
|
|
296
|
+
errors.push(
|
|
297
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
298
|
+
path,
|
|
299
|
+
repairClass: "replace-innerhtml-with-render",
|
|
300
|
+
ruleId: "runjs-direct-dom-render-forbidden",
|
|
301
|
+
message: `flowSurfaces authoring ${path} must render through ctx.render(...) instead of direct DOM writes`,
|
|
302
|
+
modelUse,
|
|
303
|
+
surface,
|
|
304
|
+
index: entry.index,
|
|
305
|
+
source,
|
|
306
|
+
details: {
|
|
307
|
+
capability: entry.match
|
|
308
|
+
}
|
|
309
|
+
})
|
|
310
|
+
);
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
function collectGlobalErrors(path, source, scan, modelUse, surface, errors) {
|
|
314
|
+
scan.windowDocumentNavigatorAliases.forEach((entry) => {
|
|
315
|
+
errors.push(
|
|
316
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
317
|
+
path,
|
|
318
|
+
repairClass: "blocked-global-stop",
|
|
319
|
+
message: `flowSurfaces authoring ${path} cannot alias forbidden global ${entry.root}`,
|
|
320
|
+
modelUse,
|
|
321
|
+
surface,
|
|
322
|
+
index: entry.index,
|
|
323
|
+
source,
|
|
324
|
+
details: {
|
|
325
|
+
global: entry.root,
|
|
326
|
+
alias: entry.alias
|
|
327
|
+
}
|
|
328
|
+
})
|
|
329
|
+
);
|
|
330
|
+
});
|
|
331
|
+
scan.windowDocumentNavigatorUses.forEach((entry) => {
|
|
332
|
+
errors.push(
|
|
333
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
334
|
+
path,
|
|
335
|
+
repairClass: "blocked-global-stop",
|
|
336
|
+
ruleId: `runjs-${entry.root}-property-blocked`,
|
|
337
|
+
message: `flowSurfaces authoring ${path} cannot access ${entry.root}.${entry.member} in RunJS`,
|
|
338
|
+
modelUse,
|
|
339
|
+
surface,
|
|
340
|
+
index: entry.index,
|
|
341
|
+
source,
|
|
342
|
+
details: {
|
|
343
|
+
global: entry.root,
|
|
344
|
+
member: entry.member
|
|
345
|
+
}
|
|
346
|
+
})
|
|
347
|
+
);
|
|
348
|
+
});
|
|
349
|
+
scan.forbiddenBareGlobals.forEach((entry) => {
|
|
350
|
+
errors.push(
|
|
351
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
352
|
+
path,
|
|
353
|
+
repairClass: "blocked-global-stop",
|
|
354
|
+
message: `flowSurfaces authoring ${path} cannot access forbidden global ${entry.name}`,
|
|
355
|
+
modelUse,
|
|
356
|
+
surface,
|
|
357
|
+
index: entry.index,
|
|
358
|
+
source,
|
|
359
|
+
details: {
|
|
360
|
+
global: entry.name
|
|
361
|
+
}
|
|
362
|
+
})
|
|
363
|
+
);
|
|
364
|
+
});
|
|
365
|
+
scan.unknownBareGlobals.forEach((entry) => {
|
|
366
|
+
const suggestion = entry.suggestedCapability ? `; use ${entry.suggestedCapability} or assign it to a local variable first` : "; declare or import it before using it";
|
|
367
|
+
errors.push(
|
|
368
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
369
|
+
path,
|
|
370
|
+
repairClass: "unknown-global-stop",
|
|
371
|
+
ruleId: "runjs-global-unknown",
|
|
372
|
+
message: `flowSurfaces authoring ${path} cannot access unknown RunJS global ${entry.name}${suggestion}`,
|
|
373
|
+
modelUse,
|
|
374
|
+
surface,
|
|
375
|
+
index: entry.index,
|
|
376
|
+
source,
|
|
377
|
+
details: {
|
|
378
|
+
global: entry.name,
|
|
379
|
+
suggestedCapability: entry.suggestedCapability
|
|
380
|
+
}
|
|
381
|
+
})
|
|
382
|
+
);
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
function collectReactRuntimeErrors(path, source, scan, modelUse, surface, errors) {
|
|
386
|
+
scan.topLevelReactHookCalls.forEach((entry) => {
|
|
387
|
+
errors.push(
|
|
388
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
389
|
+
path,
|
|
390
|
+
repairClass: "react-runtime-contract-stop",
|
|
391
|
+
ruleId: "runjs-react-hook-top-level-forbidden",
|
|
392
|
+
message: `flowSurfaces authoring ${path} cannot call React Hook ${entry.hook}(...) from top-level RunJS code`,
|
|
393
|
+
modelUse,
|
|
394
|
+
surface,
|
|
395
|
+
index: entry.index,
|
|
396
|
+
source,
|
|
397
|
+
details: {
|
|
398
|
+
hook: entry.hook,
|
|
399
|
+
capability: entry.match
|
|
400
|
+
}
|
|
401
|
+
})
|
|
402
|
+
);
|
|
403
|
+
});
|
|
404
|
+
scan.unboundReactCreateElementCalls.forEach((entry) => {
|
|
405
|
+
errors.push(
|
|
406
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
407
|
+
path,
|
|
408
|
+
repairClass: "react-runtime-contract-stop",
|
|
409
|
+
ruleId: "runjs-react-global-unbound",
|
|
410
|
+
message: `flowSurfaces authoring ${path} cannot use bare React.createElement(...) without binding React from ctx.React`,
|
|
411
|
+
modelUse,
|
|
412
|
+
surface,
|
|
413
|
+
index: entry.index,
|
|
414
|
+
source,
|
|
415
|
+
details: {
|
|
416
|
+
capability: "React.createElement"
|
|
417
|
+
}
|
|
418
|
+
})
|
|
419
|
+
);
|
|
420
|
+
});
|
|
421
|
+
scan.invalidReactRuntimeBindings.forEach((entry) => {
|
|
422
|
+
errors.push(
|
|
423
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
424
|
+
path,
|
|
425
|
+
repairClass: "react-runtime-contract-stop",
|
|
426
|
+
ruleId: entry.ruleId,
|
|
427
|
+
message: `flowSurfaces authoring ${path} cannot bind ${entry.binding} from ${entry.capability}; bind React with "const React = ctx.React" before using JSX or React.createElement`,
|
|
428
|
+
modelUse,
|
|
429
|
+
surface,
|
|
430
|
+
index: entry.declarationStart ?? entry.start,
|
|
431
|
+
source,
|
|
432
|
+
details: {
|
|
433
|
+
binding: entry.binding,
|
|
434
|
+
capability: entry.capability,
|
|
435
|
+
repairClass: "react-runtime-contract-stop"
|
|
436
|
+
}
|
|
437
|
+
})
|
|
438
|
+
);
|
|
439
|
+
});
|
|
440
|
+
scan.reactComponentFunctionCalls.forEach((entry) => {
|
|
441
|
+
errors.push(
|
|
442
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
443
|
+
path,
|
|
444
|
+
repairClass: "react-runtime-contract-stop",
|
|
445
|
+
ruleId: "runjs-react-component-call-forbidden",
|
|
446
|
+
message: `flowSurfaces authoring ${path} cannot call React component ${entry.component} as a plain function`,
|
|
447
|
+
modelUse,
|
|
448
|
+
surface,
|
|
449
|
+
index: entry.index,
|
|
450
|
+
source,
|
|
451
|
+
details: {
|
|
452
|
+
capability: entry.capability,
|
|
453
|
+
component: entry.component
|
|
454
|
+
}
|
|
455
|
+
})
|
|
456
|
+
);
|
|
457
|
+
});
|
|
458
|
+
scan.reactAsyncComponentReferences.forEach((entry) => {
|
|
459
|
+
errors.push(
|
|
460
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
461
|
+
path,
|
|
462
|
+
repairClass: "react-runtime-contract-stop",
|
|
463
|
+
ruleId: "runjs-react-async-component-forbidden",
|
|
464
|
+
message: `flowSurfaces authoring ${path} cannot render async function ${entry.component} as a React component because React receives a Promise`,
|
|
465
|
+
modelUse,
|
|
466
|
+
surface,
|
|
467
|
+
index: entry.index,
|
|
468
|
+
source,
|
|
469
|
+
details: {
|
|
470
|
+
capability: entry.capability,
|
|
471
|
+
component: entry.component
|
|
472
|
+
}
|
|
473
|
+
})
|
|
474
|
+
);
|
|
475
|
+
});
|
|
476
|
+
scan.ctxRenderComponentSignatureCalls.forEach((entry) => {
|
|
477
|
+
errors.push(
|
|
478
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
479
|
+
path,
|
|
480
|
+
repairClass: "react-runtime-contract-stop",
|
|
481
|
+
ruleId: "runjs-render-component-signature-invalid",
|
|
482
|
+
message: `flowSurfaces authoring ${path} cannot pass React component ${entry.component} directly to ctx.render(...)`,
|
|
483
|
+
modelUse,
|
|
484
|
+
surface,
|
|
485
|
+
index: entry.index,
|
|
486
|
+
source,
|
|
487
|
+
details: {
|
|
488
|
+
capability: entry.capability,
|
|
489
|
+
component: entry.component
|
|
490
|
+
}
|
|
491
|
+
})
|
|
492
|
+
);
|
|
493
|
+
});
|
|
494
|
+
scan.reactComponentPropReferences.forEach((entry) => {
|
|
495
|
+
errors.push(
|
|
496
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
497
|
+
path,
|
|
498
|
+
repairClass: "react-runtime-contract-stop",
|
|
499
|
+
ruleId: "runjs-react-component-prop-node-required",
|
|
500
|
+
message: `flowSurfaces authoring ${path} cannot pass React component ${entry.component} as ${entry.prop}; create a React element first`,
|
|
501
|
+
modelUse,
|
|
502
|
+
surface,
|
|
503
|
+
index: entry.index,
|
|
504
|
+
source,
|
|
505
|
+
details: {
|
|
506
|
+
capability: entry.capability,
|
|
507
|
+
component: entry.component,
|
|
508
|
+
prop: entry.prop
|
|
509
|
+
}
|
|
510
|
+
})
|
|
511
|
+
);
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
function collectCtxContractErrors(path, source, scan, modelUse, surface, errors) {
|
|
515
|
+
scan.ctxAliases.forEach((entry) => {
|
|
516
|
+
errors.push(
|
|
517
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
518
|
+
path,
|
|
519
|
+
repairClass: "ctx-root-mismatch-stop",
|
|
520
|
+
ruleId: "runjs-ctx-root-unknown",
|
|
521
|
+
message: `flowSurfaces authoring ${path} cannot alias ctx in RunJS`,
|
|
522
|
+
modelUse,
|
|
523
|
+
surface,
|
|
524
|
+
index: entry.index,
|
|
525
|
+
source,
|
|
526
|
+
details: {
|
|
527
|
+
member: entry.alias
|
|
528
|
+
}
|
|
529
|
+
})
|
|
530
|
+
);
|
|
531
|
+
});
|
|
532
|
+
scan.ctxLibMemberCaseMismatches.forEach((entry) => {
|
|
533
|
+
errors.push(
|
|
534
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
535
|
+
path,
|
|
536
|
+
repairClass: "ctx-libs-member-mismatch-stop",
|
|
537
|
+
ruleId: "runjs-ctx-libs-member-case-invalid",
|
|
538
|
+
message: `flowSurfaces authoring ${path} ${entry.capability} is not a valid RunJS library key; use ${entry.expectedCapability} because ctx.libs keys are case-sensitive`,
|
|
539
|
+
modelUse,
|
|
540
|
+
surface,
|
|
541
|
+
index: entry.index,
|
|
542
|
+
source,
|
|
543
|
+
details: {
|
|
544
|
+
accessKind: entry.accessKind,
|
|
545
|
+
capability: entry.capability,
|
|
546
|
+
expectedCapability: entry.expectedCapability,
|
|
547
|
+
expectedMember: entry.expectedMember,
|
|
548
|
+
member: entry.member
|
|
549
|
+
}
|
|
550
|
+
})
|
|
551
|
+
);
|
|
552
|
+
});
|
|
553
|
+
scan.invalidCtxLibMemberAccesses.forEach((entry) => {
|
|
554
|
+
const importHint = entry.suggestedImport ? `; import it with await ctx.importAsync('${entry.suggestedImport}') instead` : "";
|
|
555
|
+
errors.push(
|
|
556
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
557
|
+
path,
|
|
558
|
+
repairClass: "ctx-libs-member-mismatch-stop",
|
|
559
|
+
ruleId: entry.ruleId,
|
|
560
|
+
message: `flowSurfaces authoring ${path} ${entry.capability} is not a supported RunJS ctx.libs.${entry.library} member${importHint}`,
|
|
561
|
+
modelUse,
|
|
562
|
+
surface,
|
|
563
|
+
index: entry.index,
|
|
564
|
+
source,
|
|
565
|
+
details: {
|
|
566
|
+
accessKind: entry.accessKind,
|
|
567
|
+
capability: entry.capability,
|
|
568
|
+
library: entry.library,
|
|
569
|
+
member: entry.member,
|
|
570
|
+
suggestedImport: entry.suggestedImport
|
|
571
|
+
}
|
|
572
|
+
})
|
|
573
|
+
);
|
|
574
|
+
});
|
|
575
|
+
scan.invalidCtxApiMemberAccesses.forEach((entry) => {
|
|
576
|
+
const message = entry.ruleId === "runjs-ctx-api-member-dynamic-unresolved" ? `flowSurfaces authoring ${path} cannot validate dynamic ${entry.capability} access` : entry.ruleId === "runjs-ctx-api-auth-member-readonly" ? `flowSurfaces authoring ${path} cannot write readonly RunJS ${entry.capability}; read ctx.api.auth.locale, role, token, or authenticator without mutating them` : entry.ruleId === "runjs-ctx-api-auth-member-unsupported" ? `flowSurfaces authoring ${path} ${entry.capability} is not a supported RunJS ctx.api.auth member; read ctx.api.auth.locale, role, token, or authenticator instead` : `flowSurfaces authoring ${path} ${entry.capability} is not a supported RunJS ctx.api member; use ctx.request(...), ctx.api.request(...), ctx.api.resource(...), or readonly ctx.api.auth fields`;
|
|
577
|
+
errors.push(
|
|
578
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
579
|
+
path,
|
|
580
|
+
repairClass: "ctx-root-mismatch-stop",
|
|
581
|
+
ruleId: entry.ruleId,
|
|
582
|
+
message,
|
|
583
|
+
modelUse,
|
|
584
|
+
surface,
|
|
585
|
+
index: entry.index,
|
|
586
|
+
source,
|
|
587
|
+
details: {
|
|
588
|
+
capability: entry.capability,
|
|
589
|
+
member: entry.member
|
|
590
|
+
}
|
|
591
|
+
})
|
|
592
|
+
);
|
|
593
|
+
});
|
|
594
|
+
scan.invalidCtxNonFunctionCalls.forEach((entry) => {
|
|
595
|
+
errors.push(
|
|
596
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
597
|
+
path,
|
|
598
|
+
repairClass: "ctx-root-mismatch-stop",
|
|
599
|
+
ruleId: entry.ruleId,
|
|
600
|
+
message: `flowSurfaces authoring ${path} cannot call ${entry.capability}(...); ${entry.capability} is a RunJS ctx value, not a function`,
|
|
601
|
+
modelUse,
|
|
602
|
+
surface,
|
|
603
|
+
index: entry.index,
|
|
604
|
+
source,
|
|
605
|
+
details: {
|
|
606
|
+
capability: entry.capability,
|
|
607
|
+
member: entry.member,
|
|
608
|
+
repairHint: getCtxNonFunctionCallRepairHint(entry.member)
|
|
609
|
+
}
|
|
610
|
+
})
|
|
611
|
+
);
|
|
612
|
+
});
|
|
613
|
+
scan.dynamicCtxAccesses.forEach((entry) => {
|
|
614
|
+
errors.push(
|
|
615
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
616
|
+
path,
|
|
617
|
+
repairClass: "ctx-root-mismatch-stop",
|
|
618
|
+
ruleId: "runjs-dynamic-ctx-member-unresolved",
|
|
619
|
+
message: `flowSurfaces authoring ${path} cannot validate dynamic ctx[...] access`,
|
|
620
|
+
modelUse,
|
|
621
|
+
surface,
|
|
622
|
+
index: entry.index,
|
|
623
|
+
source
|
|
624
|
+
})
|
|
625
|
+
);
|
|
626
|
+
});
|
|
627
|
+
scan.ctxMemberAccesses.forEach((entry) => {
|
|
628
|
+
const blocked = import_constants.BLOCKED_CTX_CAPABILITIES[entry.member];
|
|
629
|
+
if (blocked) {
|
|
630
|
+
errors.push(
|
|
631
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
632
|
+
path,
|
|
633
|
+
repairClass: "blocked-capability-reroute",
|
|
634
|
+
message: `flowSurfaces authoring ${path} ${blocked.capability} must be configured outside RunJS`,
|
|
635
|
+
modelUse,
|
|
636
|
+
surface,
|
|
637
|
+
index: entry.index,
|
|
638
|
+
source,
|
|
639
|
+
details: blocked
|
|
640
|
+
})
|
|
641
|
+
);
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
if (!isAllowedCtxRoot(entry.member, modelUse)) {
|
|
645
|
+
errors.push(
|
|
646
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
647
|
+
path,
|
|
648
|
+
repairClass: "ctx-root-mismatch-stop",
|
|
649
|
+
message: `flowSurfaces authoring ${path} ctx.${entry.member} is not a supported RunJS ctx root`,
|
|
650
|
+
modelUse,
|
|
651
|
+
surface,
|
|
652
|
+
index: entry.index,
|
|
653
|
+
source,
|
|
654
|
+
details: {
|
|
655
|
+
member: entry.member
|
|
656
|
+
}
|
|
657
|
+
})
|
|
658
|
+
);
|
|
659
|
+
}
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
function getCtxNonFunctionCallRepairHint(member) {
|
|
663
|
+
if (member === "collection") {
|
|
664
|
+
return "ctx.collection is collection metadata. For collection data, create a resource with ctx.makeResource(...) or use ctx.api.resource(...).";
|
|
665
|
+
}
|
|
666
|
+
if (member === "record") {
|
|
667
|
+
return "ctx.record is the current record value. Read ctx.record fields directly or use await ctx.getVar('ctx.record.id') for variable resolution.";
|
|
668
|
+
}
|
|
669
|
+
if (member === "resource") {
|
|
670
|
+
return "ctx.resource is a resource instance. Call a resource method such as ctx.resource.refresh(...), ctx.resource.getData(), or create a local resource with ctx.makeResource(...).";
|
|
671
|
+
}
|
|
672
|
+
if (member === "api") {
|
|
673
|
+
return "ctx.api is the API client object. Use ctx.api.request(...) or ctx.api.resource(...), not ctx.api(...).";
|
|
674
|
+
}
|
|
675
|
+
return `Read ctx.${member} as a value, or call one of its documented methods instead of calling ctx.${member}(...).`;
|
|
676
|
+
}
|
|
677
|
+
function collectSurfaceStyleErrors(path, source, scan, surfaceStyle, modelUse, surface, errors) {
|
|
678
|
+
var _a;
|
|
679
|
+
if (surfaceStyle === "value") {
|
|
680
|
+
const render = scan.ctxRenderCalls[0];
|
|
681
|
+
if (render) {
|
|
682
|
+
errors.push(
|
|
683
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
684
|
+
path,
|
|
685
|
+
repairClass: "value-surface-forbids-render",
|
|
686
|
+
message: `flowSurfaces authoring ${path} value RunJS must return a value and cannot call ctx.render(...)`,
|
|
687
|
+
modelUse,
|
|
688
|
+
surface,
|
|
689
|
+
index: render.index,
|
|
690
|
+
source
|
|
691
|
+
})
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
if (!scan.topLevelReturns.length) {
|
|
695
|
+
errors.push(
|
|
696
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
697
|
+
path,
|
|
698
|
+
repairClass: "missing-top-level-return",
|
|
699
|
+
message: `flowSurfaces authoring ${path} value RunJS must include a top-level return`,
|
|
700
|
+
modelUse,
|
|
701
|
+
surface,
|
|
702
|
+
index: 0,
|
|
703
|
+
source
|
|
704
|
+
})
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
if (surfaceStyle !== "render") {
|
|
710
|
+
return;
|
|
711
|
+
}
|
|
712
|
+
if (scan.reactComponentCtxRenderCalls.length) {
|
|
713
|
+
scan.reactComponentCtxRenderCalls.forEach((entry) => {
|
|
714
|
+
errors.push(
|
|
715
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
716
|
+
path,
|
|
717
|
+
repairClass: "react-runtime-contract-stop",
|
|
718
|
+
ruleId: "runjs-react-component-ctx-render-forbidden",
|
|
719
|
+
message: `flowSurfaces authoring ${path} React component ${entry.component} cannot call ctx.render(...) while React is rendering it; return JSX from ${entry.component} and keep ctx.render(<${entry.component} />) on the directly executed render path`,
|
|
720
|
+
modelUse,
|
|
721
|
+
surface,
|
|
722
|
+
index: entry.index,
|
|
723
|
+
source,
|
|
724
|
+
details: {
|
|
725
|
+
capability: entry.capability,
|
|
726
|
+
component: entry.component
|
|
727
|
+
}
|
|
728
|
+
})
|
|
729
|
+
);
|
|
730
|
+
});
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
const firstTopLevelRender = scan.topLevelReachableCtxRenderCalls[0];
|
|
734
|
+
const firstTopLevelReturn = scan.topLevelReturns[0];
|
|
735
|
+
if (firstTopLevelRender && (!firstTopLevelReturn || firstTopLevelRender.index < firstTopLevelReturn.index)) {
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
738
|
+
if (firstTopLevelRender && firstTopLevelReturn && firstTopLevelReturn.index < firstTopLevelRender.index) {
|
|
739
|
+
errors.push(
|
|
740
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
741
|
+
path,
|
|
742
|
+
repairClass: "render-unreachable-render-call",
|
|
743
|
+
message: `flowSurfaces authoring ${path} ctx.render(...) must be reachable before any top-level return`,
|
|
744
|
+
modelUse,
|
|
745
|
+
surface,
|
|
746
|
+
index: firstTopLevelRender.index,
|
|
747
|
+
source
|
|
748
|
+
})
|
|
749
|
+
);
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
if (scan.directDomWrites[0]) {
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
if (scan.isTopLevelFunctionWrapper) {
|
|
756
|
+
errors.push(
|
|
757
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
758
|
+
path,
|
|
759
|
+
repairClass: "render-top-level-function-wrapper",
|
|
760
|
+
message: `flowSurfaces authoring ${path} render code cannot hide all render logic inside an uncalled top-level function`,
|
|
761
|
+
modelUse,
|
|
762
|
+
surface,
|
|
763
|
+
index: ((_a = scan.functionRanges[0]) == null ? void 0 : _a.start) || 0,
|
|
764
|
+
source
|
|
765
|
+
})
|
|
766
|
+
);
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
if (scan.ctxRenderCalls.length) {
|
|
770
|
+
errors.push(
|
|
771
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
772
|
+
path,
|
|
773
|
+
repairClass: "render-unreachable-render-call",
|
|
774
|
+
message: `flowSurfaces authoring ${path} ctx.render(...) must be on the directly executed top-level path`,
|
|
775
|
+
modelUse,
|
|
776
|
+
surface,
|
|
777
|
+
index: scan.ctxRenderCalls[0].index,
|
|
778
|
+
source
|
|
779
|
+
})
|
|
780
|
+
);
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
errors.push(
|
|
784
|
+
(0, import_errors.buildRunJsAuthoringError)({
|
|
785
|
+
path,
|
|
786
|
+
repairClass: "replace-innerhtml-with-render",
|
|
787
|
+
ruleId: "runjs-render-required",
|
|
788
|
+
message: `flowSurfaces authoring ${path} render JS surfaces must call ctx.render(...) from reachable top-level code`,
|
|
789
|
+
modelUse,
|
|
790
|
+
surface,
|
|
791
|
+
index: 0,
|
|
792
|
+
source
|
|
793
|
+
})
|
|
794
|
+
);
|
|
795
|
+
}
|
|
796
|
+
function isAllowedCtxRoot(member, modelUse) {
|
|
797
|
+
return import_constants.ALLOWED_CTX_ROOTS.has(member) || (modelUse === "ChartOptionModel" || modelUse === "ChartEventsModel") && import_constants.CHART_CTX_ROOTS.has(member);
|
|
798
|
+
}
|
|
799
|
+
const createLegacyValidator = (id, collect) => ({
|
|
800
|
+
id,
|
|
801
|
+
validate(runtime) {
|
|
802
|
+
const errors = [];
|
|
803
|
+
collect(runtime, errors);
|
|
804
|
+
return errors;
|
|
805
|
+
}
|
|
806
|
+
});
|
|
807
|
+
const RUNJS_INSPECTION_VALIDATORS = [
|
|
808
|
+
createLegacyValidator(
|
|
809
|
+
"nested-runjs",
|
|
810
|
+
(runtime, errors) => collectNestedRunJsErrors(
|
|
811
|
+
runtime.input.path,
|
|
812
|
+
runtime.source,
|
|
813
|
+
runtime.scan,
|
|
814
|
+
runtime.modelUse,
|
|
815
|
+
runtime.surface,
|
|
816
|
+
errors
|
|
817
|
+
)
|
|
818
|
+
),
|
|
819
|
+
createLegacyValidator(
|
|
820
|
+
"resource-api",
|
|
821
|
+
(runtime, errors) => collectResourceApiErrors(
|
|
822
|
+
runtime.input.path,
|
|
823
|
+
runtime.source,
|
|
824
|
+
runtime.scan,
|
|
825
|
+
runtime.modelUse,
|
|
826
|
+
runtime.surface,
|
|
827
|
+
errors
|
|
828
|
+
)
|
|
829
|
+
),
|
|
830
|
+
createLegacyValidator(
|
|
831
|
+
"resource-runtime",
|
|
832
|
+
(runtime, errors) => collectResourceRuntimeErrors(
|
|
833
|
+
runtime.input.path,
|
|
834
|
+
runtime.source,
|
|
835
|
+
runtime.scan,
|
|
836
|
+
runtime.modelUse,
|
|
837
|
+
runtime.surface,
|
|
838
|
+
errors
|
|
839
|
+
)
|
|
840
|
+
),
|
|
841
|
+
createLegacyValidator("dom-global", (runtime, errors) => {
|
|
842
|
+
collectDirectDomErrors(runtime.input.path, runtime.source, runtime.scan, runtime.modelUse, runtime.surface, errors);
|
|
843
|
+
collectGlobalErrors(runtime.input.path, runtime.source, runtime.scan, runtime.modelUse, runtime.surface, errors);
|
|
844
|
+
}),
|
|
845
|
+
createLegacyValidator(
|
|
846
|
+
"react-runtime",
|
|
847
|
+
(runtime, errors) => collectReactRuntimeErrors(
|
|
848
|
+
runtime.input.path,
|
|
849
|
+
runtime.source,
|
|
850
|
+
runtime.scan,
|
|
851
|
+
runtime.modelUse,
|
|
852
|
+
runtime.surface,
|
|
853
|
+
errors
|
|
854
|
+
)
|
|
855
|
+
),
|
|
856
|
+
createLegacyValidator(
|
|
857
|
+
"ctx-contract",
|
|
858
|
+
(runtime, errors) => collectCtxContractErrors(
|
|
859
|
+
runtime.input.path,
|
|
860
|
+
runtime.source,
|
|
861
|
+
runtime.scan,
|
|
862
|
+
runtime.modelUse,
|
|
863
|
+
runtime.surface,
|
|
864
|
+
errors
|
|
865
|
+
)
|
|
866
|
+
),
|
|
867
|
+
createLegacyValidator(
|
|
868
|
+
"surface-style",
|
|
869
|
+
(runtime, errors) => collectSurfaceStyleErrors(
|
|
870
|
+
runtime.input.path,
|
|
871
|
+
runtime.source,
|
|
872
|
+
runtime.scan,
|
|
873
|
+
runtime.surfaceStyle,
|
|
874
|
+
runtime.modelUse,
|
|
875
|
+
runtime.surface,
|
|
876
|
+
errors
|
|
877
|
+
)
|
|
878
|
+
)
|
|
879
|
+
];
|
|
880
|
+
function collectRunJsInspectionErrors(runtime) {
|
|
881
|
+
return RUNJS_INSPECTION_VALIDATORS.flatMap((validator) => validator.validate(runtime));
|
|
882
|
+
}
|
|
883
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
884
|
+
0 && (module.exports = {
|
|
885
|
+
RUNJS_INSPECTION_VALIDATORS,
|
|
886
|
+
collectRunJsInspectionErrors
|
|
887
|
+
});
|