@pactor-app/runtime 1.51.0 → 1.53.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 CHANGED
@@ -194,6 +194,42 @@ var DataStore = class {
194
194
  init() {
195
195
  return Promise.all(this.autoLoadNames().map((name) => this.load(name)));
196
196
  }
197
+ /**
198
+ * 运行时注册数据源(如 DslSourceRef 片段载荷携带的 dataSources):
199
+ * 名称冲突时告警并跳过(同一引用重复注册幂等),成功时播种空状态、
200
+ * 递增版本并通知订阅者。返回是否注册成功。
201
+ */
202
+ register(name, config) {
203
+ if (this.configs[name] !== void 0) {
204
+ console.warn(
205
+ `[@pactor-app/runtime] dataSource \u540D\u79F0\u51B2\u7A81\uFF1A"${name}" \u5DF2\u6CE8\u518C\uFF0C\u8DF3\u8FC7\u91CD\u590D\u6CE8\u518C`
206
+ );
207
+ return false;
208
+ }
209
+ this.configs[name] = config;
210
+ this.statuses.set(name, { loading: false });
211
+ this.notify();
212
+ return true;
213
+ }
214
+ /** 批量运行时注册,返回实际注册成功的名称列表(冲突名跳过) */
215
+ registerAll(configs) {
216
+ const registered = [];
217
+ for (const [name, config] of Object.entries(configs)) {
218
+ if (this.register(name, config)) {
219
+ registered.push(name);
220
+ }
221
+ }
222
+ return registered;
223
+ }
224
+ /** 注销运行时注册的数据源(如片段边界卸载时回收);未知名为 no-op */
225
+ unregister(name) {
226
+ if (this.configs[name] === void 0) {
227
+ return;
228
+ }
229
+ delete this.configs[name];
230
+ this.statuses.delete(name);
231
+ this.notify();
232
+ }
197
233
  /**
198
234
  * 加载指定数据源。状态流转:开始置 loading 并清空 error;
199
235
  * 成功写入 data;失败写入 error(保留旧 data)。MUST NOT 抛出。
@@ -267,6 +303,9 @@ var DataStore = class {
267
303
  }
268
304
  update(name, status) {
269
305
  this.statuses.set(name, status);
306
+ this.notify();
307
+ }
308
+ notify() {
270
309
  this.version += 1;
271
310
  for (const listener of [...this.listeners]) {
272
311
  listener();
@@ -512,6 +551,8 @@ var defaultMessages = {
512
551
  "pactor.select.clear": "\u6E05\u9664",
513
552
  "pactor.select.search": "\u641C\u7D22\u9009\u9879",
514
553
  "pactor.input.clear": "\u6E05\u9664",
554
+ "pactor.input.showPassword": "\u663E\u793A\u5BC6\u7801",
555
+ "pactor.input.hidePassword": "\u9690\u85CF\u5BC6\u7801",
515
556
  "pactor.input.placeholder": "\u8BF7\u8F93\u5165",
516
557
  "pactor.numberInput.increase": "\u589E\u52A0",
517
558
  "pactor.numberInput.decrease": "\u51CF\u5C11",
@@ -621,6 +662,8 @@ var defaultMessages = {
621
662
  "pactor.select.clear": "Clear",
622
663
  "pactor.select.search": "Search options",
623
664
  "pactor.input.clear": "Clear",
665
+ "pactor.input.showPassword": "Show password",
666
+ "pactor.input.hidePassword": "Hide password",
624
667
  "pactor.input.placeholder": "Please enter",
625
668
  "pactor.numberInput.increase": "Increase",
626
669
  "pactor.numberInput.decrease": "Decrease",
@@ -1033,12 +1076,13 @@ var ActionEngine = class {
1033
1076
  };
1034
1077
 
1035
1078
  // src/renderer/renderer.tsx
1036
- var import_core3 = require("@pactor-app/core");
1079
+ var import_core4 = require("@pactor-app/core");
1037
1080
  var import_expression3 = require("@pactor-app/expression");
1038
1081
  var import_schema = require("@pactor-app/schema");
1039
1082
  var import_react4 = require("react");
1040
1083
 
1041
1084
  // src/renderer/dsl-source-boundary.tsx
1085
+ var import_core3 = require("@pactor-app/core");
1042
1086
  var import_react2 = require("react");
1043
1087
  var import_jsx_runtime = require("react/jsx-runtime");
1044
1088
  function DslSourceBoundary({
@@ -1051,12 +1095,32 @@ function DslSourceBoundary({
1051
1095
  const key = dslSourceKey(sourceRef);
1052
1096
  (0, import_react2.useEffect)(() => {
1053
1097
  let cancelled = false;
1098
+ let registeredSources = [];
1054
1099
  setState({ status: "loading" });
1055
1100
  context.dslSources.resolve(sourceRef).then(
1056
1101
  (content) => {
1057
- if (!cancelled) {
1058
- setState({ status: "ready", content });
1102
+ if (cancelled) {
1103
+ return;
1104
+ }
1105
+ if ((0, import_core3.isDslFragmentPayload)(content)) {
1106
+ if (content.state) {
1107
+ context.state.set(content.state);
1108
+ }
1109
+ if (content.dataSources) {
1110
+ registeredSources = context.data.registerAll(content.dataSources);
1111
+ for (const name of registeredSources) {
1112
+ if (content.dataSources[name]?.autoLoad === true) {
1113
+ context.data.load(name).catch((cause) => {
1114
+ console.warn(
1115
+ `[@pactor-app/runtime] \u7247\u6BB5\u6570\u636E\u6E90 "${name}" \u52A0\u8F7D\u5931\u8D25`,
1116
+ cause
1117
+ );
1118
+ });
1119
+ }
1120
+ }
1121
+ }
1059
1122
  }
1123
+ setState({ status: "ready", content });
1060
1124
  },
1061
1125
  (cause) => {
1062
1126
  if (!cancelled) {
@@ -1067,6 +1131,9 @@ function DslSourceBoundary({
1067
1131
  );
1068
1132
  return () => {
1069
1133
  cancelled = true;
1134
+ for (const name of registeredSources) {
1135
+ context.data.unregister(name);
1136
+ }
1070
1137
  };
1071
1138
  }, [context, key]);
1072
1139
  if (state.status === "ready") {
@@ -1179,7 +1246,7 @@ function renderNode(node, value, key) {
1179
1246
  referenceStack: [...stack, name]
1180
1247
  };
1181
1248
  scoped.renderChildren = (children, extraScope) => renderChildrenOf(scoped, children, extraScope);
1182
- if ((0, import_core3.isDslSourceRef)(subtree)) {
1249
+ if ((0, import_core4.isDslSourceRef)(subtree)) {
1183
1250
  const ref = subtree;
1184
1251
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RendererContextProvider, { value: scoped, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1185
1252
  DslSourceBoundary,
@@ -1281,6 +1348,17 @@ function validateResolvedNode(content, label) {
1281
1348
  return content;
1282
1349
  }
1283
1350
  function validateResolvedNodes(content, label) {
1351
+ if ((0, import_core4.isDslFragmentPayload)(content)) {
1352
+ const errors2 = (0, import_schema.validateDslFragmentPayload)(content);
1353
+ if (errors2.length > 0) {
1354
+ console.warn(
1355
+ `[@pactor-app/runtime] \u52A8\u6001\u5F15\u7528\uFF08${label}\uFF09\u8FD4\u56DE\u7684\u7247\u6BB5\u8F7D\u8377\u672A\u901A\u8FC7\u6821\u9A8C`,
1356
+ errors2
1357
+ );
1358
+ return null;
1359
+ }
1360
+ return content.children;
1361
+ }
1284
1362
  const errors = (0, import_schema.validateDslNodes)(content);
1285
1363
  if (errors.length > 0) {
1286
1364
  console.warn(
@@ -1292,7 +1370,7 @@ function validateResolvedNodes(content, label) {
1292
1370
  return content;
1293
1371
  }
1294
1372
  function renderChildItem(value, item, key) {
1295
- if ((0, import_core3.isDslSourceRef)(item)) {
1373
+ if ((0, import_core4.isDslSourceRef)(item)) {
1296
1374
  const ref = item;
1297
1375
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1298
1376
  DslSourceBoundary,
@@ -1306,7 +1384,7 @@ function renderChildItem(value, item, key) {
1306
1384
  return null;
1307
1385
  }
1308
1386
  return nodes.map(
1309
- (child, index) => renderChildItem(value, child, (0, import_core3.isDslSourceRef)(child) ? `ref-${index}` : child.id ?? index)
1387
+ (child, index) => renderChildItem(value, child, (0, import_core4.isDslSourceRef)(child) ? `ref-${index}` : child.id ?? index)
1310
1388
  );
1311
1389
  }
1312
1390
  },
@@ -1319,7 +1397,7 @@ function renderChildrenOf(value, children, extraScope) {
1319
1397
  if (!children || Array.isArray(children) && children.length === 0) {
1320
1398
  return null;
1321
1399
  }
1322
- if ((0, import_core3.isDslSourceRef)(children)) {
1400
+ if ((0, import_core4.isDslSourceRef)(children)) {
1323
1401
  const ref = children;
1324
1402
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1325
1403
  DslSourceBoundary,
@@ -1333,14 +1411,14 @@ function renderChildrenOf(value, children, extraScope) {
1333
1411
  return null;
1334
1412
  }
1335
1413
  return nodes.map(
1336
- (child, index) => renderChildItem(value, child, (0, import_core3.isDslSourceRef)(child) ? `ref-${index}` : child.id ?? index)
1414
+ (child, index) => renderChildItem(value, child, (0, import_core4.isDslSourceRef)(child) ? `ref-${index}` : child.id ?? index)
1337
1415
  );
1338
1416
  }
1339
1417
  },
1340
1418
  "dsl-source"
1341
1419
  );
1342
1420
  }
1343
- const itemKey = (child, index) => (0, import_core3.isDslSourceRef)(child) ? `ref-${index}` : child.id ?? index;
1421
+ const itemKey = (child, index) => (0, import_core4.isDslSourceRef)(child) ? `ref-${index}` : child.id ?? index;
1344
1422
  if (!extraScope) {
1345
1423
  return children.map(
1346
1424
  (child, index) => renderChildItem(value, child, itemKey(child, index))
@@ -1381,7 +1459,7 @@ function isEmbeddedDslNode(value) {
1381
1459
  }
1382
1460
 
1383
1461
  // src/page/page-runtime.tsx
1384
- var import_core4 = require("@pactor-app/core");
1462
+ var import_core5 = require("@pactor-app/core");
1385
1463
  var import_schema2 = require("@pactor-app/schema");
1386
1464
  var import_jsx_runtime4 = require("react/jsx-runtime");
1387
1465
  var PageRuntimeError = class extends Error {
@@ -1471,7 +1549,7 @@ function PageRuntimeView({
1471
1549
  return renderRoots(runtime.pageDsl, runtime.context, runtime.engine, children);
1472
1550
  }
1473
1551
  function renderRoots(pageDsl, context, engine, children) {
1474
- if (!pageDsl.body && (0, import_core4.isDslSourceRef)(pageDsl.children)) {
1552
+ if (!pageDsl.body && (0, import_core5.isDslSourceRef)(pageDsl.children)) {
1475
1553
  const ref = pageDsl.children;
1476
1554
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1477
1555
  DslSourceBoundary,
@@ -1483,13 +1561,29 @@ function renderRoots(pageDsl, context, engine, children) {
1483
1561
  }
1484
1562
  );
1485
1563
  }
1486
- const roots = (0, import_core4.resolveRootNodes)(pageDsl);
1564
+ const roots = (0, import_core5.resolveRootNodes)(pageDsl);
1487
1565
  if (roots.length === 0) {
1488
1566
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: children ?? null });
1489
1567
  }
1490
1568
  return renderRootItems(roots, context, engine, children);
1491
1569
  }
1492
1570
  function renderResolvedRoots(content, context, engine, children) {
1571
+ if ((0, import_core5.isDslFragmentPayload)(content)) {
1572
+ const fragmentErrors = (0, import_schema2.validateDslFragmentPayload)(content);
1573
+ if (fragmentErrors.length > 0) {
1574
+ console.warn(
1575
+ "[@pactor-app/runtime] \u6839\u7EA7 children \u52A8\u6001\u5F15\u7528\u8FD4\u56DE\u7684\u7247\u6BB5\u8F7D\u8377\u672A\u901A\u8FC7\u6821\u9A8C",
1576
+ fragmentErrors
1577
+ );
1578
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: children ?? null });
1579
+ }
1580
+ return renderRootItems(
1581
+ content.children,
1582
+ context,
1583
+ engine,
1584
+ children
1585
+ );
1586
+ }
1493
1587
  const errors = (0, import_schema2.validateDslNodes)(content);
1494
1588
  if (errors.length > 0) {
1495
1589
  console.warn(
@@ -1502,7 +1596,7 @@ function renderResolvedRoots(content, context, engine, children) {
1502
1596
  }
1503
1597
  function renderRootItems(items, context, engine, children) {
1504
1598
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: items.map(
1505
- (item, index) => (0, import_core4.isDslSourceRef)(item) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1599
+ (item, index) => (0, import_core5.isDslSourceRef)(item) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1506
1600
  DslSourceBoundary,
1507
1601
  {
1508
1602
  context,
package/dist/index.d.cts CHANGED
@@ -135,6 +135,16 @@ declare class DataStore {
135
135
  getVersion(): number;
136
136
  /** 触发所有 `autoLoad: true` 的数据源(PageRuntime 初始化阶段调用) */
137
137
  init(): Promise<void[]>;
138
+ /**
139
+ * 运行时注册数据源(如 DslSourceRef 片段载荷携带的 dataSources):
140
+ * 名称冲突时告警并跳过(同一引用重复注册幂等),成功时播种空状态、
141
+ * 递增版本并通知订阅者。返回是否注册成功。
142
+ */
143
+ register(name: string, config: DataSourceConfig): boolean;
144
+ /** 批量运行时注册,返回实际注册成功的名称列表(冲突名跳过) */
145
+ registerAll(configs: Record<string, DataSourceConfig>): string[];
146
+ /** 注销运行时注册的数据源(如片段边界卸载时回收);未知名为 no-op */
147
+ unregister(name: string): void;
138
148
  /**
139
149
  * 加载指定数据源。状态流转:开始置 loading 并清空 error;
140
150
  * 成功写入 data;失败写入 error(保留旧 data)。MUST NOT 抛出。
@@ -150,6 +160,7 @@ declare class DataStore {
150
160
  private autoLoadNames;
151
161
  private loadByType;
152
162
  private update;
163
+ private notify;
153
164
  }
154
165
 
155
166
  interface DslSourceResolverDeps {
@@ -442,6 +453,12 @@ interface DslSourceBoundaryProps {
442
453
  * 非 DSL 组件类型):解析中渲染 placeholder(缺省空)、成功交给
443
454
  * 调用方渲染、失败告警并渲染空——MUST NOT 抛错击穿渲染层。
444
455
  * 解析经 `context.dslSources`(Promise 级缓存去重)。
456
+ *
457
+ * 解析结果为片段载荷(DslFragmentPayload)时,在 effect 中应用副作用
458
+ * (MUST NOT 在 render 期注册——注册会推高 DataStore 版本引发重渲染循环):
459
+ * `state` 合并进页面 state、`dataSources` 运行时注册(冲突名跳过),
460
+ * 随后触发其中 `autoLoad: true` 的数据源加载;卸载时注销本边界注册的
461
+ * 数据源名。裸数组形态无任何副作用。
445
462
  */
446
463
  declare function DslSourceBoundary({ context, sourceRef, placeholder, children, }: DslSourceBoundaryProps): react.JSX.Element | null;
447
464
 
package/dist/index.d.ts CHANGED
@@ -135,6 +135,16 @@ declare class DataStore {
135
135
  getVersion(): number;
136
136
  /** 触发所有 `autoLoad: true` 的数据源(PageRuntime 初始化阶段调用) */
137
137
  init(): Promise<void[]>;
138
+ /**
139
+ * 运行时注册数据源(如 DslSourceRef 片段载荷携带的 dataSources):
140
+ * 名称冲突时告警并跳过(同一引用重复注册幂等),成功时播种空状态、
141
+ * 递增版本并通知订阅者。返回是否注册成功。
142
+ */
143
+ register(name: string, config: DataSourceConfig): boolean;
144
+ /** 批量运行时注册,返回实际注册成功的名称列表(冲突名跳过) */
145
+ registerAll(configs: Record<string, DataSourceConfig>): string[];
146
+ /** 注销运行时注册的数据源(如片段边界卸载时回收);未知名为 no-op */
147
+ unregister(name: string): void;
138
148
  /**
139
149
  * 加载指定数据源。状态流转:开始置 loading 并清空 error;
140
150
  * 成功写入 data;失败写入 error(保留旧 data)。MUST NOT 抛出。
@@ -150,6 +160,7 @@ declare class DataStore {
150
160
  private autoLoadNames;
151
161
  private loadByType;
152
162
  private update;
163
+ private notify;
153
164
  }
154
165
 
155
166
  interface DslSourceResolverDeps {
@@ -442,6 +453,12 @@ interface DslSourceBoundaryProps {
442
453
  * 非 DSL 组件类型):解析中渲染 placeholder(缺省空)、成功交给
443
454
  * 调用方渲染、失败告警并渲染空——MUST NOT 抛错击穿渲染层。
444
455
  * 解析经 `context.dslSources`(Promise 级缓存去重)。
456
+ *
457
+ * 解析结果为片段载荷(DslFragmentPayload)时,在 effect 中应用副作用
458
+ * (MUST NOT 在 render 期注册——注册会推高 DataStore 版本引发重渲染循环):
459
+ * `state` 合并进页面 state、`dataSources` 运行时注册(冲突名跳过),
460
+ * 随后触发其中 `autoLoad: true` 的数据源加载;卸载时注销本边界注册的
461
+ * 数据源名。裸数组形态无任何副作用。
445
462
  */
446
463
  declare function DslSourceBoundary({ context, sourceRef, placeholder, children, }: DslSourceBoundaryProps): react.JSX.Element | null;
447
464
 
package/dist/index.js CHANGED
@@ -149,6 +149,42 @@ var DataStore = class {
149
149
  init() {
150
150
  return Promise.all(this.autoLoadNames().map((name) => this.load(name)));
151
151
  }
152
+ /**
153
+ * 运行时注册数据源(如 DslSourceRef 片段载荷携带的 dataSources):
154
+ * 名称冲突时告警并跳过(同一引用重复注册幂等),成功时播种空状态、
155
+ * 递增版本并通知订阅者。返回是否注册成功。
156
+ */
157
+ register(name, config) {
158
+ if (this.configs[name] !== void 0) {
159
+ console.warn(
160
+ `[@pactor-app/runtime] dataSource \u540D\u79F0\u51B2\u7A81\uFF1A"${name}" \u5DF2\u6CE8\u518C\uFF0C\u8DF3\u8FC7\u91CD\u590D\u6CE8\u518C`
161
+ );
162
+ return false;
163
+ }
164
+ this.configs[name] = config;
165
+ this.statuses.set(name, { loading: false });
166
+ this.notify();
167
+ return true;
168
+ }
169
+ /** 批量运行时注册,返回实际注册成功的名称列表(冲突名跳过) */
170
+ registerAll(configs) {
171
+ const registered = [];
172
+ for (const [name, config] of Object.entries(configs)) {
173
+ if (this.register(name, config)) {
174
+ registered.push(name);
175
+ }
176
+ }
177
+ return registered;
178
+ }
179
+ /** 注销运行时注册的数据源(如片段边界卸载时回收);未知名为 no-op */
180
+ unregister(name) {
181
+ if (this.configs[name] === void 0) {
182
+ return;
183
+ }
184
+ delete this.configs[name];
185
+ this.statuses.delete(name);
186
+ this.notify();
187
+ }
152
188
  /**
153
189
  * 加载指定数据源。状态流转:开始置 loading 并清空 error;
154
190
  * 成功写入 data;失败写入 error(保留旧 data)。MUST NOT 抛出。
@@ -222,6 +258,9 @@ var DataStore = class {
222
258
  }
223
259
  update(name, status) {
224
260
  this.statuses.set(name, status);
261
+ this.notify();
262
+ }
263
+ notify() {
225
264
  this.version += 1;
226
265
  for (const listener of [...this.listeners]) {
227
266
  listener();
@@ -467,6 +506,8 @@ var defaultMessages = {
467
506
  "pactor.select.clear": "\u6E05\u9664",
468
507
  "pactor.select.search": "\u641C\u7D22\u9009\u9879",
469
508
  "pactor.input.clear": "\u6E05\u9664",
509
+ "pactor.input.showPassword": "\u663E\u793A\u5BC6\u7801",
510
+ "pactor.input.hidePassword": "\u9690\u85CF\u5BC6\u7801",
470
511
  "pactor.input.placeholder": "\u8BF7\u8F93\u5165",
471
512
  "pactor.numberInput.increase": "\u589E\u52A0",
472
513
  "pactor.numberInput.decrease": "\u51CF\u5C11",
@@ -576,6 +617,8 @@ var defaultMessages = {
576
617
  "pactor.select.clear": "Clear",
577
618
  "pactor.select.search": "Search options",
578
619
  "pactor.input.clear": "Clear",
620
+ "pactor.input.showPassword": "Show password",
621
+ "pactor.input.hidePassword": "Hide password",
579
622
  "pactor.input.placeholder": "Please enter",
580
623
  "pactor.numberInput.increase": "Increase",
581
624
  "pactor.numberInput.decrease": "Decrease",
@@ -990,11 +1033,11 @@ var ActionEngine = class {
990
1033
  };
991
1034
 
992
1035
  // src/renderer/renderer.tsx
993
- import { isDslSourceRef } from "@pactor-app/core";
1036
+ import { isDslFragmentPayload as isDslFragmentPayload2, isDslSourceRef } from "@pactor-app/core";
994
1037
  import {
995
1038
  resolveTemplate as resolveTemplate3
996
1039
  } from "@pactor-app/expression";
997
- import { validateDslNode, validateDslNodes } from "@pactor-app/schema";
1040
+ import { validateDslFragmentPayload, validateDslNode, validateDslNodes } from "@pactor-app/schema";
998
1041
  import {
999
1042
  createElement,
1000
1043
  useMemo,
@@ -1002,6 +1045,7 @@ import {
1002
1045
  } from "react";
1003
1046
 
1004
1047
  // src/renderer/dsl-source-boundary.tsx
1048
+ import { isDslFragmentPayload } from "@pactor-app/core";
1005
1049
  import { useEffect, useState } from "react";
1006
1050
  import { Fragment, jsx } from "react/jsx-runtime";
1007
1051
  function DslSourceBoundary({
@@ -1014,12 +1058,32 @@ function DslSourceBoundary({
1014
1058
  const key = dslSourceKey(sourceRef);
1015
1059
  useEffect(() => {
1016
1060
  let cancelled = false;
1061
+ let registeredSources = [];
1017
1062
  setState({ status: "loading" });
1018
1063
  context.dslSources.resolve(sourceRef).then(
1019
1064
  (content) => {
1020
- if (!cancelled) {
1021
- setState({ status: "ready", content });
1065
+ if (cancelled) {
1066
+ return;
1022
1067
  }
1068
+ if (isDslFragmentPayload(content)) {
1069
+ if (content.state) {
1070
+ context.state.set(content.state);
1071
+ }
1072
+ if (content.dataSources) {
1073
+ registeredSources = context.data.registerAll(content.dataSources);
1074
+ for (const name of registeredSources) {
1075
+ if (content.dataSources[name]?.autoLoad === true) {
1076
+ context.data.load(name).catch((cause) => {
1077
+ console.warn(
1078
+ `[@pactor-app/runtime] \u7247\u6BB5\u6570\u636E\u6E90 "${name}" \u52A0\u8F7D\u5931\u8D25`,
1079
+ cause
1080
+ );
1081
+ });
1082
+ }
1083
+ }
1084
+ }
1085
+ }
1086
+ setState({ status: "ready", content });
1023
1087
  },
1024
1088
  (cause) => {
1025
1089
  if (!cancelled) {
@@ -1030,6 +1094,9 @@ function DslSourceBoundary({
1030
1094
  );
1031
1095
  return () => {
1032
1096
  cancelled = true;
1097
+ for (const name of registeredSources) {
1098
+ context.data.unregister(name);
1099
+ }
1033
1100
  };
1034
1101
  }, [context, key]);
1035
1102
  if (state.status === "ready") {
@@ -1248,6 +1315,17 @@ function validateResolvedNode(content, label) {
1248
1315
  return content;
1249
1316
  }
1250
1317
  function validateResolvedNodes(content, label) {
1318
+ if (isDslFragmentPayload2(content)) {
1319
+ const errors2 = validateDslFragmentPayload(content);
1320
+ if (errors2.length > 0) {
1321
+ console.warn(
1322
+ `[@pactor-app/runtime] \u52A8\u6001\u5F15\u7528\uFF08${label}\uFF09\u8FD4\u56DE\u7684\u7247\u6BB5\u8F7D\u8377\u672A\u901A\u8FC7\u6821\u9A8C`,
1323
+ errors2
1324
+ );
1325
+ return null;
1326
+ }
1327
+ return content.children;
1328
+ }
1251
1329
  const errors = validateDslNodes(content);
1252
1330
  if (errors.length > 0) {
1253
1331
  console.warn(
@@ -1348,8 +1426,9 @@ function isEmbeddedDslNode(value) {
1348
1426
  }
1349
1427
 
1350
1428
  // src/page/page-runtime.tsx
1351
- import { isDslSourceRef as isDslSourceRef2, resolveRootNodes } from "@pactor-app/core";
1429
+ import { isDslFragmentPayload as isDslFragmentPayload3, isDslSourceRef as isDslSourceRef2, resolveRootNodes } from "@pactor-app/core";
1352
1430
  import {
1431
+ validateDslFragmentPayload as validateDslFragmentPayload2,
1353
1432
  validateDslNodes as validateDslNodes2,
1354
1433
  validatePageDsl
1355
1434
  } from "@pactor-app/schema";
@@ -1460,6 +1539,22 @@ function renderRoots(pageDsl, context, engine, children) {
1460
1539
  return renderRootItems(roots, context, engine, children);
1461
1540
  }
1462
1541
  function renderResolvedRoots(content, context, engine, children) {
1542
+ if (isDslFragmentPayload3(content)) {
1543
+ const fragmentErrors = validateDslFragmentPayload2(content);
1544
+ if (fragmentErrors.length > 0) {
1545
+ console.warn(
1546
+ "[@pactor-app/runtime] \u6839\u7EA7 children \u52A8\u6001\u5F15\u7528\u8FD4\u56DE\u7684\u7247\u6BB5\u8F7D\u8377\u672A\u901A\u8FC7\u6821\u9A8C",
1547
+ fragmentErrors
1548
+ );
1549
+ return /* @__PURE__ */ jsx3(Fragment2, { children: children ?? null });
1550
+ }
1551
+ return renderRootItems(
1552
+ content.children,
1553
+ context,
1554
+ engine,
1555
+ children
1556
+ );
1557
+ }
1463
1558
  const errors = validateDslNodes2(content);
1464
1559
  if (errors.length > 0) {
1465
1560
  console.warn(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pactor-app/runtime",
3
- "version": "1.51.0",
3
+ "version": "1.53.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/expression": "1.51.0",
49
- "@pactor-app/schema": "1.51.0",
50
- "@pactor-app/core": "1.51.0"
48
+ "@pactor-app/core": "1.53.0",
49
+ "@pactor-app/schema": "1.53.0",
50
+ "@pactor-app/expression": "1.53.0"
51
51
  },
52
52
  "peerDependencies": {
53
53
  "react": ">=18"