openxiangda-devkit-core 2.0.0-alpha.98 → 2.0.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/LICENSE +21 -0
- package/README.md +3 -9
- package/dist/app-spec.d.ts +30 -12
- package/dist/app-spec.d.ts.map +1 -1
- package/dist/app-spec.js +238 -57
- package/dist/app-spec.js.map +1 -1
- package/dist/application-services.d.ts +625 -42
- package/dist/application-services.d.ts.map +1 -1
- package/dist/application-services.js +321 -85
- package/dist/application-services.js.map +1 -1
- package/dist/application-ui-contract.d.ts +5 -0
- package/dist/application-ui-contract.d.ts.map +1 -0
- package/dist/application-ui-contract.js +149 -0
- package/dist/application-ui-contract.js.map +1 -0
- package/dist/backend-image-build.js +6 -11
- package/dist/backend-image-build.js.map +1 -1
- package/dist/command-process.d.ts +14 -0
- package/dist/command-process.d.ts.map +1 -0
- package/dist/command-process.js +51 -0
- package/dist/command-process.js.map +1 -0
- package/dist/command-registry.d.ts +44 -4
- package/dist/command-registry.d.ts.map +1 -1
- package/dist/command-registry.js +10 -6
- package/dist/command-registry.js.map +1 -1
- package/dist/compiler/ai-catalog.d.ts.map +1 -1
- package/dist/compiler/ai-catalog.js +2 -1
- package/dist/compiler/ai-catalog.js.map +1 -1
- package/dist/compiler/application-model.d.ts +60 -0
- package/dist/compiler/application-model.d.ts.map +1 -0
- package/dist/compiler/application-model.js +141 -0
- package/dist/compiler/application-model.js.map +1 -0
- package/dist/compiler/bundle.d.ts.map +1 -1
- package/dist/compiler/bundle.js +196 -98
- package/dist/compiler/bundle.js.map +1 -1
- package/dist/compiler/config.d.ts +36 -10
- package/dist/compiler/config.d.ts.map +1 -1
- package/dist/compiler/config.js +536 -171
- package/dist/compiler/config.js.map +1 -1
- package/dist/compiler/field-surface.js +1 -1
- package/dist/compiler/field-surface.js.map +1 -1
- package/dist/compiler/package-compiler.d.ts.map +1 -1
- package/dist/compiler/package-compiler.js +12 -0
- package/dist/compiler/package-compiler.js.map +1 -1
- package/dist/compiler/permission-review.d.ts +139 -0
- package/dist/compiler/permission-review.d.ts.map +1 -0
- package/dist/compiler/permission-review.js +131 -0
- package/dist/compiler/permission-review.js.map +1 -0
- package/dist/configuration-preflight.d.ts +7 -0
- package/dist/configuration-preflight.d.ts.map +1 -0
- package/dist/configuration-preflight.js +13 -0
- package/dist/configuration-preflight.js.map +1 -0
- package/dist/control-plane-client.d.ts +56 -61
- package/dist/control-plane-client.d.ts.map +1 -1
- package/dist/control-plane-client.js +89 -8
- package/dist/control-plane-client.js.map +1 -1
- package/dist/delivery-cache.d.ts +34 -0
- package/dist/delivery-cache.d.ts.map +1 -0
- package/dist/delivery-cache.js +186 -0
- package/dist/delivery-cache.js.map +1 -0
- package/dist/delivery-source.d.ts +17 -0
- package/dist/delivery-source.d.ts.map +1 -0
- package/dist/delivery-source.js +85 -0
- package/dist/delivery-source.js.map +1 -0
- package/dist/deployment-observer.d.ts +14 -0
- package/dist/deployment-observer.d.ts.map +1 -0
- package/dist/deployment-observer.js +68 -0
- package/dist/deployment-observer.js.map +1 -0
- package/dist/deployment.d.ts +17 -1
- package/dist/deployment.d.ts.map +1 -1
- package/dist/deployment.js +55 -15
- package/dist/deployment.js.map +1 -1
- package/dist/design-readiness.d.ts +24 -0
- package/dist/design-readiness.d.ts.map +1 -0
- package/dist/design-readiness.js +102 -0
- package/dist/design-readiness.js.map +1 -0
- package/dist/developer-errors.d.ts +11 -0
- package/dist/developer-errors.d.ts.map +1 -0
- package/dist/developer-errors.js +16 -0
- package/dist/developer-errors.js.map +1 -0
- package/dist/developer-operations.d.ts +190 -0
- package/dist/developer-operations.d.ts.map +1 -0
- package/dist/developer-operations.js +65 -0
- package/dist/developer-operations.js.map +1 -0
- package/dist/development-lifecycle.d.ts +75 -0
- package/dist/development-lifecycle.d.ts.map +1 -0
- package/dist/development-lifecycle.js +189 -0
- package/dist/development-lifecycle.js.map +1 -0
- package/dist/documentation.d.ts +111 -0
- package/dist/documentation.d.ts.map +1 -0
- package/dist/documentation.js +112 -0
- package/dist/documentation.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/operation-progress.d.ts +26 -0
- package/dist/operation-progress.d.ts.map +1 -0
- package/dist/operation-progress.js +92 -0
- package/dist/operation-progress.js.map +1 -0
- package/dist/optional-backend.d.ts +14 -0
- package/dist/optional-backend.d.ts.map +1 -0
- package/dist/optional-backend.js +145 -0
- package/dist/optional-backend.js.map +1 -0
- package/dist/session.d.ts +22 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +36 -0
- package/dist/session.js.map +1 -1
- package/dist/workspace-loader.d.ts.map +1 -1
- package/dist/workspace-loader.js +17 -2
- package/dist/workspace-loader.js.map +1 -1
- package/dist/workspace-operation.d.ts +3 -0
- package/dist/workspace-operation.d.ts.map +1 -0
- package/dist/workspace-operation.js +45 -0
- package/dist/workspace-operation.js.map +1 -0
- package/dist/workspace.d.ts.map +1 -1
- package/dist/workspace.js +1 -0
- package/dist/workspace.js.map +1 -1
- package/package.json +18 -4
- package/templates/backend/Dockerfile +20 -0
- package/templates/backend/package.json +27 -0
- package/templates/backend/src/app.module.ts +23 -0
- package/templates/backend/src/main.ts +5 -0
- package/templates/backend/tsconfig.json +9 -0
package/dist/compiler/bundle.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { projectDataResourceView } from 'openxiangda-contracts';
|
|
2
|
+
import { nativeFieldRequiresCreateInputV2 } from 'openxiangda-contracts/native-compiler';
|
|
1
3
|
import { createHash } from 'node:crypto';
|
|
2
4
|
import { canonicalJson, applicationEventHandlerPathV2, DATA_EVENT_TYPES_V2, nativePlatformCapabilityCatalog, OPENXIANGDA_COMPILER_CONTRACT_VERSION, SCHEMA_VERSIONS, WORKFLOW_EVENT_TYPES_V2, sha256Digest, } from 'openxiangda-contracts';
|
|
3
5
|
import { AppConfigValidationError, } from './config.js';
|
|
@@ -237,6 +239,9 @@ export function normalizeConfiguration(config) {
|
|
|
237
239
|
...(operation.platformAccess
|
|
238
240
|
? {
|
|
239
241
|
platformAccess: {
|
|
242
|
+
...(operation.platformAccess.roleAssertions ? {
|
|
243
|
+
roleAssertions: { roleCodes: uniqueSorted(operation.platformAccess.roleAssertions.roleCodes) },
|
|
244
|
+
} : {}),
|
|
240
245
|
...(operation.platformAccess.directory
|
|
241
246
|
? {
|
|
242
247
|
directory: {
|
|
@@ -306,6 +311,19 @@ export function normalizeConfiguration(config) {
|
|
|
306
311
|
},
|
|
307
312
|
data: {
|
|
308
313
|
resources: sorted((config.data?.resources || []).map(normalizeDataResource), item => item.code),
|
|
314
|
+
...((config.data?.resources || []).some(resource => resource.detailRouteCode)
|
|
315
|
+
? {
|
|
316
|
+
resourceDetailRoutes: sorted((config.data?.resources || []).flatMap(resource => resource.detailRouteCode
|
|
317
|
+
? [
|
|
318
|
+
{
|
|
319
|
+
resourceCode: resource.code,
|
|
320
|
+
desktop: resource.detailRouteCode.desktop,
|
|
321
|
+
mobile: resource.detailRouteCode.mobile,
|
|
322
|
+
},
|
|
323
|
+
]
|
|
324
|
+
: []), item => item.resourceCode),
|
|
325
|
+
}
|
|
326
|
+
: {}),
|
|
309
327
|
},
|
|
310
328
|
events: {
|
|
311
329
|
schemas: sorted((config.events?.schemas || []).map(schema => ({
|
|
@@ -381,7 +399,7 @@ export function normalizeConfiguration(config) {
|
|
|
381
399
|
definitions: sorted((config.workflows?.definitions || []).map(item => ({
|
|
382
400
|
version: item.version,
|
|
383
401
|
definition: normalizeWorkflowDefinition(item.definition),
|
|
384
|
-
launch:
|
|
402
|
+
launch: normalizeWorkflowLaunchDeclaration(item.launch),
|
|
385
403
|
...(item.detailRouteCode
|
|
386
404
|
? { detailRouteCode: { ...item.detailRouteCode } }
|
|
387
405
|
: {}),
|
|
@@ -427,12 +445,35 @@ export function normalizeConfiguration(config) {
|
|
|
427
445
|
},
|
|
428
446
|
frontend: {
|
|
429
447
|
routes: compileFrontendRoutes(config),
|
|
448
|
+
user: {
|
|
449
|
+
applicationTodoCenter: config.frontend.user?.applicationTodoCenter === true,
|
|
450
|
+
},
|
|
430
451
|
devicePolicy: compileRouteManifestDevicePolicy(config),
|
|
431
452
|
authentication: compileApplicationAuthentication(config),
|
|
432
453
|
...(config.frontend.publicAccess
|
|
433
454
|
? { publicAccess: compileAnonymousPublicAccess(config) }
|
|
434
455
|
: {}),
|
|
435
456
|
admin: {
|
|
457
|
+
...(config.frontend.admin?.access
|
|
458
|
+
? {
|
|
459
|
+
access: {
|
|
460
|
+
...(config.frontend.admin.access.allOf
|
|
461
|
+
? {
|
|
462
|
+
allOf: uniqueSorted([
|
|
463
|
+
...config.frontend.admin.access.allOf,
|
|
464
|
+
]),
|
|
465
|
+
}
|
|
466
|
+
: {}),
|
|
467
|
+
...(config.frontend.admin.access.anyOf
|
|
468
|
+
? {
|
|
469
|
+
anyOf: uniqueSorted([
|
|
470
|
+
...config.frontend.admin.access.anyOf,
|
|
471
|
+
]),
|
|
472
|
+
}
|
|
473
|
+
: {}),
|
|
474
|
+
},
|
|
475
|
+
}
|
|
476
|
+
: {}),
|
|
436
477
|
navigation: (config.frontend.admin?.navigation || []).map(group => ({
|
|
437
478
|
code: group.code,
|
|
438
479
|
label: group.label,
|
|
@@ -593,7 +634,7 @@ function compileContractBundleFromNormalized(config, configDigest, generatorVers
|
|
|
593
634
|
appCode: config.app.code,
|
|
594
635
|
configDigest,
|
|
595
636
|
perspectives: normalizedConfiguration.perspectives,
|
|
596
|
-
resources: compileResources(
|
|
637
|
+
resources: compileResources(normalizedConfiguration),
|
|
597
638
|
capabilities,
|
|
598
639
|
operations: compileOperations(config),
|
|
599
640
|
eventConsumers,
|
|
@@ -620,7 +661,10 @@ function compileContractBundleFromNormalized(config, configDigest, generatorVers
|
|
|
620
661
|
...(config.frontend.publicAccess
|
|
621
662
|
? { publicAccess: compileAnonymousPublicAccess(config) }
|
|
622
663
|
: {}),
|
|
623
|
-
|
|
664
|
+
...(normalizedConfiguration.frontend.admin.access
|
|
665
|
+
? { adminAccess: normalizedConfiguration.frontend.admin.access }
|
|
666
|
+
: {}),
|
|
667
|
+
routeManifest: compileStandardRouteManifest(config),
|
|
624
668
|
adminPages,
|
|
625
669
|
adminNavigation: compileAdminNavigation(config),
|
|
626
670
|
};
|
|
@@ -727,8 +771,79 @@ function generatedResourceOperations(resource) {
|
|
|
727
771
|
delete: resource.surface?.generated?.delete ?? native,
|
|
728
772
|
};
|
|
729
773
|
}
|
|
730
|
-
function
|
|
731
|
-
|
|
774
|
+
function normalizeWorkflowNamedOperationIntent(intent) {
|
|
775
|
+
return {
|
|
776
|
+
operationCode: intent.operationCode,
|
|
777
|
+
inputs: Object.fromEntries(Object.entries(intent.inputs)
|
|
778
|
+
.sort(([left], [right]) => compare(left, right))
|
|
779
|
+
.map(([inputCode, binding]) => [inputCode, { ...binding }])),
|
|
780
|
+
output: { ...intent.output },
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
function normalizeWorkflowLaunchDeclaration(launch) {
|
|
784
|
+
return {
|
|
785
|
+
mode: launch?.mode || 'work-center-only',
|
|
786
|
+
...(launch?.submission
|
|
787
|
+
? {
|
|
788
|
+
submission: {
|
|
789
|
+
kind: 'named-operation',
|
|
790
|
+
...(launch.submission.create
|
|
791
|
+
? {
|
|
792
|
+
create: normalizeWorkflowNamedOperationIntent(launch.submission.create),
|
|
793
|
+
}
|
|
794
|
+
: {}),
|
|
795
|
+
...(launch.submission.existing
|
|
796
|
+
? {
|
|
797
|
+
existing: normalizeWorkflowNamedOperationIntent(launch.submission.existing),
|
|
798
|
+
}
|
|
799
|
+
: {}),
|
|
800
|
+
...(launch.submission.context
|
|
801
|
+
? {
|
|
802
|
+
context: [...launch.submission.context]
|
|
803
|
+
.map(context => ({ ...context }))
|
|
804
|
+
.sort((left, right) => compare(left.queryParameter, right.queryParameter)),
|
|
805
|
+
}
|
|
806
|
+
: {}),
|
|
807
|
+
},
|
|
808
|
+
}
|
|
809
|
+
: {}),
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
function compileWorkflowNamedOperationIntent(config, intent) {
|
|
813
|
+
const operation = (config.backend?.operations || []).find(candidate => candidate.code === intent.operationCode);
|
|
814
|
+
return {
|
|
815
|
+
...normalizeWorkflowNamedOperationIntent(intent),
|
|
816
|
+
method: 'POST',
|
|
817
|
+
path: operation.path,
|
|
818
|
+
requiredCapability: operation.capability,
|
|
819
|
+
requestSchemaDigest: sha256Digest(operation.requestSchema),
|
|
820
|
+
responseSchemaDigest: sha256Digest(operation.responseSchema),
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
function compileWorkflowLaunchContract(config, launch) {
|
|
824
|
+
const normalized = normalizeWorkflowLaunchDeclaration(launch);
|
|
825
|
+
if (!normalized.submission)
|
|
826
|
+
return { mode: normalized.mode };
|
|
827
|
+
return {
|
|
828
|
+
mode: normalized.mode,
|
|
829
|
+
submission: {
|
|
830
|
+
kind: 'named-operation',
|
|
831
|
+
...(normalized.submission.create
|
|
832
|
+
? {
|
|
833
|
+
create: compileWorkflowNamedOperationIntent(config, normalized.submission.create),
|
|
834
|
+
}
|
|
835
|
+
: {}),
|
|
836
|
+
...(normalized.submission.existing
|
|
837
|
+
? {
|
|
838
|
+
existing: compileWorkflowNamedOperationIntent(config, normalized.submission.existing),
|
|
839
|
+
}
|
|
840
|
+
: {}),
|
|
841
|
+
context: [...(normalized.submission.context || [])],
|
|
842
|
+
},
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
function generatedAdminResourcePath(resourceCode, operation, viewCode) {
|
|
846
|
+
const base = `/admin/resources/${resourceCode}${viewCode ? `/views/${viewCode}` : ""}`;
|
|
732
847
|
if (operation === 'list')
|
|
733
848
|
return base;
|
|
734
849
|
if (operation === 'create')
|
|
@@ -739,13 +854,18 @@ function generatedAdminResourcePath(resourceCode, operation) {
|
|
|
739
854
|
}
|
|
740
855
|
function compileAdminPages(config) {
|
|
741
856
|
const pages = [];
|
|
742
|
-
for (const
|
|
857
|
+
for (const selection of sorted(config.data?.resources || [], item => item.code).flatMap(resource => [
|
|
858
|
+
{ resource, viewCode: undefined },
|
|
859
|
+
...(resource.surface?.views || []).map(view => ({ viewCode: view.code,
|
|
860
|
+
resource: { ...resource, name: view.name, surface: projectDataResourceView(resource.surface, view.code) } })),
|
|
861
|
+
])) {
|
|
862
|
+
const { resource, viewCode } = selection;
|
|
743
863
|
const generated = generatedResourceOperations(resource);
|
|
744
864
|
const candidates = [
|
|
745
865
|
{
|
|
746
866
|
operation: 'list',
|
|
747
867
|
kind: 'resource-list',
|
|
748
|
-
path: generatedAdminResourcePath(resource.code, 'list'),
|
|
868
|
+
path: generatedAdminResourcePath(resource.code, 'list', viewCode),
|
|
749
869
|
label: resource.name,
|
|
750
870
|
capability: resource.capabilities.read,
|
|
751
871
|
navigationEligible: true,
|
|
@@ -753,7 +873,7 @@ function compileAdminPages(config) {
|
|
|
753
873
|
{
|
|
754
874
|
operation: 'detail',
|
|
755
875
|
kind: 'resource-detail',
|
|
756
|
-
path: generatedAdminResourcePath(resource.code, 'detail'),
|
|
876
|
+
path: generatedAdminResourcePath(resource.code, 'detail', viewCode),
|
|
757
877
|
label: `${resource.name}详情`,
|
|
758
878
|
capability: resource.capabilities.read,
|
|
759
879
|
navigationEligible: false,
|
|
@@ -761,7 +881,7 @@ function compileAdminPages(config) {
|
|
|
761
881
|
{
|
|
762
882
|
operation: 'create',
|
|
763
883
|
kind: 'resource-create',
|
|
764
|
-
path: generatedAdminResourcePath(resource.code, 'create'),
|
|
884
|
+
path: generatedAdminResourcePath(resource.code, 'create', viewCode),
|
|
765
885
|
label: `新增${resource.name}`,
|
|
766
886
|
capability: resource.capabilities.create,
|
|
767
887
|
navigationEligible: false,
|
|
@@ -769,7 +889,7 @@ function compileAdminPages(config) {
|
|
|
769
889
|
{
|
|
770
890
|
operation: 'update',
|
|
771
891
|
kind: 'resource-update',
|
|
772
|
-
path: generatedAdminResourcePath(resource.code, 'update'),
|
|
892
|
+
path: generatedAdminResourcePath(resource.code, 'update', viewCode),
|
|
773
893
|
label: `编辑${resource.name}`,
|
|
774
894
|
capability: resource.capabilities.update,
|
|
775
895
|
navigationEligible: false,
|
|
@@ -779,13 +899,14 @@ function compileAdminPages(config) {
|
|
|
779
899
|
if (!generated[candidate.operation])
|
|
780
900
|
continue;
|
|
781
901
|
pages.push({
|
|
782
|
-
code: `resource:${resource.code}:${candidate.operation}`,
|
|
902
|
+
code: `resource:${resource.code}${viewCode ? `:view:${viewCode}` : ""}:${candidate.operation}`,
|
|
783
903
|
kind: candidate.kind,
|
|
784
904
|
path: candidate.path,
|
|
785
905
|
label: candidate.label,
|
|
786
906
|
navigationEligible: candidate.navigationEligible,
|
|
787
907
|
capability: candidate.capability,
|
|
788
908
|
resourceCode: resource.code,
|
|
909
|
+
...(viewCode ? { viewCode } : {}),
|
|
789
910
|
});
|
|
790
911
|
}
|
|
791
912
|
}
|
|
@@ -797,53 +918,10 @@ function compileAdminPages(config) {
|
|
|
797
918
|
kind: 'operation',
|
|
798
919
|
path: route.path,
|
|
799
920
|
label: route.label,
|
|
800
|
-
navigationEligible: !/[:*]/.test(route.path),
|
|
921
|
+
navigationEligible: !route.path.startsWith('/m/admin') && !/[:*]/.test(route.path),
|
|
801
922
|
routeCode: route.code,
|
|
802
923
|
});
|
|
803
924
|
}
|
|
804
|
-
if ((config.frontend.admin?.navigation || []).some(group => group.items.some(item => item.page.kind === 'application-todo-center'))) {
|
|
805
|
-
pages.push({
|
|
806
|
-
code: 'application:todo-center',
|
|
807
|
-
kind: 'application-todo-center',
|
|
808
|
-
path: '/admin/todos',
|
|
809
|
-
label: '待办中心',
|
|
810
|
-
navigationEligible: true,
|
|
811
|
-
});
|
|
812
|
-
}
|
|
813
|
-
const workflows = compileWorkflows(config);
|
|
814
|
-
if (workflows.length) {
|
|
815
|
-
pages.push({
|
|
816
|
-
code: 'workflow:work-center',
|
|
817
|
-
kind: 'workflow-work-center',
|
|
818
|
-
path: '/admin/work-center',
|
|
819
|
-
label: '我的审批',
|
|
820
|
-
navigationEligible: true,
|
|
821
|
-
}, {
|
|
822
|
-
code: 'workflow:task',
|
|
823
|
-
kind: 'workflow-task',
|
|
824
|
-
path: '/tasks/:taskId',
|
|
825
|
-
label: '审批任务',
|
|
826
|
-
navigationEligible: false,
|
|
827
|
-
}, {
|
|
828
|
-
code: 'workflow:instance',
|
|
829
|
-
kind: 'workflow-instance',
|
|
830
|
-
path: '/workflows/:instanceId',
|
|
831
|
-
label: '流程详情',
|
|
832
|
-
navigationEligible: false,
|
|
833
|
-
});
|
|
834
|
-
}
|
|
835
|
-
for (const workflow of workflows) {
|
|
836
|
-
if (!['standalone', 'hidden-handoff'].includes(workflow.launch.mode))
|
|
837
|
-
continue;
|
|
838
|
-
pages.push({
|
|
839
|
-
code: `workflow:${workflow.code}:launch`,
|
|
840
|
-
kind: 'workflow-launch',
|
|
841
|
-
path: `/admin/workflows/${workflow.code}/new`,
|
|
842
|
-
label: `发起${workflow.title}`,
|
|
843
|
-
navigationEligible: workflow.launch.mode === 'standalone',
|
|
844
|
-
workflowCode: workflow.code,
|
|
845
|
-
});
|
|
846
|
-
}
|
|
847
925
|
return pages.sort((left, right) => compare(left.code, right.code));
|
|
848
926
|
}
|
|
849
927
|
function routePathParams(path) {
|
|
@@ -860,14 +938,14 @@ function compileRouteManifestDevicePolicy(config) {
|
|
|
860
938
|
...(config.frontend.devicePolicy || {}),
|
|
861
939
|
};
|
|
862
940
|
}
|
|
863
|
-
function compileStandardRouteManifestRoute(routeCode, path, surface,
|
|
941
|
+
function compileStandardRouteManifestRoute(routeCode, path, surface, access) {
|
|
864
942
|
return {
|
|
865
943
|
routeCode,
|
|
866
944
|
path,
|
|
867
945
|
surface,
|
|
868
946
|
pathParams: routePathParams(path),
|
|
869
|
-
...(
|
|
870
|
-
...(
|
|
947
|
+
...(access?.capability ? { capability: access.capability } : {}),
|
|
948
|
+
...(access?.access ? { access: access.access } : {}),
|
|
871
949
|
requiresAuthentication: true,
|
|
872
950
|
};
|
|
873
951
|
}
|
|
@@ -878,35 +956,38 @@ function standardRouteCode(kind, device, workflowCode) {
|
|
|
878
956
|
return `application.todo-center.${device}`;
|
|
879
957
|
return `${kind.replaceAll('-', '.')}.${device}`;
|
|
880
958
|
}
|
|
881
|
-
function compileStandardRouteManifest(config
|
|
959
|
+
function compileStandardRouteManifest(config) {
|
|
882
960
|
const routes = [];
|
|
883
|
-
|
|
884
|
-
if (page.kind !== 'application-todo-center' &&
|
|
885
|
-
page.kind !== 'workflow-work-center' &&
|
|
886
|
-
page.kind !== 'workflow-task' &&
|
|
887
|
-
page.kind !== 'workflow-instance' &&
|
|
888
|
-
page.kind !== 'workflow-launch')
|
|
889
|
-
continue;
|
|
890
|
-
const workflowCode = page.workflowCode;
|
|
891
|
-
const desktopPath = page.path;
|
|
892
|
-
const mobilePath = page.kind === 'application-todo-center'
|
|
893
|
-
? '/m/todos'
|
|
894
|
-
: page.kind === 'workflow-work-center'
|
|
895
|
-
? '/m/work-center'
|
|
896
|
-
: page.kind === 'workflow-task'
|
|
897
|
-
? '/m/tasks/:taskId'
|
|
898
|
-
: page.kind === 'workflow-instance'
|
|
899
|
-
? '/m/workflows/:instanceId'
|
|
900
|
-
: '/m/workflows/:workflowCode/start';
|
|
901
|
-
const desktop = compileStandardRouteManifestRoute(standardRouteCode(page.kind, 'desktop', workflowCode), desktopPath, 'admin', page);
|
|
902
|
-
const mobile = compileStandardRouteManifestRoute(standardRouteCode(page.kind, 'mobile', workflowCode), mobilePath, 'user', page);
|
|
961
|
+
const addRoute = (code, kind, desktopPath, mobilePath, workflowCode, access) => {
|
|
903
962
|
routes.push({
|
|
904
|
-
code
|
|
905
|
-
kind
|
|
963
|
+
code,
|
|
964
|
+
kind,
|
|
906
965
|
...(workflowCode ? { workflowCode } : {}),
|
|
907
|
-
desktop,
|
|
908
|
-
mobile,
|
|
966
|
+
desktop: compileStandardRouteManifestRoute(standardRouteCode(kind, 'desktop', workflowCode), desktopPath, 'user', access),
|
|
967
|
+
mobile: compileStandardRouteManifestRoute(standardRouteCode(kind, 'mobile', workflowCode), mobilePath, 'user', access),
|
|
909
968
|
});
|
|
969
|
+
};
|
|
970
|
+
if (config.frontend.user?.applicationTodoCenter === true) {
|
|
971
|
+
addRoute('application:todo-center', 'application-todo-center', '/todos', '/m/todos');
|
|
972
|
+
}
|
|
973
|
+
const workflows = compileWorkflows(config);
|
|
974
|
+
if (workflows.length > 0) {
|
|
975
|
+
addRoute('workflow:work-center', 'workflow-work-center', '/work-center', '/m/work-center');
|
|
976
|
+
addRoute('workflow:task', 'workflow-task', '/tasks/:taskId', '/m/tasks/:taskId');
|
|
977
|
+
addRoute('workflow:instance', 'workflow-instance', '/workflows/:instanceId', '/m/workflows/:instanceId');
|
|
978
|
+
}
|
|
979
|
+
for (const workflow of workflows) {
|
|
980
|
+
if (!['standalone', 'hidden-handoff'].includes(workflow.launch.mode))
|
|
981
|
+
continue;
|
|
982
|
+
const namedCapabilities = uniqueSorted([
|
|
983
|
+
workflow.launch.submission?.create?.requiredCapability,
|
|
984
|
+
workflow.launch.submission?.existing?.requiredCapability,
|
|
985
|
+
].filter((capability) => Boolean(capability)));
|
|
986
|
+
addRoute(`workflow:${workflow.code}:launch`, 'workflow-launch', '/workflows/:workflowCode/start', '/m/workflows/:workflowCode/start', workflow.code, namedCapabilities.length === 1
|
|
987
|
+
? { capability: namedCapabilities[0] }
|
|
988
|
+
: namedCapabilities.length > 1
|
|
989
|
+
? { access: { anyOf: namedCapabilities } }
|
|
990
|
+
: undefined);
|
|
910
991
|
}
|
|
911
992
|
const normalizedRoutes = routes.sort((left, right) => compare(left.code, right.code));
|
|
912
993
|
const staticRoute = (device) => {
|
|
@@ -975,14 +1056,8 @@ function validManifestStaticPath(path) {
|
|
|
975
1056
|
}
|
|
976
1057
|
function pageCodeForReference(reference) {
|
|
977
1058
|
if (reference.kind === 'resource')
|
|
978
|
-
return `resource:${reference.resourceCode}:list`;
|
|
979
|
-
|
|
980
|
-
return `operation:${reference.routeCode}`;
|
|
981
|
-
if (reference.kind === 'application-todo-center')
|
|
982
|
-
return 'application:todo-center';
|
|
983
|
-
if (reference.kind === 'workflow-work-center')
|
|
984
|
-
return 'workflow:work-center';
|
|
985
|
-
return `workflow:${reference.workflowCode}:launch`;
|
|
1059
|
+
return `resource:${reference.resourceCode}${reference.viewCode ? `:view:${reference.viewCode}` : ""}:list`;
|
|
1060
|
+
return `operation:${reference.routeCode}`;
|
|
986
1061
|
}
|
|
987
1062
|
function compileAdminNavigation(config) {
|
|
988
1063
|
return (config.frontend.admin?.navigation || [])
|
|
@@ -1061,8 +1136,12 @@ function compileCapabilities(configuration) {
|
|
|
1061
1136
|
return [...capabilities.values()].sort((left, right) => compare(left.code, right.code));
|
|
1062
1137
|
}
|
|
1063
1138
|
function compileResources(config) {
|
|
1064
|
-
|
|
1065
|
-
|
|
1139
|
+
const detailRouteByResourceCode = new Map((config.data.resourceDetailRoutes || []).map(declaration => [
|
|
1140
|
+
declaration.resourceCode,
|
|
1141
|
+
declaration,
|
|
1142
|
+
]));
|
|
1143
|
+
return sorted(config.data.resources.map(resource => {
|
|
1144
|
+
const detailRouteCode = detailRouteByResourceCode.get(resource.code);
|
|
1066
1145
|
return {
|
|
1067
1146
|
code: resource.code,
|
|
1068
1147
|
// The platform only receives immutable artifact bytes. Bind the
|
|
@@ -1073,6 +1152,14 @@ function compileResources(config) {
|
|
|
1073
1152
|
code: field.code,
|
|
1074
1153
|
type: field.type,
|
|
1075
1154
|
})), field => field.code),
|
|
1155
|
+
...(detailRouteCode
|
|
1156
|
+
? {
|
|
1157
|
+
detailRouteCode: {
|
|
1158
|
+
desktop: detailRouteCode.desktop,
|
|
1159
|
+
mobile: detailRouteCode.mobile,
|
|
1160
|
+
},
|
|
1161
|
+
}
|
|
1162
|
+
: {}),
|
|
1076
1163
|
};
|
|
1077
1164
|
}), item => item.code);
|
|
1078
1165
|
}
|
|
@@ -1090,6 +1177,9 @@ function compileOperations(config) {
|
|
|
1090
1177
|
...(operation.platformAccess
|
|
1091
1178
|
? {
|
|
1092
1179
|
platformAccess: {
|
|
1180
|
+
...(operation.platformAccess.roleAssertions ? {
|
|
1181
|
+
roleAssertions: { roleCodes: uniqueSorted(operation.platformAccess.roleAssertions.roleCodes) },
|
|
1182
|
+
} : {}),
|
|
1093
1183
|
...(operation.platformAccess.directory
|
|
1094
1184
|
? {
|
|
1095
1185
|
directory: {
|
|
@@ -1164,10 +1254,8 @@ function compileWorkflows(config) {
|
|
|
1164
1254
|
? [...currentDefinition.definition.subject.summaryFields]
|
|
1165
1255
|
: [],
|
|
1166
1256
|
},
|
|
1167
|
-
launch:
|
|
1168
|
-
|
|
1169
|
-
},
|
|
1170
|
-
...(['standalone', 'hidden-handoff'].includes(currentDefinition.launch?.mode || 'work-center-only')
|
|
1257
|
+
launch: compileWorkflowLaunchContract(config, currentDefinition.launch),
|
|
1258
|
+
...(['standalone', 'hidden-handoff'].includes(currentDefinition.launch?.mode || 'work-center-only') && !currentDefinition.launch?.submission
|
|
1171
1259
|
? {
|
|
1172
1260
|
processOperationCode: `openxiangda.workflow.${code}.submit`,
|
|
1173
1261
|
}
|
|
@@ -1426,6 +1514,9 @@ export function renderGeneratedContracts(config, contract = compileContractBundl
|
|
|
1426
1514
|
.map(item => ` ${JSON.stringify(item.code)}: {\n` +
|
|
1427
1515
|
` code: ${JSON.stringify(item.code)},\n` +
|
|
1428
1516
|
` name: ${JSON.stringify(item.name)},\n` +
|
|
1517
|
+
(item.detailRouteCode
|
|
1518
|
+
? ` detailRouteCode: ${JSON.stringify(item.detailRouteCode)},\n`
|
|
1519
|
+
: '') +
|
|
1429
1520
|
` capabilities: ${JSON.stringify(item.capabilities, null, 2)
|
|
1430
1521
|
.split('\n')
|
|
1431
1522
|
.map((line, index) => (index === 0 ? line : ` ${line}`))
|
|
@@ -1491,6 +1582,9 @@ export function renderGeneratedContracts(config, contract = compileContractBundl
|
|
|
1491
1582
|
platformAuthManifest
|
|
1492
1583
|
? `export const platformAuthManifest = ${JSON.stringify(platformAuthManifest, null, 2)} as const;`
|
|
1493
1584
|
: 'export const platformAuthManifest = null;',
|
|
1585
|
+
contract.adminAccess
|
|
1586
|
+
? `export const adminAccess = ${JSON.stringify(contract.adminAccess, null, 2)} as const;`
|
|
1587
|
+
: 'export const adminAccess = undefined;',
|
|
1494
1588
|
`export const routeManifest = ${JSON.stringify(contract.routeManifest, null, 2)} as const;`,
|
|
1495
1589
|
`export const adminPages = ${JSON.stringify(contract.adminPages, null, 2)} as const;`,
|
|
1496
1590
|
`export const adminNavigation = ${JSON.stringify(contract.adminNavigation, null, 2)} as const;`,
|
|
@@ -1526,6 +1620,7 @@ export function renderGeneratedContracts(config, contract = compileContractBundl
|
|
|
1526
1620
|
'export type ApplicationAuthenticationSurface = (typeof authenticationSurfaces)[keyof typeof authenticationSurfaces];',
|
|
1527
1621
|
'export type ApplicationAuthenticationSurfaceCode = ApplicationAuthenticationSurface["routeCode"];',
|
|
1528
1622
|
'export type AnonymousPublicAccess = typeof anonymousPublicAccess;',
|
|
1623
|
+
'export type AdminAccess = typeof adminAccess;',
|
|
1529
1624
|
'export type RouteManifest = typeof routeManifest;',
|
|
1530
1625
|
'export type AdminPage = (typeof adminPages)[number];',
|
|
1531
1626
|
'export type AdminNavigationGroup = (typeof adminNavigation)[number];',
|
|
@@ -1611,6 +1706,7 @@ function normalizeResourceSurface(surface) {
|
|
|
1611
1706
|
? { requiredHint: field.requiredHint }
|
|
1612
1707
|
: {}),
|
|
1613
1708
|
...(field.system !== undefined ? { system: field.system } : {}),
|
|
1709
|
+
...(field.hidden !== undefined ? { hidden: field.hidden } : {}),
|
|
1614
1710
|
readCapabilities: uniqueSorted(field.readCapabilities),
|
|
1615
1711
|
createCapabilities: uniqueSorted(field.createCapabilities),
|
|
1616
1712
|
updateCapabilities: uniqueSorted(field.updateCapabilities),
|
|
@@ -1642,6 +1738,7 @@ function normalizeResourceSurface(surface) {
|
|
|
1642
1738
|
},
|
|
1643
1739
|
]));
|
|
1644
1740
|
return {
|
|
1741
|
+
...(surface.views?.length ? { views: sorted(surface.views, view => view.code) } : {}),
|
|
1645
1742
|
...(surface.mutationOwner !== undefined
|
|
1646
1743
|
? { mutationOwner: surface.mutationOwner }
|
|
1647
1744
|
: {}),
|
|
@@ -1652,6 +1749,7 @@ function normalizeResourceSurface(surface) {
|
|
|
1652
1749
|
...(surface.list
|
|
1653
1750
|
? {
|
|
1654
1751
|
list: {
|
|
1752
|
+
...(surface.list.fieldOrder ? { fieldOrder: [...surface.list.fieldOrder] } : {}),
|
|
1655
1753
|
...(surface.list.defaultPageSize !== undefined
|
|
1656
1754
|
? { defaultPageSize: surface.list.defaultPageSize }
|
|
1657
1755
|
: {}),
|
|
@@ -1686,7 +1784,7 @@ function defaultResourceSurface(resource) {
|
|
|
1686
1784
|
label: field.code,
|
|
1687
1785
|
type: field.type,
|
|
1688
1786
|
widget: resolveDataFieldSurfaceWidget(field),
|
|
1689
|
-
...(field
|
|
1787
|
+
...(nativeFieldRequiresCreateInputV2(field) ? { requiredHint: true } : {}),
|
|
1690
1788
|
...(field.maxLength !== undefined ? { maxLength: field.maxLength } : {}),
|
|
1691
1789
|
...(field.precision !== undefined ? { precision: field.precision } : {}),
|
|
1692
1790
|
...(field.scale !== undefined ? { scale: field.scale } : {}),
|