@oj-module/cli 0.2.17 → 0.2.20
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 +4 -4
- package/devkit/SKILL.md +41 -37
- package/devkit/framework-dev.md +6 -5
- package/devkit/manual.md +260 -162
- package/devkit/menu-rules.md +3 -4
- package/devkit/module-dev-and-cdn-playground.md +31 -22
- package/devkit/sql-builder-missing-capabilities-pr.md +11 -6
- package/package.json +2 -2
- package/shell-dist/assets/runtime.js +2 -2
- package/shell-dist/index.html +2 -2
- package/shell-dist/versions.json +3 -3
- package/src/__tests__/build-backend.test.ts +54 -0
- package/src/__tests__/layout.test.ts +176 -0
- package/src/__tests__/module-list.test.ts +66 -0
- package/src/__tests__/oj-caps.test.ts +114 -0
- package/src/alias-paths.ts +102 -0
- package/src/build.ts +41 -9
- package/src/bundle.ts +25 -13
- package/src/config.ts +82 -9
- package/src/contract/__tests__/market-client.integration.test.ts +2 -2
- package/src/contract/check.ts +56 -28
- package/src/contract/emit-stub.ts +21 -9
- package/src/contract/handler-scan.ts +19 -10
- package/src/contract/run.ts +14 -4
- package/src/dev.ts +22 -7
- package/src/index.ts +1 -1
- package/src/info.ts +20 -3
- package/src/init.ts +91 -21
- package/src/layout.ts +282 -24
- package/src/lifecycle/__tests__/bundle.test.ts +16 -1
- package/src/lifecycle/__tests__/manifest-contract.test.ts +17 -58
- package/src/manifest-contract.ts +2 -25
- package/src/market/__tests__/bootstrap.test.ts +17 -9
- package/src/market/bootstrap.ts +30 -17
- package/src/oj-caps.ts +133 -0
- package/src/oj.ts +27 -4
- package/src/preview-config.ts +1 -1
- package/src/preview.ts +2 -1
- package/src/site.ts +2 -2
- package/src/usage.ts +6 -6
- package/src/vendor.ts +5 -1
- package/templates/{api/config.yaml → config.yaml} +13 -8
- package/templates/global.d.ts +7 -6
- package/templates/init.include.yaml +41 -36
- package/templates/package.json +1 -1
- package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/installer.ts +4 -0
- package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/smoke.ts +21 -2
- package/templates/{api/src/_platform → src/_platform/api}/market/api.ts +25 -15
- package/templates/{api/src/_platform → src/_platform/api}/solutions/api.ts +7 -3
- package/templates/{api/src/auth → src/auth/api}/_shared/login-throttle.ts +2 -2
- package/templates/{api/src/auth → src/auth/api}/_shared/session.ts +2 -2
- package/templates/{api/src/auth → src/auth/api}/api.ts +1 -1
- package/templates/{api/src/auth → src/auth/api}/ldap-login/api.ts +1 -1
- package/templates/src/auth/api/manifest.yaml +6 -0
- package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/InstallDialog.test.tsx +53 -1
- package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/marketClient.fake.ts +6 -0
- package/templates/{web/src/oj-market → src/oj-market/web}/api/client.ts +5 -0
- package/templates/{web/src/oj-market → src/oj-market/web}/api/defaultClient.ts +7 -1
- package/templates/{web/src/oj-market → src/oj-market/web}/components/InstallDialog.tsx +80 -5
- package/templates/{web/src/oj-market → src/oj-market/web}/hooks/useMarket.ts +6 -1
- package/templates/{web/src/oj-market → src/oj-market/web}/locales/en-US.json +10 -1
- package/templates/{web/src/oj-market → src/oj-market/web}/locales/zh-CN.json +10 -1
- package/templates/{web/src/oj-market → src/oj-market/web}/types.ts +15 -2
- package/templates/{api/src/system → src/system/api}/login-methods/api.ts +2 -2
- package/templates/src/system/api/manifest.yaml +6 -0
- package/templates/{api/src/system → src/system/api}/oplog/api.ts +4 -4
- package/templates/{api/src/system → src/system/api}/permissions/api.ts +3 -3
- package/templates/{api/src/system → src/system/api}/roles/api.ts +3 -3
- package/templates/{api/src/system → src/system/api}/roles/bindings/api.ts +3 -3
- package/templates/{api/src/system → src/system/api}/settings/api.ts +3 -3
- package/templates/{api/src/system → src/system/api}/users/api.ts +3 -3
- package/templates/{api/src/system → src/system/api}/users/forbidden/api.ts +3 -3
- package/templates/{api/src/system → src/system/api}/users/password/api.ts +3 -3
- package/templates/{api/src/system → src/system/api}/users/roles/api.ts +3 -3
- package/templates/src/tsconfig.json +16 -0
- package/templates/{api/tests → tests}/auth-ldap.spec.ts +2 -2
- package/templates/{api/tests → tests}/auth-session.spec.ts +3 -3
- package/templates/{api/tests → tests}/auth-throttle.spec.ts +1 -1
- package/templates/tests/fixture.ts +434 -0
- package/templates/{api/tests → tests}/guard.spec.ts +1 -1
- package/templates/{api/tests → tests}/lifecycle/atomic-state.spec.ts +3 -3
- package/templates/{api/tests → tests}/lifecycle/bootstrap.spec.ts +8 -4
- package/templates/{api/tests → tests}/lifecycle/deploy-smoke.spec.ts +31 -8
- package/templates/{api/tests → tests}/lifecycle/installer.spec.ts +15 -15
- package/templates/{api/tests → tests}/lifecycle/market-api.spec.ts +30 -29
- package/templates/{api/tests → tests}/lifecycle/migrate.spec.ts +6 -6
- package/templates/{api/tests → tests}/lifecycle/preflight.spec.ts +4 -4
- package/templates/{api/tests → tests}/lifecycle/register.spec.ts +1 -1
- package/templates/{api/tests → tests}/lifecycle/semver.spec.ts +1 -1
- package/templates/{api/tests → tests}/lifecycle/sha384.spec.ts +1 -1
- package/templates/{api/tests → tests}/lifecycle/sig-fixtures.spec.ts +1 -1
- package/templates/{api/tests → tests}/lifecycle/solutions-api.spec.ts +1 -1
- package/templates/{api/tests → tests}/lifecycle/steps-fs.spec.ts +12 -12
- package/templates/{api/tests → tests}/lifecycle/text-edit.spec.ts +1 -1
- package/templates/{api/tests → tests}/lifecycle/tgz-guard.spec.ts +1 -1
- package/templates/{api/tests → tests}/lifecycle/trust.spec.ts +5 -5
- package/templates/{api/tests → tests}/lifecycle/uninstall.spec.ts +7 -7
- package/templates/{api/tests → tests}/lifecycle/verify-checks.spec.ts +9 -6
- package/templates/{api/tests → tests}/lifecycle/verify-report.spec.ts +7 -5
- package/templates/{api/tests → tests}/query-utils.spec.ts +1 -1
- package/templates/{api/tests → tests}/rbac-audit.spec.ts +1 -1
- package/templates/{api/tests → tests}/rbac-contacts.spec.ts +2 -2
- package/templates/{api/tests → tests}/rbac-guard.spec.ts +1 -1
- package/templates/{api/tests → tests}/rbac-roles.spec.ts +2 -2
- package/templates/{api/tests → tests}/rbac-seed.spec.ts +1 -1
- package/templates/{api/tests → tests}/rbac-settings.spec.ts +2 -2
- package/templates/{api/tests → tests}/rbac-solution-perms.spec.ts +1 -1
- package/templates/{api/tests → tests}/rbac-users.spec.ts +3 -3
- package/templates/tsconfig.json +5 -1
- package/templates/tsconfig.paths.json +19 -0
- package/templates/types/oj-modules.d.ts +17 -0
- package/templates/vitest.config.ts +22 -0
- package/templates/web.config.ts +23 -13
- package/vendor/host-versions.json +3 -3
- package/templates/api/src/auth/manifest.yaml +0 -5
- package/templates/api/src/system/manifest.yaml +0 -5
- package/templates/api/tests/fixture.ts +0 -58
- package/templates/api/tsconfig.json +0 -8
- package/templates/api/vitest.config.ts +0 -12
- package/templates/logs/task-events.jsonl +0 -0
- /package/templates/{api/.ojm-api-exempt.json → .ojm-api-exempt.json} +0 -0
- /package/templates/{api/seed.mysql.sql → seed.mysql.sql} +0 -0
- /package/templates/{api/seed.pg.sql → seed.pg.sql} +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/README.md +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/atomic.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/history.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/lock.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/semver.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/sha384.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/state.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/deploy-web.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/download.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/extract.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/migrate.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/preflight.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/register.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/reload.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/steps/verify.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/tasks.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/text-edit.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/tgz-guard.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/trust.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/types.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/uninstall.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/verify-checks.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_lifecycle/verify-report.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_shared/respond.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/contacts.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/roles.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/settings.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/solution-perms.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/domain/users.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/access.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/audit.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/guard.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/oplog.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/query.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_shared/service/infra/rate.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/_shared/site-facade.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/contacts/api.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/contacts/detail/api.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/fixtures/l1-test-user.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/manifest.yaml +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/market/bootstrap.ts +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0001__create_users.mysql.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0001__create_users.pg.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0001__create_users.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0002__add_users_avatar_base64.mysql.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0002__add_users_avatar_base64.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0003__users_source_display_name.mysql.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0003__users_source_display_name.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0004__sys_rbac.mysql.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0004__sys_rbac.pg.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0004__sys_rbac.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0005__users_must_change.mysql.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0005__users_must_change.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0006__users_is_forbidden.mysql.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0006__users_is_forbidden.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0007__users_email.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0008__sys_refresh_token.mysql.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0008__sys_refresh_token.pg.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0008__sys_refresh_token.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0009__sys_throttle.mysql.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0009__sys_throttle.pg.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0009__sys_throttle.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0010__sys_solution_route.mysql.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0010__sys_solution_route.pg.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0010__sys_solution_route.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0011__sys_setting_group_label.mysql.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0011__sys_setting_group_label.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0012__market_history.mysql.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0012__market_history.pg.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0012__market_history.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/migrations/0013__users_profile.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/schema.yaml +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/seed.mysql.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/seed.pg.sql +0 -0
- /package/templates/{api/src/_platform → src/_platform/api}/seed.sql +0 -0
- /package/templates/{web/src/_platform → src/_platform/web}/__client/api.schemas.ts +0 -0
- /package/templates/{web/src/_platform → src/_platform/web}/__client/api.ts +0 -0
- /package/templates/{web/src/about → src/about/web}/entry.ts +0 -0
- /package/templates/{web/src/about → src/about/web}/locales/en-US.json +0 -0
- /package/templates/{web/src/about → src/about/web}/locales/zh-CN.json +0 -0
- /package/templates/{web/src/about → src/about/web}/pages/constants.ts +0 -0
- /package/templates/{web/src/about → src/about/web}/pages/index.tsx +0 -0
- /package/templates/{web/src/access → src/access/web}/entry.ts +0 -0
- /package/templates/{web/src/access → src/access/web}/locales/en-US.json +0 -0
- /package/templates/{web/src/access → src/access/web}/locales/zh-CN.json +0 -0
- /package/templates/{web/src/access → src/access/web}/pages/access-mode/index.tsx +0 -0
- /package/templates/{web/src/access → src/access/web}/pages/admin-visible/index.tsx +0 -0
- /package/templates/{web/src/access → src/access/web}/pages/button-control/index.tsx +0 -0
- /package/templates/{web/src/access → src/access/web}/pages/common-visible/index.tsx +0 -0
- /package/templates/{web/src/access → src/access/web}/pages/page-control/index.tsx +0 -0
- /package/templates/{api/src/auth → src/auth/api}/_shared/ldap-login.ts +0 -0
- /package/templates/{api/src/auth → src/auth/api}/_shared/ldap.ts +0 -0
- /package/templates/{web/src/auth → src/auth/web}/__client/api.schemas.ts +0 -0
- /package/templates/{web/src/auth → src/auth/web}/__client/api.ts +0 -0
- /package/templates/{api/src/demo → src/demo/api}/manifest.yaml +0 -0
- /package/templates/{api/src/demo → src/demo/api}/migrations/0001__create_todos.sql +0 -0
- /package/templates/{api/src/demo → src/demo/api}/schema.yaml +0 -0
- /package/templates/{api/src/demo → src/demo/api}/seed.sql +0 -0
- /package/templates/{api/src/demo → src/demo/api}/todos/api.ts +0 -0
- /package/templates/{web/src/demo → src/demo/web}/__client/api.schemas.ts +0 -0
- /package/templates/{web/src/demo → src/demo/web}/__client/api.ts +0 -0
- /package/templates/{web/src/demo → src/demo/web}/entry.ts +0 -0
- /package/templates/{web/src/demo → src/demo/web}/locales/en-US.json +0 -0
- /package/templates/{web/src/demo → src/demo/web}/locales/zh-CN.json +0 -0
- /package/templates/{web/src/demo → src/demo/web}/pages/index.tsx +0 -0
- /package/templates/{web/src/exception → src/exception/web}/entry.ts +0 -0
- /package/templates/{web/src/exception → src/exception/web}/locales/en-US.json +0 -0
- /package/templates/{web/src/exception → src/exception/web}/locales/zh-CN.json +0 -0
- /package/templates/{web/src/exception → src/exception/web}/pages/403/index.tsx +0 -0
- /package/templates/{web/src/exception → src/exception/web}/pages/404/index.tsx +0 -0
- /package/templates/{web/src/exception → src/exception/web}/pages/500/index.tsx +0 -0
- /package/templates/{web/src/exception → src/exception/web}/pages/unknown-component/index.tsx +0 -0
- /package/templates/{api/src/home → src/home/api}/line/api.ts +0 -0
- /package/templates/{api/src/home → src/home/api}/manifest.yaml +0 -0
- /package/templates/{api/src/home → src/home/api}/migrations/0001__create_home_tables.sql +0 -0
- /package/templates/{api/src/home → src/home/api}/pie/api.ts +0 -0
- /package/templates/{api/src/home → src/home/api}/schema.yaml +0 -0
- /package/templates/{api/src/home → src/home/api}/seed.sql +0 -0
- /package/templates/{web/src/home → src/home/web}/__client/api.schemas.ts +0 -0
- /package/templates/{web/src/home → src/home/web}/__client/api.ts +0 -0
- /package/templates/{web/src/home → src/home/web}/entry.ts +0 -0
- /package/templates/{web/src/home → src/home/web}/locales/en-US.json +0 -0
- /package/templates/{web/src/home → src/home/web}/locales/zh-CN.json +0 -0
- /package/templates/{web/src/home → src/home/web}/pages/components/bar-chart.tsx +0 -0
- /package/templates/{web/src/home → src/home/web}/pages/components/card-list.tsx +0 -0
- /package/templates/{web/src/home → src/home/web}/pages/components/line-chart.tsx +0 -0
- /package/templates/{web/src/home → src/home/web}/pages/components/pie-chart.tsx +0 -0
- /package/templates/{web/src/home → src/home/web}/pages/index.tsx +0 -0
- /package/templates/{web/src/login → src/login/web}/entry.ts +0 -0
- /package/templates/{web/src/login → src/login/web}/locales/en-US.json +0 -0
- /package/templates/{web/src/login → src/login/web}/locales/zh-CN.json +0 -0
- /package/templates/{web/src/login → src/login/web}/pages/change-password.tsx +0 -0
- /package/templates/{web/src/login → src/login/web}/pages/login.tsx +0 -0
- /package/templates/{api/src/notification → src/notification/api}/_shared/notify.ts +0 -0
- /package/templates/{api/src/notification → src/notification/api}/api.ts +0 -0
- /package/templates/{api/src/notification → src/notification/api}/del/api.ts +0 -0
- /package/templates/{api/src/notification → src/notification/api}/manifest.yaml +0 -0
- /package/templates/{api/src/notification → src/notification/api}/migrations/0001__create_notifications.sql +0 -0
- /package/templates/{api/src/notification → src/notification/api}/migrations/0002__notifications_user.sql +0 -0
- /package/templates/{api/src/notification → src/notification/api}/migrations/0003__notifications_broadcast.sql +0 -0
- /package/templates/{api/src/notification → src/notification/api}/migrations/0004__notifications_broadcast_hidden.sql +0 -0
- /package/templates/{api/src/notification → src/notification/api}/schema.yaml +0 -0
- /package/templates/{api/src/notification → src/notification/api}/seed.sql +0 -0
- /package/templates/{web/src/notification → src/notification/web}/__client/api.schemas.ts +0 -0
- /package/templates/{web/src/notification → src/notification/web}/__client/api.ts +0 -0
- /package/templates/{web/src/notification → src/notification/web}/entry.ts +0 -0
- /package/templates/{web/src/notification → src/notification/web}/locales/en-US.json +0 -0
- /package/templates/{web/src/notification → src/notification/web}/locales/zh-CN.json +0 -0
- /package/templates/{web/src/notification → src/notification/web}/pages/center/index.tsx +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/CardGrid.test.tsx +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/HistoryDrawer.test.tsx +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/RollbackDialog.test.tsx +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/UninstallConfirm.test.tsx +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/poll.test.ts +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/render.tsx +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/runtime-stub.ts +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/__tests__/semver.test.ts +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/api/MarketClientProvider.tsx +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/api/context.ts +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/components/CardGrid.tsx +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/components/CardItem.tsx +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/components/DetailDrawer.tsx +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/components/HistoryDrawer.tsx +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/components/RollbackDialog.tsx +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/components/UninstallConfirm.tsx +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/entry.ts +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/pages/MarketApp.tsx +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/utils/poll.ts +0 -0
- /package/templates/{web/src/oj-market → src/oj-market/web}/utils/semver.ts +0 -0
- /package/templates/{web/src/outside → src/outside/web}/entry.ts +0 -0
- /package/templates/{web/src/outside → src/outside/web}/locales/en-US.json +0 -0
- /package/templates/{web/src/outside → src/outside/web}/locales/zh-CN.json +0 -0
- /package/templates/{api/src/personal-center → src/personal-center/api}/manifest.yaml +0 -0
- /package/templates/{api/src/personal-center → src/personal-center/api}/profile/api.ts +0 -0
- /package/templates/{api/src/personal-center → src/personal-center/api}/upload/api.ts +0 -0
- /package/templates/{web/src/personal-center → src/personal-center/web}/__client/api.schemas.ts +0 -0
- /package/templates/{web/src/personal-center → src/personal-center/web}/__client/api.ts +0 -0
- /package/templates/{web/src/personal-center → src/personal-center/web}/entry.ts +0 -0
- /package/templates/{web/src/personal-center → src/personal-center/web}/locales/en-US.json +0 -0
- /package/templates/{web/src/personal-center → src/personal-center/web}/locales/zh-CN.json +0 -0
- /package/templates/{web/src/personal-center → src/personal-center/web}/pages/my-profile/index.tsx +0 -0
- /package/templates/{web/src/route-nest → src/route-nest/web}/entry.ts +0 -0
- /package/templates/{web/src/route-nest → src/route-nest/web}/locales/en-US.json +0 -0
- /package/templates/{web/src/route-nest → src/route-nest/web}/locales/zh-CN.json +0 -0
- /package/templates/{web/src/route-nest → src/route-nest/web}/pages/menu1/menu1-1/index.tsx +0 -0
- /package/templates/{web/src/route-nest → src/route-nest/web}/pages/menu1/menu1-2/index.tsx +0 -0
- /package/templates/{web/src/route-nest → src/route-nest/web}/pages/menu2/index.tsx +0 -0
- /package/templates/{web/src → src}/styles.css +0 -0
- /package/templates/{web/src/system → src/system/web}/__client/api.schemas.ts +0 -0
- /package/templates/{web/src/system → src/system/web}/__client/api.ts +0 -0
- /package/templates/{web/src/system → src/system/web}/entry.ts +0 -0
- /package/templates/{web/src/system → src/system/web}/locales/en-US.json +0 -0
- /package/templates/{web/src/system → src/system/web}/locales/zh-CN.json +0 -0
- /package/templates/{web/src/system → src/system/web}/pages/errors.ts +0 -0
- /package/templates/{web/src/system → src/system/web}/pages/forbidden.tsx +0 -0
- /package/templates/{web/src/system → src/system/web}/pages/login-methods/index.tsx +0 -0
- /package/templates/{web/src/system → src/system/web}/pages/oplog/index.tsx +0 -0
- /package/templates/{web/src/system → src/system/web}/pages/roles/index.tsx +0 -0
- /package/templates/{web/src/system → src/system/web}/pages/settings/index.tsx +0 -0
- /package/templates/{web/src/system → src/system/web}/pages/users/index.tsx +0 -0
- /package/templates/{web/src/system → src/system/web}/pages/users/roles.tsx +0 -0
- /package/templates/{api/src/web → src/web/api}/get-async-routes/api.ts +0 -0
- /package/templates/{api/src/web → src/web/api}/hello/api.ts +0 -0
- /package/templates/{api/src/web → src/web/api}/manifest.yaml +0 -0
- /package/templates/{api/src/web → src/web/api}/user-info/api.ts +0 -0
- /package/templates/{web/src → src/web}/web/__client/api.schemas.ts +0 -0
- /package/templates/{web/src → src/web}/web/__client/api.ts +0 -0
- /package/templates/{api/tests → tests}/l1-builder.test.ts +0 -0
- /package/templates/{api/tests → tests}/rbac-tables.spec.ts +0 -0
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
// 简报 `task/:id` 段参数形态在模板 http 面无先例(contacts/detail?id= 同款 query 惯例),备案于任务报告。
|
|
8
8
|
// 步骤面全 stub 注入(DIP):fetch/exec/reload 不真跑;register/smoke/audit 走真实内存库夹具。
|
|
9
9
|
/* eslint-disable test/prefer-lowercase-title -- 端点动词/路径是验收锚点,保留大写(installer.spec 同约定) */
|
|
10
|
-
import type { FsFace } from "../../src/_platform/_lifecycle/atomic";
|
|
11
|
-
import type { FetchFace } from "../../src/_platform/_lifecycle/steps/download";
|
|
12
|
-
import type { ExecFace } from "../../src/_platform/_lifecycle/steps/extract";
|
|
13
|
-
import type { ReloadFace } from "../../src/_platform/_lifecycle/steps/reload";
|
|
14
|
-
import type { MarketEnv } from "../../src/_platform/market/api";
|
|
10
|
+
import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
|
|
11
|
+
import type { FetchFace } from "../../src/_platform/api/_lifecycle/steps/download";
|
|
12
|
+
import type { ExecFace } from "../../src/_platform/api/_lifecycle/steps/extract";
|
|
13
|
+
import type { ReloadFace } from "../../src/_platform/api/_lifecycle/steps/reload";
|
|
14
|
+
import type { MarketEnv } from "../../src/_platform/api/market/api";
|
|
15
15
|
import { createHash } from "node:crypto";
|
|
16
16
|
import { readFileSync } from "node:fs";
|
|
17
17
|
import * as fsp from "node:fs/promises";
|
|
@@ -20,14 +20,14 @@ import { dirname, join } from "node:path";
|
|
|
20
20
|
import { fileURLToPath } from "node:url";
|
|
21
21
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
22
22
|
import { parse } from "yaml";
|
|
23
|
-
import { defaultTestKey, nodeVerifyEd25519, signedArchiveFor } from "
|
|
24
|
-
import { signIndex } from "
|
|
25
|
-
import { readLock, writeLock } from "../../src/_platform/_lifecycle/lock";
|
|
26
|
-
import { createStateStore } from "../../src/_platform/_lifecycle/state";
|
|
27
|
-
import { getTask, writeTask } from "../../src/_platform/_lifecycle/tasks";
|
|
28
|
-
import { createTrustStore } from "../../src/_platform/_lifecycle/trust";
|
|
29
|
-
import { invalidateAllUsers } from "../../src/_platform/_shared/service/infra/access";
|
|
30
|
-
import { createMarketApi, marketEnv, parseVersionsJson, versionsJsonPathOf } from "../../src/_platform/market/api";
|
|
23
|
+
import { defaultTestKey, nodeVerifyEd25519, signedArchiveFor } from "../../../src/lifecycle/__tests__/helpers";
|
|
24
|
+
import { signIndex } from "../../../src/publish";
|
|
25
|
+
import { readLock, writeLock } from "../../src/_platform/api/_lifecycle/lock";
|
|
26
|
+
import { createStateStore } from "../../src/_platform/api/_lifecycle/state";
|
|
27
|
+
import { getTask, writeTask } from "../../src/_platform/api/_lifecycle/tasks";
|
|
28
|
+
import { createTrustStore } from "../../src/_platform/api/_lifecycle/trust";
|
|
29
|
+
import { invalidateAllUsers } from "../../src/_platform/api/_shared/service/infra/access";
|
|
30
|
+
import { createMarketApi, marketEnv, parseVersionsJson, versionsJsonPathOf } from "../../src/_platform/api/market/api";
|
|
31
31
|
import { installDb } from "../fixture";
|
|
32
32
|
|
|
33
33
|
function hexToBytes(hex: string): Uint8Array {
|
|
@@ -274,7 +274,7 @@ describe("权限门(R9:市场编排 superadmin 独占,meta 登录即可)
|
|
|
274
274
|
it("pair-pin:meta apiVersion === _platform/manifest.yaml version(手工镜像漂移防护,P2-9)", async () => {
|
|
275
275
|
// API_VERSION(market/api.ts)与 _platform/manifest.yaml version 为手工同步的双真源;
|
|
276
276
|
// 本测试经 meta 端点间接钉住 API_VERSION,漂移即红(peerPlatform 预检口径失真)。
|
|
277
|
-
const manifestPath = join(dirname(fileURLToPath(import.meta.url)), "../../src/_platform/manifest.yaml");
|
|
277
|
+
const manifestPath = join(dirname(fileURLToPath(import.meta.url)), "../../src/_platform/api/manifest.yaml");
|
|
278
278
|
const manifestVersion = (parse(readFileSync(manifestPath, "utf8")) as { version: string }).version;
|
|
279
279
|
const api = createMarketApi(makeEnv());
|
|
280
280
|
g.http = { user: { id: 1 } };
|
|
@@ -503,7 +503,7 @@ describe("POST /market/trust {task_id}(P2-3 TOFU 确认:混淆代理防线
|
|
|
503
503
|
|
|
504
504
|
it("确认成功:任务 needs_trust → 指纹复算一致 → 入信任库 added", async () => {
|
|
505
505
|
const api = createMarketApi(makeEnv());
|
|
506
|
-
const { generateKeyPair } = await import("
|
|
506
|
+
const { generateKeyPair } = await import("../../../src/lifecycle/keygen");
|
|
507
507
|
const kp = generateKeyPair();
|
|
508
508
|
const id = await seedNeedsTrust("stranger.pub", kp.publicKeyHex);
|
|
509
509
|
g.http = { user: { id: 1 }, body: { task_id: id } };
|
|
@@ -539,7 +539,7 @@ describe("POST /market/trust {task_id}(P2-3 TOFU 确认:混淆代理防线
|
|
|
539
539
|
|
|
540
540
|
it("混淆代理:任务记录指纹与公钥不符 → 409 拒,信任库零变化", async () => {
|
|
541
541
|
const api = createMarketApi(makeEnv());
|
|
542
|
-
const { generateKeyPair } = await import("
|
|
542
|
+
const { generateKeyPair } = await import("../../../src/lifecycle/keygen");
|
|
543
543
|
const kp = generateKeyPair();
|
|
544
544
|
const id = await seedNeedsTrust("stranger.pub", kp.publicKeyHex, "f".repeat(64)); // 指纹造假
|
|
545
545
|
g.http = { user: { id: 1 }, body: { task_id: id } };
|
|
@@ -552,7 +552,7 @@ describe("POST /market/trust {task_id}(P2-3 TOFU 确认:混淆代理防线
|
|
|
552
552
|
|
|
553
553
|
it("撞绑定:key_id 已绑其他公钥 → 409 trust_bound_mismatch,库内不动", async () => {
|
|
554
554
|
const api = createMarketApi(makeEnv());
|
|
555
|
-
const { generateKeyPair } = await import("
|
|
555
|
+
const { generateKeyPair } = await import("../../../src/lifecycle/keygen");
|
|
556
556
|
const kp = generateKeyPair();
|
|
557
557
|
const id = await seedNeedsTrust("test.publisher", kp.publicKeyHex); // 已播种的 key_id
|
|
558
558
|
g.http = { user: { id: 1 }, body: { task_id: id } };
|
|
@@ -815,10 +815,11 @@ describe("P3-7 索引签名校验(G4 fail-closed:署名相符采用 / 篡改
|
|
|
815
815
|
});
|
|
816
816
|
|
|
817
817
|
describe("hostVersions 缺省接线(B-11:C2-09 比对真源 = <dist>/versions.json,ojm 宿主构建产物)", () => {
|
|
818
|
-
it("versionsJsonPathOf 布局推导:
|
|
819
|
-
expect(versionsJsonPathOf("dist
|
|
820
|
-
expect(versionsJsonPathOf("/site/dist
|
|
821
|
-
expect(versionsJsonPathOf("
|
|
818
|
+
it("versionsJsonPathOf 布局推导:release 根下的 versions.json(相对/绝对/尾斜杠同构)", () => {
|
|
819
|
+
expect(versionsJsonPathOf("api/dist")).toBe("api/dist/versions.json");
|
|
820
|
+
expect(versionsJsonPathOf("/site/api/dist")).toBe("/site/api/dist/versions.json");
|
|
821
|
+
expect(versionsJsonPathOf("api/dist/")).toBe("api/dist/versions.json");
|
|
822
|
+
expect(versionsJsonPathOf("")).toBe("versions.json");
|
|
822
823
|
});
|
|
823
824
|
|
|
824
825
|
it("parseVersionsJson:{packageName: version} 全字符串表 → 解析;任何违约(非对象/值非字符串/坏 JSON)→ undefined(fail-closed 不猜)", () => {
|
|
@@ -829,9 +830,9 @@ describe("hostVersions 缺省接线(B-11:C2-09 比对真源 = <dist>/version
|
|
|
829
830
|
}
|
|
830
831
|
});
|
|
831
832
|
|
|
832
|
-
it("集成:env 未注入 hostVersions +
|
|
833
|
-
await fsp.mkdir(
|
|
834
|
-
await fsp.writeFile(join(
|
|
833
|
+
it("集成:env 未注入 hostVersions + <release 根>/versions.json 在盘 → install 全链 done(C2-09 比对走缺省真源)", async () => {
|
|
834
|
+
await fsp.mkdir(sharedRoot, { recursive: true });
|
|
835
|
+
await fsp.writeFile(join(sharedRoot, "versions.json"), JSON.stringify({ "@oj-module/runtime": "0.1.77" }));
|
|
835
836
|
const env = makeEnv();
|
|
836
837
|
delete (env as Partial<MarketEnv>).hostVersions;
|
|
837
838
|
const api = createMarketApi(env);
|
|
@@ -857,12 +858,12 @@ describe("hostVersions 缺省接线(B-11:C2-09 比对真源 = <dist>/version
|
|
|
857
858
|
});
|
|
858
859
|
|
|
859
860
|
describe("P1-16 接线:marketEnv 生产口径 / exec opts 转发 / operator 通道 / 账本真源 / index 即对账入口", () => {
|
|
860
|
-
it("marketEnv() 缺省 =
|
|
861
|
+
it("marketEnv() 缺省 = 布局 v2 生产口径:版本目录与 versions.json 在 release 根 api/dist,站点 modules 在 web/dist;暂存/任务/sidecar 留 jail 根", () => {
|
|
861
862
|
const env = marketEnv();
|
|
862
|
-
expect(env.sharedRoot).toBe("dist");
|
|
863
|
-
expect(env.siteModulesDir).toBe("dist/modules");
|
|
864
|
-
expect(env.modulesJsonPath).toBe("dist/modules.json");
|
|
865
|
-
expect(versionsJsonPathOf(env.
|
|
863
|
+
expect(env.sharedRoot).toBe("api/dist");
|
|
864
|
+
expect(env.siteModulesDir).toBe("web/dist/modules");
|
|
865
|
+
expect(env.modulesJsonPath).toBe("web/dist/modules.json");
|
|
866
|
+
expect(versionsJsonPathOf(env.sharedRoot)).toBe("api/dist/versions.json");
|
|
866
867
|
expect(env.staging).toBe("modules/.staging");
|
|
867
868
|
expect(env.taskDir).toBe("modules/.install-tasks");
|
|
868
869
|
expect(env.statePath).toBe("modules/.solutions/state.yaml");
|
|
@@ -7,16 +7,16 @@
|
|
|
7
7
|
// rollbackGuard 纯函数:目标产物 max seq < 账本 head = 降版部署,禁止(OJ-9/M003 同源红线);
|
|
8
8
|
// seq 为数值非版本号,直接数值比较(semver.ts 不适用)。
|
|
9
9
|
// exec/fs 面注入 stub(同 steps-fs 范式),不真跑 oj/sqlite。
|
|
10
|
-
import type { FsFace } from "../../src/_platform/_lifecycle/atomic";
|
|
11
|
-
import type { StateStore } from "../../src/_platform/_lifecycle/state";
|
|
12
|
-
import type { ExecFace } from "../../src/_platform/_lifecycle/steps/extract";
|
|
13
|
-
import type { MigrateContext } from "../../src/_platform/_lifecycle/steps/migrate";
|
|
10
|
+
import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
|
|
11
|
+
import type { StateStore } from "../../src/_platform/api/_lifecycle/state";
|
|
12
|
+
import type { ExecFace } from "../../src/_platform/api/_lifecycle/steps/extract";
|
|
13
|
+
import type { MigrateContext } from "../../src/_platform/api/_lifecycle/steps/migrate";
|
|
14
14
|
import * as fsp from "node:fs/promises";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { join } from "node:path";
|
|
17
17
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
18
|
-
import { parseLock } from "../../src/_platform/_lifecycle/lock";
|
|
19
|
-
import { buildMigrateCmd, maxAppliedSeq, migrate, migrateSvcDirOf, parseMigrateOutput, rollbackGuard } from "../../src/_platform/_lifecycle/steps/migrate";
|
|
18
|
+
import { parseLock } from "../../src/_platform/api/_lifecycle/lock";
|
|
19
|
+
import { buildMigrateCmd, maxAppliedSeq, migrate, migrateSvcDirOf, parseMigrateOutput, rollbackGuard } from "../../src/_platform/api/_lifecycle/steps/migrate";
|
|
20
20
|
|
|
21
21
|
const g = globalThis as any;
|
|
22
22
|
const DB_BYTES = new TextEncoder().encode("sqlite-header-bytes\n");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { SolutionState, StateStore } from "../../src/_platform/_lifecycle/state";
|
|
2
|
-
import type { InstallContext } from "../../src/_platform/_lifecycle/steps/preflight";
|
|
1
|
+
import type { SolutionState, StateStore } from "../../src/_platform/api/_lifecycle/state";
|
|
2
|
+
import type { InstallContext } from "../../src/_platform/api/_lifecycle/steps/preflight";
|
|
3
3
|
// BDD:安装预检规则引擎(P1-5,R7/R8/R9/R24,十阶段状态机 stage 1)。
|
|
4
4
|
// 规则真源:docs/prd/solution/202610171254-lifecycle-manifest-contract.md(C2-01~33 安装列);
|
|
5
5
|
// 期望真源:packages/cli/src/lifecycle/__tests__/fixtures/(fixture-valid 零违规、fixture-invalid 七码齐报)。
|
|
@@ -12,9 +12,9 @@ import { fileURLToPath } from "node:url";
|
|
|
12
12
|
|
|
13
13
|
import { describe, expect, it } from "vitest";
|
|
14
14
|
import { parse } from "yaml";
|
|
15
|
-
import { preflight } from "../../src/_platform/_lifecycle/steps/preflight";
|
|
15
|
+
import { preflight } from "../../src/_platform/api/_lifecycle/steps/preflight";
|
|
16
16
|
|
|
17
|
-
const FIXTURES = join(dirname(fileURLToPath(import.meta.url)), "
|
|
17
|
+
const FIXTURES = join(dirname(fileURLToPath(import.meta.url)), "../../../src/lifecycle/__tests__/fixtures");
|
|
18
18
|
const VALID = parse(readFileSync(join(FIXTURES, "fixture-valid/manifest.yaml"), "utf8")) as any;
|
|
19
19
|
|
|
20
20
|
/** 宿主 versions.json 假数据(C2-09 真源键:@oj-module/runtime,shell/src/manifest.ts P7.6) */
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
/* eslint-disable test/prefer-lowercase-title -- 任务/AC 编号是验收锚点,保留大写(DB/P1-5) */
|
|
9
9
|
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
|
10
10
|
|
|
11
|
-
import { checkOccupancy, queryAllRegistered, queryRegistered, registerSolution } from "../../src/_platform/_lifecycle/steps/register";
|
|
11
|
+
import { checkOccupancy, queryAllRegistered, queryRegistered, registerSolution } from "../../src/_platform/api/_lifecycle/steps/register";
|
|
12
12
|
import { installDb } from "../fixture";
|
|
13
13
|
|
|
14
14
|
let dbo: ReturnType<typeof installDb>;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// 无 prerelease > 有 prerelease;「1.0」「1.0.0」「1.0.0.0」视为相等(安装器容错口径)。
|
|
4
4
|
import { describe, expect, it } from "vitest";
|
|
5
5
|
|
|
6
|
-
import { compareVersions } from "../../src/_platform/_lifecycle/semver";
|
|
6
|
+
import { compareVersions } from "../../src/_platform/api/_lifecycle/semver";
|
|
7
7
|
|
|
8
8
|
const cases: Array<[a: string, b: string, expected: -1 | 0 | 1]> = [
|
|
9
9
|
// 主版本数值比较(非字典序)
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { Buffer } from "node:buffer";
|
|
5
5
|
import { createHash } from "node:crypto";
|
|
6
6
|
import { describe, expect, it } from "vitest";
|
|
7
|
-
import { bytesToBase64, sha384B64, sha384Bytes } from "../../src/_platform/_lifecycle/sha384";
|
|
7
|
+
import { bytesToBase64, sha384B64, sha384Bytes } from "../../src/_platform/api/_lifecycle/sha384";
|
|
8
8
|
|
|
9
9
|
const hex = (bytes: Uint8Array): string => Array.from(bytes, b => b.toString(16).padStart(2, "0")).join("");
|
|
10
10
|
|
|
@@ -10,7 +10,7 @@ import { fileURLToPath } from "node:url";
|
|
|
10
10
|
import { describe, expect, it } from "vitest";
|
|
11
11
|
|
|
12
12
|
const HERE = path.dirname(fileURLToPath(import.meta.url));
|
|
13
|
-
const SIG_DIR = path.resolve(HERE, "
|
|
13
|
+
const SIG_DIR = path.resolve(HERE, "../../../src/lifecycle/__tests__/fixtures/sig");
|
|
14
14
|
const GEN = path.join(SIG_DIR, "gen-signed-fixtures.mjs");
|
|
15
15
|
|
|
16
16
|
const HEX64 = /^[0-9a-f]{64}$/;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
/* eslint-disable test/prefer-lowercase-title -- 端点路径是验收锚点 */
|
|
6
6
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
7
7
|
|
|
8
|
-
import api from "../../src/_platform/solutions/api";
|
|
8
|
+
import api from "../../src/_platform/api/solutions/api";
|
|
9
9
|
import { installDb } from "../fixture";
|
|
10
10
|
|
|
11
11
|
let dbo: ReturnType<typeof installDb>;
|
|
@@ -6,11 +6,11 @@
|
|
|
6
6
|
// 命令构造为纯函数,argv 逐字断言(与平台 exec 白名单逐字对齐,S1-2 基座);
|
|
7
7
|
// exec/fetch/sha256 面经 ctx 注入 stub,不真跑网络;合法夹具集成用例的 exec stub 落到真实系统 tar
|
|
8
8
|
// (与生产同路径:isolate 不内嵌解压,exec.run 系统 tar)。
|
|
9
|
-
import type { FsFace } from "../../src/_platform/_lifecycle/atomic";
|
|
10
|
-
import type { StateStore } from "../../src/_platform/_lifecycle/state";
|
|
11
|
-
import type { DownloadContext } from "../../src/_platform/_lifecycle/steps/download";
|
|
12
|
-
import type { ExecFace, ExtractContext } from "../../src/_platform/_lifecycle/steps/extract";
|
|
13
|
-
import type { VerifyContext } from "../../src/_platform/_lifecycle/steps/verify";
|
|
9
|
+
import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
|
|
10
|
+
import type { StateStore } from "../../src/_platform/api/_lifecycle/state";
|
|
11
|
+
import type { DownloadContext } from "../../src/_platform/api/_lifecycle/steps/download";
|
|
12
|
+
import type { ExecFace, ExtractContext } from "../../src/_platform/api/_lifecycle/steps/extract";
|
|
13
|
+
import type { VerifyContext } from "../../src/_platform/api/_lifecycle/steps/verify";
|
|
14
14
|
import { execFile as execFileCb } from "node:child_process";
|
|
15
15
|
import { createHash } from "node:crypto";
|
|
16
16
|
import * as fsp from "node:fs/promises";
|
|
@@ -18,11 +18,11 @@ import { tmpdir } from "node:os";
|
|
|
18
18
|
import { join } from "node:path";
|
|
19
19
|
import { promisify } from "node:util";
|
|
20
20
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
21
|
-
import { defaultTestKey, nodeVerifyEd25519, signedArchiveFor } from "
|
|
22
|
-
import { archiveFileOf, download } from "../../src/_platform/_lifecycle/steps/download";
|
|
23
|
-
import { buildExtractCmd, buildListCmd, checkModuleManifest, extract } from "../../src/_platform/_lifecycle/steps/extract";
|
|
24
|
-
import { verify } from "../../src/_platform/_lifecycle/steps/verify";
|
|
25
|
-
import { createTrustStore } from "../../src/_platform/_lifecycle/trust";
|
|
21
|
+
import { defaultTestKey, nodeVerifyEd25519, signedArchiveFor } from "../../../src/lifecycle/__tests__/helpers";
|
|
22
|
+
import { archiveFileOf, download } from "../../src/_platform/api/_lifecycle/steps/download";
|
|
23
|
+
import { buildExtractCmd, buildListCmd, checkModuleManifest, extract } from "../../src/_platform/api/_lifecycle/steps/extract";
|
|
24
|
+
import { verify } from "../../src/_platform/api/_lifecycle/steps/verify";
|
|
25
|
+
import { createTrustStore } from "../../src/_platform/api/_lifecycle/trust";
|
|
26
26
|
|
|
27
27
|
const execFileP = promisify(execFileCb);
|
|
28
28
|
const g = globalThis as any;
|
|
@@ -352,8 +352,8 @@ describe("verify(stage=verifying,C2-29 sha256 fail-closed + P2-3 六码验
|
|
|
352
352
|
it("sig_key:已信任 key_id 但包内公钥与库绑定不一致(首次绑定不可改族)", async () => {
|
|
353
353
|
await seed();
|
|
354
354
|
// 另一把私钥冒用已信任 key_id(trusted key_id + 异公钥 = 绑定不一致)
|
|
355
|
-
const { signedArchiveFor: signFor } = await import("
|
|
356
|
-
const { generateKeyPair } = await import("
|
|
355
|
+
const { signedArchiveFor: signFor } = await import("../../../src/lifecycle/__tests__/helpers");
|
|
356
|
+
const { generateKeyPair } = await import("../../../src/lifecycle/keygen");
|
|
357
357
|
const impostor = signFor(BYTES, "demo-solution", "0.1.0", { keyPair: generateKeyPair(), keyId: "test.publisher" });
|
|
358
358
|
const r = await verify(vfCtx({ manifest: manifest({ ...manifest().archive, signature: impostor.sig }) }));
|
|
359
359
|
expect(r).toMatchObject({ ok: false, code: "sig_key" });
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import * as fsp from "node:fs/promises";
|
|
6
6
|
import { describe, expect, it } from "vitest";
|
|
7
7
|
|
|
8
|
-
import { appendAnonymousPaths, bumpInstallSeq, ensureReloadApi, hasAnchor, insertAnchor } from "../../src/_platform/_lifecycle/text-edit";
|
|
8
|
+
import { appendAnonymousPaths, bumpInstallSeq, ensureReloadApi, hasAnchor, insertAnchor } from "../../src/_platform/api/_lifecycle/text-edit";
|
|
9
9
|
|
|
10
10
|
describe("insertAnchor(R18)", () => {
|
|
11
11
|
it("带注释的 config.yaml 插入后注释/缩进/空行/键序逐字保留", () => {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// 拒绝:绝对路径、任何 `..` 段、l/h 条目、空成员名、反斜杠路径;`./` 前缀相对合法。
|
|
5
5
|
import { describe, expect, it } from "vitest";
|
|
6
6
|
|
|
7
|
-
import { validateTarListing } from "../../src/_platform/_lifecycle/tgz-guard";
|
|
7
|
+
import { validateTarListing } from "../../src/_platform/api/_lifecycle/tgz-guard";
|
|
8
8
|
|
|
9
9
|
describe("validateTarListing(R1)", () => {
|
|
10
10
|
it("正常成员列表通过", () => {
|
|
@@ -2,17 +2,17 @@
|
|
|
2
2
|
// store 层:空库/幂等/首次绑定不可改/多 key/吊销/损坏 fail-closed/.bak 回落/并发读不见半截/审计。
|
|
3
3
|
// 端点层:GET /market/trust、POST /market/trust/key、DELETE /market/trust/key?key_id=(del 动词 + query,system/roles 同款先例)。
|
|
4
4
|
/* eslint-disable test/prefer-lowercase-title -- 端点动词/路径是验收锚点,保留大写(market-api.spec 同约定) */
|
|
5
|
-
import type { FsFace } from "../../src/_platform/_lifecycle/atomic";
|
|
6
|
-
import type { MarketEnv } from "../../src/_platform/market/api";
|
|
5
|
+
import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
|
|
6
|
+
import type { MarketEnv } from "../../src/_platform/api/market/api";
|
|
7
7
|
import { Buffer } from "node:buffer";
|
|
8
8
|
import { createHash } from "node:crypto";
|
|
9
9
|
import * as fsp from "node:fs/promises";
|
|
10
10
|
import { tmpdir } from "node:os";
|
|
11
11
|
import { join } from "node:path";
|
|
12
12
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
13
|
-
import { createTrustStore, isValidKeyId } from "../../src/_platform/_lifecycle/trust";
|
|
14
|
-
import { invalidateAllUsers } from "../../src/_platform/_shared/service/infra/access";
|
|
15
|
-
import { createMarketApi, marketEnv } from "../../src/_platform/market/api";
|
|
13
|
+
import { createTrustStore, isValidKeyId } from "../../src/_platform/api/_lifecycle/trust";
|
|
14
|
+
import { invalidateAllUsers } from "../../src/_platform/api/_shared/service/infra/access";
|
|
15
|
+
import { createMarketApi, marketEnv } from "../../src/_platform/api/market/api";
|
|
16
16
|
import { installDb } from "../fixture";
|
|
17
17
|
|
|
18
18
|
const g = globalThis as any;
|
|
@@ -5,17 +5,17 @@
|
|
|
5
5
|
// 夹具:本仓范式(node:sqlite 真实迁移建表 + 真实 fs 面 g.fs);market_history 表由平台迁移
|
|
6
6
|
// 0012(IF NOT EXISTS)随 installDb 重放建立,守卫语义(表不存在静默跳过)单列一例。
|
|
7
7
|
/* eslint-disable test/prefer-lowercase-title -- 端点动词/路径是验收锚点,保留大写(market-api.spec 同约定) */
|
|
8
|
-
import type { FsFace } from "../../src/_platform/_lifecycle/atomic";
|
|
9
|
-
import type { MarketEnv } from "../../src/_platform/market/api";
|
|
8
|
+
import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
|
|
9
|
+
import type { MarketEnv } from "../../src/_platform/api/market/api";
|
|
10
10
|
import * as fsp from "node:fs/promises";
|
|
11
11
|
import { tmpdir } from "node:os";
|
|
12
12
|
import { dirname, join } from "node:path";
|
|
13
13
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
14
|
-
import { readLock, writeLock } from "../../src/_platform/_lifecycle/lock";
|
|
15
|
-
import { createStateStore } from "../../src/_platform/_lifecycle/state";
|
|
16
|
-
import { collectRetainedTables, moduleTablePrefix } from "../../src/_platform/_lifecycle/uninstall";
|
|
17
|
-
import { invalidateAllUsers } from "../../src/_platform/_shared/service/infra/access";
|
|
18
|
-
import { createMarketApi } from "../../src/_platform/market/api";
|
|
14
|
+
import { readLock, writeLock } from "../../src/_platform/api/_lifecycle/lock";
|
|
15
|
+
import { createStateStore } from "../../src/_platform/api/_lifecycle/state";
|
|
16
|
+
import { collectRetainedTables, moduleTablePrefix } from "../../src/_platform/api/_lifecycle/uninstall";
|
|
17
|
+
import { invalidateAllUsers } from "../../src/_platform/api/_shared/service/infra/access";
|
|
18
|
+
import { createMarketApi } from "../../src/_platform/api/market/api";
|
|
19
19
|
import { installDb } from "../fixture";
|
|
20
20
|
|
|
21
21
|
const g = globalThis as any;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// BDD:深检后端四项 + 端点(P2-7,C2-42)+ SSRF 三钉。
|
|
2
2
|
// 纯 diff 函数 / 探针分类 / SSRF 钉(出站拦截 / header 清洗 / 不跟随重定向)+ 端点门(401/403/404)+ 编排。
|
|
3
3
|
/* eslint-disable test/prefer-lowercase-title -- 端点动词/路径是验收锚点,保留大写(market-api.spec 同约定) */
|
|
4
|
-
import type { FsFace } from "../../src/_platform/_lifecycle/atomic";
|
|
5
|
-
import type { SolutionRouteRow } from "../../src/_platform/_lifecycle/verify-checks";
|
|
4
|
+
import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
|
|
5
|
+
import type { SolutionRouteRow } from "../../src/_platform/api/_lifecycle/verify-checks";
|
|
6
6
|
import * as fsp from "node:fs/promises";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { join } from "node:path";
|
|
@@ -18,9 +18,9 @@ import {
|
|
|
18
18
|
sha384B64,
|
|
19
19
|
|
|
20
20
|
verifyRouteReachability,
|
|
21
|
-
} from "../../src/_platform/_lifecycle/verify-checks";
|
|
22
|
-
import { siteOrigin } from "../../src/_platform/market/api";
|
|
23
|
-
import { createSolutionsApi, solutionsEnv } from "../../src/_platform/solutions/api";
|
|
21
|
+
} from "../../src/_platform/api/_lifecycle/verify-checks";
|
|
22
|
+
import { siteOrigin } from "../../src/_platform/api/market/api";
|
|
23
|
+
import { createSolutionsApi, solutionsEnv } from "../../src/_platform/api/solutions/api";
|
|
24
24
|
import { installDb } from "../fixture";
|
|
25
25
|
|
|
26
26
|
const g = globalThis as any;
|
|
@@ -278,7 +278,10 @@ function setHttp(over: Record<string, unknown>) {
|
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
function makeEnv() {
|
|
281
|
-
|
|
281
|
+
// modulesJsonPath 钉进临时目录(readFile 失败 → 不打 web 项):默认值 `web/dist/modules.json`
|
|
282
|
+
// 是相对 cwd 的,会把模板本机构建产物卷进用例,全绿用例随「模板 build 过没有」摇摆。
|
|
283
|
+
// P4-2 两条 integrity 用例显式覆盖它。
|
|
284
|
+
return { ...solutionsEnv(), sharedRoot: root, statePath: join(root, "state.yaml"), modulesJsonPath: join(root, "modules.json") };
|
|
282
285
|
}
|
|
283
286
|
|
|
284
287
|
describe("深检端点门(admin 域)", () => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// BDD:P2-8 深检报告结构 + 留存 N=10 + 可信性项(trust_state)+ i18n 降级项 + 设值不进报告。
|
|
2
2
|
// 纯模块单测(verify-report.ts)+ 端点编排(persist-on-POST / GET verify/last / 降级项 / secret 不泄漏)。
|
|
3
3
|
/* eslint-disable test/prefer-lowercase-title -- 端点动词/路径是验收锚点,保留大写(verify-checks.spec 同约定) */
|
|
4
|
-
import type { FsFace } from "../../src/_platform/_lifecycle/atomic";
|
|
5
|
-
import type { VerifyReport } from "../../src/_platform/_lifecycle/verify-report";
|
|
4
|
+
import type { FsFace } from "../../src/_platform/api/_lifecycle/atomic";
|
|
5
|
+
import type { VerifyReport } from "../../src/_platform/api/_lifecycle/verify-report";
|
|
6
6
|
import * as fsp from "node:fs/promises";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
8
|
import { join } from "node:path";
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
persistReport,
|
|
13
13
|
VERIFY_REPORTS_KEEP,
|
|
14
14
|
verifyReportsDirOf,
|
|
15
|
-
} from "../../src/_platform/_lifecycle/verify-report";
|
|
16
|
-
import { createSolutionsApi, solutionsEnv } from "../../src/_platform/solutions/api";
|
|
15
|
+
} from "../../src/_platform/api/_lifecycle/verify-report";
|
|
16
|
+
import { createSolutionsApi, solutionsEnv } from "../../src/_platform/api/solutions/api";
|
|
17
17
|
import { installDb } from "../fixture";
|
|
18
18
|
|
|
19
19
|
const g = globalThis as any;
|
|
@@ -127,7 +127,9 @@ function setHttp(over: Record<string, unknown> = {}) {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
function makeEnv() {
|
|
130
|
-
|
|
130
|
+
// modulesJsonPath 同 verify-checks.spec:钉进临时目录(缺文件 → 跳过 web 项),
|
|
131
|
+
// 不吃模板本机 `web/dist/modules.json`。
|
|
132
|
+
return { ...solutionsEnv(), sharedRoot: root, statePath: join(root, "state.yaml"), modulesJsonPath: join(root, "modules.json"), verifyReportsDir: reportsDir };
|
|
131
133
|
}
|
|
132
134
|
|
|
133
135
|
async function insertRoute(perm: string | null) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
|
|
4
4
|
import { beforeAll, describe, expect, it } from "vitest";
|
|
5
5
|
|
|
6
|
-
import { likePattern, paged, pagedFactory } from "../src/_platform/_shared/service/infra/query";
|
|
6
|
+
import { likePattern, paged, pagedFactory } from "../src/_platform/api/_shared/service/infra/query";
|
|
7
7
|
import { installDb } from "./fixture";
|
|
8
8
|
|
|
9
9
|
let dbo: ReturnType<typeof installDb>;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
|
|
4
4
|
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
|
5
5
|
|
|
6
|
-
import { auditDeny, auditOp, recordOp, resetDenyAudit } from "../src/_platform/_shared/service/infra/audit";
|
|
6
|
+
import { auditDeny, auditOp, recordOp, resetDenyAudit } from "../src/_platform/api/_shared/service/infra/audit";
|
|
7
7
|
import { installDb } from "./fixture";
|
|
8
8
|
|
|
9
9
|
let dbo: ReturnType<typeof installDb>;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
/* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
|
|
5
5
|
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
|
6
6
|
|
|
7
|
-
import { contactDetail, searchContacts } from "../src/_platform/_shared/service/domain/contacts";
|
|
7
|
+
import { contactDetail, searchContacts } from "../src/_platform/api/_shared/service/domain/contacts";
|
|
8
8
|
import { installDb } from "./fixture";
|
|
9
9
|
|
|
10
10
|
let dbo: ReturnType<typeof installDb>;
|
|
@@ -74,7 +74,7 @@ describe("详情与限速", () => {
|
|
|
74
74
|
it("接口级限速:同用户突发超限 → 429", async () => {
|
|
75
75
|
const uid = mkUser("c_rate");
|
|
76
76
|
g.http = { user: { id: uid } };
|
|
77
|
-
const { rateLimit } = await import("../src/_platform/_shared/service/infra/rate");
|
|
77
|
+
const { rateLimit } = await import("../src/_platform/api/_shared/service/infra/rate");
|
|
78
78
|
// 窗口 60s / 限额 3(测试参数;生产端点各自定额)
|
|
79
79
|
for (let i = 0; i < 3; i++)
|
|
80
80
|
await rateLimit(`contacts:${uid}`, 3, 60_000);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
/* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
|
|
5
5
|
import { afterEach, beforeAll, describe, expect, it, vi } from "vitest";
|
|
6
6
|
|
|
7
|
-
import { assertPermission, assertSuperAdmin, assertSystemAdmin, invalidateUser } from "../src/_platform/_shared/service/infra/access";
|
|
7
|
+
import { assertPermission, assertSuperAdmin, assertSystemAdmin, invalidateUser } from "../src/_platform/api/_shared/service/infra/access";
|
|
8
8
|
import { installDb } from "./fixture";
|
|
9
9
|
|
|
10
10
|
let dbo: ReturnType<typeof installDb>;
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
/* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
|
|
5
5
|
import { afterEach, beforeAll, describe, expect, it } from "vitest";
|
|
6
6
|
|
|
7
|
-
import { createRole, deleteRole, listPermissions, listRoles, updateBindings } from "../src/_platform/_shared/service/domain/roles";
|
|
8
|
-
import { assertPermission } from "../src/_platform/_shared/service/infra/access";
|
|
7
|
+
import { createRole, deleteRole, listPermissions, listRoles, updateBindings } from "../src/_platform/api/_shared/service/domain/roles";
|
|
8
|
+
import { assertPermission } from "../src/_platform/api/_shared/service/infra/access";
|
|
9
9
|
import { installDb } from "./fixture";
|
|
10
10
|
|
|
11
11
|
let dbo: ReturnType<typeof installDb>;
|
|
@@ -7,7 +7,7 @@ import { beforeAll, describe, expect, it } from "vitest";
|
|
|
7
7
|
|
|
8
8
|
import { installDb } from "./fixture";
|
|
9
9
|
|
|
10
|
-
const SEED = join(dirname(fileURLToPath(import.meta.url)), "..", "src", "_platform", "seed.sql");
|
|
10
|
+
const SEED = join(dirname(fileURLToPath(import.meta.url)), "..", "src", "_platform", "api", "seed.sql");
|
|
11
11
|
let dbo: ReturnType<typeof installDb>;
|
|
12
12
|
|
|
13
13
|
beforeAll(() => {
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
/* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
|
|
3
3
|
import { afterEach, beforeAll, describe, expect, it } from "vitest";
|
|
4
4
|
|
|
5
|
-
import { listLoginMethods, listSettings, updateSetting } from "../src/_platform/_shared/service/domain/settings";
|
|
6
|
-
import { searchOplog } from "../src/_platform/_shared/service/infra/oplog";
|
|
5
|
+
import { listLoginMethods, listSettings, updateSetting } from "../src/_platform/api/_shared/service/domain/settings";
|
|
6
|
+
import { searchOplog } from "../src/_platform/api/_shared/service/infra/oplog";
|
|
7
7
|
import { installDb } from "./fixture";
|
|
8
8
|
|
|
9
9
|
let dbo: ReturnType<typeof installDb>;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
/* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
|
|
5
5
|
import { afterEach, beforeAll, describe, expect, it } from "vitest";
|
|
6
6
|
|
|
7
|
-
import { uninstallSolution, upsertSolutionPerms } from "../src/_platform/_shared/service/domain/solution-perms";
|
|
7
|
+
import { uninstallSolution, upsertSolutionPerms } from "../src/_platform/api/_shared/service/domain/solution-perms";
|
|
8
8
|
import { installDb } from "./fixture";
|
|
9
9
|
|
|
10
10
|
let dbo: ReturnType<typeof installDb>;
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
// 禁止操作自己(AC1-10 注);roles 写 sys_user_role 唯一权威源 + 写时失效(AC1-7/D10);
|
|
4
4
|
// 禁用/重置口令级联删 refresh(§3.1 吊销联动)。
|
|
5
5
|
/* eslint-disable test/prefer-lowercase-title -- AC 编号是验收锚点,保留大写 */
|
|
6
|
-
import type { SessionDeps } from "../src/auth/_shared/session";
|
|
6
|
+
import type { SessionDeps } from "../src/auth/api/_shared/session";
|
|
7
7
|
|
|
8
8
|
import { afterEach, beforeAll, describe, expect, it } from "vitest";
|
|
9
|
-
import { changePasswordByAdmin, createUser, listUsers, setForbidden, updateUserRoles } from "../src/_platform/_shared/service/domain/users";
|
|
10
|
-
import { createSession } from "../src/auth/_shared/session";
|
|
9
|
+
import { changePasswordByAdmin, createUser, listUsers, setForbidden, updateUserRoles } from "../src/_platform/api/_shared/service/domain/users";
|
|
10
|
+
import { createSession } from "../src/auth/api/_shared/session";
|
|
11
11
|
import { installDb } from "./fixture";
|
|
12
12
|
|
|
13
13
|
let dbo: ReturnType<typeof installDb>;
|
package/templates/tsconfig.json
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// 由 ojm 生成:ojm init / ojm build / ojm dev 会按 src/*/api/manifest.yaml 重写本文件,请勿手改。
|
|
2
|
+
//
|
|
3
|
+
// oj 别名 `#/<模块名>/…` 锚在目标模块根(本布局下即 src/<模块名>/api)。tsconfig 的
|
|
4
|
+
// paths 只能静态全局映射,且每条规则的替换值只允许一个 `*`(`./src/*/api/*` 会被 TS
|
|
5
|
+
// 以 TS5062 拒掉),故按模块逐条枚举。
|
|
6
|
+
{
|
|
7
|
+
"compilerOptions": {
|
|
8
|
+
"paths": {
|
|
9
|
+
"#/_platform/*": ["./src/_platform/api/*"],
|
|
10
|
+
"#/auth/*": ["./src/auth/api/*"],
|
|
11
|
+
"#/demo/*": ["./src/demo/api/*"],
|
|
12
|
+
"#/home/*": ["./src/home/api/*"],
|
|
13
|
+
"#/notification/*": ["./src/notification/api/*"],
|
|
14
|
+
"#/personal-center/*": ["./src/personal-center/api/*"],
|
|
15
|
+
"#/system/*": ["./src/system/api/*"],
|
|
16
|
+
"#/web/*": ["./src/web/api/*"]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// oj 导入别名(`#` 开头)的类型兜底。
|
|
2
|
+
//
|
|
3
|
+
// 背景:oj 的 `#x`(**本模块根**,本布局下即 `src/<name>/api`)/ `#/<模块名>/x`
|
|
4
|
+
// (**目标模块根**)是「引用方所在模块」相对的,而 tsconfig 的 `paths` 只能做**静态
|
|
5
|
+
// 全局映射**。`tsconfig.paths.json` 因此按模块枚举了 `"#/<模块名>/*"`,仅能命中
|
|
6
|
+
// **已存在**的文件;跨模块别名的模块名写错、或用了尚未创建的 `#_shared/view` 这类
|
|
7
|
+
// 模块内别名,编辑器会报 TS2307「Cannot find module」。
|
|
8
|
+
//
|
|
9
|
+
// 本文件是**非模块**(无顶层 import/export),其中的 `declare module` 才是真正的
|
|
10
|
+
// ambient 声明——放在模块化的 `global.d.ts` 里会被当作 module augmentation 而不生效。
|
|
11
|
+
// 通配 ambient 作为 `paths` 解析失败后的兜底:无法静态定位的 `#` 导入降级为 `any`
|
|
12
|
+
// 且不再报错;**已存在、能被 `paths` 命中的别名仍走其真实文件类型**(解析优先)。
|
|
13
|
+
//
|
|
14
|
+
// 运行时始终由 oj 的 loader(`module_loader.rs::resolve_alias`)解析,本文件只影响
|
|
15
|
+
// 编辑器 / tsc。模块名写错这类事故由 `oj build` 的 S008(别名无法解析)在构建期拦下,
|
|
16
|
+
// 不会拖到运行期。业务项目若自定义了全局或别名,可仿此在源码根另建 `.d.ts`。
|
|
17
|
+
declare module "#*";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
2
|
+
import { defineConfig } from "vitest/config";
|
|
3
|
+
|
|
4
|
+
// 后端模块测试(BDD):node:sqlite 内存库 + 真实迁移建表(见 tests/fixture.ts)。
|
|
5
|
+
// root 锚定本目录,保证从工程根跑 vitest 时 include 相对本目录解析。
|
|
6
|
+
const srcDir = fileURLToPath(new URL("./src", import.meta.url));
|
|
7
|
+
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
root: fileURLToPath(new URL(".", import.meta.url)),
|
|
10
|
+
// `#/<模块名>/…` 是 oj 的模块别名(锚在目标模块根,本布局下即 `src/<模块名>/api`)。
|
|
11
|
+
// oj build / ojm dev 在打包器里解析它,vitest 走 vite 的 resolve,必须在此显式映射,
|
|
12
|
+
// 否则跨模块 import 的后端 spec 会以「Cannot find module」整文件跳过。
|
|
13
|
+
// 形如 `#x`(锚本模块根)与导入方相对,静态 alias 表达不了——模板后端不用这种形态,
|
|
14
|
+
// 一旦引入需先补 vitest 侧解析(或改写成 `#/<模块名>/…`)。
|
|
15
|
+
resolve: {
|
|
16
|
+
alias: [{ find: /^#\/([^/]+)\/(.*)$/, replacement: `${srcDir}/$1/api/$2` }],
|
|
17
|
+
},
|
|
18
|
+
test: {
|
|
19
|
+
include: ["tests/**/*.spec.ts"],
|
|
20
|
+
environment: "node",
|
|
21
|
+
},
|
|
22
|
+
});
|