@pactor-app/runtime 0.1.0 → 1.0.0
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/index.cjs +400 -40
- package/dist/index.d.cts +92 -27
- package/dist/index.d.ts +92 -27
- package/dist/index.js +382 -24
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -120,6 +120,14 @@ var DataStore = class {
|
|
|
120
120
|
}
|
|
121
121
|
return out;
|
|
122
122
|
}
|
|
123
|
+
/** 各数据源的加载状态(loading / error),供表达式作用域的 `dataStatus` 键使用 */
|
|
124
|
+
getAllStatus() {
|
|
125
|
+
const out = {};
|
|
126
|
+
for (const [name, status] of this.statuses) {
|
|
127
|
+
out[name] = { loading: status.loading, error: status.error };
|
|
128
|
+
}
|
|
129
|
+
return out;
|
|
130
|
+
}
|
|
123
131
|
subscribe(listener) {
|
|
124
132
|
this.listeners.add(listener);
|
|
125
133
|
return () => {
|
|
@@ -146,7 +154,8 @@ var DataStore = class {
|
|
|
146
154
|
const previous = this.get(name);
|
|
147
155
|
this.update(name, { loading: true, error: void 0, data: previous.data });
|
|
148
156
|
try {
|
|
149
|
-
const
|
|
157
|
+
const raw = await this.loadByType(config);
|
|
158
|
+
const data = applyOptionMapping(raw, config);
|
|
150
159
|
this.update(name, { loading: false, data, error: void 0 });
|
|
151
160
|
} catch (cause) {
|
|
152
161
|
this.update(name, {
|
|
@@ -212,6 +221,69 @@ var DataStore = class {
|
|
|
212
221
|
}
|
|
213
222
|
}
|
|
214
223
|
};
|
|
224
|
+
function applyOptionMapping(data, config) {
|
|
225
|
+
if (!config.valueField && !config.labelField && !config.disabledField) {
|
|
226
|
+
return data;
|
|
227
|
+
}
|
|
228
|
+
if (!Array.isArray(data)) {
|
|
229
|
+
return data;
|
|
230
|
+
}
|
|
231
|
+
const valueField = config.valueField ?? "value";
|
|
232
|
+
const labelField = config.labelField ?? "label";
|
|
233
|
+
return data.map((item) => {
|
|
234
|
+
if (item === null || typeof item !== "object") {
|
|
235
|
+
return item;
|
|
236
|
+
}
|
|
237
|
+
const record = item;
|
|
238
|
+
return {
|
|
239
|
+
...record,
|
|
240
|
+
label: record[labelField],
|
|
241
|
+
value: record[valueField],
|
|
242
|
+
disabled: config.disabledField ? Boolean(record[config.disabledField]) : Boolean(record.disabled)
|
|
243
|
+
};
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// src/datasource/dsl-source-resolver.ts
|
|
248
|
+
function dslSourceKey(ref) {
|
|
249
|
+
const source = ref.source;
|
|
250
|
+
if (source.type === "service") {
|
|
251
|
+
return `service:${source.service}:${JSON.stringify(source.params ?? {})}`;
|
|
252
|
+
}
|
|
253
|
+
const request = source.request;
|
|
254
|
+
return `http:${(request.method ?? "GET").toUpperCase()}:${request.url}:${JSON.stringify(request.params ?? {})}:${JSON.stringify(request.headers ?? {})}`;
|
|
255
|
+
}
|
|
256
|
+
var DslSourceResolver = class {
|
|
257
|
+
constructor(deps) {
|
|
258
|
+
this.deps = deps;
|
|
259
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
260
|
+
}
|
|
261
|
+
resolve(ref) {
|
|
262
|
+
const key = dslSourceKey(ref);
|
|
263
|
+
let cached = this.cache.get(key);
|
|
264
|
+
if (cached === void 0) {
|
|
265
|
+
cached = this.load(ref);
|
|
266
|
+
this.cache.set(key, cached);
|
|
267
|
+
}
|
|
268
|
+
return cached;
|
|
269
|
+
}
|
|
270
|
+
async load(ref) {
|
|
271
|
+
const scope = this.deps.getScope();
|
|
272
|
+
const source = ref.source;
|
|
273
|
+
if (source.type === "service") {
|
|
274
|
+
const handler = this.deps.services.get(source.service);
|
|
275
|
+
if (!handler) {
|
|
276
|
+
throw new Error(
|
|
277
|
+
`[@pactor-app/runtime] service not registered: "${source.service}"`
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
const params = resolveDeep(source.params ?? {}, scope);
|
|
281
|
+
return handler(params);
|
|
282
|
+
}
|
|
283
|
+
const request = resolveDeep(source.request, scope);
|
|
284
|
+
return this.deps.http.request(request);
|
|
285
|
+
}
|
|
286
|
+
};
|
|
215
287
|
|
|
216
288
|
// src/context/scope.ts
|
|
217
289
|
function buildScope(context, local) {
|
|
@@ -221,6 +293,7 @@ function buildScope(context, local) {
|
|
|
221
293
|
state: context.state.getState(),
|
|
222
294
|
form: context.state.get("form"),
|
|
223
295
|
data: context.data.getAllData(),
|
|
296
|
+
dataStatus: context.data.getAllStatus(),
|
|
224
297
|
route: context.route,
|
|
225
298
|
user: context.user,
|
|
226
299
|
params: context.route.params,
|
|
@@ -330,6 +403,11 @@ function createRuntimeContext(options = {}) {
|
|
|
330
403
|
http,
|
|
331
404
|
getScope: () => buildScope(context)
|
|
332
405
|
});
|
|
406
|
+
const dslSources = new DslSourceResolver({
|
|
407
|
+
services,
|
|
408
|
+
http,
|
|
409
|
+
getScope: () => buildScope(context)
|
|
410
|
+
});
|
|
333
411
|
context = {
|
|
334
412
|
app: options.app ?? {},
|
|
335
413
|
page: options.page ?? {},
|
|
@@ -342,9 +420,12 @@ function createRuntimeContext(options = {}) {
|
|
|
342
420
|
actions,
|
|
343
421
|
forms,
|
|
344
422
|
actionResults: {},
|
|
423
|
+
namedActions: options.namedActions ?? {},
|
|
424
|
+
pageComponents: options.pageComponents ?? {},
|
|
345
425
|
permission,
|
|
346
426
|
capabilities,
|
|
347
427
|
http,
|
|
428
|
+
dslSources,
|
|
348
429
|
locale: options.locale ?? "zh-CN",
|
|
349
430
|
i18n: createI18nContext({
|
|
350
431
|
locale: options.locale,
|
|
@@ -360,8 +441,8 @@ import { createI18nContext as createI18nContext2 } from "@pactor-app/core";
|
|
|
360
441
|
import { createContext, useContext } from "react";
|
|
361
442
|
var I18nReactContext = createContext(null);
|
|
362
443
|
var I18nContextProvider = I18nReactContext.Provider;
|
|
363
|
-
var
|
|
364
|
-
|
|
444
|
+
var defaultMessages = {
|
|
445
|
+
"zh-CN": {
|
|
365
446
|
"pactor.layout.expandSidebar": "\u5C55\u5F00\u4FA7\u8FB9\u680F",
|
|
366
447
|
"pactor.layout.collapseSidebar": "\u6536\u8D77\u4FA7\u8FB9\u680F",
|
|
367
448
|
"pactor.layout.closeTab": "\u5173\u95ED {{title}}",
|
|
@@ -369,19 +450,42 @@ var defaultI18n = createI18nContext2({
|
|
|
369
450
|
"pactor.table.loading": "\u52A0\u8F7D\u4E2D\u2026",
|
|
370
451
|
"pactor.table.empty": "\u6682\u65E0\u6570\u636E",
|
|
371
452
|
"pactor.form.required": "\u5FC5\u586B",
|
|
372
|
-
"pactor.select.clear": "\u6E05\u9664"
|
|
453
|
+
"pactor.select.clear": "\u6E05\u9664",
|
|
454
|
+
"pactor.alertDialog.confirm": "\u786E\u5B9A",
|
|
455
|
+
"pactor.alertDialog.cancel": "\u53D6\u6D88",
|
|
456
|
+
"pactor.command.empty": "\u65E0\u5339\u914D\u7ED3\u679C",
|
|
457
|
+
"pactor.overlay.close": "\u5173\u95ED"
|
|
458
|
+
},
|
|
459
|
+
"en-US": {
|
|
460
|
+
"pactor.layout.expandSidebar": "Expand sidebar",
|
|
461
|
+
"pactor.layout.collapseSidebar": "Collapse sidebar",
|
|
462
|
+
"pactor.layout.closeTab": "Close {{title}}",
|
|
463
|
+
"pactor.layout.breadcrumb": "Breadcrumb",
|
|
464
|
+
"pactor.table.loading": "Loading\u2026",
|
|
465
|
+
"pactor.table.empty": "No data",
|
|
466
|
+
"pactor.form.required": "Required",
|
|
467
|
+
"pactor.select.clear": "Clear",
|
|
468
|
+
"pactor.alertDialog.confirm": "Confirm",
|
|
469
|
+
"pactor.alertDialog.cancel": "Cancel",
|
|
470
|
+
"pactor.command.empty": "No results found",
|
|
471
|
+
"pactor.overlay.close": "Close"
|
|
373
472
|
}
|
|
374
|
-
}
|
|
473
|
+
};
|
|
474
|
+
function createDefaultI18n(locale) {
|
|
475
|
+
return createI18nContext2({ locale, messages: defaultMessages });
|
|
476
|
+
}
|
|
477
|
+
var defaultI18n = createDefaultI18n();
|
|
375
478
|
function useI18n() {
|
|
376
479
|
const value = useContext(I18nReactContext);
|
|
377
480
|
if (value === null) {
|
|
378
481
|
return defaultI18n;
|
|
379
482
|
}
|
|
483
|
+
const fallback = createDefaultI18n(value.locale);
|
|
380
484
|
return {
|
|
381
485
|
...value,
|
|
382
486
|
t: (key, params) => {
|
|
383
487
|
const translated = value.t(key, params);
|
|
384
|
-
return translated === key ?
|
|
488
|
+
return translated === key ? fallback.t(key, params) : translated;
|
|
385
489
|
}
|
|
386
490
|
};
|
|
387
491
|
}
|
|
@@ -446,6 +550,45 @@ function registerBuiltinActions(registry) {
|
|
|
446
550
|
}
|
|
447
551
|
return { ok: true };
|
|
448
552
|
});
|
|
553
|
+
register("call", async (action, ctx) => {
|
|
554
|
+
const name = action.params?.["name"];
|
|
555
|
+
if (typeof name !== "string" || !name) {
|
|
556
|
+
return {
|
|
557
|
+
ok: false,
|
|
558
|
+
error: new Error("[@pactor-app/runtime] call \u52A8\u4F5C\u7F3A\u5C11 name \u53C2\u6570")
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
const target = ctx.context.namedActions[name];
|
|
562
|
+
if (target === void 0) {
|
|
563
|
+
return {
|
|
564
|
+
ok: false,
|
|
565
|
+
error: new Error(
|
|
566
|
+
`[@pactor-app/runtime] unknown named action: "${name}"`
|
|
567
|
+
)
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
const depth = (callDepth.get(ctx.context) ?? 0) + 1;
|
|
571
|
+
if (depth > MAX_CALL_DEPTH) {
|
|
572
|
+
return {
|
|
573
|
+
ok: false,
|
|
574
|
+
error: new Error(
|
|
575
|
+
`[@pactor-app/runtime] call \u5D4C\u5957\u8D85\u8FC7 ${MAX_CALL_DEPTH} \u5C42\uFF08\u7591\u4F3C\u5FAA\u73AF\u5F15\u7528\uFF09: "${name}"`
|
|
576
|
+
)
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
callDepth.set(ctx.context, depth);
|
|
580
|
+
try {
|
|
581
|
+
for (const child of asActions(target)) {
|
|
582
|
+
const result = await ctx.execute(child);
|
|
583
|
+
if (!result.ok) {
|
|
584
|
+
return result;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
return { ok: true };
|
|
588
|
+
} finally {
|
|
589
|
+
callDepth.set(ctx.context, depth - 1);
|
|
590
|
+
}
|
|
591
|
+
});
|
|
449
592
|
register("parallel", async (action, ctx) => {
|
|
450
593
|
const results = await Promise.all(
|
|
451
594
|
asActions(action.params?.["actions"]).map((child) => ctx.execute(child))
|
|
@@ -502,6 +645,8 @@ function asActions(value) {
|
|
|
502
645
|
}
|
|
503
646
|
return [];
|
|
504
647
|
}
|
|
648
|
+
var callDepth = /* @__PURE__ */ new WeakMap();
|
|
649
|
+
var MAX_CALL_DEPTH = 20;
|
|
505
650
|
function isRecord(value) {
|
|
506
651
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
507
652
|
}
|
|
@@ -557,7 +702,7 @@ var ActionEngine = class {
|
|
|
557
702
|
// Renderer 的 resolveProps)保持原样,由各自执行/渲染时
|
|
558
703
|
// 按当时的 state 与作用域求值
|
|
559
704
|
params: resolveDeep(action.params ?? {}, scope, {
|
|
560
|
-
isOpaque: (value) => typeof value["action"] === "string" || typeof value["type"] === "string"
|
|
705
|
+
isOpaque: (value) => typeof value["action"] === "string" || typeof value["type"] === "string" || typeof value["component"] === "string"
|
|
561
706
|
})
|
|
562
707
|
};
|
|
563
708
|
const ctx = {
|
|
@@ -592,15 +737,57 @@ var ActionEngine = class {
|
|
|
592
737
|
};
|
|
593
738
|
|
|
594
739
|
// src/renderer/renderer.tsx
|
|
740
|
+
import { isDslSourceRef } from "@pactor-app/core";
|
|
595
741
|
import {
|
|
596
742
|
resolveTemplate as resolveTemplate3
|
|
597
743
|
} from "@pactor-app/expression";
|
|
744
|
+
import { validateDslNode, validateDslNodes } from "@pactor-app/schema";
|
|
598
745
|
import {
|
|
599
746
|
createElement,
|
|
600
747
|
useMemo,
|
|
601
748
|
useSyncExternalStore as useSyncExternalStore2
|
|
602
749
|
} from "react";
|
|
603
750
|
|
|
751
|
+
// src/renderer/dsl-source-boundary.tsx
|
|
752
|
+
import { useEffect, useState } from "react";
|
|
753
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
754
|
+
function DslSourceBoundary({
|
|
755
|
+
context,
|
|
756
|
+
sourceRef,
|
|
757
|
+
placeholder,
|
|
758
|
+
children
|
|
759
|
+
}) {
|
|
760
|
+
const [state, setState] = useState({ status: "loading" });
|
|
761
|
+
const key = dslSourceKey(sourceRef);
|
|
762
|
+
useEffect(() => {
|
|
763
|
+
let cancelled = false;
|
|
764
|
+
setState({ status: "loading" });
|
|
765
|
+
context.dslSources.resolve(sourceRef).then(
|
|
766
|
+
(content) => {
|
|
767
|
+
if (!cancelled) {
|
|
768
|
+
setState({ status: "ready", content });
|
|
769
|
+
}
|
|
770
|
+
},
|
|
771
|
+
(cause) => {
|
|
772
|
+
if (!cancelled) {
|
|
773
|
+
console.warn("[@pactor-app/runtime] DSL \u52A8\u6001\u5F15\u7528\u89E3\u6790\u5931\u8D25", cause);
|
|
774
|
+
setState({ status: "error" });
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
);
|
|
778
|
+
return () => {
|
|
779
|
+
cancelled = true;
|
|
780
|
+
};
|
|
781
|
+
}, [context, key]);
|
|
782
|
+
if (state.status === "ready") {
|
|
783
|
+
return /* @__PURE__ */ jsx(Fragment, { children: children(state.content) });
|
|
784
|
+
}
|
|
785
|
+
if (state.status === "error") {
|
|
786
|
+
return null;
|
|
787
|
+
}
|
|
788
|
+
return /* @__PURE__ */ jsx(Fragment, { children: placeholder ?? null });
|
|
789
|
+
}
|
|
790
|
+
|
|
604
791
|
// src/renderer/renderer-context.ts
|
|
605
792
|
import {
|
|
606
793
|
createContext as createContext2,
|
|
@@ -654,7 +841,7 @@ function UnsupportedComponent({ type }) {
|
|
|
654
841
|
}
|
|
655
842
|
|
|
656
843
|
// src/renderer/renderer.tsx
|
|
657
|
-
import { jsx, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
844
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
658
845
|
function DslRenderer({ context, node, engine, children }) {
|
|
659
846
|
useSyncExternalStore2(
|
|
660
847
|
(onChange) => {
|
|
@@ -676,6 +863,7 @@ function DslRenderer({ context, node, engine, children }) {
|
|
|
676
863
|
context,
|
|
677
864
|
engine: resolvedEngine,
|
|
678
865
|
scope: {},
|
|
866
|
+
referenceStack: [],
|
|
679
867
|
renderChildren: (children2, extraScope) => renderChildrenOf(root, children2, extraScope)
|
|
680
868
|
};
|
|
681
869
|
return root;
|
|
@@ -687,6 +875,44 @@ function DslRenderer({ context, node, engine, children }) {
|
|
|
687
875
|
}
|
|
688
876
|
function renderNode(node, value, key) {
|
|
689
877
|
const scope = buildScope(value.context, value.scope);
|
|
878
|
+
if (node.component !== void 0) {
|
|
879
|
+
const name = node.component;
|
|
880
|
+
const stack = value.referenceStack ?? [];
|
|
881
|
+
if (stack.includes(name)) {
|
|
882
|
+
console.warn(
|
|
883
|
+
`[@pactor-app/runtime] \u7EC4\u4EF6\u5F15\u7528\u5FAA\u73AF\uFF1A${[...stack, name].join(" \u2192 ")}`
|
|
884
|
+
);
|
|
885
|
+
return null;
|
|
886
|
+
}
|
|
887
|
+
const subtree = value.context.pageComponents[name];
|
|
888
|
+
if (!subtree) {
|
|
889
|
+
return /* @__PURE__ */ jsx2(UnsupportedComponent, { type: `component(${name})` }, key);
|
|
890
|
+
}
|
|
891
|
+
const scoped = {
|
|
892
|
+
...value,
|
|
893
|
+
referenceStack: [...stack, name]
|
|
894
|
+
};
|
|
895
|
+
scoped.renderChildren = (children, extraScope) => renderChildrenOf(scoped, children, extraScope);
|
|
896
|
+
if (isDslSourceRef(subtree)) {
|
|
897
|
+
const ref = subtree;
|
|
898
|
+
return /* @__PURE__ */ jsx2(RendererContextProvider, { value: scoped, children: /* @__PURE__ */ jsx2(
|
|
899
|
+
DslSourceBoundary,
|
|
900
|
+
{
|
|
901
|
+
context: value.context,
|
|
902
|
+
sourceRef: ref,
|
|
903
|
+
placeholder: ref.placeholder ? renderNode(ref.placeholder, scoped, "placeholder") : null,
|
|
904
|
+
children: (content) => {
|
|
905
|
+
const resolved = validateResolvedNode(content, `components.${name}`);
|
|
906
|
+
if (!resolved) {
|
|
907
|
+
return null;
|
|
908
|
+
}
|
|
909
|
+
return renderNode(mergeReferenceNode(resolved, node), scoped, key);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
) }, key);
|
|
913
|
+
}
|
|
914
|
+
return /* @__PURE__ */ jsx2(RendererContextProvider, { value: scoped, children: renderNode(mergeReferenceNode(subtree, node), scoped, key) }, key);
|
|
915
|
+
}
|
|
690
916
|
if (node.when !== void 0) {
|
|
691
917
|
const expression = typeof node.when === "string" ? node.when : node.when.expression;
|
|
692
918
|
let visible;
|
|
@@ -713,7 +939,7 @@ function renderNode(node, value, key) {
|
|
|
713
939
|
const entry = value.context.components.get(node.type);
|
|
714
940
|
const normalized = normalizeEntry(entry);
|
|
715
941
|
if (!normalized) {
|
|
716
|
-
return /* @__PURE__ */
|
|
942
|
+
return /* @__PURE__ */ jsx2(UnsupportedComponent, { type: node.type }, key);
|
|
717
943
|
}
|
|
718
944
|
const props = resolveProps(node.props, scope);
|
|
719
945
|
if (node.events) {
|
|
@@ -747,23 +973,102 @@ function resolveDeniedStrategy(permission) {
|
|
|
747
973
|
}
|
|
748
974
|
return "hidden";
|
|
749
975
|
}
|
|
976
|
+
function mergeReferenceNode(definition, reference) {
|
|
977
|
+
return {
|
|
978
|
+
...definition,
|
|
979
|
+
props: { ...definition.props, ...reference.props },
|
|
980
|
+
events: { ...definition.events, ...reference.events },
|
|
981
|
+
when: reference.when ?? definition.when,
|
|
982
|
+
permission: reference.permission ?? definition.permission,
|
|
983
|
+
id: reference.id ?? definition.id
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
function validateResolvedNode(content, label) {
|
|
987
|
+
const errors = validateDslNode(content);
|
|
988
|
+
if (errors.length > 0) {
|
|
989
|
+
console.warn(
|
|
990
|
+
`[@pactor-app/runtime] \u52A8\u6001\u5F15\u7528\uFF08${label}\uFF09\u8FD4\u56DE\u5185\u5BB9\u672A\u901A\u8FC7\u6821\u9A8C`,
|
|
991
|
+
errors
|
|
992
|
+
);
|
|
993
|
+
return null;
|
|
994
|
+
}
|
|
995
|
+
return content;
|
|
996
|
+
}
|
|
997
|
+
function validateResolvedNodes(content, label) {
|
|
998
|
+
const errors = validateDslNodes(content);
|
|
999
|
+
if (errors.length > 0) {
|
|
1000
|
+
console.warn(
|
|
1001
|
+
`[@pactor-app/runtime] \u52A8\u6001\u5F15\u7528\uFF08${label}\uFF09\u8FD4\u56DE\u5185\u5BB9\u672A\u901A\u8FC7\u6821\u9A8C`,
|
|
1002
|
+
errors
|
|
1003
|
+
);
|
|
1004
|
+
return null;
|
|
1005
|
+
}
|
|
1006
|
+
return content;
|
|
1007
|
+
}
|
|
1008
|
+
function renderChildItem(value, item, key) {
|
|
1009
|
+
if (isDslSourceRef(item)) {
|
|
1010
|
+
const ref = item;
|
|
1011
|
+
return /* @__PURE__ */ jsx2(
|
|
1012
|
+
DslSourceBoundary,
|
|
1013
|
+
{
|
|
1014
|
+
context: value.context,
|
|
1015
|
+
sourceRef: ref,
|
|
1016
|
+
placeholder: ref.placeholder ? renderNode(ref.placeholder, value, "placeholder") : null,
|
|
1017
|
+
children: (content) => {
|
|
1018
|
+
const nodes = validateResolvedNodes(content, "children");
|
|
1019
|
+
if (!nodes) {
|
|
1020
|
+
return null;
|
|
1021
|
+
}
|
|
1022
|
+
return nodes.map(
|
|
1023
|
+
(child, index) => renderChildItem(value, child, isDslSourceRef(child) ? `ref-${index}` : child.id ?? index)
|
|
1024
|
+
);
|
|
1025
|
+
}
|
|
1026
|
+
},
|
|
1027
|
+
key
|
|
1028
|
+
);
|
|
1029
|
+
}
|
|
1030
|
+
return renderNode(item, value, key);
|
|
1031
|
+
}
|
|
750
1032
|
function renderChildrenOf(value, children, extraScope) {
|
|
751
|
-
if (!children || children.length === 0) {
|
|
1033
|
+
if (!children || Array.isArray(children) && children.length === 0) {
|
|
752
1034
|
return null;
|
|
753
1035
|
}
|
|
1036
|
+
if (isDslSourceRef(children)) {
|
|
1037
|
+
const ref = children;
|
|
1038
|
+
return /* @__PURE__ */ jsx2(
|
|
1039
|
+
DslSourceBoundary,
|
|
1040
|
+
{
|
|
1041
|
+
context: value.context,
|
|
1042
|
+
sourceRef: ref,
|
|
1043
|
+
placeholder: ref.placeholder ? renderNode(ref.placeholder, value, "placeholder") : null,
|
|
1044
|
+
children: (content) => {
|
|
1045
|
+
const nodes = validateResolvedNodes(content, "children");
|
|
1046
|
+
if (!nodes) {
|
|
1047
|
+
return null;
|
|
1048
|
+
}
|
|
1049
|
+
return nodes.map(
|
|
1050
|
+
(child, index) => renderChildItem(value, child, isDslSourceRef(child) ? `ref-${index}` : child.id ?? index)
|
|
1051
|
+
);
|
|
1052
|
+
}
|
|
1053
|
+
},
|
|
1054
|
+
"dsl-source"
|
|
1055
|
+
);
|
|
1056
|
+
}
|
|
1057
|
+
const itemKey = (child, index) => isDslSourceRef(child) ? `ref-${index}` : child.id ?? index;
|
|
754
1058
|
if (!extraScope) {
|
|
755
1059
|
return children.map(
|
|
756
|
-
(child, index) =>
|
|
1060
|
+
(child, index) => renderChildItem(value, child, itemKey(child, index))
|
|
757
1061
|
);
|
|
758
1062
|
}
|
|
759
1063
|
const scoped = {
|
|
760
1064
|
context: value.context,
|
|
761
1065
|
engine: value.engine,
|
|
762
1066
|
scope: { ...value.scope, ...extraScope },
|
|
1067
|
+
referenceStack: value.referenceStack,
|
|
763
1068
|
renderChildren: (nested, nestedScope) => renderChildrenOf(scoped, nested, nestedScope)
|
|
764
1069
|
};
|
|
765
|
-
return /* @__PURE__ */
|
|
766
|
-
(child, index) =>
|
|
1070
|
+
return /* @__PURE__ */ jsx2(RendererContextProvider, { value: scoped, children: children.map(
|
|
1071
|
+
(child, index) => renderChildItem(scoped, child, itemKey(child, index))
|
|
767
1072
|
) });
|
|
768
1073
|
}
|
|
769
1074
|
function normalizeEntry(entry) {
|
|
@@ -786,14 +1091,16 @@ function resolveProps(props, scope) {
|
|
|
786
1091
|
return out;
|
|
787
1092
|
}
|
|
788
1093
|
function isEmbeddedDslNode(value) {
|
|
789
|
-
return typeof value.type === "string";
|
|
1094
|
+
return typeof value.type === "string" || typeof value.component === "string";
|
|
790
1095
|
}
|
|
791
1096
|
|
|
792
1097
|
// src/page/page-runtime.tsx
|
|
1098
|
+
import { isDslSourceRef as isDslSourceRef2, resolveRootNodes } from "@pactor-app/core";
|
|
793
1099
|
import {
|
|
1100
|
+
validateDslNodes as validateDslNodes2,
|
|
794
1101
|
validatePageDsl
|
|
795
1102
|
} from "@pactor-app/schema";
|
|
796
|
-
import { Fragment, jsx as
|
|
1103
|
+
import { Fragment as Fragment2, jsx as jsx3 } from "react/jsx-runtime";
|
|
797
1104
|
var PageRuntimeError = class extends Error {
|
|
798
1105
|
constructor(errors) {
|
|
799
1106
|
super(
|
|
@@ -812,7 +1119,9 @@ function createPageRuntime(pageDsl, options = {}) {
|
|
|
812
1119
|
...options,
|
|
813
1120
|
page: pageDsl.page,
|
|
814
1121
|
state: pageDsl.state ?? options.state,
|
|
815
|
-
dataSources: pageDsl.dataSources ?? options.dataSources
|
|
1122
|
+
dataSources: pageDsl.dataSources ?? options.dataSources,
|
|
1123
|
+
namedActions: pageDsl.actions ?? options.namedActions,
|
|
1124
|
+
pageComponents: pageDsl.components ?? options.pageComponents
|
|
816
1125
|
});
|
|
817
1126
|
registerBuiltinActions(context.actions);
|
|
818
1127
|
const engine = new ActionEngine(context);
|
|
@@ -848,10 +1157,7 @@ function createPageRuntime(pageDsl, options = {}) {
|
|
|
848
1157
|
return destroyed;
|
|
849
1158
|
},
|
|
850
1159
|
render() {
|
|
851
|
-
|
|
852
|
-
return null;
|
|
853
|
-
}
|
|
854
|
-
return /* @__PURE__ */ jsx2(DslRenderer, { context, node: pageDsl.body, engine });
|
|
1160
|
+
return renderRoots(pageDsl, context, engine);
|
|
855
1161
|
},
|
|
856
1162
|
ready: () => triggerWhenAlive("onReady"),
|
|
857
1163
|
show: () => triggerWhenAlive("onShow"),
|
|
@@ -879,16 +1185,67 @@ function PageRuntimeView({
|
|
|
879
1185
|
runtime,
|
|
880
1186
|
children
|
|
881
1187
|
}) {
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
1188
|
+
return renderRoots(runtime.pageDsl, runtime.context, runtime.engine, children);
|
|
1189
|
+
}
|
|
1190
|
+
function renderRoots(pageDsl, context, engine, children) {
|
|
1191
|
+
if (!pageDsl.body && isDslSourceRef2(pageDsl.children)) {
|
|
1192
|
+
const ref = pageDsl.children;
|
|
1193
|
+
return /* @__PURE__ */ jsx3(
|
|
1194
|
+
DslSourceBoundary,
|
|
1195
|
+
{
|
|
1196
|
+
context,
|
|
1197
|
+
sourceRef: ref,
|
|
1198
|
+
placeholder: ref.placeholder ? /* @__PURE__ */ jsx3(DslRenderer, { context, node: ref.placeholder, engine }) : null,
|
|
1199
|
+
children: (content) => renderResolvedRoots(content, context, engine, children)
|
|
1200
|
+
}
|
|
1201
|
+
);
|
|
1202
|
+
}
|
|
1203
|
+
const roots = resolveRootNodes(pageDsl);
|
|
1204
|
+
if (roots.length === 0) {
|
|
1205
|
+
return /* @__PURE__ */ jsx3(Fragment2, { children: children ?? null });
|
|
885
1206
|
}
|
|
886
|
-
return
|
|
1207
|
+
return renderRootItems(roots, context, engine, children);
|
|
1208
|
+
}
|
|
1209
|
+
function renderResolvedRoots(content, context, engine, children) {
|
|
1210
|
+
const errors = validateDslNodes2(content);
|
|
1211
|
+
if (errors.length > 0) {
|
|
1212
|
+
console.warn(
|
|
1213
|
+
"[@pactor-app/runtime] \u6839\u7EA7 children \u52A8\u6001\u5F15\u7528\u8FD4\u56DE\u5185\u5BB9\u672A\u901A\u8FC7\u6821\u9A8C",
|
|
1214
|
+
errors
|
|
1215
|
+
);
|
|
1216
|
+
return /* @__PURE__ */ jsx3(Fragment2, { children: children ?? null });
|
|
1217
|
+
}
|
|
1218
|
+
return renderRootItems(content, context, engine, children);
|
|
1219
|
+
}
|
|
1220
|
+
function renderRootItems(items, context, engine, children) {
|
|
1221
|
+
return /* @__PURE__ */ jsx3(Fragment2, { children: items.map(
|
|
1222
|
+
(item, index) => isDslSourceRef2(item) ? /* @__PURE__ */ jsx3(
|
|
1223
|
+
DslSourceBoundary,
|
|
1224
|
+
{
|
|
1225
|
+
context,
|
|
1226
|
+
sourceRef: item,
|
|
1227
|
+
placeholder: item.placeholder ? /* @__PURE__ */ jsx3(DslRenderer, { context, node: item.placeholder, engine }) : null,
|
|
1228
|
+
children: (content) => renderResolvedRoots(content, context, engine, children)
|
|
1229
|
+
},
|
|
1230
|
+
dslSourceKey(item)
|
|
1231
|
+
) : /* @__PURE__ */ jsx3(
|
|
1232
|
+
DslRenderer,
|
|
1233
|
+
{
|
|
1234
|
+
context,
|
|
1235
|
+
node: item,
|
|
1236
|
+
engine,
|
|
1237
|
+
children: index === items.length - 1 ? children : null
|
|
1238
|
+
},
|
|
1239
|
+
item.id ?? index
|
|
1240
|
+
)
|
|
1241
|
+
) });
|
|
887
1242
|
}
|
|
888
1243
|
export {
|
|
889
1244
|
ActionEngine,
|
|
890
1245
|
DataStore,
|
|
891
1246
|
DslRenderer,
|
|
1247
|
+
DslSourceBoundary,
|
|
1248
|
+
DslSourceResolver,
|
|
892
1249
|
I18nContextProvider,
|
|
893
1250
|
PageRuntimeError,
|
|
894
1251
|
PageRuntimeView,
|
|
@@ -900,6 +1257,7 @@ export {
|
|
|
900
1257
|
createFetchHttpAdapter,
|
|
901
1258
|
createPageRuntime,
|
|
902
1259
|
createRuntimeContext,
|
|
1260
|
+
dslSourceKey,
|
|
903
1261
|
registerBuiltinActions,
|
|
904
1262
|
resolveDeep,
|
|
905
1263
|
useDataSource,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pactor-app/runtime",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Pactor runtime: RuntimeContext, StateStore, DataSource runtime, action engine, React renderer and page runtime",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pactor",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"access": "public"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@pactor-app/core": "
|
|
49
|
-
"@pactor-app/expression": "
|
|
50
|
-
"@pactor-app/schema": "
|
|
48
|
+
"@pactor-app/core": "1.0.0",
|
|
49
|
+
"@pactor-app/expression": "1.0.0",
|
|
50
|
+
"@pactor-app/schema": "1.0.0"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"react": ">=18"
|