@nocobase/plugin-flow-engine 2.0.0-alpha.7 → 2.0.0-alpha.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/externalVersion.js +9 -9
- package/dist/locale/de-DE.json +62 -0
- package/dist/locale/en-US.json +57 -45
- package/dist/locale/es-ES.json +62 -0
- package/dist/locale/fr-FR.json +62 -0
- package/dist/locale/hu-HU.json +62 -0
- package/dist/locale/id-ID.json +62 -0
- package/dist/locale/index.d.ts +114 -90
- package/dist/locale/it-IT.json +62 -0
- package/dist/locale/ja-JP.json +62 -0
- package/dist/locale/ko-KR.json +62 -0
- package/dist/locale/nl-NL.json +62 -0
- package/dist/locale/pt-BR.json +62 -0
- package/dist/locale/ru-RU.json +62 -0
- package/dist/locale/tr-TR.json +62 -0
- package/dist/locale/uk-UA.json +62 -0
- package/dist/locale/vi-VN.json +62 -0
- package/dist/locale/zh-CN.json +58 -46
- package/dist/locale/zh-TW.json +62 -0
- package/dist/node_modules/ses/package.json +1 -1
- package/dist/server/collections/flowsql.js +1 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +6 -0
- package/dist/server/plugin.d.ts +0 -5
- package/dist/server/plugin.js +17 -98
- package/dist/server/repository.d.ts +13 -2
- package/dist/server/repository.js +258 -8
- package/dist/server/server.js +22 -3
- package/dist/server/template/resolver.js +10 -6
- package/dist/server/variables/records.d.ts +38 -0
- package/dist/server/variables/records.js +120 -0
- package/dist/server/variables/registry.d.ts +10 -0
- package/dist/server/variables/registry.js +278 -64
- package/dist/server/variables/selects.d.ts +19 -0
- package/dist/server/variables/selects.js +80 -0
- package/dist/server/variables/utils.d.ts +17 -0
- package/dist/server/variables/utils.js +163 -0
- package/package.json +2 -2
|
@@ -36,12 +36,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
36
36
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
37
|
var registry_exports = {};
|
|
38
38
|
__export(registry_exports, {
|
|
39
|
+
inferSelectsFromUsage: () => inferSelectsFromUsage,
|
|
39
40
|
variables: () => variables
|
|
40
41
|
});
|
|
41
42
|
module.exports = __toCommonJS(registry_exports);
|
|
42
43
|
var import_lodash = __toESM(require("lodash"));
|
|
43
44
|
var import_contexts = require("../template/contexts");
|
|
44
45
|
var import_utils = require("@nocobase/utils");
|
|
46
|
+
var import_selects = require("./selects");
|
|
47
|
+
var import_records = require("./records");
|
|
45
48
|
class VariableRegistry {
|
|
46
49
|
vars = /* @__PURE__ */ new Map();
|
|
47
50
|
register(def) {
|
|
@@ -90,40 +93,51 @@ if (!g[GLOBAL_KEY]) {
|
|
|
90
93
|
g[GLOBAL_KEY] = new VariableRegistry();
|
|
91
94
|
}
|
|
92
95
|
const variables = g[GLOBAL_KEY];
|
|
93
|
-
function inferSelectsFromUsage(paths = [],
|
|
96
|
+
function inferSelectsFromUsage(paths = [], _params) {
|
|
94
97
|
if (!Array.isArray(paths) || paths.length === 0) {
|
|
95
98
|
return { generatedAppends: void 0, generatedFields: void 0 };
|
|
96
99
|
}
|
|
97
100
|
const appendSet = /* @__PURE__ */ new Set();
|
|
98
101
|
const fieldSet = /* @__PURE__ */ new Set();
|
|
102
|
+
const normalizePath = (raw) => {
|
|
103
|
+
if (!raw) return "";
|
|
104
|
+
let s = String(raw);
|
|
105
|
+
s = s.replace(/\[(?:\d+)\]/g, "");
|
|
106
|
+
s = s.replace(/\[(?:"((?:[^"\\]|\\.)*)"|'((?:[^'\\]|\\.)*)')\]/g, (_m, g1, g2) => `.${g1 || g2}`);
|
|
107
|
+
s = s.replace(/\.\.+/g, ".");
|
|
108
|
+
s = s.replace(/^\./, "").replace(/\.$/, "");
|
|
109
|
+
return s;
|
|
110
|
+
};
|
|
99
111
|
for (let path of paths) {
|
|
100
112
|
if (!path) continue;
|
|
101
113
|
while (/^\[(\d+)\](\.|$)/.test(path)) {
|
|
102
114
|
path = path.replace(/^\[(\d+)\]\.?/, "");
|
|
103
115
|
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
rest = (m == null ? void 0 : m[2]) ?? "";
|
|
116
|
+
const norm = normalizePath(path);
|
|
117
|
+
if (!norm) continue;
|
|
118
|
+
const segments = norm.split(".").filter(Boolean);
|
|
119
|
+
if (segments.length === 0) continue;
|
|
120
|
+
if (segments.length === 1) {
|
|
121
|
+
fieldSet.add(segments[0]);
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
125
|
+
appendSet.add(segments.slice(0, i + 1).join("."));
|
|
115
126
|
}
|
|
116
|
-
|
|
117
|
-
const hasDeep = rest.includes(".") || rest.includes("[");
|
|
118
|
-
if (hasDeep) appendSet.add(first);
|
|
119
|
-
else fieldSet.add(first);
|
|
127
|
+
fieldSet.add(segments.join("."));
|
|
120
128
|
}
|
|
121
129
|
const generatedAppends = appendSet.size ? Array.from(appendSet) : void 0;
|
|
122
130
|
const generatedFields = fieldSet.size ? Array.from(fieldSet) : void 0;
|
|
123
131
|
return { generatedAppends, generatedFields };
|
|
124
132
|
}
|
|
125
|
-
async function fetchRecordWithRequestCache(koaCtx, dataSourceKey, collection, filterByTk, fields, appends) {
|
|
133
|
+
async function fetchRecordWithRequestCache(koaCtx, dataSourceKey, collection, filterByTk, fields, appends, strictSelects, preferFullRecord, associationName, sourceId) {
|
|
134
|
+
var _a, _b, _c, _d, _e;
|
|
126
135
|
try {
|
|
136
|
+
const log = (_b = (_a = koaCtx.app) == null ? void 0 : _a.logger) == null ? void 0 : _b.child({
|
|
137
|
+
module: "plugin-flow-engine",
|
|
138
|
+
submodule: "variables.resolve",
|
|
139
|
+
method: "fetchRecordWithRequestCache"
|
|
140
|
+
});
|
|
127
141
|
const kctx = koaCtx;
|
|
128
142
|
if (!kctx.state) kctx.state = {};
|
|
129
143
|
if (!kctx.state["__varResolveBatchCache"]) {
|
|
@@ -133,42 +147,89 @@ async function fetchRecordWithRequestCache(koaCtx, dataSourceKey, collection, fi
|
|
|
133
147
|
const ds = koaCtx.app.dataSourceManager.get(dataSourceKey || "main");
|
|
134
148
|
const cm = ds.collectionManager;
|
|
135
149
|
if (!(cm == null ? void 0 : cm.db)) return void 0;
|
|
136
|
-
const repo = cm.db.getRepository(collection);
|
|
150
|
+
const repo = associationName && typeof sourceId !== "undefined" ? cm.db.getRepository(associationName, sourceId) : cm.db.getRepository(collection);
|
|
151
|
+
const modelInfo = (_c = repo.collection) == null ? void 0 : _c.model;
|
|
152
|
+
const pkAttr = modelInfo == null ? void 0 : modelInfo.primaryKeyAttribute;
|
|
153
|
+
const pkIsValid = pkAttr && (modelInfo == null ? void 0 : modelInfo.rawAttributes) && Object.prototype.hasOwnProperty.call(modelInfo.rawAttributes, pkAttr);
|
|
154
|
+
const collectionInfo = repo == null ? void 0 : repo.collection;
|
|
155
|
+
const filterTargetKey = collectionInfo == null ? void 0 : collectionInfo.filterTargetKey;
|
|
156
|
+
const extraKeys = (0, import_records.getExtraKeyFieldsForSelect)(filterByTk, {
|
|
157
|
+
filterTargetKey,
|
|
158
|
+
pkAttr,
|
|
159
|
+
pkIsValid,
|
|
160
|
+
rawAttributes: (modelInfo == null ? void 0 : modelInfo.rawAttributes) || void 0
|
|
161
|
+
});
|
|
162
|
+
const effectiveExtras = strictSelects && Array.isArray(extraKeys) && extraKeys.length ? extraKeys.filter((k) => k === pkAttr) : extraKeys;
|
|
163
|
+
const fieldsWithExtras = (0, import_records.mergeFieldsWithExtras)(fields, effectiveExtras);
|
|
164
|
+
const cacheKeyFields = preferFullRecord && pkIsValid ? void 0 : Array.isArray(fieldsWithExtras) ? [...fieldsWithExtras].sort() : void 0;
|
|
165
|
+
const cacheKeyAppends = preferFullRecord ? void 0 : Array.isArray(appends) ? [...appends].sort() : void 0;
|
|
137
166
|
const keyObj = {
|
|
138
167
|
ds: dataSourceKey || "main",
|
|
139
168
|
c: collection,
|
|
140
169
|
tk: filterByTk,
|
|
141
|
-
f:
|
|
142
|
-
a:
|
|
170
|
+
f: cacheKeyFields,
|
|
171
|
+
a: cacheKeyAppends,
|
|
172
|
+
full: preferFullRecord ? true : void 0,
|
|
173
|
+
assoc: associationName,
|
|
174
|
+
sid: typeof sourceId === "undefined" ? void 0 : sourceId
|
|
143
175
|
};
|
|
144
176
|
const key = JSON.stringify(keyObj);
|
|
145
177
|
if (cache) {
|
|
146
|
-
if (cache.has(key))
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
178
|
+
if (cache.has(key)) {
|
|
179
|
+
return cache.get(key);
|
|
180
|
+
}
|
|
181
|
+
if (!strictSelects) {
|
|
182
|
+
const needFields = !preferFullRecord && Array.isArray(fieldsWithExtras) ? [...new Set(fieldsWithExtras)] : void 0;
|
|
183
|
+
const needAppends = !preferFullRecord && Array.isArray(appends) ? new Set(appends) : void 0;
|
|
184
|
+
for (const [cacheKey, cacheVal] of cache.entries()) {
|
|
185
|
+
const parsed = JSON.parse(cacheKey);
|
|
186
|
+
if (!parsed || parsed.ds !== keyObj.ds || parsed.c !== keyObj.c || !import_lodash.default.isEqual(parsed.tk, keyObj.tk) || parsed.assoc !== keyObj.assoc || !import_lodash.default.isEqual(parsed.sid, keyObj.sid))
|
|
187
|
+
continue;
|
|
188
|
+
const cachedFields = new Set(parsed.f || []);
|
|
189
|
+
const cachedAppends = new Set(parsed.a || []);
|
|
190
|
+
const fieldCoveredByAppends = (fieldPath) => {
|
|
191
|
+
const p = String(fieldPath || "");
|
|
192
|
+
for (const a of cachedAppends) {
|
|
193
|
+
if (!a) continue;
|
|
194
|
+
if (p === a || p.startsWith(a + ".")) return true;
|
|
195
|
+
}
|
|
196
|
+
return false;
|
|
197
|
+
};
|
|
198
|
+
const fieldsOk = needFields ? needFields.every((f) => cachedFields.has(f) || fieldCoveredByAppends(f)) : parsed.f === void 0;
|
|
199
|
+
const appendsOk = !needAppends || [...needAppends].every((a) => cachedAppends.has(a));
|
|
200
|
+
const fullOk = preferFullRecord ? parsed.full === true : true;
|
|
201
|
+
if (fieldsOk && appendsOk && fullOk) {
|
|
202
|
+
return cacheVal;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
159
205
|
}
|
|
160
|
-
if (typeof fallbackAny !== "undefined") return fallbackAny;
|
|
161
206
|
}
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
fields,
|
|
166
|
-
appends
|
|
207
|
+
const json = await (0, import_records.fetchRecordOrRecordsJson)(repo, {
|
|
208
|
+
filterByTk,
|
|
209
|
+
preferFullRecord,
|
|
210
|
+
fields: fieldsWithExtras,
|
|
211
|
+
appends,
|
|
212
|
+
filterTargetKey,
|
|
213
|
+
pkAttr,
|
|
214
|
+
pkIsValid
|
|
167
215
|
});
|
|
168
|
-
const json = rec ? rec.toJSON() : void 0;
|
|
169
216
|
if (cache) cache.set(key, json);
|
|
170
217
|
return json;
|
|
171
|
-
} catch (
|
|
218
|
+
} catch (e) {
|
|
219
|
+
const log = (_e = (_d = koaCtx.app) == null ? void 0 : _d.logger) == null ? void 0 : _e.child({
|
|
220
|
+
module: "plugin-flow-engine",
|
|
221
|
+
submodule: "variables.resolve",
|
|
222
|
+
method: "fetchRecordWithRequestCache"
|
|
223
|
+
});
|
|
224
|
+
const errMsg = e instanceof Error ? e.message : String(e);
|
|
225
|
+
log == null ? void 0 : log.warn("[variables.resolve] fetchRecordWithRequestCache error", {
|
|
226
|
+
ds: dataSourceKey,
|
|
227
|
+
collection,
|
|
228
|
+
tk: filterByTk,
|
|
229
|
+
fields,
|
|
230
|
+
appends,
|
|
231
|
+
error: errMsg
|
|
232
|
+
});
|
|
172
233
|
return void 0;
|
|
173
234
|
}
|
|
174
235
|
}
|
|
@@ -183,19 +244,107 @@ function attachGenericRecordVariables(flowCtx, koaCtx, usage, contextParams) {
|
|
|
183
244
|
for (const varName of Object.keys(usage)) {
|
|
184
245
|
const usedPaths = usage[varName] || [];
|
|
185
246
|
const topParams = import_lodash.default.get(contextParams, varName);
|
|
247
|
+
const deepRecordMap = /* @__PURE__ */ new Map();
|
|
248
|
+
const cp = contextParams;
|
|
249
|
+
if (cp && typeof cp === "object") {
|
|
250
|
+
const cpRec = cp;
|
|
251
|
+
for (const key of Object.keys(cpRec)) {
|
|
252
|
+
if (!key || key !== varName && !key.startsWith(`${varName}.`)) continue;
|
|
253
|
+
if (key === varName) continue;
|
|
254
|
+
const val = cpRec[key];
|
|
255
|
+
if (!isRecordParams(val)) continue;
|
|
256
|
+
const relative = key.slice(varName.length + 1);
|
|
257
|
+
if (!relative) continue;
|
|
258
|
+
deepRecordMap.set(relative, val);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
186
261
|
if (isRecordParams(topParams)) {
|
|
187
|
-
const
|
|
262
|
+
const usedPathsForBase = deepRecordMap.size ? (usedPaths || []).filter((p) => {
|
|
263
|
+
if (!p) return true;
|
|
264
|
+
for (const relative of deepRecordMap.keys()) {
|
|
265
|
+
if (!relative) continue;
|
|
266
|
+
if (p === relative || p.startsWith(relative + ".") || p.startsWith(relative + "[")) return false;
|
|
267
|
+
}
|
|
268
|
+
return true;
|
|
269
|
+
}) : usedPaths || [];
|
|
270
|
+
const hasDirectRefTop = usedPathsForBase.some((p) => p === "");
|
|
188
271
|
flowCtx.defineProperty(varName, {
|
|
189
272
|
get: async () => {
|
|
190
273
|
const dataSourceKey = (topParams == null ? void 0 : topParams.dataSourceKey) || "main";
|
|
191
|
-
|
|
274
|
+
const strictSelects = Array.isArray(topParams == null ? void 0 : topParams.fields) || Array.isArray(topParams == null ? void 0 : topParams.appends);
|
|
275
|
+
let { generatedAppends, generatedFields } = inferSelectsFromUsage(usedPathsForBase, topParams);
|
|
276
|
+
if (Array.isArray(topParams == null ? void 0 : topParams.fields)) generatedFields = topParams.fields;
|
|
277
|
+
if (Array.isArray(topParams == null ? void 0 : topParams.appends)) generatedAppends = topParams.appends;
|
|
278
|
+
const fixed = (0, import_selects.adjustSelectsForCollection)(
|
|
192
279
|
koaCtx,
|
|
193
280
|
dataSourceKey,
|
|
194
281
|
topParams.collection,
|
|
195
|
-
topParams.filterByTk,
|
|
196
282
|
generatedFields,
|
|
197
283
|
generatedAppends
|
|
198
284
|
);
|
|
285
|
+
const base = await fetchRecordWithRequestCache(
|
|
286
|
+
koaCtx,
|
|
287
|
+
dataSourceKey,
|
|
288
|
+
topParams.collection,
|
|
289
|
+
topParams.filterByTk,
|
|
290
|
+
fixed.fields,
|
|
291
|
+
fixed.appends,
|
|
292
|
+
strictSelects,
|
|
293
|
+
hasDirectRefTop,
|
|
294
|
+
topParams.associationName,
|
|
295
|
+
topParams.sourceId
|
|
296
|
+
);
|
|
297
|
+
if (!deepRecordMap.size) return base;
|
|
298
|
+
const merged = base && typeof base === "object" && !Array.isArray(base) ? { ...base } : {};
|
|
299
|
+
const setClonedPath = (obj, path, value) => {
|
|
300
|
+
const segs = String(path || "").split(".").filter(Boolean);
|
|
301
|
+
if (!segs.length) return;
|
|
302
|
+
if (segs.length === 1) {
|
|
303
|
+
obj[segs[0]] = value;
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
let cur = obj;
|
|
307
|
+
for (let i = 0; i < segs.length - 1; i++) {
|
|
308
|
+
const seg = segs[i];
|
|
309
|
+
const prev = cur[seg];
|
|
310
|
+
const next = prev && typeof prev === "object" && !Array.isArray(prev) ? { ...prev } : {};
|
|
311
|
+
cur[seg] = next;
|
|
312
|
+
cur = next;
|
|
313
|
+
}
|
|
314
|
+
cur[segs[segs.length - 1]] = value;
|
|
315
|
+
};
|
|
316
|
+
const buildNestedPromise = (recordParams, relative) => {
|
|
317
|
+
const subPaths = (usedPaths || []).map((p) => p === relative ? "" : p.startsWith(relative + ".") ? p.slice(relative.length + 1) : "").filter((x) => x !== "");
|
|
318
|
+
const hasDirectRef = (usedPaths || []).some((p) => p === relative);
|
|
319
|
+
const dataSourceKey2 = (recordParams == null ? void 0 : recordParams.dataSourceKey) || "main";
|
|
320
|
+
const strictSelects2 = Array.isArray(recordParams == null ? void 0 : recordParams.fields) || Array.isArray(recordParams == null ? void 0 : recordParams.appends);
|
|
321
|
+
let { generatedAppends: generatedAppends2, generatedFields: generatedFields2 } = inferSelectsFromUsage(subPaths, recordParams);
|
|
322
|
+
if (Array.isArray(recordParams == null ? void 0 : recordParams.fields)) generatedFields2 = recordParams.fields;
|
|
323
|
+
if (Array.isArray(recordParams == null ? void 0 : recordParams.appends)) generatedAppends2 = recordParams.appends;
|
|
324
|
+
const fixed2 = (0, import_selects.adjustSelectsForCollection)(
|
|
325
|
+
koaCtx,
|
|
326
|
+
dataSourceKey2,
|
|
327
|
+
recordParams.collection,
|
|
328
|
+
generatedFields2,
|
|
329
|
+
generatedAppends2
|
|
330
|
+
);
|
|
331
|
+
return fetchRecordWithRequestCache(
|
|
332
|
+
koaCtx,
|
|
333
|
+
dataSourceKey2,
|
|
334
|
+
recordParams.collection,
|
|
335
|
+
recordParams.filterByTk,
|
|
336
|
+
fixed2.fields,
|
|
337
|
+
fixed2.appends,
|
|
338
|
+
strictSelects2,
|
|
339
|
+
hasDirectRef,
|
|
340
|
+
recordParams.associationName,
|
|
341
|
+
recordParams.sourceId
|
|
342
|
+
);
|
|
343
|
+
};
|
|
344
|
+
for (const [relative, recordParams] of deepRecordMap.entries()) {
|
|
345
|
+
setClonedPath(merged, relative, buildNestedPromise(recordParams, relative));
|
|
346
|
+
}
|
|
347
|
+
return merged;
|
|
199
348
|
},
|
|
200
349
|
cache: true
|
|
201
350
|
});
|
|
@@ -228,44 +377,97 @@ function attachGenericRecordVariables(flowCtx, koaCtx, usage, contextParams) {
|
|
|
228
377
|
segmentMap.set(seg, arr);
|
|
229
378
|
}
|
|
230
379
|
const segEntries = Array.from(segmentMap.entries());
|
|
231
|
-
const
|
|
380
|
+
const oneLevelRecordChildren = segEntries.filter(([seg]) => {
|
|
232
381
|
const idx = parseIndexSegment(seg);
|
|
233
382
|
const nestedObj = import_lodash.default.get(contextParams, [varName, seg]) ?? (idx ? import_lodash.default.get(contextParams, [varName, idx]) : void 0);
|
|
234
383
|
const dotted = (contextParams || {})[`${varName}.${seg}`] ?? (idx ? (contextParams || {})[`${varName}.${idx}`] : void 0);
|
|
235
384
|
return isRecordParams(nestedObj) || isRecordParams(dotted);
|
|
236
385
|
});
|
|
237
|
-
if (!
|
|
386
|
+
if (!oneLevelRecordChildren.length && deepRecordMap.size === 0) continue;
|
|
238
387
|
flowCtx.defineProperty(varName, {
|
|
239
388
|
get: () => {
|
|
240
|
-
const
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
const
|
|
244
|
-
let
|
|
245
|
-
if (
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
).filter((x) => !!x);
|
|
249
|
-
if (all.length) effRemainders = all;
|
|
250
|
-
}
|
|
251
|
-
const { generatedAppends, generatedFields } = inferSelectsFromUsage(effRemainders, recordParams);
|
|
252
|
-
const definitionKey = idx ?? seg;
|
|
253
|
-
subContext.defineProperty(definitionKey, {
|
|
389
|
+
const root = new import_contexts.ServerBaseContext();
|
|
390
|
+
const definedFirstLevel = /* @__PURE__ */ new Set();
|
|
391
|
+
const defineRecordGetter = (container, key, recordParams, subPaths = [], preferFull) => {
|
|
392
|
+
const strictSelects = Array.isArray(recordParams == null ? void 0 : recordParams.fields) || Array.isArray(recordParams == null ? void 0 : recordParams.appends);
|
|
393
|
+
let { generatedAppends, generatedFields } = inferSelectsFromUsage(subPaths, recordParams);
|
|
394
|
+
if (Array.isArray(recordParams == null ? void 0 : recordParams.fields)) generatedFields = recordParams.fields;
|
|
395
|
+
if (Array.isArray(recordParams == null ? void 0 : recordParams.appends)) generatedAppends = recordParams.appends;
|
|
396
|
+
container.defineProperty(key, {
|
|
254
397
|
get: async () => {
|
|
255
398
|
const dataSourceKey = (recordParams == null ? void 0 : recordParams.dataSourceKey) || "main";
|
|
256
|
-
|
|
399
|
+
const fixed = (0, import_selects.adjustSelectsForCollection)(
|
|
257
400
|
koaCtx,
|
|
258
401
|
dataSourceKey,
|
|
259
402
|
recordParams.collection,
|
|
260
|
-
recordParams.filterByTk,
|
|
261
403
|
generatedFields,
|
|
262
404
|
generatedAppends
|
|
263
405
|
);
|
|
406
|
+
return await fetchRecordWithRequestCache(
|
|
407
|
+
koaCtx,
|
|
408
|
+
dataSourceKey,
|
|
409
|
+
recordParams.collection,
|
|
410
|
+
recordParams.filterByTk,
|
|
411
|
+
fixed.fields,
|
|
412
|
+
fixed.appends,
|
|
413
|
+
strictSelects,
|
|
414
|
+
preferFull || ((subPaths == null ? void 0 : subPaths.length) ?? 0) === 0,
|
|
415
|
+
recordParams.associationName,
|
|
416
|
+
recordParams.sourceId
|
|
417
|
+
);
|
|
264
418
|
},
|
|
265
419
|
cache: true
|
|
266
420
|
});
|
|
421
|
+
};
|
|
422
|
+
const subContainers = /* @__PURE__ */ new Map();
|
|
423
|
+
const ensureSubContainer = (parent, key) => {
|
|
424
|
+
let map = subContainers.get(parent);
|
|
425
|
+
if (!map) {
|
|
426
|
+
map = /* @__PURE__ */ new Map();
|
|
427
|
+
subContainers.set(parent, map);
|
|
428
|
+
}
|
|
429
|
+
let child = map.get(key);
|
|
430
|
+
if (!child) {
|
|
431
|
+
const inst = new import_contexts.ServerBaseContext();
|
|
432
|
+
parent.defineProperty(key, { get: () => inst.createProxy(), cache: true });
|
|
433
|
+
map.set(key, inst);
|
|
434
|
+
child = inst;
|
|
435
|
+
}
|
|
436
|
+
return child;
|
|
437
|
+
};
|
|
438
|
+
for (const [seg, remainders] of oneLevelRecordChildren) {
|
|
439
|
+
const idx = parseIndexSegment(seg);
|
|
440
|
+
const recordParams = import_lodash.default.get(contextParams, [varName, seg]) ?? (idx ? import_lodash.default.get(contextParams, [varName, idx]) : void 0) ?? (contextParams || {})[`${varName}.${seg}`] ?? (idx ? (contextParams || {})[`${varName}.${idx}`] : void 0);
|
|
441
|
+
let effRemainders = (remainders || []).filter((r) => !!r);
|
|
442
|
+
if (!effRemainders.length) {
|
|
443
|
+
const all = usedPaths.map(
|
|
444
|
+
(p) => p.startsWith(`${seg}.`) ? p.slice(seg.length + 1) : p.startsWith(`${seg}[`) ? p.slice(seg.length) : ""
|
|
445
|
+
).filter((x) => !!x);
|
|
446
|
+
if (all.length) effRemainders = all;
|
|
447
|
+
}
|
|
448
|
+
const hasDirectRefOne = (usedPaths || []).some((p) => p === seg || !!idx && p === `[${idx}]`);
|
|
449
|
+
defineRecordGetter(root, idx ?? seg, recordParams, effRemainders, hasDirectRefOne);
|
|
450
|
+
definedFirstLevel.add(idx ?? seg);
|
|
451
|
+
}
|
|
452
|
+
for (const [relative, recordParams] of deepRecordMap.entries()) {
|
|
453
|
+
const segs = String(relative).split(".").filter(Boolean);
|
|
454
|
+
if (segs.length === 0) continue;
|
|
455
|
+
const first = segs[0];
|
|
456
|
+
let container;
|
|
457
|
+
if (definedFirstLevel.has(first)) {
|
|
458
|
+
continue;
|
|
459
|
+
} else {
|
|
460
|
+
container = root;
|
|
461
|
+
for (let i = 0; i < segs.length - 1; i++) {
|
|
462
|
+
container = ensureSubContainer(container, segs[i]);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
const leaf = segs[segs.length - 1];
|
|
466
|
+
const subPaths = (usedPaths || []).map((p) => p === relative ? "" : p.startsWith(relative + ".") ? p.slice(relative.length + 1) : "").filter((x) => x !== "");
|
|
467
|
+
const hasDirectRef = (usedPaths || []).some((p) => p === relative);
|
|
468
|
+
defineRecordGetter(container, leaf, recordParams, subPaths, hasDirectRef);
|
|
267
469
|
}
|
|
268
|
-
return
|
|
470
|
+
return root.createProxy();
|
|
269
471
|
},
|
|
270
472
|
cache: true
|
|
271
473
|
});
|
|
@@ -285,7 +487,18 @@ function registerBuiltInVariables(reg) {
|
|
|
285
487
|
const authObj = koaCtx.auth;
|
|
286
488
|
const uid = (_a = authObj == null ? void 0 : authObj.user) == null ? void 0 : _a.id;
|
|
287
489
|
if (typeof uid === "undefined" || uid === null) return void 0;
|
|
288
|
-
return await fetchRecordWithRequestCache(
|
|
490
|
+
return await fetchRecordWithRequestCache(
|
|
491
|
+
koaCtx,
|
|
492
|
+
"main",
|
|
493
|
+
"users",
|
|
494
|
+
uid,
|
|
495
|
+
generatedFields,
|
|
496
|
+
generatedAppends,
|
|
497
|
+
false,
|
|
498
|
+
void 0,
|
|
499
|
+
void 0,
|
|
500
|
+
void 0
|
|
501
|
+
);
|
|
289
502
|
},
|
|
290
503
|
cache: true
|
|
291
504
|
});
|
|
@@ -295,5 +508,6 @@ function registerBuiltInVariables(reg) {
|
|
|
295
508
|
registerBuiltInVariables(variables);
|
|
296
509
|
// Annotate the CommonJS export names for ESM import in node:
|
|
297
510
|
0 && (module.exports = {
|
|
511
|
+
inferSelectsFromUsage,
|
|
298
512
|
variables
|
|
299
513
|
});
|
|
@@ -0,0 +1,19 @@
|
|
|
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 { ResourcerContext } from '@nocobase/resourcer';
|
|
10
|
+
/**
|
|
11
|
+
* 针对给定集合,修正 selects:
|
|
12
|
+
* - 若 fields 中包含单段且为关联名(如 'roles'),则将其从 fields 移到 appends。
|
|
13
|
+
* - 若 fields 中包含多段且首段为关联名(如 'roles.name'),确保 appends 包含该关联名,并将首段替换为模型真实关联名。
|
|
14
|
+
* - 非关联字段:仅当模型存在该属性(或其 snake/camel 变体)时才保留,否则丢弃以避免数据库错误。
|
|
15
|
+
*/
|
|
16
|
+
export declare function adjustSelectsForCollection(koaCtx: ResourcerContext, dataSourceKey: string, collection: string, fields?: string[], appends?: string[]): {
|
|
17
|
+
fields?: string[];
|
|
18
|
+
appends?: string[];
|
|
19
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
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 selects_exports = {};
|
|
28
|
+
__export(selects_exports, {
|
|
29
|
+
adjustSelectsForCollection: () => adjustSelectsForCollection
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(selects_exports);
|
|
32
|
+
function adjustSelectsForCollection(koaCtx, dataSourceKey, collection, fields, appends) {
|
|
33
|
+
var _a, _b, _c, _d;
|
|
34
|
+
const ds = koaCtx.app.dataSourceManager.get(dataSourceKey || "main");
|
|
35
|
+
const cm = ds.collectionManager;
|
|
36
|
+
const coll = (_b = (_a = cm == null ? void 0 : cm.db) == null ? void 0 : _a.getCollection) == null ? void 0 : _b.call(_a, collection);
|
|
37
|
+
const assocKeys = Object.keys(((_c = coll == null ? void 0 : coll.model) == null ? void 0 : _c.associations) || {});
|
|
38
|
+
const rawAttrs = ((_d = coll == null ? void 0 : coll.model) == null ? void 0 : _d.rawAttributes) || {};
|
|
39
|
+
const toCamel = (s) => s.replace(/_([a-zA-Z0-9])/g, (_m, c) => String(c).toUpperCase());
|
|
40
|
+
const toSnake = (s) => s.replace(/([A-Z])/g, "_$1").toLowerCase().replace(/^_/, "");
|
|
41
|
+
const assocMap = /* @__PURE__ */ new Map();
|
|
42
|
+
for (const k of assocKeys) {
|
|
43
|
+
assocMap.set(k, k);
|
|
44
|
+
assocMap.set(toSnake(k), k);
|
|
45
|
+
assocMap.set(toCamel(k), k);
|
|
46
|
+
}
|
|
47
|
+
const outFields = [];
|
|
48
|
+
const outAppends = new Set(appends || []);
|
|
49
|
+
for (const f of fields || []) {
|
|
50
|
+
const segs = String(f).split(".").filter(Boolean);
|
|
51
|
+
if (!segs.length) continue;
|
|
52
|
+
const first = segs[0];
|
|
53
|
+
const assocCanonical = assocMap.get(first) || assocMap.get(toCamel(first)) || assocMap.get(toSnake(first));
|
|
54
|
+
if (assocCanonical) {
|
|
55
|
+
outAppends.add(assocCanonical);
|
|
56
|
+
if (segs.length === 1) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
outFields.push([assocCanonical, ...segs.slice(1)].join("."));
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
if (rawAttrs[first]) {
|
|
63
|
+
outFields.push(f);
|
|
64
|
+
} else if (rawAttrs[toSnake(first)]) {
|
|
65
|
+
outFields.push([toSnake(first), ...segs.slice(1)].join("."));
|
|
66
|
+
} else if (rawAttrs[toCamel(first)]) {
|
|
67
|
+
outFields.push([toCamel(first), ...segs.slice(1)].join("."));
|
|
68
|
+
} else {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
fields: outFields.length ? outFields : void 0,
|
|
74
|
+
appends: outAppends.size ? Array.from(outAppends) : void 0
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
78
|
+
0 && (module.exports = {
|
|
79
|
+
adjustSelectsForCollection
|
|
80
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
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 { ResourcerContext } from '@nocobase/resourcer';
|
|
10
|
+
import type { JSONValue } from '../template/resolver';
|
|
11
|
+
/**
|
|
12
|
+
* 预取:构建“同记录”的字段/关联并集,一次查询写入 ctx.state.__varResolveBatchCache,供后续解析复用
|
|
13
|
+
*/
|
|
14
|
+
export declare function prefetchRecordsForResolve(koaCtx: ResourcerContext, items: Array<{
|
|
15
|
+
template: JSONValue;
|
|
16
|
+
contextParams?: Record<string, unknown>;
|
|
17
|
+
}>): Promise<void>;
|