openxiangda-devkit-core 2.0.0-alpha.106 → 2.0.0-alpha.107
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/compiler/bundle.d.ts.map +1 -1
- package/dist/compiler/bundle.js +31 -3
- package/dist/compiler/bundle.js.map +1 -1
- package/dist/compiler/config.d.ts +8 -3
- package/dist/compiler/config.d.ts.map +1 -1
- package/dist/compiler/config.js +68 -1
- package/dist/compiler/config.js.map +1 -1
- package/package.json +2 -2
package/dist/compiler/config.js
CHANGED
|
@@ -835,6 +835,7 @@ export function validateAppConfig(value) {
|
|
|
835
835
|
validateApplicationAuthentication(config, diagnostics);
|
|
836
836
|
validateFrontendDevicePolicy(config, diagnostics);
|
|
837
837
|
validateFrontendRoutes(config, diagnostics);
|
|
838
|
+
validateResourceDetailRoutes(config, diagnostics);
|
|
838
839
|
validateFrontendUser(config, diagnostics);
|
|
839
840
|
validateAnonymousPublicAccess(config, diagnostics);
|
|
840
841
|
validateAdminAccess(config, diagnostics);
|
|
@@ -2717,6 +2718,68 @@ function validateFrontendDevicePolicy(config, diagnostics) {
|
|
|
2717
2718
|
diagnostics.push(diagnostic('APP_CONFIG_FRONTEND_DEVICE_POLICY_INVALID', 'frontend.devicePolicy 必须是 viewport-family,移动最大宽度和桌面最小宽度为 320-1600 的相邻整数', 'frontend.devicePolicy'));
|
|
2718
2719
|
}
|
|
2719
2720
|
}
|
|
2721
|
+
function validateResourceDetailRoutes(config, diagnostics) {
|
|
2722
|
+
const frontend = object(config.frontend);
|
|
2723
|
+
const routesByCode = new Map((Array.isArray(frontend.routes) ? frontend.routes : []).map(rawRoute => {
|
|
2724
|
+
const route = object(rawRoute);
|
|
2725
|
+
return [string(route.code), route];
|
|
2726
|
+
}));
|
|
2727
|
+
const data = object(config.data);
|
|
2728
|
+
const resources = Array.isArray(data.resources) ? data.resources : [];
|
|
2729
|
+
resources.forEach((rawResource, resourceIndex) => {
|
|
2730
|
+
const resource = object(rawResource);
|
|
2731
|
+
if (resource.detailRouteCode === undefined)
|
|
2732
|
+
return;
|
|
2733
|
+
const path = `data.resources[${resourceIndex}].detailRouteCode`;
|
|
2734
|
+
const detailRouteCode = object(resource.detailRouteCode);
|
|
2735
|
+
const desktopCode = string(detailRouteCode.desktop);
|
|
2736
|
+
const mobileCode = string(detailRouteCode.mobile);
|
|
2737
|
+
if (Object.keys(detailRouteCode).some(key => !['desktop', 'mobile'].includes(key)) ||
|
|
2738
|
+
!OPERATION_CODE_PATTERN.test(desktopCode) ||
|
|
2739
|
+
!OPERATION_CODE_PATTERN.test(mobileCode) ||
|
|
2740
|
+
desktopCode === mobileCode) {
|
|
2741
|
+
diagnostics.push(diagnostic('APP_CONFIG_DATA_RESOURCE_DETAIL_ROUTE_INVALID', 'detailRouteCode 必须声明两个不同且合法的 desktop/mobile route code', path));
|
|
2742
|
+
return;
|
|
2743
|
+
}
|
|
2744
|
+
const readCapability = string(object(resource.capabilities).read);
|
|
2745
|
+
for (const [device, code] of [
|
|
2746
|
+
['desktop', desktopCode],
|
|
2747
|
+
['mobile', mobileCode],
|
|
2748
|
+
]) {
|
|
2749
|
+
const route = routesByCode.get(code);
|
|
2750
|
+
const routePointer = `${path}.${device}`;
|
|
2751
|
+
if (!route) {
|
|
2752
|
+
diagnostics.push(diagnostic('APP_CONFIG_DATA_RESOURCE_DETAIL_ROUTE_REFERENCE_MISSING', `detailRouteCode.${device} 必须引用已声明 frontend route`, routePointer));
|
|
2753
|
+
continue;
|
|
2754
|
+
}
|
|
2755
|
+
if (string(route.surface) !== 'user') {
|
|
2756
|
+
diagnostics.push(diagnostic('APP_CONFIG_DATA_RESOURCE_DETAIL_ROUTE_SURFACE_INVALID', `detailRouteCode.${device} 必须引用 user surface`, routePointer));
|
|
2757
|
+
}
|
|
2758
|
+
const routePath = string(route.path);
|
|
2759
|
+
const parameters = [
|
|
2760
|
+
...routePath.matchAll(/:([A-Za-z][A-Za-z0-9_]*)/g),
|
|
2761
|
+
].map(match => match[1]);
|
|
2762
|
+
const wrongDeviceFamily = device === 'mobile'
|
|
2763
|
+
? !routePath.startsWith('/m/')
|
|
2764
|
+
: routePath === '/m' || routePath.startsWith('/m/');
|
|
2765
|
+
if (routePath.includes('*') ||
|
|
2766
|
+
routePath.includes('?') ||
|
|
2767
|
+
routePath.includes('#') ||
|
|
2768
|
+
routePath.split('/').includes('..') ||
|
|
2769
|
+
parameters.length !== 1 ||
|
|
2770
|
+
wrongDeviceFamily) {
|
|
2771
|
+
diagnostics.push(diagnostic('APP_CONFIG_DATA_RESOURCE_DETAIL_ROUTE_PATH_INVALID', `detailRouteCode.${device} 路由必须属于对应端且只能声明一个有界动态记录参数`, routePointer));
|
|
2772
|
+
}
|
|
2773
|
+
const access = object(route.access);
|
|
2774
|
+
const allOf = Array.isArray(access.allOf) ? access.allOf.map(string) : [];
|
|
2775
|
+
if (!readCapability ||
|
|
2776
|
+
(string(route.capability) !== readCapability &&
|
|
2777
|
+
!allOf.includes(readCapability))) {
|
|
2778
|
+
diagnostics.push(diagnostic('APP_CONFIG_DATA_RESOURCE_DETAIL_ROUTE_CAPABILITY_INVALID', `detailRouteCode.${device} 路由必须要求当前资源的 read capability`, routePointer));
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
});
|
|
2782
|
+
}
|
|
2720
2783
|
function validateFrontendRoutes(config, diagnostics) {
|
|
2721
2784
|
const frontend = object(config.frontend);
|
|
2722
2785
|
const rawRoutes = frontend.routes;
|
|
@@ -3646,6 +3709,9 @@ export function materializeDataResource(appCode, declaration) {
|
|
|
3646
3709
|
...(declaration.dataPolicyCode
|
|
3647
3710
|
? { dataPolicyCode: declaration.dataPolicyCode }
|
|
3648
3711
|
: {}),
|
|
3712
|
+
...(declaration.detailRouteCode
|
|
3713
|
+
? { detailRouteCode: { ...declaration.detailRouteCode } }
|
|
3714
|
+
: {}),
|
|
3649
3715
|
fieldPolicies: Object.fromEntries(declaration.fields.map(field => [
|
|
3650
3716
|
field.code,
|
|
3651
3717
|
{
|
|
@@ -3675,6 +3741,7 @@ export function validateAppDeclaration(value) {
|
|
|
3675
3741
|
'detail',
|
|
3676
3742
|
'mobile',
|
|
3677
3743
|
'dataPolicyCode',
|
|
3744
|
+
'detailRouteCode',
|
|
3678
3745
|
]);
|
|
3679
3746
|
const fieldKeys = new Set([
|
|
3680
3747
|
'code',
|
|
@@ -3708,7 +3775,7 @@ export function validateAppDeclaration(value) {
|
|
|
3708
3775
|
const resourcePath = `data.resources[${resourceIndex}]`;
|
|
3709
3776
|
for (const key of Object.keys(resource)) {
|
|
3710
3777
|
if (!resourceKeys.has(key)) {
|
|
3711
|
-
diagnostics.push(diagnostic('APP_CONFIG_DATA_RESOURCE_PROPERTY_UNSUPPORTED', `${resourcePath}.${key} 不属于单次资源声明合同`, `${resourcePath}.${key}`, '只声明 code、name、fields
|
|
3778
|
+
diagnostics.push(diagnostic('APP_CONFIG_DATA_RESOURCE_PROPERTY_UNSUPPORTED', `${resourcePath}.${key} 不属于单次资源声明合同`, `${resourcePath}.${key}`, '只声明 code、name、fields 及可选列表/布局/数据策略/详情路由'));
|
|
3712
3779
|
}
|
|
3713
3780
|
}
|
|
3714
3781
|
const fields = Array.isArray(resource.fields) ? resource.fields : [];
|