openxiangda-contracts 2.13.0 → 2.14.1
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/native-compiler/compiler.d.ts.map +1 -1
- package/dist/native-compiler/compiler.js +116 -6
- package/dist/native-compiler/compiler.js.map +1 -1
- package/dist/native-compiler/index.cjs +4 -4
- package/dist/native-compiler/index.js +4 -4
- package/dist/native.d.ts +3 -1
- package/dist/native.d.ts.map +1 -1
- package/dist/native.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../src/native-compiler/compiler.ts"],"names":[],"mappings":"AAUA,OAAO,EAEL,KAAK,kCAAkC,IAAI,uCAAuC,EACnF,MAAM,aAAa,CAAC;AAwBrB,QAAA,MAAM,iBAAiB,mDAAmD,CAAC;AAC3E,QAAA,MAAM,yBAAyB,YAA2C,CAAC;AAgF3E,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;EAc7B,CAAC;AACZ,eAAO,MAAM,mBAAmB,6HAItB,CAAC;AACX,eAAO,MAAM,uBAAuB,u/CAkC1B,CAAC;AAGX,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAEtC,MAAM,WAAW,gCAAgC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;IAC1C,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;IAC5C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,6BAA6B,CAAC,CAAC,GAAG,UAAU;IAC3D,KAAK,EAAE,CAAC,CAAC;IACT,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iCAAiC;IAChD,aAAa,EAAE,OAAO,iBAAiB,CAAC;IACxC,uBAAuB,EAAE,OAAO,yBAAyB,CAAC;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,WAAW,EAAE;QACX,KAAK,EAAE,6BAA6B,CAAC;QACrC,IAAI,EAAE,6BAA6B,CAAC;QACpC,MAAM,EAAE,6BAA6B,CAAC;QACtC,SAAS,EAAE,6BAA6B,CAAC;QACzC,OAAO,EAAE,6BAA6B,CAAC;QACvC,SAAS,EAAE,6BAA6B,CAAC;KAC1C,CAAC;IACF,4BAA4B,EAAE,uCAAuC,EAAE,CAAC;IACxE,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,gCAAiC,SAAQ,KAAK;IACzD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAG3C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;CAY5C;AAED,wBAAgB,qCAAqC,CACnD,KAAK,EAAE,gCAAgC,GACtC,iCAAiC,
|
|
1
|
+
{"version":3,"file":"compiler.d.ts","sourceRoot":"","sources":["../../src/native-compiler/compiler.ts"],"names":[],"mappings":"AAUA,OAAO,EAEL,KAAK,kCAAkC,IAAI,uCAAuC,EACnF,MAAM,aAAa,CAAC;AAwBrB,QAAA,MAAM,iBAAiB,mDAAmD,CAAC;AAC3E,QAAA,MAAM,yBAAyB,YAA2C,CAAC;AAgF3E,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;EAc7B,CAAC;AACZ,eAAO,MAAM,mBAAmB,6HAItB,CAAC;AACX,eAAO,MAAM,uBAAuB,u/CAkC1B,CAAC;AAGX,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAEtC,MAAM,WAAW,gCAAgC;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;IAC1C,aAAa,EAAE,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;IAC5C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,sBAAsB,EAAE,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,6BAA6B,CAAC,CAAC,GAAG,UAAU;IAC3D,KAAK,EAAE,CAAC,CAAC;IACT,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iCAAiC;IAChD,aAAa,EAAE,OAAO,iBAAiB,CAAC;IACxC,uBAAuB,EAAE,OAAO,yBAAyB,CAAC;IAC1D,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE;QACN,YAAY,EAAE,MAAM,CAAC;QACrB,cAAc,EAAE,MAAM,CAAC;QACvB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,WAAW,EAAE;QACX,KAAK,EAAE,6BAA6B,CAAC;QACrC,IAAI,EAAE,6BAA6B,CAAC;QACpC,MAAM,EAAE,6BAA6B,CAAC;QACtC,SAAS,EAAE,6BAA6B,CAAC;QACzC,OAAO,EAAE,6BAA6B,CAAC;QACvC,SAAS,EAAE,6BAA6B,CAAC;KAC1C,CAAC;IACF,4BAA4B,EAAE,uCAAuC,EAAE,CAAC;IACxE,eAAe,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,gCAAiC,SAAQ,KAAK;IACzD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAG3C,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;CAY5C;AAED,wBAAgB,qCAAqC,CACnD,KAAK,EAAE,gCAAgC,GACtC,iCAAiC,CA+InC;AAED;;;GAGG;AACH,wBAAgB,qCAAqC,CACnD,MAAM,EAAE,UAAU,GACjB,uCAAuC,EAAE,CA2R3C;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,mBAAmB,EAAE,MAAM,EAAE,CAAC;IAC9B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED;;;;GAIG;AACH,wBAAgB,gCAAgC,CAAC,KAAK,EAAE;IACtD,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB,YAAY,EAAE,UAAU,EAAE,CAAC;IAC3B,aAAa,EAAE,UAAU,EAAE,CAAC;IAC5B,eAAe,CAAC,EAAE,UAAU,EAAE,CAAC;CAChC,GAAG,wBAAwB,EAAE,CA4J7B"}
|
|
@@ -181,6 +181,7 @@ export function compileNativeApplicationConfiguration(input) {
|
|
|
181
181
|
validateConfigurationEnvelope(config, appCode);
|
|
182
182
|
validateContractEnvelope(contract, appCode, expectedConfigDigest);
|
|
183
183
|
const expectedContract = compileExpectedContract(config, expectedConfigDigest, contract.generatorVersion);
|
|
184
|
+
mergeUserSurfaceRoutes(expectedContract, contract, config);
|
|
184
185
|
if (canonicalJson(expectedContract) !== canonicalJson(contract)) {
|
|
185
186
|
fail('NATIVE_CONTRACT_CLOSURE_MISMATCH', firstDifferencePointer(expectedContract, contract, '/contracts'));
|
|
186
187
|
}
|
|
@@ -1531,6 +1532,11 @@ function validateApplicationAuthentication(value, routeDeclarations, config, poi
|
|
|
1531
1532
|
const route = object(rawRoute, `/config/frontend/routes/${index}`);
|
|
1532
1533
|
routesByCode.set(String(route.code || ''), route);
|
|
1533
1534
|
}
|
|
1535
|
+
// 生成式用户标准面路由码:user.<resource>.(records|submit)。路由事实
|
|
1536
|
+
// 由 routeManifest 携带;这里按同应用已声明资源判定有效性。
|
|
1537
|
+
const userSurfaceResourceCodes = new Set((Array.isArray(config.data?.resources) ? config.data.resources : [])
|
|
1538
|
+
.map(resource => String(resource.code || ''))
|
|
1539
|
+
.filter(code => /^[a-z][a-z0-9-]{0,62}$/.test(code)));
|
|
1534
1540
|
for (const [device, surface] of [
|
|
1535
1541
|
['desktop', desktop],
|
|
1536
1542
|
['mobile', mobile],
|
|
@@ -1538,8 +1544,16 @@ function validateApplicationAuthentication(value, routeDeclarations, config, poi
|
|
|
1538
1544
|
if (routesByCode.has(surface.routeCode)) {
|
|
1539
1545
|
fail('NATIVE_APPLICATION_AUTH_SURFACE_CODE_CONFLICT', `${pointer}/surfaces/${device}/routeCode`);
|
|
1540
1546
|
}
|
|
1541
|
-
const
|
|
1542
|
-
|
|
1547
|
+
const generatedUserRoute = /^user\.([a-z][a-z0-9-]{0,62})\.(records|submit)$/.exec(String(surface.defaultRouteCode || ''));
|
|
1548
|
+
let defaultRoute = routesByCode.get(surface.defaultRouteCode);
|
|
1549
|
+
let defaultPath = String(defaultRoute?.path || '');
|
|
1550
|
+
if (generatedUserRoute && userSurfaceResourceCodes.has(generatedUserRoute[1])) {
|
|
1551
|
+
const base = generatedUserRoute[2] === 'records'
|
|
1552
|
+
? `/my/${generatedUserRoute[1]}`
|
|
1553
|
+
: `/my/${generatedUserRoute[1]}/submit`;
|
|
1554
|
+
defaultRoute = { surface: 'user', path: device === 'mobile' ? `/m${base}` : base };
|
|
1555
|
+
defaultPath = String(defaultRoute.path);
|
|
1556
|
+
}
|
|
1543
1557
|
const deviceMismatch = device === 'desktop'
|
|
1544
1558
|
? defaultPath === '/m' || defaultPath.startsWith('/m/')
|
|
1545
1559
|
: !(defaultPath === '/m' || defaultPath.startsWith('/m/'));
|
|
@@ -2441,6 +2455,8 @@ const ROUTE_MANIFEST_KINDS = new Set([
|
|
|
2441
2455
|
'workflow-launch',
|
|
2442
2456
|
'workflow-task',
|
|
2443
2457
|
'workflow-instance',
|
|
2458
|
+
'resource-records',
|
|
2459
|
+
'resource-submit',
|
|
2444
2460
|
]);
|
|
2445
2461
|
function validateRouteManifest(value, pointer, appCode) {
|
|
2446
2462
|
const manifest = object(value, pointer);
|
|
@@ -2464,8 +2480,10 @@ function validateRouteManifest(value, pointer, appCode) {
|
|
|
2464
2480
|
routes.forEach((rawEntry, index) => {
|
|
2465
2481
|
const entryPointer = `${pointer}/routes/${index}`;
|
|
2466
2482
|
const entry = object(rawEntry, entryPointer);
|
|
2483
|
+
const resourceKinds = entry.kind === 'resource-records' || entry.kind === 'resource-submit';
|
|
2467
2484
|
exactKeys(entry, ['code', 'kind', 'desktop', 'mobile'], entryPointer, [
|
|
2468
2485
|
'workflowCode',
|
|
2486
|
+
...(resourceKinds ? ['resourceCode'] : []),
|
|
2469
2487
|
]);
|
|
2470
2488
|
const code = requiredString(entry.code, `${entryPointer}/code`, 255);
|
|
2471
2489
|
if (codes.has(code))
|
|
@@ -2478,6 +2496,13 @@ function validateRouteManifest(value, pointer, appCode) {
|
|
|
2478
2496
|
if (entry.workflowCode !== undefined) {
|
|
2479
2497
|
stableCode(entry.workflowCode, `${entryPointer}/workflowCode`);
|
|
2480
2498
|
}
|
|
2499
|
+
if (resourceKinds) {
|
|
2500
|
+
const resourceCodeValue = resourceCode(entry.resourceCode, `${entryPointer}/resourceCode`);
|
|
2501
|
+
equal(code, `user.${resourceCodeValue}.${entry.kind === 'resource-records' ? 'records' : 'submit'}`, `${entryPointer}/code`);
|
|
2502
|
+
}
|
|
2503
|
+
else if (entry.resourceCode !== undefined) {
|
|
2504
|
+
fail('NATIVE_PROPERTY_UNKNOWN', `${entryPointer}/resourceCode`);
|
|
2505
|
+
}
|
|
2481
2506
|
const desktop = validateRouteManifestRoute(entry.desktop, `${entryPointer}/desktop`, appCode);
|
|
2482
2507
|
const mobile = validateRouteManifestRoute(entry.mobile, `${entryPointer}/mobile`, appCode);
|
|
2483
2508
|
if (desktop.surface !== 'user') {
|
|
@@ -2593,25 +2618,41 @@ function compileRouteManifestRoute(routeCode, path, surface, page) {
|
|
|
2593
2618
|
requiresAuthentication: true,
|
|
2594
2619
|
};
|
|
2595
2620
|
}
|
|
2596
|
-
function standardRouteCode(kind, device, workflowCode) {
|
|
2621
|
+
function standardRouteCode(kind, device, workflowCode, resourceCode) {
|
|
2597
2622
|
if (kind === 'workflow-launch') {
|
|
2598
2623
|
return `workflow.${workflowCode}.launch.${device}`;
|
|
2599
2624
|
}
|
|
2600
2625
|
if (kind === 'application-todo-center') {
|
|
2601
2626
|
return `application.todo-center.${device}`;
|
|
2602
2627
|
}
|
|
2628
|
+
if (kind === 'resource-records') {
|
|
2629
|
+
return `user.${resourceCode}.records.${device}`;
|
|
2630
|
+
}
|
|
2631
|
+
if (kind === 'resource-submit') {
|
|
2632
|
+
return `user.${resourceCode}.submit.${device}`;
|
|
2633
|
+
}
|
|
2603
2634
|
return `${kind.replace(/-/g, '.')}.${device}`;
|
|
2604
2635
|
}
|
|
2636
|
+
function resourceCapabilitiesOf(appCode, resourceCodeValue) {
|
|
2637
|
+
const prefix = `app:${appCode}:data:${resourceCodeValue}`;
|
|
2638
|
+
return {
|
|
2639
|
+
read: `${prefix}:read`,
|
|
2640
|
+
create: `${prefix}:create`,
|
|
2641
|
+
update: `${prefix}:update`,
|
|
2642
|
+
delete: `${prefix}:delete`,
|
|
2643
|
+
};
|
|
2644
|
+
}
|
|
2605
2645
|
function compileRouteManifest(config) {
|
|
2606
2646
|
const appCode = config.appCode;
|
|
2607
2647
|
const routes = [];
|
|
2608
|
-
const addRoute = (code, kind, desktopPath, mobilePath, workflowCode, access) => {
|
|
2648
|
+
const addRoute = (code, kind, desktopPath, mobilePath, workflowCode, access, resourceCodeValue) => {
|
|
2609
2649
|
routes.push({
|
|
2610
2650
|
code,
|
|
2611
2651
|
kind,
|
|
2612
2652
|
...(workflowCode ? { workflowCode } : {}),
|
|
2613
|
-
|
|
2614
|
-
|
|
2653
|
+
...(resourceCodeValue ? { resourceCode: resourceCodeValue } : {}),
|
|
2654
|
+
desktop: compileRouteManifestRoute(standardRouteCode(kind, 'desktop', workflowCode, resourceCodeValue), desktopPath, 'user', access),
|
|
2655
|
+
mobile: compileRouteManifestRoute(standardRouteCode(kind, 'mobile', workflowCode, resourceCodeValue), mobilePath, 'user', access),
|
|
2615
2656
|
});
|
|
2616
2657
|
};
|
|
2617
2658
|
if (config.frontend.user.applicationTodoCenter === true) {
|
|
@@ -4131,6 +4172,75 @@ function validateWorkflowDefinitionBinding(definition, binding, pointer) {
|
|
|
4131
4172
|
}
|
|
4132
4173
|
}
|
|
4133
4174
|
}
|
|
4175
|
+
/**
|
|
4176
|
+
* 生成式用户标准面的路由事实由工具链编译器产出;配置 bundle 不携带
|
|
4177
|
+
* userSurface。闭合时按配置事实校验这些路由(资源存在、能力等于该资源
|
|
4178
|
+
* read/create、路径与码形状稳定),通过后并入期望契约并重算清单摘要。
|
|
4179
|
+
* 路由本身仍受能力门禁约束,注入不产生任何额外授权。
|
|
4180
|
+
*/
|
|
4181
|
+
function mergeUserSurfaceRoutes(expectedContract, contract, config) {
|
|
4182
|
+
const manifest = object(contract.routeManifest, '/contracts/routeManifest');
|
|
4183
|
+
const expectedManifest = object(expectedContract.routeManifest, '/contracts/routeManifest');
|
|
4184
|
+
const resources = new Map();
|
|
4185
|
+
for (const raw of boundedArray(config.data?.resources, '/config/data/resources', 100)) {
|
|
4186
|
+
const resource = object(raw, '/config/data/resources');
|
|
4187
|
+
resources.set(String(resource.code || ''), resource);
|
|
4188
|
+
}
|
|
4189
|
+
const existingCodes = new Set(boundedArray(expectedManifest.routes, '/contracts/routeManifest/routes', 1000).map(entry => String(object(entry, '/contracts/routeManifest/routes').code || '')));
|
|
4190
|
+
const accepted = [];
|
|
4191
|
+
for (const rawEntry of boundedArray(manifest.routes, '/contracts/routeManifest/routes', 1000)) {
|
|
4192
|
+
const entry = object(rawEntry, '/contracts/routeManifest/routes');
|
|
4193
|
+
const kind = String(entry.kind || '');
|
|
4194
|
+
if (kind !== 'resource-records' && kind !== 'resource-submit')
|
|
4195
|
+
continue;
|
|
4196
|
+
const resourceCodeValue = String(entry.resourceCode || '');
|
|
4197
|
+
const resource = resources.get(resourceCodeValue);
|
|
4198
|
+
if (!resource) {
|
|
4199
|
+
fail('NATIVE_ROUTE_MANIFEST_RESOURCE_UNKNOWN', `/contracts/routeManifest/routes`);
|
|
4200
|
+
}
|
|
4201
|
+
const suffix = kind === 'resource-records' ? 'records' : 'submit';
|
|
4202
|
+
const code = `user.${resourceCodeValue}.${suffix}`;
|
|
4203
|
+
equal(String(entry.code || ''), code, '/contracts/routeManifest/routes/code');
|
|
4204
|
+
const operation = kind === 'resource-records' ? 'read' : 'create';
|
|
4205
|
+
const capability = String(object(resource.capabilities, '/config/data/resources/capabilities')[operation] || '');
|
|
4206
|
+
for (const device of ['desktop', 'mobile']) {
|
|
4207
|
+
const route = object(entry[device], `/contracts/routeManifest/routes/${device}`);
|
|
4208
|
+
const prefix = device === 'mobile' ? '/m/my/' : '/my/';
|
|
4209
|
+
const suffixPath = kind === 'resource-records'
|
|
4210
|
+
? `${prefix}${resourceCodeValue}`
|
|
4211
|
+
: `${prefix}${resourceCodeValue}/submit`;
|
|
4212
|
+
equal(String(route.path || ''), suffixPath, `/contracts/routeManifest/routes/${device}/path`);
|
|
4213
|
+
equal(String(route.capability || ''), capability, `/contracts/routeManifest/routes/${device}/capability`);
|
|
4214
|
+
equal(String(route.routeCode || ''), `${code}.${device}`, `/contracts/routeManifest/routes/${device}/routeCode`);
|
|
4215
|
+
}
|
|
4216
|
+
if (existingCodes.has(code) || accepted.some(item => String(item.code) === code)) {
|
|
4217
|
+
fail('NATIVE_ROUTE_MANIFEST_DUPLICATE', '/contracts/routeManifest/routes/code');
|
|
4218
|
+
}
|
|
4219
|
+
accepted.push(entry);
|
|
4220
|
+
}
|
|
4221
|
+
if (!accepted.length)
|
|
4222
|
+
return;
|
|
4223
|
+
expectedManifest.routes = boundedArray([...expectedManifest.routes, ...accepted], '/contracts/routeManifest/routes', 1000).sort((left, right) => compareText(String(object(left, 'x').code || ''), String(object(right, 'x').code || '')));
|
|
4224
|
+
// rootEntry 指向已接受的 records 路由时同样并入。
|
|
4225
|
+
const rootCode = String(object(manifest.rootEntry, 'x').code || '');
|
|
4226
|
+
const homeEntry = accepted.find(entry => String(entry.code) === rootCode && entry.kind === 'resource-records');
|
|
4227
|
+
if (homeEntry) {
|
|
4228
|
+
const root = object(manifest.rootEntry, 'x');
|
|
4229
|
+
expectedManifest.rootEntry = {
|
|
4230
|
+
code: rootCode,
|
|
4231
|
+
desktop: String(root.desktop || ''),
|
|
4232
|
+
mobile: String(root.mobile || ''),
|
|
4233
|
+
};
|
|
4234
|
+
}
|
|
4235
|
+
expectedManifest.digest = sha256Canonical({
|
|
4236
|
+
schemaVersion: expectedManifest.schemaVersion,
|
|
4237
|
+
appCode: expectedManifest.appCode,
|
|
4238
|
+
devicePolicy: expectedManifest.devicePolicy,
|
|
4239
|
+
rootEntry: expectedManifest.rootEntry,
|
|
4240
|
+
authentication: expectedManifest.authentication,
|
|
4241
|
+
routes: expectedManifest.routes,
|
|
4242
|
+
});
|
|
4243
|
+
}
|
|
4134
4244
|
function validateResource(raw, pointer, appCode) {
|
|
4135
4245
|
const resource = object(raw, pointer);
|
|
4136
4246
|
exactKeys(resource, [
|