@oj-module/cli 0.2.54 → 0.2.57
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/devkit/README.md +7 -4
- package/devkit/SKILL.md +7 -4
- package/devkit/manual.md +63 -54
- package/devkit/module-dev-and-cdn-playground.md +7 -0
- package/devkit/publish-walkthrough.md +199 -0
- package/package.json +2 -2
- package/shell-dist/assets/{index-e_Mp2mb5.js → index-CImwskAz.js} +24 -11
- package/shell-dist/assets/runtime.js +5 -5
- package/shell-dist/index.html +3 -3
- package/shell-dist/versions.json +3 -3
- package/src/__tests__/layout.test.ts +30 -1
- package/src/__tests__/templates-schema-columns.test.ts +99 -0
- package/src/__tests__/vendor-devkit.test.ts +87 -0
- package/src/alias-paths.ts +11 -12
- package/src/build/backend.ts +131 -0
- package/src/build/module-build.ts +364 -0
- package/src/build/module-def.ts +381 -0
- package/src/build/site-merge.ts +33 -0
- package/src/build.ts +16 -885
- package/src/builtin.ts +10 -3
- package/src/bundle.ts +61 -0
- package/src/cli.ts +4 -1
- package/src/contract/__tests__/emit-client.test.ts +4 -4
- package/src/contract/__tests__/market-client.integration.test.ts +2 -2
- package/src/contract/__tests__/run-api.test.ts +2 -2
- package/src/contract/check.ts +6 -2
- package/src/contract/emit-client.ts +10 -3
- package/src/contract/run.ts +10 -2
- package/src/init.ts +31 -46
- package/src/layout.ts +72 -16
- package/src/lifecycle/__tests__/bundle-summary.test.ts +106 -0
- package/src/lifecycle/__tests__/bundle.test.ts +6 -0
- package/src/lifecycle/__tests__/manifest-contract.test.ts +2 -2
- package/src/market/__tests__/bootstrap.test.ts +1 -1
- package/src/site.ts +1 -1
- package/src/vendor.ts +34 -0
- package/templates/README.md +30 -20
- package/templates/init.include.yaml +19 -11
- package/templates/openapi.json +102 -86
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/installer.ts +8 -3
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/register.ts +53 -0
- package/templates/src/{_platform/api → app/api/_platform}/_shared/service/domain/roles.ts +4 -1
- package/templates/src/{_platform/api → app/api/_platform}/_shared/service/domain/solution-perms.ts +7 -3
- package/templates/src/{_platform/api → app/api/_platform}/_shared/service/domain/users.ts +27 -0
- package/templates/src/{_platform/api → app/api/_platform}/_shared/service/infra/oplog.ts +4 -2
- package/templates/src/app/api/_platform/migrations/0017__users_employee_no.mysql.sql +7 -0
- package/templates/src/app/api/_platform/migrations/0017__users_employee_no.pg.sql +4 -0
- package/templates/src/app/api/_platform/migrations/0017__users_employee_no.sql +8 -0
- package/templates/src/app/api/_platform/migrations/0018__sys_role_title_key.mysql.sql +3 -0
- package/templates/src/app/api/_platform/migrations/0018__sys_role_title_key.pg.sql +3 -0
- package/templates/src/app/api/_platform/migrations/0018__sys_role_title_key.sql +8 -0
- package/templates/src/{_platform/api → app/api/_platform}/schema.yaml +7 -0
- package/templates/src/{auth/api → app/api/auth}/_shared/wecom/replay.ts +9 -3
- package/templates/src/{auth/api → app/api/auth}/_shared/wecom/tenant-admin.ts +18 -27
- package/templates/src/{system/api → app/api/system}/oplog/api.ts +5 -3
- package/templates/src/{system/api → app/api/system}/roles/api.ts +2 -1
- package/templates/src/{_platform/web/__client/api.ts → app/web/_platform/__client/index.ts} +5 -2
- package/templates/src/{auth/web/__client/api.ts → app/web/auth/__client/index.ts} +5 -2
- package/templates/src/app/web/notification/pages/center/index.tsx +1 -1
- package/templates/src/app/web/notification/routes.ts +1 -1
- package/templates/src/app/web/personal-center/pages/my-profile/index.tsx +1 -1
- package/templates/src/app/web/personal-center/routes.ts +1 -1
- package/templates/src/app/web/system/__client/api.schemas.ts +2 -0
- package/templates/src/app/web/system/locales/en-US.json +2 -3
- package/templates/src/app/web/system/locales/zh-CN.json +2 -3
- package/templates/src/app/web/system/pages/departments/index.tsx +2 -2
- package/templates/src/app/web/system/pages/login-methods/index.tsx +1 -1
- package/templates/src/app/web/system/pages/oplog/index.tsx +44 -19
- package/templates/src/app/web/system/pages/roles/index.tsx +12 -4
- package/templates/src/app/web/system/pages/roles/visible-roles.ts +14 -0
- package/templates/src/app/web/system/pages/settings/index.tsx +2 -2
- package/templates/src/app/web/system/pages/users/can-manage.ts +21 -0
- package/templates/src/app/web/system/pages/users/index.tsx +25 -17
- package/templates/src/app/web/system/pages/users/roles.tsx +1 -1
- package/templates/src/app/web/system/routes.ts +1 -1
- package/templates/src/{web/web/__client/api.ts → app/web/web/__client/index.ts} +5 -2
- package/templates/src/oj-market/web/api/defaultClient.ts +1 -1
- package/templates/tests/auth-ldap.spec.ts +2 -2
- package/templates/tests/auth-session.spec.ts +3 -3
- package/templates/tests/auth-throttle.spec.ts +1 -1
- package/templates/tests/fixture.ts +6 -4
- package/templates/tests/guard.spec.ts +1 -1
- package/templates/tests/lifecycle/atomic-state.spec.ts +3 -3
- package/templates/tests/lifecycle/bootstrap.spec.ts +3 -3
- package/templates/tests/lifecycle/deploy-smoke.spec.ts +8 -8
- package/templates/tests/lifecycle/installer.spec.ts +10 -10
- package/templates/tests/lifecycle/market-api.spec.ts +14 -14
- package/templates/tests/lifecycle/migrate.spec.ts +6 -6
- package/templates/tests/lifecycle/preflight.spec.ts +3 -3
- package/templates/tests/lifecycle/register.spec.ts +1 -1
- package/templates/tests/lifecycle/role-title-translate.spec.ts +171 -0
- package/templates/tests/lifecycle/semver.spec.ts +1 -1
- package/templates/tests/lifecycle/sha384.spec.ts +1 -1
- package/templates/tests/lifecycle/solutions-api.spec.ts +1 -1
- package/templates/tests/lifecycle/source-seq.spec.ts +1 -1
- package/templates/tests/lifecycle/steps-fs.spec.ts +9 -9
- package/templates/tests/lifecycle/text-edit.spec.ts +1 -1
- package/templates/tests/lifecycle/tgz-guard.spec.ts +2 -2
- package/templates/tests/lifecycle/trust.spec.ts +5 -5
- package/templates/tests/lifecycle/uninstall.spec.ts +7 -7
- package/templates/tests/lifecycle/verify-checks.spec.ts +5 -5
- package/templates/tests/lifecycle/verify-report.spec.ts +4 -4
- package/templates/tests/org-departments.spec.ts +10 -6
- package/templates/tests/org-read.spec.ts +7 -7
- package/templates/tests/query-utils.spec.ts +1 -1
- package/templates/tests/rbac-audit.spec.ts +1 -1
- package/templates/tests/rbac-contacts.spec.ts +2 -2
- package/templates/tests/rbac-guard.spec.ts +1 -1
- package/templates/tests/rbac-roles.spec.ts +19 -2
- package/templates/tests/rbac-seed.spec.ts +1 -1
- package/templates/tests/rbac-settings.spec.ts +77 -7
- package/templates/tests/rbac-solution-perms.spec.ts +1 -1
- package/templates/tests/rbac-tables.spec.ts +29 -0
- package/templates/tests/rbac-users.spec.ts +55 -3
- package/templates/tests/roles-page.spec.ts +40 -0
- package/templates/tests/seed-role-accounts.spec.ts +1 -1
- package/templates/tests/tenant-access-cache.spec.ts +1 -1
- package/templates/tests/tenant-forgery.spec.ts +5 -5
- package/templates/tests/tenant-isolation.spec.ts +5 -4
- package/templates/tests/username-namespace.spec.ts +3 -3
- package/templates/tests/users-page.spec.ts +39 -0
- package/templates/tests/wecom-admin.spec.ts +6 -6
- package/templates/tests/wecom-client-timeout.spec.ts +1 -1
- package/templates/tests/wecom-connector.spec.ts +9 -9
- package/templates/tests/wecom-corp.spec.ts +9 -9
- package/templates/tests/wecom-crypt.spec.ts +1 -1
- package/templates/tests/wecom-endpoints.spec.ts +2 -2
- package/templates/tests/wecom-landing.spec.ts +1 -1
- package/templates/tests/wecom-org-sync.spec.ts +7 -7
- package/templates/tests/wecom-sync.spec.ts +3 -3
- package/templates/tsconfig.paths.json +11 -11
- package/templates/vitest.config.ts +2 -2
- package/templates/web.config.ts +5 -2
- package/vendor/host-versions.json +3 -3
- package/templates/src/{_platform/api → app/api/_platform}/README.md +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/atomic.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/history.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/limits.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/lock.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/semver.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/sha384.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/source-seq.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/state.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/deploy-web.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/download.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/extract.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/migrate.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/preflight.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/reload.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/smoke.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/steps/verify.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/tasks.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/text-edit.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/tgz-guard.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/trust.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/types.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/uninstall.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/verify-checks.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_lifecycle/verify-report.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_shared/respond.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_shared/service/domain/contacts.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_shared/service/domain/org-read.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_shared/service/domain/org.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_shared/service/domain/settings.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_shared/service/infra/access.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_shared/service/infra/audit.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_shared/service/infra/guard.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_shared/service/infra/query.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_shared/service/infra/rate.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/_shared/site-facade.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/contacts/api.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/contacts/detail/api.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/fixtures/l1-test-user.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/manifest.yaml +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/market/api.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/market/bootstrap.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/market/index-source.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0001__create_users.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0001__create_users.pg.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0001__create_users.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0002__add_users_avatar_base64.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0002__add_users_avatar_base64.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0003__users_source_display_name.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0003__users_source_display_name.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0004__sys_rbac.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0004__sys_rbac.pg.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0004__sys_rbac.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0005__users_must_change.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0005__users_must_change.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0006__users_is_forbidden.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0006__users_is_forbidden.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0007__users_email.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0008__sys_refresh_token.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0008__sys_refresh_token.pg.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0008__sys_refresh_token.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0009__sys_throttle.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0009__sys_throttle.pg.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0009__sys_throttle.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0010__sys_solution_route.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0010__sys_solution_route.pg.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0010__sys_solution_route.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0011__sys_setting_group_label.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0011__sys_setting_group_label.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0012__market_history.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0012__market_history.pg.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0012__market_history.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0013__users_profile.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0014__reg_source_seq.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0014__reg_source_seq.pg.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0014__reg_source_seq.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0015__tenant.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0015__tenant.pg.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0015__tenant.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0016__org.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0016__org.pg.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/migrations/0016__org.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/org/departments/api.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/org/is-member/api.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/org/members/api.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/org/picker/api.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/org/resolve/api.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/org/tree/api.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/org/user/api.ts +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/seed.mysql.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/seed.pg.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/seed.sql +0 -0
- package/templates/src/{_platform/api → app/api/_platform}/solutions/api.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/_shared/ldap-login.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/_shared/ldap.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/_shared/login-throttle.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/_shared/session.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/_shared/wecom/admin.ts +1 -1
- package/templates/src/{auth/api → app/api/auth}/_shared/wecom/client.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/_shared/wecom/config.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/_shared/wecom/contacts.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/_shared/wecom/crypt.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/_shared/wecom/events.ts +1 -1
- package/templates/src/{auth/api → app/api/auth}/_shared/wecom/login.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/_shared/wecom/payload.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/_shared/wecom/store.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/_shared/wecom/sync.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/api.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/ldap-login/api.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/manifest.yaml +0 -0
- package/templates/src/{auth/api → app/api/auth}/migrations/0001__wecom.mysql.sql +0 -0
- package/templates/src/{auth/api → app/api/auth}/migrations/0001__wecom.pg.sql +0 -0
- package/templates/src/{auth/api → app/api/auth}/migrations/0001__wecom.sql +0 -0
- package/templates/src/{auth/api → app/api/auth}/migrations/0002__org_sync.mysql.sql +0 -0
- package/templates/src/{auth/api → app/api/auth}/migrations/0002__org_sync.pg.sql +0 -0
- package/templates/src/{auth/api → app/api/auth}/migrations/0002__org_sync.sql +0 -0
- package/templates/src/{auth/api → app/api/auth}/migrations/0003__credential_kind.mysql.sql +0 -0
- package/templates/src/{auth/api → app/api/auth}/migrations/0003__credential_kind.pg.sql +0 -0
- package/templates/src/{auth/api → app/api/auth}/migrations/0003__credential_kind.sql +0 -0
- package/templates/src/{auth/api → app/api/auth}/schema.yaml +0 -0
- package/templates/src/{auth/api → app/api/auth}/wecom/admin/api.ts +0 -0
- package/templates/src/{auth/api → app/api/auth}/wecom/admin/tenant-admin/api.ts +1 -1
- package/templates/src/{auth/api → app/api/auth}/wecom/admin/tenant-admin/password/api.ts +1 -1
- /package/templates/src/{auth/api → app/api/auth}/wecom/api.ts +0 -0
- /package/templates/src/{auth/api → app/api/auth}/wecom/sync/api.ts +0 -0
- /package/templates/src/{home/api → app/api/home}/line/api.ts +0 -0
- /package/templates/src/{home/api → app/api/home}/manifest.yaml +0 -0
- /package/templates/src/{home/api → app/api/home}/migrations/0001__create_home_tables.sql +0 -0
- /package/templates/src/{home/api → app/api/home}/migrations/0002__tenant.mysql.sql +0 -0
- /package/templates/src/{home/api → app/api/home}/migrations/0002__tenant.sql +0 -0
- /package/templates/src/{home/api → app/api/home}/pie/api.ts +0 -0
- /package/templates/src/{home/api → app/api/home}/schema.yaml +0 -0
- /package/templates/src/{home/api → app/api/home}/seed.sql +0 -0
- /package/templates/src/{notification/api → app/api/notification}/_shared/notify.ts +0 -0
- /package/templates/src/{notification/api → app/api/notification}/api.ts +0 -0
- /package/templates/src/{notification/api → app/api/notification}/del/api.ts +0 -0
- /package/templates/src/{notification/api → app/api/notification}/manifest.yaml +0 -0
- /package/templates/src/{notification/api → app/api/notification}/migrations/0001__create_notifications.sql +0 -0
- /package/templates/src/{notification/api → app/api/notification}/migrations/0002__notifications_user.sql +0 -0
- /package/templates/src/{notification/api → app/api/notification}/migrations/0003__notifications_broadcast.sql +0 -0
- /package/templates/src/{notification/api → app/api/notification}/migrations/0004__notifications_broadcast_hidden.sql +0 -0
- /package/templates/src/{notification/api → app/api/notification}/migrations/0005__tenant.mysql.sql +0 -0
- /package/templates/src/{notification/api → app/api/notification}/migrations/0005__tenant.sql +0 -0
- /package/templates/src/{notification/api → app/api/notification}/schema.yaml +0 -0
- /package/templates/src/{notification/api → app/api/notification}/seed.sql +0 -0
- /package/templates/src/{personal-center/api → app/api/personal-center}/manifest.yaml +0 -0
- /package/templates/src/{personal-center/api → app/api/personal-center}/profile/api.ts +0 -0
- /package/templates/src/{personal-center/api → app/api/personal-center}/upload/api.ts +0 -0
- /package/templates/src/{system/api → app/api/system}/departments/api.ts +0 -0
- /package/templates/src/{system/api → app/api/system}/departments/detach/api.ts +0 -0
- /package/templates/src/{system/api → app/api/system}/departments/members/api.ts +0 -0
- /package/templates/src/{system/api → app/api/system}/departments/move/api.ts +0 -0
- /package/templates/src/{system/api → app/api/system}/login-methods/api.ts +0 -0
- /package/templates/src/{system/api → app/api/system}/manifest.yaml +0 -0
- /package/templates/src/{system/api → app/api/system}/permissions/api.ts +0 -0
- /package/templates/src/{system/api → app/api/system}/roles/bindings/api.ts +0 -0
- /package/templates/src/{system/api → app/api/system}/settings/api.ts +0 -0
- /package/templates/src/{system/api → app/api/system}/users/api.ts +0 -0
- /package/templates/src/{system/api → app/api/system}/users/forbidden/api.ts +0 -0
- /package/templates/src/{system/api → app/api/system}/users/password/api.ts +0 -0
- /package/templates/src/{system/api → app/api/system}/users/profile/api.ts +0 -0
- /package/templates/src/{system/api → app/api/system}/users/roles/api.ts +0 -0
- /package/templates/src/{web/api → app/api/web}/get-async-routes/api.ts +0 -0
- /package/templates/src/{web/api → app/api/web}/hello/api.ts +0 -0
- /package/templates/src/{web/api → app/api/web}/manifest.yaml +0 -0
- /package/templates/src/{web/api → app/api/web}/user-info/api.ts +0 -0
- /package/templates/src/{_platform/web → app/web/_platform}/__client/api.schemas.ts +0 -0
- /package/templates/src/{auth/web → app/web/auth}/__client/api.schemas.ts +0 -0
- /package/templates/src/app/web/home/__client/{api.ts → index.ts} +0 -0
- /package/templates/src/app/web/notification/__client/{api.ts → index.ts} +0 -0
- /package/templates/src/app/web/personal-center/__client/{api.ts → index.ts} +0 -0
- /package/templates/src/app/web/system/__client/{api.ts → index.ts} +0 -0
- /package/templates/src/{web → app/web}/web/__client/api.schemas.ts +0 -0
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
// 前端模块构建(SRP 拆分自 build.ts,2026-11-03,计划 docs/plans/20261103-0930):
|
|
2
|
+
// 逐模块 vite/rolldown 构建 → 产物完整性(sha384 chunks、importmap 说明符校验、
|
|
3
|
+
// CJS require 门禁)→ modules.json 清单。元数据读取见 module-def.ts,
|
|
4
|
+
// 后端编排见 backend.ts。
|
|
5
|
+
import type { Plugin } from "vite";
|
|
6
|
+
import type { ProjectLayout } from "../layout";
|
|
7
|
+
import crypto from "node:crypto";
|
|
8
|
+
import fs from "node:fs";
|
|
9
|
+
import path from "node:path";
|
|
10
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
11
|
+
import { build } from "vite";
|
|
12
|
+
import { parse as parseYaml } from "yaml";
|
|
13
|
+
import { assertModuleList, loadSiteConfig, mergeModuleList, resolveModuleEntry } from "../config";
|
|
14
|
+
import { moduleDir, resolveLayout, scanModules } from "../layout";
|
|
15
|
+
import { isPrebuiltDep, isSharedDep, SHARED_DEPS } from "../shared-deps";
|
|
16
|
+
import { checkSharedVersions, resolveShellDist } from "../versions";
|
|
17
|
+
import { readModuleDefinition } from "./module-def";
|
|
18
|
+
import { mergeShellSite } from "./site-merge";
|
|
19
|
+
|
|
20
|
+
/** modules.json 中的 chunk 条目 */
|
|
21
|
+
export interface ChunkEntry {
|
|
22
|
+
url: string
|
|
23
|
+
integrity: string
|
|
24
|
+
/** 懒加载 chunk:L2 完整性档位下不受保护(设计文档 §4.7) */
|
|
25
|
+
lazy: boolean
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** modules.json 中的模块条目 */
|
|
29
|
+
export interface BuiltModule {
|
|
30
|
+
name: string
|
|
31
|
+
version: string
|
|
32
|
+
enabled: boolean
|
|
33
|
+
dependencies: string[]
|
|
34
|
+
peerRuntime?: string
|
|
35
|
+
entry: string
|
|
36
|
+
integrity: string
|
|
37
|
+
css: string[]
|
|
38
|
+
chunks: ChunkEntry[]
|
|
39
|
+
/**
|
|
40
|
+
* 生效的 web 路由前缀段(契约 C2-14:`web.route_prefix` 缺省 `/<name>`)。
|
|
41
|
+
* 运行期据其改写模块路由根(单根约定下仅根段),缺省 = name 保证零漂移。
|
|
42
|
+
*/
|
|
43
|
+
routePrefix: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 解析模块生效的 web 路由前缀段(R1.1)。
|
|
48
|
+
* module-root:读 `src/<name>/solution.yaml` 的 `web.route_prefix`(契约 C2-14,缺省 `/<name>`);
|
|
49
|
+
* 未配置/非法/非 module-root → 缺省 `name`,与现有路由根(顶层段即 name)逐字节一致。
|
|
50
|
+
*/
|
|
51
|
+
function resolveRoutePrefix(layout: ProjectLayout, name: string): string {
|
|
52
|
+
if (layout.kind !== "module-root")
|
|
53
|
+
return name;
|
|
54
|
+
const solPath = path.join(moduleDir(layout, name), "solution.yaml");
|
|
55
|
+
if (!fs.existsSync(solPath))
|
|
56
|
+
return name;
|
|
57
|
+
try {
|
|
58
|
+
const doc = parseYaml(fs.readFileSync(solPath, "utf-8")) as Record<string, unknown>;
|
|
59
|
+
const web = doc.web;
|
|
60
|
+
if (web && typeof web === "object" && !Array.isArray(web)) {
|
|
61
|
+
const rp = (web as Record<string, unknown>).route_prefix;
|
|
62
|
+
if (typeof rp === "string" && /^\/[a-z][a-z0-9-]{0,63}$/.test(rp))
|
|
63
|
+
return rp.slice(1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// YAML 解析失败 → 缺省,不阻断构建(契约校验会在别处暴露)
|
|
68
|
+
}
|
|
69
|
+
return name;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const ALGORITHM = "sha384";
|
|
73
|
+
|
|
74
|
+
function sha384(file: string): string {
|
|
75
|
+
const digest = crypto.createHash(ALGORITHM).update(fs.readFileSync(file)).digest("base64");
|
|
76
|
+
return `${ALGORITHM}-${digest}`;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function warnUnsharedDeps(projectRoot: string) {
|
|
80
|
+
const pkgPath = path.join(projectRoot, "package.json");
|
|
81
|
+
if (!fs.existsSync(pkgPath))
|
|
82
|
+
return;
|
|
83
|
+
|
|
84
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
85
|
+
const deps = Object.keys(pkg.dependencies ?? {});
|
|
86
|
+
const unshared = deps.filter(dep => !isSharedDep(dep) && !dep.startsWith("@oj-module/"));
|
|
87
|
+
|
|
88
|
+
if (unshared.length) {
|
|
89
|
+
console.warn(
|
|
90
|
+
`[ojm] ⚠️ 以下运行时依赖不在共享表内,会被打进模块产物:${unshared.join(", ")}\n`
|
|
91
|
+
+ " 若它应与宿主共用,请加入 SHARED_DEPS 并在宿主 importmap 中映射(设计文档 C8)",
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** 提取产物文件中的全部裸说明符(排除相对/绝对/# 路径) */
|
|
97
|
+
function collectBareSpecifiers(file: string): string[] {
|
|
98
|
+
const source = fs.readFileSync(file, "utf-8");
|
|
99
|
+
const found = new Set<string>();
|
|
100
|
+
const patterns = [
|
|
101
|
+
/(?:import|export)\s[^'";]*?from\s*["']([^"']+)["']/g, // import/export ... from "x"
|
|
102
|
+
/import\s*["']([^"']+)["']/g, // 副作用导入 import "x"
|
|
103
|
+
/import\(\s*["']([^"']+)["']\s*\)/g, // 动态 import("x")
|
|
104
|
+
];
|
|
105
|
+
for (const pattern of patterns) {
|
|
106
|
+
for (const match of source.matchAll(pattern)) {
|
|
107
|
+
const spec = match[1]!;
|
|
108
|
+
if (!spec.startsWith(".") && !spec.startsWith("/") && !spec.startsWith("#"))
|
|
109
|
+
found.add(spec);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return [...found];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* P7.9 / B11 + C8:构建期扫描模块产物的裸说明符。
|
|
117
|
+
* - 深路径命中共享表前缀但非精确 importmap 键(如 dayjs/plugin/utc):
|
|
118
|
+
* 构建期直接报错——importmap 无前缀通配,浏览器必抛
|
|
119
|
+
* "Failed to resolve module specifier",不能拖到运行期(§4.7 错误契约)。
|
|
120
|
+
* - 表外说明符:C8 构建期告警(按真实 import 分析,不依赖 package.json 字段)。
|
|
121
|
+
*/
|
|
122
|
+
function assertResolvableSpecifiers(
|
|
123
|
+
moduleName: string,
|
|
124
|
+
moduleOutDir: string,
|
|
125
|
+
emitted: Map<string, { type: string, fileName: string }>,
|
|
126
|
+
): void {
|
|
127
|
+
const exactKeys = new Set(SHARED_DEPS.map(dep => dep.specifier));
|
|
128
|
+
const deepPathErrors: string[] = [];
|
|
129
|
+
const unsharedWarnings = new Set<string>();
|
|
130
|
+
|
|
131
|
+
for (const info of emitted.values()) {
|
|
132
|
+
if (info.type !== "chunk")
|
|
133
|
+
continue;
|
|
134
|
+
for (const spec of collectBareSpecifiers(path.join(moduleOutDir, info.fileName))) {
|
|
135
|
+
if (exactKeys.has(spec))
|
|
136
|
+
continue;
|
|
137
|
+
if (isSharedDep(spec)) {
|
|
138
|
+
deepPathErrors.push(` · ${info.fileName} → "${spec}"`);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
unsharedWarnings.add(spec);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (deepPathErrors.length > 0) {
|
|
147
|
+
throw new Error(
|
|
148
|
+
`[ojm] 模块 "${moduleName}" 的产物含 importmap 无法解析的深路径说明符:\n`
|
|
149
|
+
+ `${deepPathErrors.join("\n")}\n`
|
|
150
|
+
+ "共享表只提供精确键(importmap 无前缀通配)。修复建议:改从包根导入"
|
|
151
|
+
+ "(如 dayjs 插件改在宿主侧注册),或联系框架方在 SHARED_DEPS 增补该深路径条目。",
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (unsharedWarnings.size > 0) {
|
|
156
|
+
console.warn(
|
|
157
|
+
`[ojm] ⚠️ 模块 "${moduleName}" import 了共享表外的三方库:${[...unsharedWarnings].join(", ")}\n`
|
|
158
|
+
+ " 它们会被打进模块产物。若应与宿主共用,请加入 SHARED_DEPS(设计文档 C8)",
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* 构建模块工程。
|
|
165
|
+
*
|
|
166
|
+
* 产出(layout.distDir:module-root / new → dist/web;flat → build):
|
|
167
|
+
* <dist>/modules/<name>/<version>/{entry.js, chunk-*.js, *.css}
|
|
168
|
+
* <dist>/modules.json
|
|
169
|
+
*
|
|
170
|
+
* opts.mergeSite 仅 `ojm build` 传 true:清场 + 拷 shell dist 全量;
|
|
171
|
+
* devServer 热重建默认 false,只写模块产物。
|
|
172
|
+
*/
|
|
173
|
+
export async function buildModules(
|
|
174
|
+
projectRoot: string,
|
|
175
|
+
opts: { mergeSite?: boolean } = {},
|
|
176
|
+
): Promise<BuiltModule[]> {
|
|
177
|
+
const layout = resolveLayout(projectRoot);
|
|
178
|
+
const config = await loadSiteConfig(projectRoot);
|
|
179
|
+
// module-root:模块清单由 src/*/web/entry.ts 扫描得出(web.config.ts 仅可选覆盖);
|
|
180
|
+
// 历史布局:仍以 web.config.ts 的 modules 为唯一真源。
|
|
181
|
+
const modules = layout.kind === "module-root"
|
|
182
|
+
? mergeModuleList(scanModules(layout), config.modules, projectRoot)
|
|
183
|
+
: assertModuleList(projectRoot, config.modules);
|
|
184
|
+
const outDir = layout.distDir;
|
|
185
|
+
const baseUrl = config.baseUrl ?? "";
|
|
186
|
+
|
|
187
|
+
if (opts.mergeSite)
|
|
188
|
+
mergeShellSite(outDir, config.siteBase ?? "", config.apiBase ?? "");
|
|
189
|
+
|
|
190
|
+
// P4.5 / C4 / D12:构建前先过版本矩阵门禁,版本漂移直接拒绝
|
|
191
|
+
checkSharedVersions(projectRoot, resolveShellDist());
|
|
192
|
+
|
|
193
|
+
warnUnsharedDeps(projectRoot);
|
|
194
|
+
|
|
195
|
+
const built: BuiltModule[] = [];
|
|
196
|
+
|
|
197
|
+
for (const item of modules) {
|
|
198
|
+
if (item.enabled === false) {
|
|
199
|
+
console.log(`[ojm] 跳过已禁用模块 ${item.name}`);
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const entryFile = resolveModuleEntry(projectRoot, item.entry);
|
|
204
|
+
const definition = await readModuleDefinition(entryFile, projectRoot);
|
|
205
|
+
|
|
206
|
+
if (definition.name !== item.name) {
|
|
207
|
+
throw new Error(
|
|
208
|
+
`模块名不一致:${layout.kind === "module-root" ? `src/${item.name}` : "web.config.ts"} 中为 "${item.name}",entry.ts 中为 "${definition.name}"`,
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const moduleOutDir = path.join(outDir, "modules", definition.name, definition.version);
|
|
213
|
+
const emitted = new Map<string, { fileName: string, type: "chunk" | "asset", isEntry: boolean, isDynamicEntry: boolean }>();
|
|
214
|
+
|
|
215
|
+
const collectChunks: Plugin = {
|
|
216
|
+
name: "ojm:collect-chunks",
|
|
217
|
+
writeBundle(_options, bundle) {
|
|
218
|
+
for (const [fileName, output] of Object.entries(bundle)) {
|
|
219
|
+
emitted.set(fileName, {
|
|
220
|
+
fileName,
|
|
221
|
+
type: output.type,
|
|
222
|
+
isEntry: output.type === "chunk" && output.isEntry,
|
|
223
|
+
isDynamicEntry: output.type === "chunk" && output.isDynamicEntry,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
console.log(`[ojm] 构建 ${definition.name}@${definition.version} ...`);
|
|
230
|
+
|
|
231
|
+
await build({
|
|
232
|
+
root: projectRoot,
|
|
233
|
+
logLevel: "warn",
|
|
234
|
+
// §4.1-④:tailwind 模块管线——模块内 import 的 css 经 @tailwindcss/vite
|
|
235
|
+
// 编译,产物由宿主 <link> 注入(R16);模块无 css 入口时插件不产生任何产物
|
|
236
|
+
plugins: [collectChunks, tailwindcss()],
|
|
237
|
+
// Spike A 坑 2:lib 模式不替换 process.env.NODE_ENV,
|
|
238
|
+
// 浏览器顶层求值会抛 process is not defined(风险 R15)
|
|
239
|
+
define: { "process.env.NODE_ENV": JSON.stringify("production") },
|
|
240
|
+
build: {
|
|
241
|
+
outDir: moduleOutDir,
|
|
242
|
+
emptyOutDir: true,
|
|
243
|
+
sourcemap: false,
|
|
244
|
+
/**
|
|
245
|
+
* 模块产物压缩(2026-09-17 由 `false` 改为 `true`)。
|
|
246
|
+
*
|
|
247
|
+
* 本行原为 `false` **且无注释**(同文件其余设置都带 rationale)—— 经查出自
|
|
248
|
+
* 2026-08-31 的调试提交 `1bf3200`,疑似调试期临时值遗留。实测代价极大:
|
|
249
|
+
* 仅这一项就让 planning 的 gzip 从 186,730 → **75,872(−59.4%)**、
|
|
250
|
+
* workitems 88,351 → **40,113(−54.6%)**(同一份产物只做压缩,未改任何配置)。
|
|
251
|
+
* 背景:曾评估「把重复的生成 client 提成共享资产来省体积」,实测 gzip 净变化
|
|
252
|
+
* 仅 −364 B(生成 client 压缩率 6.8%,且重复内容已被同一 bundle 内的 gzip
|
|
253
|
+
* 滑窗吃掉)⇒ **真正的杠杆是压缩,不是去重**(见 oj-module 台账 T54)。
|
|
254
|
+
*
|
|
255
|
+
* ⚠️ **本项只作用于「模块产物」**,与宿主共享资产无关:`shell-dist/assets/*.js`
|
|
256
|
+
* 由 `shell/scripts/build.mts` 自己的 esbuild 构建,且 `esm-exports.ts` 的
|
|
257
|
+
* 导出面解析**依赖资产顶格输出**(其文件头写明「`minify: false` 下顶层语句
|
|
258
|
+
* 一律顶格输出」)⇒ **不要**顺手把共享资产也压了,那会让导入完整性门禁失效。
|
|
259
|
+
*
|
|
260
|
+
* 代价(已知并接受):生产产物栈不可读(`sourcemap: false` 保持不变 —— 开
|
|
261
|
+
* sourcemap 会额外部署 .map 文件,属另一个决策)。
|
|
262
|
+
*/
|
|
263
|
+
minify: true,
|
|
264
|
+
lib: {
|
|
265
|
+
entry: entryFile,
|
|
266
|
+
formats: ["es"],
|
|
267
|
+
fileName: () => "entry.js",
|
|
268
|
+
},
|
|
269
|
+
rolldownOptions: {
|
|
270
|
+
// 只把共享依赖留给宿主 importmap;
|
|
271
|
+
// 相对路径 / 绝对路径是模块自身代码,需要打包
|
|
272
|
+
external: (id: string) => !id.startsWith(".") && !path.isAbsolute(id) && isPrebuiltDep(id),
|
|
273
|
+
output: {
|
|
274
|
+
// P7.x / e2e:模块产物内联动态 import(lazy 页面、i18n 等),
|
|
275
|
+
// 输出为**单文件**。原因:
|
|
276
|
+
// 1. 拆出的 chunk 只能靠 import.meta.url 在「真实 HTTP 服务」下解析,
|
|
277
|
+
// 任何非 HTTP 加载上下文(e2e harness、离线/原生壳、L2 完整性之外的
|
|
278
|
+
// 加载路径)都会 ECONNREFUSED / 404,导致页面空白;
|
|
279
|
+
// 2. 拆出的 lazy chunk 不受 L2 完整性保护(构建期已告警),是模块化
|
|
280
|
+
// 方案的真实完整性缺陷;单文件后整包受 modulepreload+integrity 覆盖;
|
|
281
|
+
// 3. 单文件模块是微前端模块的通用形态,宿主按真实 URL 一次性加载即可,
|
|
282
|
+
// 无孤儿 chunk 依赖。
|
|
283
|
+
codeSplitting: false as any,
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// 运行期 require 门禁:CJS 依赖 require 了 external 共享包时,rolldown 只留一个浏览器
|
|
290
|
+
// 不可用的 require 桩("Calling `require` for ..."),表现为模块加载即抛错、页面空白。
|
|
291
|
+
// 这类依赖必须移出 bundle 走宿主 importmap(shell 侧有 CJS→ESM 垫片)。
|
|
292
|
+
const builtEntry = path.join(moduleOutDir, "entry.js");
|
|
293
|
+
if (fs.existsSync(builtEntry)) {
|
|
294
|
+
const code = fs.readFileSync(builtEntry, "utf-8");
|
|
295
|
+
if (code.includes("doesn't expose the `require` function")) {
|
|
296
|
+
const specs = [...new Set([...code.matchAll(/ne\("([^"]+)"\)/g)].map(m => m[1]))];
|
|
297
|
+
throw new Error(
|
|
298
|
+
`[ojm] ${definition.name}@${definition.version} 产物含运行期 require(${specs.join(", ") || "?"})`
|
|
299
|
+
+ "——浏览器没有 require,模块加载即抛错。"
|
|
300
|
+
+ "根因:该 CJS 依赖被标为 bundle(自带副本),但它 require 的共享包被 external 了。"
|
|
301
|
+
+ "修复:把它从 SHARED_DEPS 的 bundle 列表移回共享资产,或改用该依赖的 ESM 入口。",
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const prefix = `${baseUrl}/modules/${definition.name}/${definition.version}/`;
|
|
307
|
+
const chunks: ChunkEntry[] = [];
|
|
308
|
+
const css: string[] = [];
|
|
309
|
+
|
|
310
|
+
for (const info of emitted.values()) {
|
|
311
|
+
if (info.type === "asset") {
|
|
312
|
+
if (info.fileName.endsWith(".css"))
|
|
313
|
+
css.push(`${prefix}${info.fileName}`);
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// P7.3:entry 也进 chunks(lazy:false)——宿主 L2 完整性按 chunks[]
|
|
318
|
+
// 注入 modulepreload+integrity,此前 entry 被 isEntry 跳过导致
|
|
319
|
+
// 顶层 integrity 成为死字段(评审 S3:入口恰好不受保护)
|
|
320
|
+
chunks.push({
|
|
321
|
+
url: `${prefix}${info.fileName}`,
|
|
322
|
+
integrity: sha384(path.join(moduleOutDir, info.fileName)),
|
|
323
|
+
lazy: info.isEntry ? false : info.isDynamicEntry,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// §4.6:lazy chunk 不受 L2 完整性保护,构建期必须显式提示
|
|
328
|
+
const lazyChunks = chunks.filter(c => c.lazy);
|
|
329
|
+
if (lazyChunks.length > 0) {
|
|
330
|
+
console.warn(
|
|
331
|
+
`[ojm] 模块 "${definition.name}" 含 ${lazyChunks.length} 个 lazy chunk,`
|
|
332
|
+
+ "它们在 L2 完整性档位下不受保护(§4.7 D7):\n"
|
|
333
|
+
+ `${lazyChunks.map(c => ` · ${c.url}`).join("\n")}\n`
|
|
334
|
+
+ "若这些 chunk 也要求完整性,请升级到 L3(Service Worker)或使用逃生通道(§4.7)。",
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// P7.9 / B11:扫描产物中的裸说明符,构建期拦截 importmap 无法解析的
|
|
339
|
+
// 深路径(如 dayjs/plugin/utc——isSharedDep 前缀命中但 importmap 只有
|
|
340
|
+
// 精确键,浏览器必抛 Failed to resolve module specifier);
|
|
341
|
+
// 顺带以真实 import 分析落地 C8 表外依赖告警(不再只扫 package.json 字段)
|
|
342
|
+
assertResolvableSpecifiers(definition.name, moduleOutDir, emitted);
|
|
343
|
+
|
|
344
|
+
built.push({
|
|
345
|
+
name: definition.name,
|
|
346
|
+
version: definition.version,
|
|
347
|
+
enabled: true,
|
|
348
|
+
dependencies: definition.config?.dependencies ?? [],
|
|
349
|
+
peerRuntime: definition.peerRuntime,
|
|
350
|
+
entry: `${prefix}entry.js`,
|
|
351
|
+
integrity: sha384(path.join(moduleOutDir, "entry.js")),
|
|
352
|
+
css,
|
|
353
|
+
chunks,
|
|
354
|
+
routePrefix: resolveRoutePrefix(layout, definition.name),
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const manifestPath = path.join(outDir, "modules.json");
|
|
359
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
360
|
+
fs.writeFileSync(manifestPath, `${JSON.stringify(built, null, 2)}\n`);
|
|
361
|
+
console.log(`[ojm] 清单已生成 → ${manifestPath}`);
|
|
362
|
+
|
|
363
|
+
return built;
|
|
364
|
+
}
|