@pactor-app/runtime 0.1.0 → 1.1.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.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 data = await this.loadByType(config);
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,28 +441,53 @@ 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 defaultI18n = createI18nContext2({
364
- messages: {
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",
448
+ "pactor.layout.openNavigation": "\u6253\u5F00\u5BFC\u822A",
367
449
  "pactor.layout.closeTab": "\u5173\u95ED {{title}}",
368
450
  "pactor.layout.breadcrumb": "\u9762\u5305\u5C51",
369
451
  "pactor.table.loading": "\u52A0\u8F7D\u4E2D\u2026",
370
452
  "pactor.table.empty": "\u6682\u65E0\u6570\u636E",
371
453
  "pactor.form.required": "\u5FC5\u586B",
372
- "pactor.select.clear": "\u6E05\u9664"
454
+ "pactor.select.clear": "\u6E05\u9664",
455
+ "pactor.alertDialog.confirm": "\u786E\u5B9A",
456
+ "pactor.alertDialog.cancel": "\u53D6\u6D88",
457
+ "pactor.command.empty": "\u65E0\u5339\u914D\u7ED3\u679C",
458
+ "pactor.overlay.close": "\u5173\u95ED"
459
+ },
460
+ "en-US": {
461
+ "pactor.layout.expandSidebar": "Expand sidebar",
462
+ "pactor.layout.collapseSidebar": "Collapse sidebar",
463
+ "pactor.layout.openNavigation": "Open navigation",
464
+ "pactor.layout.closeTab": "Close {{title}}",
465
+ "pactor.layout.breadcrumb": "Breadcrumb",
466
+ "pactor.table.loading": "Loading\u2026",
467
+ "pactor.table.empty": "No data",
468
+ "pactor.form.required": "Required",
469
+ "pactor.select.clear": "Clear",
470
+ "pactor.alertDialog.confirm": "Confirm",
471
+ "pactor.alertDialog.cancel": "Cancel",
472
+ "pactor.command.empty": "No results found",
473
+ "pactor.overlay.close": "Close"
373
474
  }
374
- });
475
+ };
476
+ function createDefaultI18n(locale) {
477
+ return createI18nContext2({ locale, messages: defaultMessages });
478
+ }
479
+ var defaultI18n = createDefaultI18n();
375
480
  function useI18n() {
376
481
  const value = useContext(I18nReactContext);
377
482
  if (value === null) {
378
483
  return defaultI18n;
379
484
  }
485
+ const fallback = createDefaultI18n(value.locale);
380
486
  return {
381
487
  ...value,
382
488
  t: (key, params) => {
383
489
  const translated = value.t(key, params);
384
- return translated === key ? defaultI18n.t(key, params) : translated;
490
+ return translated === key ? fallback.t(key, params) : translated;
385
491
  }
386
492
  };
387
493
  }
@@ -446,6 +552,45 @@ function registerBuiltinActions(registry) {
446
552
  }
447
553
  return { ok: true };
448
554
  });
