@pactor-app/runtime 1.54.4 → 1.54.5
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 +95 -41
- package/dist/index.d.cts +59 -23
- package/dist/index.d.ts +59 -23
- package/dist/index.js +73 -17
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -26,6 +26,7 @@ __export(index_exports, {
|
|
|
26
26
|
DslSourceBoundary: () => DslSourceBoundary,
|
|
27
27
|
DslSourceResolver: () => DslSourceResolver,
|
|
28
28
|
I18nContextProvider: () => I18nContextProvider,
|
|
29
|
+
LocalizationProtocolError: () => LocalizationProtocolError,
|
|
29
30
|
PageRuntimeError: () => PageRuntimeError,
|
|
30
31
|
PageRuntimeView: () => PageRuntimeView,
|
|
31
32
|
StateStore: () => StateStore,
|
|
@@ -109,13 +110,42 @@ function createFetchHttpAdapter() {
|
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
// src/context/context.ts
|
|
112
|
-
var
|
|
113
|
+
var import_core2 = require("@pactor-app/core");
|
|
113
114
|
|
|
114
115
|
// src/utils/resolve.ts
|
|
116
|
+
var import_core = require("@pactor-app/core");
|
|
115
117
|
var import_expression = require("@pactor-app/expression");
|
|
116
118
|
function isPlainRecord(value) {
|
|
117
119
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
118
120
|
}
|
|
121
|
+
var LocalizationProtocolError = class extends Error {
|
|
122
|
+
constructor(message) {
|
|
123
|
+
super(`[@pactor-app/runtime] ${message}`);
|
|
124
|
+
this.name = "LocalizationProtocolError";
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
function interpolateLocalizedText(template, params) {
|
|
128
|
+
return template.replace(/\{\{(\w+)\}\}/g, (match, name) => {
|
|
129
|
+
const value = params[name];
|
|
130
|
+
if (value === void 0 || value === null) {
|
|
131
|
+
console.warn(
|
|
132
|
+
`[@pactor-app/runtime] $localizedText \u672A\u77E5\u53C2\u6570 "${name}"\uFF0C\u4FDD\u7559\u5360\u4F4D\u7B26 ${match}`
|
|
133
|
+
);
|
|
134
|
+
return match;
|
|
135
|
+
}
|
|
136
|
+
return String(value);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function resolveLocalizedText(value, scope, options) {
|
|
140
|
+
const { template, params } = value.$localizedText;
|
|
141
|
+
const resolvedParams = {};
|
|
142
|
+
if (isPlainRecord(params)) {
|
|
143
|
+
for (const [key, item] of Object.entries(params)) {
|
|
144
|
+
resolvedParams[key] = resolveDeep(item, scope, options);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return interpolateLocalizedText(template, resolvedParams);
|
|
148
|
+
}
|
|
119
149
|
function resolveDeep(value, scope, options = {}) {
|
|
120
150
|
if (typeof value === "string") {
|
|
121
151
|
return (0, import_expression.hasExpression)(value) ? (0, import_expression.resolveTemplate)(value, scope) : value;
|
|
@@ -124,6 +154,14 @@ function resolveDeep(value, scope, options = {}) {
|
|
|
124
154
|
return value.map((item) => resolveDeep(item, scope, options));
|
|
125
155
|
}
|
|
126
156
|
if (isPlainRecord(value)) {
|
|
157
|
+
if (options.localizationMode === "server" && (0, import_core.isI18nDescriptor)(value)) {
|
|
158
|
+
throw new LocalizationProtocolError(
|
|
159
|
+
"server \u672C\u5730\u5316\u6A21\u5F0F\u4E0B\u4F5C\u8005\u6001 `$i18n` \u4E0D\u5141\u8BB8\u51FA\u73B0\u5728\u5BA2\u6237\u7AEF\u89E3\u6790\u8DEF\u5F84"
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
if ((0, import_core.isLocalizedText)(value)) {
|
|
163
|
+
return resolveLocalizedText(value, scope, options);
|
|
164
|
+
}
|
|
127
165
|
if (options.isOpaque?.(value)) {
|
|
128
166
|
return value;
|
|
129
167
|
}
|
|
@@ -149,6 +187,7 @@ var DataStore = class {
|
|
|
149
187
|
this.services = deps.services;
|
|
150
188
|
this.http = deps.http;
|
|
151
189
|
this.getScope = deps.getScope;
|
|
190
|
+
this.localizationMode = deps.localizationMode;
|
|
152
191
|
for (const name of Object.keys(deps.dataSources)) {
|
|
153
192
|
this.statuses.set(name, { loading: false });
|
|
154
193
|
}
|
|
@@ -282,7 +321,9 @@ var DataStore = class {
|
|
|
282
321
|
`[@pactor-app/runtime] service not registered: "${serviceName}"`
|
|
283
322
|
);
|
|
284
323
|
}
|
|
285
|
-
const params = resolveDeep(config.params ?? {}, this.getScope()
|
|
324
|
+
const params = resolveDeep(config.params ?? {}, this.getScope(), {
|
|
325
|
+
localizationMode: this.localizationMode
|
|
326
|
+
});
|
|
286
327
|
return handler(params);
|
|
287
328
|
}
|
|
288
329
|
case "http": {
|
|
@@ -291,7 +332,8 @@ var DataStore = class {
|
|
|
291
332
|
}
|
|
292
333
|
const request = resolveDeep(
|
|
293
334
|
config.request,
|
|
294
|
-
this.getScope()
|
|
335
|
+
this.getScope(),
|
|
336
|
+
{ localizationMode: this.localizationMode }
|
|
295
337
|
);
|
|
296
338
|
return this.http.request(request);
|
|
297
339
|
}
|
|
@@ -336,13 +378,10 @@ function applyOptionMapping(data, config) {
|
|
|
336
378
|
}
|
|
337
379
|
|
|
338
380
|
// src/datasource/dsl-source-resolver.ts
|
|
339
|
-
function dslSourceKey(ref) {
|
|
381
|
+
function dslSourceKey(ref, locale) {
|
|
340
382
|
const source = ref.source;
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
}
|
|
344
|
-
const request = source.request;
|
|
345
|
-
return `http:${(request.method ?? "GET").toUpperCase()}:${request.url}:${JSON.stringify(request.params ?? {})}:${JSON.stringify(request.headers ?? {})}`;
|
|
383
|
+
const base = source.type === "service" ? `service:${source.service}:${JSON.stringify(source.params ?? {})}` : `http:${(source.request.method ?? "GET").toUpperCase()}:${source.request.url}:${JSON.stringify(source.request.params ?? {})}:${JSON.stringify(source.request.headers ?? {})}`;
|
|
384
|
+
return locale ? `${locale}|${base}` : base;
|
|
346
385
|
}
|
|
347
386
|
var DslSourceResolver = class {
|
|
348
387
|
constructor(deps) {
|
|
@@ -350,7 +389,7 @@ var DslSourceResolver = class {
|
|
|
350
389
|
this.cache = /* @__PURE__ */ new Map();
|
|
351
390
|
}
|
|
352
391
|
resolve(ref) {
|
|
353
|
-
const key = dslSourceKey(ref);
|
|
392
|
+
const key = dslSourceKey(ref, this.deps.locale);
|
|
354
393
|
let cached = this.cache.get(key);
|
|
355
394
|
if (cached === void 0) {
|
|
356
395
|
cached = this.load(ref);
|
|
@@ -360,6 +399,7 @@ var DslSourceResolver = class {
|
|
|
360
399
|
}
|
|
361
400
|
async load(ref) {
|
|
362
401
|
const scope = this.deps.getScope();
|
|
402
|
+
const resolveOptions = { localizationMode: this.deps.localizationMode };
|
|
363
403
|
const source = ref.source;
|
|
364
404
|
if (source.type === "service") {
|
|
365
405
|
const handler = this.deps.services.get(source.service);
|
|
@@ -368,10 +408,14 @@ var DslSourceResolver = class {
|
|
|
368
408
|
`[@pactor-app/runtime] service not registered: "${source.service}"`
|
|
369
409
|
);
|
|
370
410
|
}
|
|
371
|
-
const params = resolveDeep(source.params ?? {}, scope);
|
|
411
|
+
const params = resolveDeep(source.params ?? {}, scope, resolveOptions);
|
|
372
412
|
return handler(params);
|
|
373
413
|
}
|
|
374
|
-
const request = resolveDeep(
|
|
414
|
+
const request = resolveDeep(
|
|
415
|
+
source.request,
|
|
416
|
+
scope,
|
|
417
|
+
resolveOptions
|
|
418
|
+
);
|
|
375
419
|
return this.deps.http.request(request);
|
|
376
420
|
}
|
|
377
421
|
};
|
|
@@ -474,11 +518,11 @@ function setPath(source, path, value) {
|
|
|
474
518
|
// src/context/context.ts
|
|
475
519
|
function createRuntimeContext(options = {}) {
|
|
476
520
|
const state = new StateStore(options.state);
|
|
477
|
-
const services = options.services ?? new
|
|
478
|
-
const components = options.components ?? new
|
|
479
|
-
const actions = options.actions ?? new
|
|
480
|
-
const forms = options.forms ?? new
|
|
481
|
-
const capabilities = options.capabilities ?? new
|
|
521
|
+
const services = options.services ?? new import_core2.Registry("ServiceRegistry");
|
|
522
|
+
const components = options.components ?? new import_core2.Registry("ComponentRegistry");
|
|
523
|
+
const actions = options.actions ?? new import_core2.Registry("ActionRegistry");
|
|
524
|
+
const forms = options.forms ?? new import_core2.Registry("FormRegistry");
|
|
525
|
+
const capabilities = options.capabilities ?? new import_core2.Registry("CapabilityRegistry");
|
|
482
526
|
const permission = options.permission ?? createDefaultPermissionAdapter();
|
|
483
527
|
const router = options.router ?? createDefaultRouterAdapter();
|
|
484
528
|
const http = options.http ?? createFetchHttpAdapter();
|
|
@@ -492,12 +536,16 @@ function createRuntimeContext(options = {}) {
|
|
|
492
536
|
dataSources: options.dataSources ?? {},
|
|
493
537
|
services,
|
|
494
538
|
http,
|
|
495
|
-
getScope: () => buildScope(context)
|
|
539
|
+
getScope: () => buildScope(context),
|
|
540
|
+
localizationMode: options.localizationMode
|
|
496
541
|
});
|
|
497
542
|
const dslSources = new DslSourceResolver({
|
|
498
543
|
services,
|
|
499
544
|
http,
|
|
500
|
-
getScope: () => buildScope(context)
|
|
545
|
+
getScope: () => buildScope(context),
|
|
546
|
+
localizationMode: options.localizationMode,
|
|
547
|
+
// 语言上下文注入(G25):页面运行时按语言重建,缓存键随 locale 隔离
|
|
548
|
+
locale: options.locale
|
|
501
549
|
});
|
|
502
550
|
context = {
|
|
503
551
|
app: options.app ?? {},
|
|
@@ -518,17 +566,18 @@ function createRuntimeContext(options = {}) {
|
|
|
518
566
|
http,
|
|
519
567
|
dslSources,
|
|
520
568
|
locale: options.locale ?? "zh-CN",
|
|
521
|
-
i18n: (0,
|
|
569
|
+
i18n: (0, import_core2.createI18nContext)({
|
|
522
570
|
locale: options.locale,
|
|
523
571
|
defaultLocale: options.defaultLocale,
|
|
524
572
|
messages: options.messages
|
|
525
|
-
})
|
|
573
|
+
}),
|
|
574
|
+
localizationMode: options.localizationMode ?? "client"
|
|
526
575
|
};
|
|
527
576
|
return context;
|
|
528
577
|
}
|
|
529
578
|
|
|
530
579
|
// src/context/i18n-context.ts
|
|
531
|
-
var
|
|
580
|
+
var import_core3 = require("@pactor-app/core");
|
|
532
581
|
var import_react = require("react");
|
|
533
582
|
|
|
534
583
|
// src/context/locales/en-US.ts
|
|
@@ -1141,7 +1190,7 @@ var defaultMessages = {
|
|
|
1141
1190
|
var I18nReactContext = (0, import_react.createContext)(null);
|
|
1142
1191
|
var I18nContextProvider = I18nReactContext.Provider;
|
|
1143
1192
|
function createDefaultI18n(locale) {
|
|
1144
|
-
return (0,
|
|
1193
|
+
return (0, import_core3.createI18nContext)({ locale, messages: defaultMessages });
|
|
1145
1194
|
}
|
|
1146
1195
|
var defaultI18n = createDefaultI18n();
|
|
1147
1196
|
function useI18n() {
|
|
@@ -1425,6 +1474,7 @@ var ActionEngine = class {
|
|
|
1425
1474
|
// Renderer 的 resolveProps)保持原样,由各自执行/渲染时
|
|
1426
1475
|
// 按当时的 state 与作用域求值
|
|
1427
1476
|
params: resolveDeep(action.params ?? {}, scope, {
|
|
1477
|
+
localizationMode: this.context.localizationMode,
|
|
1428
1478
|
isOpaque: (value) => typeof value["action"] === "string" || typeof value["type"] === "string" || typeof value["component"] === "string"
|
|
1429
1479
|
})
|
|
1430
1480
|
};
|
|
@@ -1460,13 +1510,13 @@ var ActionEngine = class {
|
|
|
1460
1510
|
};
|
|
1461
1511
|
|
|
1462
1512
|
// src/renderer/renderer.tsx
|
|
1463
|
-
var
|
|
1513
|
+
var import_core5 = require("@pactor-app/core");
|
|
1464
1514
|
var import_expression3 = require("@pactor-app/expression");
|
|
1465
1515
|
var import_schema = require("@pactor-app/schema");
|
|
1466
1516
|
var import_react4 = require("react");
|
|
1467
1517
|
|
|
1468
1518
|
// src/renderer/dsl-source-boundary.tsx
|
|
1469
|
-
var
|
|
1519
|
+
var import_core4 = require("@pactor-app/core");
|
|
1470
1520
|
var import_react2 = require("react");
|
|
1471
1521
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1472
1522
|
function DslSourceBoundary({
|
|
@@ -1486,7 +1536,7 @@ function DslSourceBoundary({
|
|
|
1486
1536
|
if (cancelled) {
|
|
1487
1537
|
return;
|
|
1488
1538
|
}
|
|
1489
|
-
if ((0,
|
|
1539
|
+
if ((0, import_core4.isDslFragmentPayload)(content)) {
|
|
1490
1540
|
if (content.state) {
|
|
1491
1541
|
context.state.set(content.state);
|
|
1492
1542
|
}
|
|
@@ -1630,7 +1680,7 @@ function renderNode(node, value, key) {
|
|
|
1630
1680
|
referenceStack: [...stack, name]
|
|
1631
1681
|
};
|
|
1632
1682
|
scoped.renderChildren = (children, extraScope) => renderChildrenOf(scoped, children, extraScope);
|
|
1633
|
-
if ((0,
|
|
1683
|
+
if ((0, import_core5.isDslSourceRef)(subtree)) {
|
|
1634
1684
|
const ref = subtree;
|
|
1635
1685
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RendererContextProvider, { value: scoped, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1636
1686
|
DslSourceBoundary,
|
|
@@ -1678,7 +1728,7 @@ function renderNode(node, value, key) {
|
|
|
1678
1728
|
if (!normalized) {
|
|
1679
1729
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(UnsupportedComponent, { type: node.type }, key);
|
|
1680
1730
|
}
|
|
1681
|
-
const props = resolveProps(node.props, scope);
|
|
1731
|
+
const props = resolveProps(node.props, scope, value.context.localizationMode);
|
|
1682
1732
|
if (node.events) {
|
|
1683
1733
|
for (const [name, actions] of Object.entries(node.events)) {
|
|
1684
1734
|
props[name] = (event) => {
|
|
@@ -1732,7 +1782,7 @@ function validateResolvedNode(content, label) {
|
|
|
1732
1782
|
return content;
|
|
1733
1783
|
}
|
|
1734
1784
|
function validateResolvedNodes(content, label) {
|
|
1735
|
-
if ((0,
|
|
1785
|
+
if ((0, import_core5.isDslFragmentPayload)(content)) {
|
|
1736
1786
|
const errors2 = (0, import_schema.validateDslFragmentPayload)(content);
|
|
1737
1787
|
if (errors2.length > 0) {
|
|
1738
1788
|
console.warn(
|
|
@@ -1754,7 +1804,7 @@ function validateResolvedNodes(content, label) {
|
|
|
1754
1804
|
return content;
|
|
1755
1805
|
}
|
|
1756
1806
|
function renderChildItem(value, item, key) {
|
|
1757
|
-
if ((0,
|
|
1807
|
+
if ((0, import_core5.isDslSourceRef)(item)) {
|
|
1758
1808
|
const ref = item;
|
|
1759
1809
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1760
1810
|
DslSourceBoundary,
|
|
@@ -1768,7 +1818,7 @@ function renderChildItem(value, item, key) {
|
|
|
1768
1818
|
return null;
|
|
1769
1819
|
}
|
|
1770
1820
|
return nodes.map(
|
|
1771
|
-
(child, index) => renderChildItem(value, child, (0,
|
|
1821
|
+
(child, index) => renderChildItem(value, child, (0, import_core5.isDslSourceRef)(child) ? `ref-${index}` : child.id ?? index)
|
|
1772
1822
|
);
|
|
1773
1823
|
}
|
|
1774
1824
|
},
|
|
@@ -1781,7 +1831,7 @@ function renderChildrenOf(value, children, extraScope) {
|
|
|
1781
1831
|
if (!children || Array.isArray(children) && children.length === 0) {
|
|
1782
1832
|
return null;
|
|
1783
1833
|
}
|
|
1784
|
-
if ((0,
|
|
1834
|
+
if ((0, import_core5.isDslSourceRef)(children)) {
|
|
1785
1835
|
const ref = children;
|
|
1786
1836
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1787
1837
|
DslSourceBoundary,
|
|
@@ -1795,14 +1845,14 @@ function renderChildrenOf(value, children, extraScope) {
|
|
|
1795
1845
|
return null;
|
|
1796
1846
|
}
|
|
1797
1847
|
return nodes.map(
|
|
1798
|
-
(child, index) => renderChildItem(value, child, (0,
|
|
1848
|
+
(child, index) => renderChildItem(value, child, (0, import_core5.isDslSourceRef)(child) ? `ref-${index}` : child.id ?? index)
|
|
1799
1849
|
);
|
|
1800
1850
|
}
|
|
1801
1851
|
},
|
|
1802
1852
|
"dsl-source"
|
|
1803
1853
|
);
|
|
1804
1854
|
}
|
|
1805
|
-
const itemKey = (child, index) => (0,
|
|
1855
|
+
const itemKey = (child, index) => (0, import_core5.isDslSourceRef)(child) ? `ref-${index}` : child.id ?? index;
|
|
1806
1856
|
if (!extraScope) {
|
|
1807
1857
|
return children.map(
|
|
1808
1858
|
(child, index) => renderChildItem(value, child, itemKey(child, index))
|
|
@@ -1828,13 +1878,16 @@ function normalizeEntry(entry) {
|
|
|
1828
1878
|
}
|
|
1829
1879
|
return { component: entry };
|
|
1830
1880
|
}
|
|
1831
|
-
function resolveProps(props, scope) {
|
|
1881
|
+
function resolveProps(props, scope, localizationMode) {
|
|
1832
1882
|
if (!props) {
|
|
1833
1883
|
return {};
|
|
1834
1884
|
}
|
|
1835
1885
|
const out = {};
|
|
1836
1886
|
for (const [key, value] of Object.entries(props)) {
|
|
1837
|
-
out[key] = typeof value === "string" && key.startsWith("on") ? value : resolveDeep(value, scope, {
|
|
1887
|
+
out[key] = typeof value === "string" && key.startsWith("on") ? value : resolveDeep(value, scope, {
|
|
1888
|
+
isOpaque: isEmbeddedDslNode,
|
|
1889
|
+
localizationMode
|
|
1890
|
+
});
|
|
1838
1891
|
}
|
|
1839
1892
|
return out;
|
|
1840
1893
|
}
|
|
@@ -1843,7 +1896,7 @@ function isEmbeddedDslNode(value) {
|
|
|
1843
1896
|
}
|
|
1844
1897
|
|
|
1845
1898
|
// src/page/page-runtime.tsx
|
|
1846
|
-
var
|
|
1899
|
+
var import_core6 = require("@pactor-app/core");
|
|
1847
1900
|
var import_schema2 = require("@pactor-app/schema");
|
|
1848
1901
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1849
1902
|
var PageRuntimeError = class extends Error {
|
|
@@ -1933,7 +1986,7 @@ function PageRuntimeView({
|
|
|
1933
1986
|
return renderRoots(runtime.pageDsl, runtime.context, runtime.engine, children);
|
|
1934
1987
|
}
|
|
1935
1988
|
function renderRoots(pageDsl, context, engine, children) {
|
|
1936
|
-
if (!pageDsl.body && (0,
|
|
1989
|
+
if (!pageDsl.body && (0, import_core6.isDslSourceRef)(pageDsl.children)) {
|
|
1937
1990
|
const ref = pageDsl.children;
|
|
1938
1991
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1939
1992
|
DslSourceBoundary,
|
|
@@ -1945,14 +1998,14 @@ function renderRoots(pageDsl, context, engine, children) {
|
|
|
1945
1998
|
}
|
|
1946
1999
|
);
|
|
1947
2000
|
}
|
|
1948
|
-
const roots = (0,
|
|
2001
|
+
const roots = (0, import_core6.resolveRootNodes)(pageDsl);
|
|
1949
2002
|
if (roots.length === 0) {
|
|
1950
2003
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: children ?? null });
|
|
1951
2004
|
}
|
|
1952
2005
|
return renderRootItems(roots, context, engine, children);
|
|
1953
2006
|
}
|
|
1954
2007
|
function renderResolvedRoots(content, context, engine, children) {
|
|
1955
|
-
if ((0,
|
|
2008
|
+
if ((0, import_core6.isDslFragmentPayload)(content)) {
|
|
1956
2009
|
const fragmentErrors = (0, import_schema2.validateDslFragmentPayload)(content);
|
|
1957
2010
|
if (fragmentErrors.length > 0) {
|
|
1958
2011
|
console.warn(
|
|
@@ -1980,7 +2033,7 @@ function renderResolvedRoots(content, context, engine, children) {
|
|
|
1980
2033
|
}
|
|
1981
2034
|
function renderRootItems(items, context, engine, children) {
|
|
1982
2035
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: items.map(
|
|
1983
|
-
(item, index) => (0,
|
|
2036
|
+
(item, index) => (0, import_core6.isDslSourceRef)(item) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1984
2037
|
DslSourceBoundary,
|
|
1985
2038
|
{
|
|
1986
2039
|
context,
|
|
@@ -2009,6 +2062,7 @@ function renderRootItems(items, context, engine, children) {
|
|
|
2009
2062
|
DslSourceBoundary,
|
|
2010
2063
|
DslSourceResolver,
|
|
2011
2064
|
I18nContextProvider,
|
|
2065
|
+
LocalizationProtocolError,
|
|
2012
2066
|
PageRuntimeError,
|
|
2013
2067
|
PageRuntimeView,
|
|
2014
2068
|
StateStore,
|
package/dist/index.d.cts
CHANGED
|
@@ -89,6 +89,39 @@ declare class ActionEngine {
|
|
|
89
89
|
executeAll(actions: ActionConfig | ActionConfig[], localScope?: ExpressionScope): Promise<ActionResult[]>;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
/**
|
|
93
|
+
* 本地化协议模式:
|
|
94
|
+
* - `client`(默认):作者态 `$i18n` 描述按普通对象递归(行为同历史版本)
|
|
95
|
+
* - `server`:本地化已在服务端完成,作者态 `$i18n` 出现在解析路径即协议错误
|
|
96
|
+
*/
|
|
97
|
+
type LocalizationMode = 'client' | 'server';
|
|
98
|
+
/** 本地化协议错误:server 模式下作者态 `$i18n` 漏入客户端解析路径时抛出 */
|
|
99
|
+
declare class LocalizationProtocolError extends Error {
|
|
100
|
+
constructor(message: string);
|
|
101
|
+
}
|
|
102
|
+
interface ResolveDeepOptions {
|
|
103
|
+
/**
|
|
104
|
+
* 返回 true 时该对象(及其子树)不求值、原样保留。
|
|
105
|
+
* Action 引擎用它跳过 params 中内嵌的子动作配置
|
|
106
|
+
* (`sequence` / `parallel` / `if` 的子动作须在各自执行时
|
|
107
|
+
* 按当时的 state 求值,不能随父动作提前求值)。
|
|
108
|
+
*/
|
|
109
|
+
isOpaque?: (value: Record<string, unknown>) => boolean;
|
|
110
|
+
/** 本地化协议模式(缺省 `client`);`server` 模式下拒绝作者态 `$i18n` */
|
|
111
|
+
localizationMode?: LocalizationMode;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* 深度表达式求值(设计文档第 21 节,D5):
|
|
115
|
+
*
|
|
116
|
+
* - 字符串经 @pactor-app/expression `resolveTemplate` 求值
|
|
117
|
+
* (整体单表达式保留原始类型,无 `${` 快速返回)
|
|
118
|
+
* - `$localizedText` 包装对象经独立插值路径解析为终值字符串
|
|
119
|
+
* - `localizationMode: 'server'` 时作者态 `$i18n` 描述为协议错误
|
|
120
|
+
* - 数组 / 普通对象递归处理
|
|
121
|
+
* - 其余类型原样保留
|
|
122
|
+
*/
|
|
123
|
+
declare function resolveDeep(value: unknown, scope: ExpressionScope, options?: ResolveDeepOptions): unknown;
|
|
124
|
+
|
|
92
125
|
/** 单个数据源的运行时状态 */
|
|
93
126
|
interface DataSourceStatus {
|
|
94
127
|
loading: boolean;
|
|
@@ -101,6 +134,8 @@ interface DataStoreDeps {
|
|
|
101
134
|
http: HttpAdapter;
|
|
102
135
|
/** 加载前取当前表达式作用域(params / request 求值用) */
|
|
103
136
|
getScope: () => ExpressionScope;
|
|
137
|
+
/** 本地化协议模式(缺省 'client'),透传给 params / request 求值 */
|
|
138
|
+
localizationMode?: LocalizationMode;
|
|
104
139
|
}
|
|
105
140
|
/**
|
|
106
141
|
* DataStore:DataSource 运行时(设计文档第 19 节,决策 D3)。
|
|
@@ -114,6 +149,7 @@ declare class DataStore {
|
|
|
114
149
|
private readonly services;
|
|
115
150
|
private readonly http;
|
|
116
151
|
private readonly getScope;
|
|
152
|
+
private readonly localizationMode?;
|
|
117
153
|
private readonly statuses;
|
|
118
154
|
private readonly listeners;
|
|
119
155
|
private version;
|
|
@@ -168,15 +204,26 @@ interface DslSourceResolverDeps {
|
|
|
168
204
|
http: HttpAdapter;
|
|
169
205
|
/** 加载前取当前表达式作用域(params 求值用) */
|
|
170
206
|
getScope: () => ExpressionScope;
|
|
207
|
+
/** 本地化协议模式(缺省 'client'),透传给 params / request 求值 */
|
|
208
|
+
localizationMode?: LocalizationMode;
|
|
209
|
+
/**
|
|
210
|
+
* 当前语言代码(G25 注入点,runtime 不依赖 app/i18n 包):纳入缓存键,
|
|
211
|
+
* 语言上下文不同的解析器互不命中;缺省维持旧键形(仅引用原文)
|
|
212
|
+
*/
|
|
213
|
+
locale?: string;
|
|
171
214
|
}
|
|
172
|
-
/**
|
|
173
|
-
|
|
215
|
+
/**
|
|
216
|
+
* 缓存 key:按固定字段序拼接引用原文(避免字段顺序差异导致重复请求);
|
|
217
|
+
* locale 给出时前置语言上下文(G25),缺省维持旧键形(仅引用原文)。
|
|
218
|
+
*/
|
|
219
|
+
declare function dslSourceKey(ref: DslSourceRef, locale?: string): string;
|
|
174
220
|
/**
|
|
175
221
|
* DslSourceResolver(spec: dsl-renderer 动态引用解析):
|
|
176
222
|
* 按 `source.type` 分派——service 经 ServiceRegistry、http 经 HttpAdapter;
|
|
177
223
|
* `params` 表达式按**首次解析时**作用域求值一次(不做联动重载)。
|
|
178
224
|
* 结果按引用原文缓存于页面运行时生命周期(Promise 级去重:并发渲染
|
|
179
|
-
*
|
|
225
|
+
* 同一引用共享一次请求;失败同样缓存,随运行时销毁清理);
|
|
226
|
+
* 注入 `locale` 时缓存键前置语言上下文,跨语言互不命中。
|
|
180
227
|
*/
|
|
181
228
|
declare class DslSourceResolver {
|
|
182
229
|
private readonly deps;
|
|
@@ -297,6 +344,12 @@ interface RuntimeContext {
|
|
|
297
344
|
locale: string;
|
|
298
345
|
/** i18n 上下文:提供 `t(key, params?)` 翻译函数 */
|
|
299
346
|
i18n: I18nContext;
|
|
347
|
+
/**
|
|
348
|
+
* 本地化协议模式(缺省 'client'):'server' 时 props / 动作参数 /
|
|
349
|
+
* dataSource 参数解析路径中遇到作者态 `$i18n` 描述抛
|
|
350
|
+
* LocalizationProtocolError;'client' 行为与历史版本一致
|
|
351
|
+
*/
|
|
352
|
+
localizationMode: LocalizationMode;
|
|
300
353
|
/**
|
|
301
354
|
* 子运行时指回创建它的宿主运行时上下文(如 OverlayHost 为 page
|
|
302
355
|
* 类型弹层创建的子 PageRuntime)。交互归属(overlay 在哪个宿主的
|
|
@@ -333,6 +386,8 @@ interface CreateRuntimeContextOptions {
|
|
|
333
386
|
defaultLocale?: string;
|
|
334
387
|
/** 翻译消息表 */
|
|
335
388
|
messages?: Record<string, string | Record<string, string>>;
|
|
389
|
+
/** 本地化协议模式(缺省 'client');'server' 时 `$i18n` 漏入解析路径为协议错误 */
|
|
390
|
+
localizationMode?: LocalizationMode;
|
|
336
391
|
}
|
|
337
392
|
/**
|
|
338
393
|
* 组装 RuntimeContext。默认情形下 registries 为空 Registry 实例、
|
|
@@ -516,23 +571,4 @@ declare function PageRuntimeView({ runtime, children, }: {
|
|
|
516
571
|
children?: ReactNode;
|
|
517
572
|
}): ReactNode;
|
|
518
573
|
|
|
519
|
-
|
|
520
|
-
/**
|
|
521
|
-
* 返回 true 时该对象(及其子树)不求值、原样保留。
|
|
522
|
-
* Action 引擎用它跳过 params 中内嵌的子动作配置
|
|
523
|
-
* (`sequence` / `parallel` / `if` 的子动作须在各自执行时
|
|
524
|
-
* 按当时的 state 求值,不能随父动作提前求值)。
|
|
525
|
-
*/
|
|
526
|
-
isOpaque?: (value: Record<string, unknown>) => boolean;
|
|
527
|
-
}
|
|
528
|
-
/**
|
|
529
|
-
* 深度表达式求值(设计文档第 21 节,D5):
|
|
530
|
-
*
|
|
531
|
-
* - 字符串经 @pactor-app/expression `resolveTemplate` 求值
|
|
532
|
-
* (整体单表达式保留原始类型,无 `${` 快速返回)
|
|
533
|
-
* - 数组 / 普通对象递归处理
|
|
534
|
-
* - 其余类型原样保留
|
|
535
|
-
*/
|
|
536
|
-
declare function resolveDeep(value: unknown, scope: ExpressionScope, options?: ResolveDeepOptions): unknown;
|
|
537
|
-
|
|
538
|
-
export { type ActionContext, ActionEngine, type ActionHandler, type ActionRegistry, type ActionResult, type CapabilityRegistry, type ComponentEntry, type ComponentRegistry, type CreateRuntimeContextOptions, type DataSourceStatus, DataStore, type DataStoreDeps, DslRenderer, type DslRendererProps, DslSourceBoundary, type DslSourceBoundaryProps, DslSourceResolver, type DslSourceResolverDeps, type FormHandle, type FormRegistry, type HttpAdapter, type HttpRequestConfig, I18nContextProvider, type LocalScope, type PageRuntime, PageRuntimeError, PageRuntimeView, type PermissionAdapter, type RendererContextValue, type RouteContext, type RouterAdapter, type RuntimeContext, type ScopedComponentEntry, type ServiceHandler, type ServiceRegistry, StateStore, UnsupportedComponent, buildScope, createDefaultPermissionAdapter, createDefaultRouterAdapter, createFetchHttpAdapter, createPageRuntime, createRuntimeContext, dslSourceKey, registerBuiltinActions, resolveDeep, useDataSource, useI18n, useRenderer, useRuntimeState };
|
|
574
|
+
export { type ActionContext, ActionEngine, type ActionHandler, type ActionRegistry, type ActionResult, type CapabilityRegistry, type ComponentEntry, type ComponentRegistry, type CreateRuntimeContextOptions, type DataSourceStatus, DataStore, type DataStoreDeps, DslRenderer, type DslRendererProps, DslSourceBoundary, type DslSourceBoundaryProps, DslSourceResolver, type DslSourceResolverDeps, type FormHandle, type FormRegistry, type HttpAdapter, type HttpRequestConfig, I18nContextProvider, type LocalScope, type LocalizationMode, LocalizationProtocolError, type PageRuntime, PageRuntimeError, PageRuntimeView, type PermissionAdapter, type RendererContextValue, type ResolveDeepOptions, type RouteContext, type RouterAdapter, type RuntimeContext, type ScopedComponentEntry, type ServiceHandler, type ServiceRegistry, StateStore, UnsupportedComponent, buildScope, createDefaultPermissionAdapter, createDefaultRouterAdapter, createFetchHttpAdapter, createPageRuntime, createRuntimeContext, dslSourceKey, registerBuiltinActions, resolveDeep, useDataSource, useI18n, useRenderer, useRuntimeState };
|
package/dist/index.d.ts
CHANGED
|
@@ -89,6 +89,39 @@ declare class ActionEngine {
|
|
|
89
89
|
executeAll(actions: ActionConfig | ActionConfig[], localScope?: ExpressionScope): Promise<ActionResult[]>;
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
/**
|
|
93
|
+
* 本地化协议模式:
|
|
94
|
+
* - `client`(默认):作者态 `$i18n` 描述按普通对象递归(行为同历史版本)
|
|
95
|
+
* - `server`:本地化已在服务端完成,作者态 `$i18n` 出现在解析路径即协议错误
|
|
96
|
+
*/
|
|
97
|
+
type LocalizationMode = 'client' | 'server';
|
|
98
|
+
/** 本地化协议错误:server 模式下作者态 `$i18n` 漏入客户端解析路径时抛出 */
|
|
99
|
+
declare class LocalizationProtocolError extends Error {
|
|
100
|
+
constructor(message: string);
|
|
101
|
+
}
|
|
102
|
+
interface ResolveDeepOptions {
|
|
103
|
+
/**
|
|
104
|
+
* 返回 true 时该对象(及其子树)不求值、原样保留。
|
|
105
|
+
* Action 引擎用它跳过 params 中内嵌的子动作配置
|
|
106
|
+
* (`sequence` / `parallel` / `if` 的子动作须在各自执行时
|
|
107
|
+
* 按当时的 state 求值,不能随父动作提前求值)。
|
|
108
|
+
*/
|
|
109
|
+
isOpaque?: (value: Record<string, unknown>) => boolean;
|
|
110
|
+
/** 本地化协议模式(缺省 `client`);`server` 模式下拒绝作者态 `$i18n` */
|
|
111
|
+
localizationMode?: LocalizationMode;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* 深度表达式求值(设计文档第 21 节,D5):
|
|
115
|
+
*
|
|
116
|
+
* - 字符串经 @pactor-app/expression `resolveTemplate` 求值
|
|
117
|
+
* (整体单表达式保留原始类型,无 `${` 快速返回)
|
|
118
|
+
* - `$localizedText` 包装对象经独立插值路径解析为终值字符串
|
|
119
|
+
* - `localizationMode: 'server'` 时作者态 `$i18n` 描述为协议错误
|
|
120
|
+
* - 数组 / 普通对象递归处理
|
|
121
|
+
* - 其余类型原样保留
|
|
122
|
+
*/
|
|
123
|
+
declare function resolveDeep(value: unknown, scope: ExpressionScope, options?: ResolveDeepOptions): unknown;
|
|
124
|
+
|
|
92
125
|
/** 单个数据源的运行时状态 */
|
|
93
126
|
interface DataSourceStatus {
|
|
94
127
|
loading: boolean;
|
|
@@ -101,6 +134,8 @@ interface DataStoreDeps {
|
|
|
101
134
|
http: HttpAdapter;
|
|
102
135
|
/** 加载前取当前表达式作用域(params / request 求值用) */
|
|
103
136
|
getScope: () => ExpressionScope;
|
|
137
|
+
/** 本地化协议模式(缺省 'client'),透传给 params / request 求值 */
|
|
138
|
+
localizationMode?: LocalizationMode;
|
|
104
139
|
}
|
|
105
140
|
/**
|
|
106
141
|
* DataStore:DataSource 运行时(设计文档第 19 节,决策 D3)。
|
|
@@ -114,6 +149,7 @@ declare class DataStore {
|
|
|
114
149
|
private readonly services;
|
|
115
150
|
private readonly http;
|
|
116
151
|
private readonly getScope;
|
|
152
|
+
private readonly localizationMode?;
|
|
117
153
|
private readonly statuses;
|
|
118
154
|
private readonly listeners;
|
|
119
155
|
private version;
|
|
@@ -168,15 +204,26 @@ interface DslSourceResolverDeps {
|
|
|
168
204
|
http: HttpAdapter;
|
|
169
205
|
/** 加载前取当前表达式作用域(params 求值用) */
|
|
170
206
|
getScope: () => ExpressionScope;
|
|
207
|
+
/** 本地化协议模式(缺省 'client'),透传给 params / request 求值 */
|
|
208
|
+
localizationMode?: LocalizationMode;
|
|
209
|
+
/**
|
|
210
|
+
* 当前语言代码(G25 注入点,runtime 不依赖 app/i18n 包):纳入缓存键,
|
|
211
|
+
* 语言上下文不同的解析器互不命中;缺省维持旧键形(仅引用原文)
|
|
212
|
+
*/
|
|
213
|
+
locale?: string;
|
|
171
214
|
}
|
|
172
|
-
/**
|
|
173
|
-
|
|
215
|
+
/**
|
|
216
|
+
* 缓存 key:按固定字段序拼接引用原文(避免字段顺序差异导致重复请求);
|
|
217
|
+
* locale 给出时前置语言上下文(G25),缺省维持旧键形(仅引用原文)。
|
|
218
|
+
*/
|
|
219
|
+
declare function dslSourceKey(ref: DslSourceRef, locale?: string): string;
|
|
174
220
|
/**
|
|
175
221
|
* DslSourceResolver(spec: dsl-renderer 动态引用解析):
|
|
176
222
|
* 按 `source.type` 分派——service 经 ServiceRegistry、http 经 HttpAdapter;
|
|
177
223
|
* `params` 表达式按**首次解析时**作用域求值一次(不做联动重载)。
|
|
178
224
|
* 结果按引用原文缓存于页面运行时生命周期(Promise 级去重:并发渲染
|
|
179
|
-
*
|
|
225
|
+
* 同一引用共享一次请求;失败同样缓存,随运行时销毁清理);
|
|
226
|
+
* 注入 `locale` 时缓存键前置语言上下文,跨语言互不命中。
|
|
180
227
|
*/
|
|
181
228
|
declare class DslSourceResolver {
|
|
182
229
|
private readonly deps;
|
|
@@ -297,6 +344,12 @@ interface RuntimeContext {
|
|
|
297
344
|
locale: string;
|
|
298
345
|
/** i18n 上下文:提供 `t(key, params?)` 翻译函数 */
|
|
299
346
|
i18n: I18nContext;
|
|
347
|
+
/**
|
|
348
|
+
* 本地化协议模式(缺省 'client'):'server' 时 props / 动作参数 /
|
|
349
|
+
* dataSource 参数解析路径中遇到作者态 `$i18n` 描述抛
|
|
350
|
+
* LocalizationProtocolError;'client' 行为与历史版本一致
|
|
351
|
+
*/
|
|
352
|
+
localizationMode: LocalizationMode;
|
|
300
353
|
/**
|
|
301
354
|
* 子运行时指回创建它的宿主运行时上下文(如 OverlayHost 为 page
|
|
302
355
|
* 类型弹层创建的子 PageRuntime)。交互归属(overlay 在哪个宿主的
|
|
@@ -333,6 +386,8 @@ interface CreateRuntimeContextOptions {
|
|
|
333
386
|
defaultLocale?: string;
|
|
334
387
|
/** 翻译消息表 */
|
|
335
388
|
messages?: Record<string, string | Record<string, string>>;
|
|
389
|
+
/** 本地化协议模式(缺省 'client');'server' 时 `$i18n` 漏入解析路径为协议错误 */
|
|
390
|
+
localizationMode?: LocalizationMode;
|
|
336
391
|
}
|
|
337
392
|
/**
|
|
338
393
|
* 组装 RuntimeContext。默认情形下 registries 为空 Registry 实例、
|
|
@@ -516,23 +571,4 @@ declare function PageRuntimeView({ runtime, children, }: {
|
|
|
516
571
|
children?: ReactNode;
|
|
517
572
|
}): ReactNode;
|
|
518
573
|
|
|
519
|
-
|
|
520
|
-
/**
|
|
521
|
-
* 返回 true 时该对象(及其子树)不求值、原样保留。
|
|
522
|
-
* Action 引擎用它跳过 params 中内嵌的子动作配置
|
|
523
|
-
* (`sequence` / `parallel` / `if` 的子动作须在各自执行时
|
|
524
|
-
* 按当时的 state 求值,不能随父动作提前求值)。
|
|
525
|
-
*/
|
|
526
|
-
isOpaque?: (value: Record<string, unknown>) => boolean;
|
|
527
|
-
}
|
|
528
|
-
/**
|
|
529
|
-
* 深度表达式求值(设计文档第 21 节,D5):
|
|
530
|
-
*
|
|
531
|
-
* - 字符串经 @pactor-app/expression `resolveTemplate` 求值
|
|
532
|
-
* (整体单表达式保留原始类型,无 `${` 快速返回)
|
|
533
|
-
* - 数组 / 普通对象递归处理
|
|
534
|
-
* - 其余类型原样保留
|
|
535
|
-
*/
|
|
536
|
-
declare function resolveDeep(value: unknown, scope: ExpressionScope, options?: ResolveDeepOptions): unknown;
|
|
537
|
-
|
|
538
|
-
export { type ActionContext, ActionEngine, type ActionHandler, type ActionRegistry, type ActionResult, type CapabilityRegistry, type ComponentEntry, type ComponentRegistry, type CreateRuntimeContextOptions, type DataSourceStatus, DataStore, type DataStoreDeps, DslRenderer, type DslRendererProps, DslSourceBoundary, type DslSourceBoundaryProps, DslSourceResolver, type DslSourceResolverDeps, type FormHandle, type FormRegistry, type HttpAdapter, type HttpRequestConfig, I18nContextProvider, type LocalScope, type PageRuntime, PageRuntimeError, PageRuntimeView, type PermissionAdapter, type RendererContextValue, type RouteContext, type RouterAdapter, type RuntimeContext, type ScopedComponentEntry, type ServiceHandler, type ServiceRegistry, StateStore, UnsupportedComponent, buildScope, createDefaultPermissionAdapter, createDefaultRouterAdapter, createFetchHttpAdapter, createPageRuntime, createRuntimeContext, dslSourceKey, registerBuiltinActions, resolveDeep, useDataSource, useI18n, useRenderer, useRuntimeState };
|
|
574
|
+
export { type ActionContext, ActionEngine, type ActionHandler, type ActionRegistry, type ActionResult, type CapabilityRegistry, type ComponentEntry, type ComponentRegistry, type CreateRuntimeContextOptions, type DataSourceStatus, DataStore, type DataStoreDeps, DslRenderer, type DslRendererProps, DslSourceBoundary, type DslSourceBoundaryProps, DslSourceResolver, type DslSourceResolverDeps, type FormHandle, type FormRegistry, type HttpAdapter, type HttpRequestConfig, I18nContextProvider, type LocalScope, type LocalizationMode, LocalizationProtocolError, type PageRuntime, PageRuntimeError, PageRuntimeView, type PermissionAdapter, type RendererContextValue, type ResolveDeepOptions, type RouteContext, type RouterAdapter, type RuntimeContext, type ScopedComponentEntry, type ServiceHandler, type ServiceRegistry, StateStore, UnsupportedComponent, buildScope, createDefaultPermissionAdapter, createDefaultRouterAdapter, createFetchHttpAdapter, createPageRuntime, createRuntimeContext, dslSourceKey, registerBuiltinActions, resolveDeep, useDataSource, useI18n, useRenderer, useRuntimeState };
|
package/dist/index.js
CHANGED
|
@@ -64,6 +64,10 @@ function createFetchHttpAdapter() {
|
|
|
64
64
|
import { Registry, createI18nContext } from "@pactor-app/core";
|
|
65
65
|
|
|
66
66
|
// src/utils/resolve.ts
|
|
67
|
+
import {
|
|
68
|
+
isI18nDescriptor,
|
|
69
|
+
isLocalizedText
|
|
70
|
+
} from "@pactor-app/core";
|
|
67
71
|
import {
|
|
68
72
|
hasExpression,
|
|
69
73
|
resolveTemplate
|
|
@@ -71,6 +75,34 @@ import {
|
|
|
71
75
|
function isPlainRecord(value) {
|
|
72
76
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
73
77
|
}
|
|
78
|
+
var LocalizationProtocolError = class extends Error {
|
|
79
|
+
constructor(message) {
|
|
80
|
+
super(`[@pactor-app/runtime] ${message}`);
|
|
81
|
+
this.name = "LocalizationProtocolError";
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
function interpolateLocalizedText(template, params) {
|
|
85
|
+
return template.replace(/\{\{(\w+)\}\}/g, (match, name) => {
|
|
86
|
+
const value = params[name];
|
|
87
|
+
if (value === void 0 || value === null) {
|
|
88
|
+
console.warn(
|
|
89
|
+
`[@pactor-app/runtime] $localizedText \u672A\u77E5\u53C2\u6570 "${name}"\uFF0C\u4FDD\u7559\u5360\u4F4D\u7B26 ${match}`
|
|
90
|
+
);
|
|
91
|
+
return match;
|
|
92
|
+
}
|
|
93
|
+
return String(value);
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function resolveLocalizedText(value, scope, options) {
|
|
97
|
+
const { template, params } = value.$localizedText;
|
|
98
|
+
const resolvedParams = {};
|
|
99
|
+
if (isPlainRecord(params)) {
|
|
100
|
+
for (const [key, item] of Object.entries(params)) {
|
|
101
|
+
resolvedParams[key] = resolveDeep(item, scope, options);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return interpolateLocalizedText(template, resolvedParams);
|
|
105
|
+
}
|
|
74
106
|
function resolveDeep(value, scope, options = {}) {
|
|
75
107
|
if (typeof value === "string") {
|
|
76
108
|
return hasExpression(value) ? resolveTemplate(value, scope) : value;
|
|
@@ -79,6 +111,14 @@ function resolveDeep(value, scope, options = {}) {
|
|
|
79
111
|
return value.map((item) => resolveDeep(item, scope, options));
|
|
80
112
|
}
|
|
81
113
|
if (isPlainRecord(value)) {
|
|
114
|
+
if (options.localizationMode === "server" && isI18nDescriptor(value)) {
|
|
115
|
+
throw new LocalizationProtocolError(
|
|
116
|
+
"server \u672C\u5730\u5316\u6A21\u5F0F\u4E0B\u4F5C\u8005\u6001 `$i18n` \u4E0D\u5141\u8BB8\u51FA\u73B0\u5728\u5BA2\u6237\u7AEF\u89E3\u6790\u8DEF\u5F84"
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
if (isLocalizedText(value)) {
|
|
120
|
+
return resolveLocalizedText(value, scope, options);
|
|
121
|
+
}
|
|
82
122
|
if (options.isOpaque?.(value)) {
|
|
83
123
|
return value;
|
|
84
124
|
}
|
|
@@ -104,6 +144,7 @@ var DataStore = class {
|
|
|
104
144
|
this.services = deps.services;
|
|
105
145
|
this.http = deps.http;
|
|
106
146
|
this.getScope = deps.getScope;
|
|
147
|
+
this.localizationMode = deps.localizationMode;
|
|
107
148
|
for (const name of Object.keys(deps.dataSources)) {
|
|
108
149
|
this.statuses.set(name, { loading: false });
|
|
109
150
|
}
|
|
@@ -237,7 +278,9 @@ var DataStore = class {
|
|
|
237
278
|
`[@pactor-app/runtime] service not registered: "${serviceName}"`
|
|
238
279
|
);
|
|
239
280
|
}
|
|
240
|
-
const params = resolveDeep(config.params ?? {}, this.getScope()
|
|
281
|
+
const params = resolveDeep(config.params ?? {}, this.getScope(), {
|
|
282
|
+
localizationMode: this.localizationMode
|
|
283
|
+
});
|
|
241
284
|
return handler(params);
|
|
242
285
|
}
|
|
243
286
|
case "http": {
|
|
@@ -246,7 +289,8 @@ var DataStore = class {
|
|
|
246
289
|
}
|
|
247
290
|
const request = resolveDeep(
|
|
248
291
|
config.request,
|
|
249
|
-
this.getScope()
|
|
292
|
+
this.getScope(),
|
|
293
|
+
{ localizationMode: this.localizationMode }
|
|
250
294
|
);
|
|
251
295
|
return this.http.request(request);
|
|
252
296
|
}
|
|
@@ -291,13 +335,10 @@ function applyOptionMapping(data, config) {
|
|
|
291
335
|
}
|
|
292
336
|
|
|
293
337
|
// src/datasource/dsl-source-resolver.ts
|
|
294
|
-
function dslSourceKey(ref) {
|
|
338
|
+
function dslSourceKey(ref, locale) {
|
|
295
339
|
const source = ref.source;
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
}
|
|
299
|
-
const request = source.request;
|
|
300
|
-
return `http:${(request.method ?? "GET").toUpperCase()}:${request.url}:${JSON.stringify(request.params ?? {})}:${JSON.stringify(request.headers ?? {})}`;
|
|
340
|
+
const base = source.type === "service" ? `service:${source.service}:${JSON.stringify(source.params ?? {})}` : `http:${(source.request.method ?? "GET").toUpperCase()}:${source.request.url}:${JSON.stringify(source.request.params ?? {})}:${JSON.stringify(source.request.headers ?? {})}`;
|
|
341
|
+
return locale ? `${locale}|${base}` : base;
|
|
301
342
|
}
|
|
302
343
|
var DslSourceResolver = class {
|
|
303
344
|
constructor(deps) {
|
|
@@ -305,7 +346,7 @@ var DslSourceResolver = class {
|
|
|
305
346
|
this.cache = /* @__PURE__ */ new Map();
|
|
306
347
|
}
|
|
307
348
|
resolve(ref) {
|
|
308
|
-
const key = dslSourceKey(ref);
|
|
349
|
+
const key = dslSourceKey(ref, this.deps.locale);
|
|
309
350
|
let cached = this.cache.get(key);
|
|
310
351
|
if (cached === void 0) {
|
|
311
352
|
cached = this.load(ref);
|
|
@@ -315,6 +356,7 @@ var DslSourceResolver = class {
|
|
|
315
356
|
}
|
|
316
357
|
async load(ref) {
|
|
317
358
|
const scope = this.deps.getScope();
|
|
359
|
+
const resolveOptions = { localizationMode: this.deps.localizationMode };
|
|
318
360
|
const source = ref.source;
|
|
319
361
|
if (source.type === "service") {
|
|
320
362
|
const handler = this.deps.services.get(source.service);
|
|
@@ -323,10 +365,14 @@ var DslSourceResolver = class {
|
|
|
323
365
|
`[@pactor-app/runtime] service not registered: "${source.service}"`
|
|
324
366
|
);
|
|
325
367
|
}
|
|
326
|
-
const params = resolveDeep(source.params ?? {}, scope);
|
|
368
|
+
const params = resolveDeep(source.params ?? {}, scope, resolveOptions);
|
|
327
369
|
return handler(params);
|
|
328
370
|
}
|
|
329
|
-
const request = resolveDeep(
|
|
371
|
+
const request = resolveDeep(
|
|
372
|
+
source.request,
|
|
373
|
+
scope,
|
|
374
|
+
resolveOptions
|
|
375
|
+
);
|
|
330
376
|
return this.deps.http.request(request);
|
|
331
377
|
}
|
|
332
378
|
};
|
|
@@ -447,12 +493,16 @@ function createRuntimeContext(options = {}) {
|
|
|
447
493
|
dataSources: options.dataSources ?? {},
|
|
448
494
|
services,
|
|
449
495
|
http,
|
|
450
|
-
getScope: () => buildScope(context)
|
|
496
|
+
getScope: () => buildScope(context),
|
|
497
|
+
localizationMode: options.localizationMode
|
|
451
498
|
});
|
|
452
499
|
const dslSources = new DslSourceResolver({
|
|
453
500
|
services,
|
|
454
501
|
http,
|
|
455
|
-
getScope: () => buildScope(context)
|
|
502
|
+
getScope: () => buildScope(context),
|
|
503
|
+
localizationMode: options.localizationMode,
|
|
504
|
+
// 语言上下文注入(G25):页面运行时按语言重建,缓存键随 locale 隔离
|
|
505
|
+
locale: options.locale
|
|
456
506
|
});
|
|
457
507
|
context = {
|
|
458
508
|
app: options.app ?? {},
|
|
@@ -477,7 +527,8 @@ function createRuntimeContext(options = {}) {
|
|
|
477
527
|
locale: options.locale,
|
|
478
528
|
defaultLocale: options.defaultLocale,
|
|
479
529
|
messages: options.messages
|
|
480
|
-
})
|
|
530
|
+
}),
|
|
531
|
+
localizationMode: options.localizationMode ?? "client"
|
|
481
532
|
};
|
|
482
533
|
return context;
|
|
483
534
|
}
|
|
@@ -1382,6 +1433,7 @@ var ActionEngine = class {
|
|
|
1382
1433
|
// Renderer 的 resolveProps)保持原样,由各自执行/渲染时
|
|
1383
1434
|
// 按当时的 state 与作用域求值
|
|
1384
1435
|
params: resolveDeep(action.params ?? {}, scope, {
|
|
1436
|
+
localizationMode: this.context.localizationMode,
|
|
1385
1437
|
isOpaque: (value) => typeof value["action"] === "string" || typeof value["type"] === "string" || typeof value["component"] === "string"
|
|
1386
1438
|
})
|
|
1387
1439
|
};
|
|
@@ -1645,7 +1697,7 @@ function renderNode(node, value, key) {
|
|
|
1645
1697
|
if (!normalized) {
|
|
1646
1698
|
return /* @__PURE__ */ jsx2(UnsupportedComponent, { type: node.type }, key);
|
|
1647
1699
|
}
|
|
1648
|
-
const props = resolveProps(node.props, scope);
|
|
1700
|
+
const props = resolveProps(node.props, scope, value.context.localizationMode);
|
|
1649
1701
|
if (node.events) {
|
|
1650
1702
|
for (const [name, actions] of Object.entries(node.events)) {
|
|
1651
1703
|
props[name] = (event) => {
|
|
@@ -1795,13 +1847,16 @@ function normalizeEntry(entry) {
|
|
|
1795
1847
|
}
|
|
1796
1848
|
return { component: entry };
|
|
1797
1849
|
}
|
|
1798
|
-
function resolveProps(props, scope) {
|
|
1850
|
+
function resolveProps(props, scope, localizationMode) {
|
|
1799
1851
|
if (!props) {
|
|
1800
1852
|
return {};
|
|
1801
1853
|
}
|
|
1802
1854
|
const out = {};
|
|
1803
1855
|
for (const [key, value] of Object.entries(props)) {
|
|
1804
|
-
out[key] = typeof value === "string" && key.startsWith("on") ? value : resolveDeep(value, scope, {
|
|
1856
|
+
out[key] = typeof value === "string" && key.startsWith("on") ? value : resolveDeep(value, scope, {
|
|
1857
|
+
isOpaque: isEmbeddedDslNode,
|
|
1858
|
+
localizationMode
|
|
1859
|
+
});
|
|
1805
1860
|
}
|
|
1806
1861
|
return out;
|
|
1807
1862
|
}
|
|
@@ -1979,6 +2034,7 @@ export {
|
|
|
1979
2034
|
DslSourceBoundary,
|
|
1980
2035
|
DslSourceResolver,
|
|
1981
2036
|
I18nContextProvider,
|
|
2037
|
+
LocalizationProtocolError,
|
|
1982
2038
|
PageRuntimeError,
|
|
1983
2039
|
PageRuntimeView,
|
|
1984
2040
|
StateStore,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pactor-app/runtime",
|
|
3
|
-
"version": "1.54.
|
|
3
|
+
"version": "1.54.5",
|
|
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/
|
|
49
|
-
"@pactor-app/
|
|
50
|
-
"@pactor-app/
|
|
48
|
+
"@pactor-app/expression": "1.54.5",
|
|
49
|
+
"@pactor-app/schema": "1.54.5",
|
|
50
|
+
"@pactor-app/core": "1.54.5"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
53
|
"react": ">=18"
|