555
+ register("call", async (action, ctx) => {
556
+ const name = action.params?.["name"];
557
+ if (typeof name !== "string" || !name) {
558
+ return {
559
+ ok: false,
560
+ error: new Error("[@pactor-app/runtime] call \u52A8\u4F5C\u7F3A\u5C11 name \u53C2\u6570")
561
+ };
562
+ }
563
+ const target = ctx.context.namedActions[name];
564
+ if (target === void 0) {
565
+ return {
566
+ ok: false,
567
+ error: new Error(
568
+ `[@pactor-app/runtime] unknown named action: "${name}"`
569
+ )
570
+ };
571
+ }
572
+ const depth = (callDepth.get(ctx.context) ?? 0) + 1;
573
+ if (depth > MAX_CALL_DEPTH) {
574
+ return {
575
+ ok: false,
576
+ error: new Error(
577
+ `[@pactor-app/runtime] call \u5D4C\u5957\u8D85\u8FC7 ${MAX_CALL_DEPTH} \u5C42\uFF08\u7591\u4F3C\u5FAA\u73AF\u5F15\u7528\uFF09: "${name}"`
578
+ )
579
+ };
580
+ }
581
+ callDepth.set(ctx.context, depth);
582
+ try {
583
+ for (const child of asActions(target)) {
584
+ const result = await ctx.execute(child);
585
+ if (!result.ok) {
586
+ return result;
587
+ }
588
+ }
589
+ return { ok: true };
590
+ } finally {
591
+ callDepth.set(ctx.context, depth - 1);
592
+ }
593
+ });
449
594
  register("parallel", async (action, ctx) => {
450
595
  const results = await Promise.all(
451
596
  asActions(action.params?.["actions"]).map((child) => ctx.execute(child))
@@ -502,6 +647,8 @@ function asActions(value) {
502
647
  }
503
648
  return [];
504
649
  }
650
+ var callDepth = /* @__PURE__ */ new WeakMap();
651
+ var MAX_CALL_DEPTH = 20;
505
652
  function isRecord(value) {
506
653
  return typeof value === "object" && value !== null && !Array.isArray(value);
507
654
  }
@@ -557,7 +704,7 @@ var ActionEngine = class {
557
704
  // Renderer 的 resolveProps)保持原样,由各自执行/渲染时
558
705
  // 按当时的 state 与作用域求值
559
706
  params: resolveDeep(action.params ?? {}, scope, {
560
- isOpaque: (value) => typeof value["action"] === "string" || typeof value["type"] === "string"
707
+ isOpaque: (value) => typeof value["action"] === "string" || typeof value["type"] === "string" || typeof value["component"] === "string"
561
708
  })
562
709
  };
563
710
  const ctx = {
@@ -592,15 +739,57 @@ var ActionEngine = class {
592
739
  };
593
740
 
594
741
  // src/renderer/renderer.tsx
742
+ import { isDslSourceRef } from "@pactor-app/core";
595
743
  import {
596
744
  resolveTemplate as resolveTemplate3
597
745
  } from "@pactor-app/expression";
746
+ import { validateDslNode, validateDslNodes } from "@pactor-app/schema";
598
747
  import {
599
748
  createElement,
600
749
  useMemo,
601
750
  useSyncExternalStore as useSyncExternalStore2
602
751
  } from "react";
603
752
 
753
+ // src/renderer/dsl-source-boundary.tsx
754
+ import { useEffect, useState } from "react";
755
+ import { Fragment, jsx } from "react/jsx-runtime";
756
+ function DslSourceBoundary({
757
+ context,
758
+ sourceRef,
759
+ placeholder,
760
+ children
761
+ }) {
762
+ const [state, setState] = useState({ status: "loading" });
763
+ const key = dslSourceKey(sourceRef);
764
+ useEffect(() => {
765
+ let cancelled = false;
766
+ setState({ status: "loading" });
767
+ context.dslSources.resolve(sourceRef).then(
768
+ (content) => {
769
+ if (!cancelled) {
770
+ setState({ status: "ready", content });
771
+ }
772
+ },
773
+ (cause) => {
774
+ if (!cancelled) {
775
+ console.warn("[@pactor-app/runtime] DSL \u52A8\u6001\u5F15\u7528\u89E3\u6790\u5931\u8D25", cause);
776
+ setState({ status: "error" });
777
+ }
778
+ }
779
+ );
780
+ return () => {
781
+ cancelled = true;
782
+ };
783
+ }, [context, key]);
784
+ if (state.status === "ready") {
785
+ return /* @__PURE__ */ jsx(Fragment, { children: children(state.content) });
786
+ }
787
+ if (state.status === "error") {
788
+ return null;
789
+ }
790
+ return /* @__PURE__ */ jsx(Fragment, { children: placeholder ?? null });
791
+ }
792
+
604
793
  // src/renderer/renderer-context.ts
605
794
  import {
606
795
  createContext as createContext2,
@@ -654,7 +843,7 @@ function UnsupportedComponent({ type }) {
654
843
  }
655
844
 
656
845
  // src/renderer/renderer.tsx
657
- import { jsx, jsxs as jsxs2 } from "react/jsx-runtime";
846
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
658
847
  function DslRenderer({ context, node, engine, children }) {
659
848
  useSyncExternalStore2(
660
849
  (onChange) => {
@@ -676,6 +865,7 @@ function DslRenderer({ context, node, engine, children }) {
676
865
  context,
677
866
  engine: resolvedEngine,
678
867
  scope: {},
868
+ referenceStack: [],
679
869
  renderChildren: (children2, extraScope) => renderChildrenOf(root, children2, extraScope)
680
870
  };
681
871
  return root;
@@ -687,6 +877,44 @@ function DslRenderer({ context, node, engine, children }) {
687
877
  }
688
878
  function renderNode(node, value, key) {
689
879
  const scope = buildScope(value.context, value.scope);
880
+ if (node.component !== void 0) {
881
+ const name = node.component;
882
+ const stack = value.referenceStack ?? [];
883
+ if (stack.includes(name)) {
884
+ console.warn(
885
+ `[@pactor-app/runtime] \u7EC4\u4EF6\u5F15\u7528\u5FAA\u73AF\uFF1A${[...stack, name].join(" \u2192 ")}`
886
+ );
887
+ return null;
888
+ }
889
+ const subtree = value.context.pageComponents[name];
890
+ if (!subtree) {
891
+ return /* @__PURE__ */ jsx2(UnsupportedComponent, { type: `component(${name})` }, key);
892
+ }
893
+ const scoped = {
894
+ ...value,
895
+ referenceStack: [...stack, name]
896
+ };
897
+ scoped.renderChildren = (children, extraScope) => renderChildrenOf(scoped, children, extraScope);
898
+ if (isDslSourceRef(subtree)) {
899
+ const ref = subtree;
900
+ return /* @__PURE__ */ jsx2(RendererContextProvider, { value: scoped, children: /* @__PURE__ */ jsx2(
901
+ DslSourceBoundary,
902
+ {
903
+ context: value.context,
904
+ sourceRef: ref,
905
+ placeholder: ref.placeholder ? renderNode(ref.placeholder, scoped, "placeholder") : null,
906
+ children: (content) => {
907
+ const resolved = validateResolvedNode(content, `components.${name}`);
908
+ if (!resolved) {
909
+ return null;
910
+ }
911
+ return renderNode(mergeReferenceNode(resolved, node), scoped, key);
912
+ }
913
+ }
914
+ ) }, key);
915
+ }
916
+ return /* @__PURE__ */ jsx2(RendererContextProvider, { value: scoped, children: renderNode(mergeReferenceNode(subtree, node), scoped, key) }, key);
917
+ }
690
918
  if (node.when !== void 0) {
691
919
  const expression = typeof node.when === "string" ? node.when : node.when.expression;
692
920
  let visible;
@@ -713,7 +941,7 @@ function renderNode(node, value, key) {
713
941
  const entry = value.context.components.get(node.type);
714
942
  const normalized = normalizeEntry(entry);
715
943
  if (!normalized) {
716
- return /* @__PURE__ */ jsx(UnsupportedComponent, { type: node.type }, key);
944
+ return /* @__PURE__ */ jsx2(UnsupportedComponent, { type: node.type }, key);
717
945
  }
718
946
  const props = resolveProps(node.props, scope);
719
947
  if (node.events) {
@@ -747,23 +975,102 @@ function resolveDeniedStrategy(permission) {
747
975
  }
748
976
  return "hidden";
749
977
  }
978
+ function mergeReferenceNode(definition, reference) {
979
+ return {
980
+ ...definition,
981
+ props: { ...definition.props, ...reference.props },
982
+ events: { ...definition.events, ...reference.events },
983
+ when: reference.when ?? definition.when,
984
+ permission: reference.permission ?? definition.permission,
985
+ id: reference.id ?? definition.id
986
+ };
987
+ }
988
+ function validateResolvedNode(content, label) {
989
+ const errors = validateDslNode(content);
990
+ if (errors.length > 0) {
991
+ console.warn(
992
+ `[@pactor-app/runtime] \u52A8\u6001\u5F15\u7528\uFF08${label}\uFF09\u8FD4\u56DE\u5185\u5BB9\u672A\u901A\u8FC7\u6821\u9A8C`,
993
+ errors
994
+ );
995
+ return null;
996
+ }
997
+ return content;
998
+ }
999
+ function validateResolvedNodes(content, label) {
1000
+ const errors = validateDslNodes(content);
1001
+ if (errors.length > 0) {
1002
+ console.warn(
1003
+ `[@pactor-app/runtime] \u52A8\u6001\u5F15\u7528\uFF08${label}\uFF09\u8FD4\u56DE\u5185\u5BB9\u672A\u901A\u8FC7\u6821\u9A8C`,
1004
+ errors
1005
+ );
1006
+ return null;
1007
+ }
1008
+ return content;
1009
+ }
1010
+ function renderChildItem(value, item, key) {
1011
+ if (isDslSourceRef(item)) {
1012
+ const ref = item;
1013
+ return /* @__PURE__ */ jsx2(
1014
+ DslSourceBoundary,
1015
+ {
1016
+ context: value.context,
1017
+ sourceRef: ref,
1018
+ placeholder: ref.placeholder ? renderNode(ref.placeholder, value, "placeholder") : null,
1019
+ children: (content) => {
1020
+ const nodes = validateResolvedNodes(content, "children");
1021
+ if (!nodes) {
1022
+ return null;
1023
+ }
1024
+ return nodes.map(
1025
+ (child, index) => renderChildItem(value, child, isDslSourceRef(child) ? `ref-${index}` : child.id ?? index)
1026
+ );
1027
+ }
1028
+ },
1029
+ key
1030
+ );
1031
+ }
1032
+ return renderNode(item, value, key);
1033
+ }
750
1034
  function renderChildrenOf(value, children, extraScope) {
751
- if (!children || children.length === 0) {
1035
+ if (!children || Array.isArray(children) && children.length === 0) {
752
1036
  return null;
753
1037
  }
1038
+ if (isDslSourceRef(children)) {
1039
+ const ref = children;
1040
+ return /* @__PURE__ */ jsx2(
1041
+ DslSourceBoundary,
1042
+ {
1043
+ context: value.context,
1044
+ sourceRef: ref,
1045
+ placeholder: ref.placeholder ? renderNode(ref.placeholder, value, "placeholder") : null,
1046
+ children: (content) => {
1047
+ const nodes = validateResolvedNodes(content, "children");
1048
+ if (!nodes) {
1049
+ return null;
1050
+ }
1051
+ return nodes.map(
1052
+ (child, index) => renderChildItem(value, child, isDslSourceRef(child) ? `ref-${index}` : child.id ?? index)
1053
+ );
1054
+ }
1055
+ },
1056
+ "dsl-source"
1057
+ );
1058
+ }
1059
+ const itemKey = (child, index) => isDslSourceRef(child) ? `ref-${index}` : child.id ?? index;
754
1060
  if (!extraScope) {
755
1061
  return children.map(
756
- (child, index) => renderNode(child, value, child.id ?? index)
1062
+ (child, index) => renderChildItem(value, child, itemKey(child, index))
757
1063
  );
758
1064
  }
759
1065
  const scoped = {
760
1066
  context: value.context,
761
1067
  engine: value.engine,
762
1068
  scope: { ...value.scope, ...extraScope },
1069
+ referenceStack: value.referenceStack,
763
1070
  renderChildren: (nested, nestedScope) => renderChildrenOf(scoped, nested, nestedScope)
764
1071
  };
765
- return /* @__PURE__ */ jsx(RendererContextProvider, { value: scoped, children: children.map(
766
- (child, index) => renderNode(child, scoped, child.id ?? index)
1072
+ return /* @__PURE__ */ jsx2(RendererContextProvider, { value: scoped, children: children.map(
1073
+ (child, index) => renderChildItem(scoped, child, itemKey(child, index))
767
1074
  ) });
768
1075
  }
769
1076
  function normalizeEntry(entry) {
@@ -786,14 +1093,16 @@ function resolveProps(props, scope) {
786
1093
  return out;
787
1094
  }
788
1095
  function isEmbeddedDslNode(value) {
789
- return typeof value.type === "string";
1096
+ return typeof value.type === "string" || typeof value.component === "string";
790
1097
  }
791
1098
 
792
1099
  // src/page/page-runtime.tsx
1100
+ import { isDslSourceRef as isDslSourceRef2, resolveRootNodes } from "@pactor-app/core";
793
1101
  import {
1102
+ validateDslNodes as validateDslNodes2,
794
1103
  validatePageDsl
795
1104
  } from "@pactor-app/schema";
796
- import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
1105
+ import { Fragment as Fragment2, jsx as jsx3 } from "react/jsx-runtime";
797
1106
  var PageRuntimeError = class extends Error {
798
1107
  constructor(errors) {
799
1108
  super(
@@ -812,7 +1121,9 @@ function createPageRuntime(pageDsl, options = {}) {
812
1121
  ...options,
813
1122
  page: pageDsl.page,
814
1123
  state: pageDsl.state ?? options.state,
815
- dataSources: pageDsl.dataSources ?? options.dataSources
1124
+ dataSources: pageDsl.dataSources ?? options.dataSources,
1125
+ namedActions: pageDsl.actions ?? options.namedActions,
1126
+ pageComponents: pageDsl.components ?? options.pageComponents
816
1127
  });
817
1128
  registerBuiltinActions(context.actions);
818
1129
  const engine = new ActionEngine(context);
@@ -848,10 +1159,7 @@ function createPageRuntime(pageDsl, options = {}) {
848
1159
  return destroyed;
849
1160
  },
850
1161
  render() {
851
- if (!pageDsl.body) {
852
- return null;
853
- }
854
- return /* @__PURE__ */ jsx2(DslRenderer, { context, node: pageDsl.body, engine });
1162
+ return renderRoots(pageDsl, context, engine);
855
1163
  },
856
1164
  ready: () => triggerWhenAlive("onReady"),
857
1165
  show: () => triggerWhenAlive("onShow"),
@@ -879,16 +1187,67 @@ function PageRuntimeView({
879
1187
  runtime,
880
1188
  children
881
1189
  }) {
882
- const body = runtime.pageDsl.body;
883
- if (!body) {
884
- return /* @__PURE__ */ jsx2(Fragment, { children: children ?? null });
1190
+ return renderRoots(runtime.pageDsl, runtime.context, runtime.engine, children);
1191
+ }
1192
+ function renderRoots(pageDsl, context, engine, children) {
1193
+ if (!pageDsl.body && isDslSourceRef2(pageDsl.children)) {
1194
+ const ref = pageDsl.children;
1195
+ return /* @__PURE__ */ jsx3(
1196
+ DslSourceBoundary,
1197
+ {
1198
+ context,
1199
+ sourceRef: ref,
1200
+ placeholder: ref.placeholder ? /* @__PURE__ */ jsx3(DslRenderer, { context, node: ref.placeholder, engine }) : null,
1201
+ children: (content) => renderResolvedRoots(content, context, engine, children)
1202
+ }
1203
+ );
1204
+ }
1205
+ const roots = resolveRootNodes(pageDsl);
1206
+ if (roots.length === 0) {
1207
+ return /* @__PURE__ */ jsx3(Fragment2, { children: children ?? null });
885
1208
  }
886
- return /* @__PURE__ */ jsx2(DslRenderer, { context: runtime.context, node: body, engine: runtime.engine, children });
1209
+ return renderRootItems(roots, context, engine, children);
1210
+ }
1211
+ function renderResolvedRoots(content, context, engine, children) {
1212
+ const errors = validateDslNodes2(content);
1213
+ if (errors.length > 0) {
1214
+ console.warn(
1215
+ "[@pactor-app/runtime] \u6839\u7EA7 children \u52A8\u6001\u5F15\u7528\u8FD4\u56DE\u5185\u5BB9\u672A\u901A\u8FC7\u6821\u9A8C",
1216
+ errors
1217
+ );
1218
+ return /* @__PURE__ */ jsx3(Fragment2, { children: children ?? null });
1219
+ }
1220
+ return renderRootItems(content, context, engine, children);
1221
+ }
1222
+ function renderRootItems(items, context, engine, children) {
1223
+ return /* @__PURE__ */ jsx3(Fragment2, { children: items.map(
1224
+ (item, index) => isDslSourceRef2(item) ? /* @__PURE__ */ jsx3(
1225
+ DslSourceBoundary,
1226
+ {
1227
+ context,
1228
+ sourceRef: item,
1229
+ placeholder: item.placeholder ? /* @__PURE__ */ jsx3(DslRenderer, { context, node: item.placeholder, engine }) : null,
1230
+ children: (content) => renderResolvedRoots(content, context, engine, children)
1231
+ },
1232
+ dslSourceKey(item)
1233
+ ) : /* @__PURE__ */ jsx3(
1234
+ DslRenderer,
1235
+ {
1236
+ context,
1237
+ node: item,
1238
+ engine,
1239
+ children: index === items.length - 1 ? children : null
1240
+ },
1241
+ item.id ?? index
1242
+ )
1243
+ ) });
887
1244
  }
888
1245
  export {
889
1246
  ActionEngine,
890
1247
  DataStore,
891
1248
  DslRenderer,
1249
+ DslSourceBoundary,
1250
+ DslSourceResolver,
892
1251
  I18nContextProvider,
893
1252
  PageRuntimeError,
894
1253
  PageRuntimeView,
@@ -900,6 +1259,7 @@ export {
900
1259
  createFetchHttpAdapter,
901
1260
  createPageRuntime,
902
1261
  createRuntimeContext,
1262
+ dslSourceKey,
903
1263
  registerBuiltinActions,
904
1264
  resolveDeep,
905
1265
  useDataSource,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pactor-app/runtime",
3
- "version": "0.1.0",
3
+ "version": "1.1.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": "0.1.0",
49
- "@pactor-app/expression": "0.1.0",
50
- "@pactor-app/schema": "0.1.0"
48
+ "@pactor-app/core": "1.1.0",
49
+ "@pactor-app/expression": "1.1.0",
50
+ "@pactor-app/schema": "1.1.0"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "react": ">=18"