@oj-module/cli 0.2.53 → 0.2.56
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/SKILL.md +4 -4
- package/devkit/manual.md +79 -65
- package/package.json +2 -2
- package/shell-dist/assets/{index-e_Mp2mb5.js → index-CImwskAz.js} +24 -11
- package/shell-dist/assets/runtime.js +7 -4
- 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__/templates-tenant-scope.test.ts +3 -2
- package/src/alias-paths.ts +11 -12
- package/src/builtin.ts +10 -3
- package/src/config.ts +9 -0
- package/src/contract/__tests__/client-path.test.ts +30 -0
- package/src/contract/__tests__/emit-client.test.ts +20 -2
- package/src/contract/__tests__/handler-scan.test.ts +23 -0
- 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 +11 -7
- package/src/contract/client-path.ts +30 -0
- package/src/contract/emit-client.ts +27 -6
- package/src/contract/handler-scan.ts +40 -3
- package/src/contract/run.ts +15 -5
- package/src/init.ts +29 -3
- package/src/layout.ts +72 -16
- 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/templates/README.md +49 -43
- package/templates/init.include.yaml +31 -19
- package/templates/openapi.json +1488 -120
- 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/{_platform/api → app/api/_platform}/contacts/api.ts +29 -1
- package/templates/src/{_platform/api → app/api/_platform}/contacts/detail/api.ts +25 -1
- 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/{_platform/api → app/api/_platform}/schema.yaml +5 -0
- package/templates/src/{_platform/api → app/api/_platform}/solutions/api.ts +60 -1
- 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/{auth/api → app/api/auth}/api.ts +59 -0
- package/templates/src/{auth/api → app/api/auth}/ldap-login/api.ts +37 -1
- package/templates/src/{auth/api → app/api/auth}/wecom/api.ts +23 -0
- package/templates/src/{notification/api → app/api/notification}/api.ts +17 -0
- package/templates/src/{notification/api → app/api/notification}/del/api.ts +2 -0
- package/templates/src/{system/api → app/api/system}/oplog/api.ts +5 -3
- package/templates/src/{system/api → app/api/system}/roles/api.ts +3 -0
- package/templates/src/{system/api → app/api/system}/roles/bindings/api.ts +3 -0
- package/templates/src/{system/api → app/api/system}/settings/api.ts +3 -0
- package/templates/src/{system/api → app/api/system}/users/forbidden/api.ts +3 -0
- package/templates/src/{system/api → app/api/system}/users/password/api.ts +3 -0
- package/templates/src/{system/api → app/api/system}/users/roles/api.ts +3 -0
- package/templates/src/app/api/web/get-async-routes/api.ts +23 -0
- package/templates/src/app/api/web/hello/api.ts +22 -0
- package/templates/src/{web/api → app/api/web}/user-info/api.ts +21 -1
- package/templates/src/{_platform/web → app/web/_platform}/__client/api.schemas.ts +99 -35
- package/templates/src/{_platform/web/__client/api.ts → app/web/_platform/__client/index.ts} +108 -61
- package/templates/src/{auth/web → app/web/auth}/__client/api.schemas.ts +133 -13
- package/templates/src/{auth/web/__client/api.ts → app/web/auth/__client/index.ts} +134 -33
- package/templates/src/app/web/entry.ts +77 -0
- package/templates/src/{home/web/__client/api.ts → app/web/home/__client/index.ts} +5 -2
- package/templates/src/app/web/home/routes.ts +41 -0
- package/templates/src/app/web/login/routes.ts +71 -0
- package/templates/src/{notification/web → app/web/notification}/__client/api.schemas.ts +14 -0
- package/templates/src/{notification/web/__client/api.ts → app/web/notification/__client/index.ts} +67 -20
- package/templates/src/{notification/web → app/web/notification}/pages/center/index.tsx +1 -1
- package/templates/src/app/web/notification/routes.ts +70 -0
- package/templates/src/{personal-center/web/__client/api.ts → app/web/personal-center/__client/index.ts} +5 -2
- package/templates/src/{personal-center/web → app/web/personal-center}/pages/my-profile/index.tsx +1 -1
- package/templates/src/app/web/personal-center/routes.ts +49 -0
- package/templates/src/{system/web → app/web/system}/__client/api.schemas.ts +29 -22
- package/templates/src/{system/web/__client/api.ts → app/web/system/__client/index.ts} +103 -58
- package/templates/src/{system/web → app/web/system}/locales/en-US.json +2 -3
- package/templates/src/{system/web → app/web/system}/locales/zh-CN.json +2 -3
- package/templates/src/{system/web → app/web/system}/pages/departments/index.tsx +2 -2
- package/templates/src/{system/web → app/web/system}/pages/login-methods/index.tsx +1 -1
- package/templates/src/{system/web → app/web/system}/pages/oplog/index.tsx +44 -19
- package/templates/src/{system/web → app/web/system}/pages/roles/index.tsx +5 -3
- package/templates/src/app/web/system/pages/roles/visible-roles.ts +14 -0
- package/templates/src/{system/web → 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/{system/web → app/web/system}/pages/users/index.tsx +23 -15
- package/templates/src/{system/web → app/web/system}/pages/users/roles.tsx +1 -1
- package/templates/src/{system/web → app/web/system}/pages/wecom/index.tsx +12 -3
- package/templates/src/{system/web/entry.ts → app/web/system/routes.ts} +25 -36
- package/templates/src/app/web/web/__client/api.schemas.ts +36 -0
- package/templates/src/{web/web/__client/api.ts → app/web/web/__client/index.ts} +38 -11
- 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/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 +10 -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 +24 -15
- package/vendor/host-versions.json +3 -3
- package/templates/src/home/web/entry.ts +0 -49
- package/templates/src/login/web/entry.ts +0 -79
- package/templates/src/notification/web/entry.ts +0 -84
- package/templates/src/personal-center/web/entry.ts +0 -60
- package/templates/src/web/api/get-async-routes/api.ts +0 -8
- package/templates/src/web/api/hello/api.ts +0 -10
- package/templates/src/web/web/__client/api.schemas.ts +0 -8
- 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/installer.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/register.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/roles.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/domain/solution-perms.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}/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/{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}/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/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}/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}/users/api.ts +0 -0
- /package/templates/src/{system/api → app/api/system}/users/profile/api.ts +0 -0
- /package/templates/src/{web/api → app/api/web}/manifest.yaml +0 -0
- /package/templates/src/{home/web → app/web/home}/__client/api.schemas.ts +0 -0
- /package/templates/src/{home/web → app/web/home}/locales/en-US.json +0 -0
- /package/templates/src/{home/web → app/web/home}/locales/zh-CN.json +0 -0
- /package/templates/src/{home/web → app/web/home}/pages/components/bar-chart.tsx +0 -0
- /package/templates/src/{home/web → app/web/home}/pages/components/card-list.tsx +0 -0
- /package/templates/src/{home/web → app/web/home}/pages/components/line-chart.tsx +0 -0
- /package/templates/src/{home/web → app/web/home}/pages/components/pie-chart.tsx +0 -0
- /package/templates/src/{home/web → app/web/home}/pages/index.tsx +0 -0
- /package/templates/src/{login/web → app/web/login}/auth-provider.ts +0 -0
- /package/templates/src/{login/web → app/web/login}/locales/en-US.json +0 -0
- /package/templates/src/{login/web → app/web/login}/locales/zh-CN.json +0 -0
- /package/templates/src/{login/web → app/web/login}/pages/change-password.tsx +0 -0
- /package/templates/src/{login/web → app/web/login}/pages/login.tsx +0 -0
- /package/templates/src/{login/web → app/web/login}/wecom.ts +0 -0
- /package/templates/src/{notification/web → app/web/notification}/locales/en-US.json +0 -0
- /package/templates/src/{notification/web → app/web/notification}/locales/zh-CN.json +0 -0
- /package/templates/src/{personal-center/web → app/web/personal-center}/__client/api.schemas.ts +0 -0
- /package/templates/src/{personal-center/web → app/web/personal-center}/locales/en-US.json +0 -0
- /package/templates/src/{personal-center/web → app/web/personal-center}/locales/zh-CN.json +0 -0
- /package/templates/src/{system/web → app/web/system}/pages/departments/sync-bar.tsx +0 -0
- /package/templates/src/{system/web → app/web/system}/pages/departments/tree.ts +0 -0
- /package/templates/src/{system/web → app/web/system}/pages/errors.ts +0 -0
- /package/templates/src/{system/web → app/web/system}/pages/forbidden.tsx +0 -0
|
@@ -4,10 +4,89 @@
|
|
|
4
4
|
import { z } from "@oj-module/runtime";
|
|
5
5
|
|
|
6
6
|
export const schemas = {
|
|
7
|
+
"authLoginPost": {
|
|
8
|
+
body: z.object({
|
|
9
|
+
"username": z.string().min(1),
|
|
10
|
+
"password": z.string().min(1)
|
|
11
|
+
}),
|
|
12
|
+
data: z.object({
|
|
13
|
+
"access_token": z.string(),
|
|
14
|
+
"refresh_token": z.string(),
|
|
15
|
+
"expires_in": z.number(),
|
|
16
|
+
"restricted": z.boolean(),
|
|
17
|
+
"user": z.object({
|
|
18
|
+
"id": z.number(),
|
|
19
|
+
"username": z.string(),
|
|
20
|
+
"display_name": z.string().nullable(),
|
|
21
|
+
"avatar_base64": z.string().nullable(),
|
|
22
|
+
"must_change": z.boolean(),
|
|
23
|
+
"roles": z.array(z.string())
|
|
24
|
+
})
|
|
25
|
+
}),
|
|
26
|
+
},
|
|
27
|
+
"authLogoutPost": {
|
|
28
|
+
body: z.object({
|
|
29
|
+
"refresh_token": z.string().min(1)
|
|
30
|
+
}),
|
|
31
|
+
data: z.null(),
|
|
32
|
+
},
|
|
33
|
+
"authRefreshPost": {
|
|
34
|
+
body: z.object({
|
|
35
|
+
"refresh_token": z.string().min(1)
|
|
36
|
+
}),
|
|
37
|
+
data: z.object({
|
|
38
|
+
"access_token": z.string(),
|
|
39
|
+
"refresh_token": z.string(),
|
|
40
|
+
"expires_in": z.number(),
|
|
41
|
+
"restricted": z.boolean(),
|
|
42
|
+
"user": z.object({
|
|
43
|
+
"id": z.number(),
|
|
44
|
+
"username": z.string(),
|
|
45
|
+
"display_name": z.string().nullable(),
|
|
46
|
+
"avatar_base64": z.string().nullable(),
|
|
47
|
+
"must_change": z.boolean(),
|
|
48
|
+
"roles": z.array(z.string())
|
|
49
|
+
})
|
|
50
|
+
}),
|
|
51
|
+
},
|
|
7
52
|
"authPasswordPut": {
|
|
8
53
|
body: z.object({
|
|
9
54
|
"old_password": z.string().min(1),
|
|
10
55
|
"new_password": z.string().min(6)
|
|
56
|
+
}),
|
|
57
|
+
data: z.object({
|
|
58
|
+
"access_token": z.string(),
|
|
59
|
+
"refresh_token": z.string(),
|
|
60
|
+
"expires_in": z.number(),
|
|
61
|
+
"restricted": z.boolean(),
|
|
62
|
+
"user": z.object({
|
|
63
|
+
"id": z.number(),
|
|
64
|
+
"username": z.string(),
|
|
65
|
+
"display_name": z.string().nullable(),
|
|
66
|
+
"avatar_base64": z.string().nullable(),
|
|
67
|
+
"must_change": z.boolean(),
|
|
68
|
+
"roles": z.array(z.string())
|
|
69
|
+
})
|
|
70
|
+
}),
|
|
71
|
+
},
|
|
72
|
+
"authLdapLoginPost": {
|
|
73
|
+
body: z.object({
|
|
74
|
+
"username": z.string().min(1),
|
|
75
|
+
"password": z.string().min(1)
|
|
76
|
+
}),
|
|
77
|
+
data: z.object({
|
|
78
|
+
"access_token": z.string(),
|
|
79
|
+
"refresh_token": z.string(),
|
|
80
|
+
"expires_in": z.number(),
|
|
81
|
+
"restricted": z.boolean(),
|
|
82
|
+
"user": z.object({
|
|
83
|
+
"id": z.number(),
|
|
84
|
+
"username": z.string(),
|
|
85
|
+
"display_name": z.string().nullable(),
|
|
86
|
+
"avatar_base64": z.string().nullable(),
|
|
87
|
+
"must_change": z.boolean(),
|
|
88
|
+
"roles": z.array(z.string())
|
|
89
|
+
})
|
|
11
90
|
}),
|
|
12
91
|
},
|
|
13
92
|
"authWecomAdminAppsGet": {
|
|
@@ -24,6 +103,16 @@ export const schemas = {
|
|
|
24
103
|
"installed_at": z.number(),
|
|
25
104
|
"update_time": z.number()
|
|
26
105
|
})),
|
|
106
|
+
},
|
|
107
|
+
"authWecomAdminOverviewGet": {
|
|
108
|
+
data: z.object({
|
|
109
|
+
"kinds": z.array(z.enum(["suite", "corp"])),
|
|
110
|
+
"configError": z.string().nullable(),
|
|
111
|
+
"callbackUrl": z.string().nullable(),
|
|
112
|
+
"corpId": z.string().nullable(),
|
|
113
|
+
"agentId": z.string().nullable(),
|
|
114
|
+
"corpCallbackConfigured": z.boolean()
|
|
115
|
+
}),
|
|
27
116
|
},
|
|
28
117
|
"authWecomAdminStatusPost": {
|
|
29
118
|
body: z.object({
|
|
@@ -41,16 +130,6 @@ export const schemas = {
|
|
|
41
130
|
"installUrl": z.string(),
|
|
42
131
|
"callbackUrl": z.string(),
|
|
43
132
|
"expiresIn": z.number()
|
|
44
|
-
}),
|
|
45
|
-
},
|
|
46
|
-
"authWecomAdminOverviewGet": {
|
|
47
|
-
data: z.object({
|
|
48
|
-
"kinds": z.array(z.enum(["suite", "corp"])),
|
|
49
|
-
"configError": z.string().nullable(),
|
|
50
|
-
"callbackUrl": z.string().nullable(),
|
|
51
|
-
"corpId": z.string().nullable(),
|
|
52
|
-
"agentId": z.string().nullable(),
|
|
53
|
-
"corpCallbackConfigured": z.boolean()
|
|
54
133
|
}),
|
|
55
134
|
},
|
|
56
135
|
"authWecomAdminConnectPost": {
|
|
@@ -59,11 +138,48 @@ export const schemas = {
|
|
|
59
138
|
"agentId": z.string(),
|
|
60
139
|
"departments": z.number(),
|
|
61
140
|
"members": z.number()
|
|
141
|
+
}),
|
|
142
|
+
},
|
|
143
|
+
"authWecomAdminTenantAdminGet": {
|
|
144
|
+
query: z.object({
|
|
145
|
+
"corpId": z.string().min(1)
|
|
146
|
+
}),
|
|
147
|
+
data: z.object({
|
|
148
|
+
"corpId": z.string(),
|
|
149
|
+
"username": z.string(),
|
|
150
|
+
"exists": z.boolean(),
|
|
151
|
+
"mustChange": z.boolean()
|
|
152
|
+
}),
|
|
153
|
+
},
|
|
154
|
+
"authWecomAdminTenantAdminPasswordPost": {
|
|
155
|
+
body: z.object({
|
|
156
|
+
"corpId": z.string().min(1),
|
|
157
|
+
"password": z.string().min(6)
|
|
158
|
+
}),
|
|
159
|
+
data: z.object({
|
|
160
|
+
"corpId": z.string(),
|
|
161
|
+
"username": z.string(),
|
|
162
|
+
"exists": z.boolean(),
|
|
163
|
+
"mustChange": z.boolean()
|
|
62
164
|
}),
|
|
63
165
|
},
|
|
64
166
|
"authWecomTicketPost": {
|
|
65
167
|
body: z.object({
|
|
66
168
|
"ticket": z.string().min(32).max(128)
|
|
169
|
+
}),
|
|
170
|
+
data: z.object({
|
|
171
|
+
"access_token": z.string(),
|
|
172
|
+
"refresh_token": z.string(),
|
|
173
|
+
"expires_in": z.number(),
|
|
174
|
+
"restricted": z.boolean(),
|
|
175
|
+
"user": z.object({
|
|
176
|
+
"id": z.number(),
|
|
177
|
+
"username": z.string(),
|
|
178
|
+
"display_name": z.string().nullable(),
|
|
179
|
+
"avatar_base64": z.string().nullable(),
|
|
180
|
+
"must_change": z.boolean(),
|
|
181
|
+
"roles": z.array(z.string())
|
|
182
|
+
})
|
|
67
183
|
}),
|
|
68
184
|
},
|
|
69
185
|
"authWecomSyncStartPost": {
|
|
@@ -74,6 +190,8 @@ export const schemas = {
|
|
|
74
190
|
"connected": z.boolean(),
|
|
75
191
|
"authMode": z.number(),
|
|
76
192
|
"profileStatus": z.string().nullable(),
|
|
193
|
+
"agentId": z.string().nullable(),
|
|
194
|
+
"credentialKind": z.union([z.literal("suite"), z.literal("corp"), z.literal(null)]).nullable(),
|
|
77
195
|
"status": z.enum(["idle", "running", "done", "failed", "cancelled"]),
|
|
78
196
|
"phase": z.enum(["departments", "members", "reconcile"]),
|
|
79
197
|
"stats": z.object({
|
|
@@ -106,6 +224,8 @@ export const schemas = {
|
|
|
106
224
|
"connected": z.boolean(),
|
|
107
225
|
"authMode": z.number(),
|
|
108
226
|
"profileStatus": z.string().nullable(),
|
|
227
|
+
"agentId": z.string().nullable(),
|
|
228
|
+
"credentialKind": z.union([z.literal("suite"), z.literal("corp"), z.literal(null)]).nullable(),
|
|
109
229
|
"status": z.enum(["idle", "running", "done", "failed", "cancelled"]),
|
|
110
230
|
"phase": z.enum(["departments", "members", "reconcile"]),
|
|
111
231
|
"stats": z.object({
|
|
@@ -127,9 +247,7 @@ export const schemas = {
|
|
|
127
247
|
}).nullable(),
|
|
128
248
|
"startedAt": z.number(),
|
|
129
249
|
"finishedAt": z.number(),
|
|
130
|
-
"updateTime": z.number()
|
|
131
|
-
"agentId": z.string().nullable(),
|
|
132
|
-
"credentialKind": z.union([z.literal("suite"), z.literal("corp"), z.literal(null)]).nullable()
|
|
250
|
+
"updateTime": z.number()
|
|
133
251
|
}),
|
|
134
252
|
},
|
|
135
253
|
"authWecomSyncCancelPost": {
|
|
@@ -140,6 +258,8 @@ export const schemas = {
|
|
|
140
258
|
"connected": z.boolean(),
|
|
141
259
|
"authMode": z.number(),
|
|
142
260
|
"profileStatus": z.string().nullable(),
|
|
261
|
+
"agentId": z.string().nullable(),
|
|
262
|
+
"credentialKind": z.union([z.literal("suite"), z.literal("corp"), z.literal(null)]).nullable(),
|
|
143
263
|
"status": z.enum(["idle", "running", "done", "failed", "cancelled"]),
|
|
144
264
|
"phase": z.enum(["departments", "members", "reconcile"]),
|
|
145
265
|
"stats": z.object({
|
|
@@ -17,6 +17,9 @@ export const API_PREFIX = "/auth";
|
|
|
17
17
|
/** 认领身份前缀(契约 apiPrefix,字面等于模块目录名):跨模块认领护栏对比基准 */
|
|
18
18
|
export const MODULE_PREFIX = "/auth";
|
|
19
19
|
|
|
20
|
+
/** 认领方模块(web.config clientOwners 指定):跨模块认领护栏对比基准 */
|
|
21
|
+
export const MODULE_OWNER = "/app";
|
|
22
|
+
|
|
20
23
|
/**
|
|
21
24
|
* 模块 entry 的 onInit 里一行创建(构造即 install):完成 apiPrefix 登记 +
|
|
22
25
|
* scoped request 绑定,返回绑好前缀的端点函数集合。一模块一 client;
|
|
@@ -28,12 +31,12 @@ export function createAuthClient(ctx: ModuleContext) {
|
|
|
28
31
|
// 单槽、卸载互相耦合;跨模块需求应由本模块创建后经 provider 暴露。
|
|
29
32
|
// 注意对比基准是 MODULE_PREFIX(目录名)而非 API_PREFIX——D-M8 映射时线上前缀
|
|
30
33
|
// 属于别的命名空间,认领身份仍按目录名。
|
|
31
|
-
if (import.meta.env.DEV && ctx.module.name !==
|
|
32
|
-
console.warn(`[ojm-api] 模块 "${ctx.module.name}" 正在认领 ${MODULE_PREFIX} 的 client——跨模块认领会共享 request 单槽、卸载互相耦合;应由 "${
|
|
34
|
+
if (import.meta.env.DEV && ctx.module.name !== MODULE_OWNER.slice(1)) {
|
|
35
|
+
console.warn(`[ojm-api] 模块 "${ctx.module.name}" 正在认领 ${MODULE_PREFIX} 的 client——跨模块认领会共享 request 单槽、卸载互相耦合;应由 "${MODULE_OWNER.slice(1)}" 模块在自身 onInit 创建,跨模块需求经 provider 暴露。`);
|
|
33
36
|
}
|
|
34
37
|
ctx.register.apiPrefix(API_PREFIX);
|
|
35
38
|
bindRequest(ctx.utils.request);
|
|
36
|
-
return { authLoginPost, authLogoutPost, authRefreshPost, authPasswordPut, authLdapLoginPost, authWecomAdminAppsGet, authWecomAdminStatusPost, authWecomAdminInstallGet,
|
|
39
|
+
return { authLoginPost, authLogoutPost, authRefreshPost, authPasswordPut, authLdapLoginPost, authWecomAdminAppsGet, authWecomAdminOverviewGet, authWecomAdminStatusPost, authWecomAdminInstallGet, authWecomAdminConnectPost, authWecomAdminTenantAdminGet, authWecomAdminTenantAdminPasswordPost, authWecomLoginGet, authWecomCallbackGet, authWecomTicketPost, authWecomEventGet, authWecomEventPost, authWecomSyncStartPost, authWecomSyncStatusGet, authWecomSyncCancelPost };
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
/**
|
|
@@ -64,14 +67,23 @@ async function toApiError(e: unknown): Promise<unknown> {
|
|
|
64
67
|
return e;
|
|
65
68
|
}
|
|
66
69
|
|
|
67
|
-
export
|
|
70
|
+
export type AuthLoginPostBody = z.input<(typeof schemas)["authLoginPost"]["body"]>;
|
|
71
|
+
export type AuthLoginPostData = z.infer<(typeof schemas)["authLoginPost"]["data"]>;
|
|
72
|
+
|
|
73
|
+
export async function authLoginPost(body: AuthLoginPostBody): Promise<AuthLoginPostData> {
|
|
68
74
|
const client = ensureReq();
|
|
69
75
|
try {
|
|
70
|
-
const env = await client.post(`auth/login
|
|
76
|
+
const env = await client.post(`auth/login`, { json: body }).json<OjEnvelope<AuthLoginPostData>>();
|
|
71
77
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
72
78
|
if (typeof env.code === "number" && env.code !== 0)
|
|
73
79
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
74
|
-
const data = env.data as
|
|
80
|
+
const data = env.data as AuthLoginPostData;
|
|
81
|
+
if (import.meta.env.DEV) {
|
|
82
|
+
const { schemas } = await import("./api.schemas");
|
|
83
|
+
const r = schemas["authLoginPost"].data.safeParse(data);
|
|
84
|
+
if (!r.success)
|
|
85
|
+
throw new ContractApiError(-1, `[契约违例] authLoginPost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
86
|
+
}
|
|
75
87
|
return data;
|
|
76
88
|
}
|
|
77
89
|
catch (e) {
|
|
@@ -79,14 +91,23 @@ export async function authLoginPost(): Promise<unknown> {
|
|
|
79
91
|
}
|
|
80
92
|
}
|
|
81
93
|
|
|
82
|
-
export
|
|
94
|
+
export type AuthLogoutPostBody = z.input<(typeof schemas)["authLogoutPost"]["body"]>;
|
|
95
|
+
export type AuthLogoutPostData = z.infer<(typeof schemas)["authLogoutPost"]["data"]>;
|
|
96
|
+
|
|
97
|
+
export async function authLogoutPost(body: AuthLogoutPostBody): Promise<AuthLogoutPostData> {
|
|
83
98
|
const client = ensureReq();
|
|
84
99
|
try {
|
|
85
|
-
const env = await client.post(`auth/logout
|
|
100
|
+
const env = await client.post(`auth/logout`, { json: body }).json<OjEnvelope<AuthLogoutPostData>>();
|
|
86
101
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
87
102
|
if (typeof env.code === "number" && env.code !== 0)
|
|
88
103
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
89
|
-
const data = env.data as
|
|
104
|
+
const data = env.data as AuthLogoutPostData;
|
|
105
|
+
if (import.meta.env.DEV) {
|
|
106
|
+
const { schemas } = await import("./api.schemas");
|
|
107
|
+
const r = schemas["authLogoutPost"].data.safeParse(data);
|
|
108
|
+
if (!r.success)
|
|
109
|
+
throw new ContractApiError(-1, `[契约违例] authLogoutPost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
110
|
+
}
|
|
90
111
|
return data;
|
|
91
112
|
}
|
|
92
113
|
catch (e) {
|
|
@@ -94,14 +115,23 @@ export async function authLogoutPost(): Promise<unknown> {
|
|
|
94
115
|
}
|
|
95
116
|
}
|
|
96
117
|
|
|
97
|
-
export
|
|
118
|
+
export type AuthRefreshPostBody = z.input<(typeof schemas)["authRefreshPost"]["body"]>;
|
|
119
|
+
export type AuthRefreshPostData = z.infer<(typeof schemas)["authRefreshPost"]["data"]>;
|
|
120
|
+
|
|
121
|
+
export async function authRefreshPost(body: AuthRefreshPostBody): Promise<AuthRefreshPostData> {
|
|
98
122
|
const client = ensureReq();
|
|
99
123
|
try {
|
|
100
|
-
const env = await client.post(`auth/refresh
|
|
124
|
+
const env = await client.post(`auth/refresh`, { json: body }).json<OjEnvelope<AuthRefreshPostData>>();
|
|
101
125
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
102
126
|
if (typeof env.code === "number" && env.code !== 0)
|
|
103
127
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
104
|
-
const data = env.data as
|
|
128
|
+
const data = env.data as AuthRefreshPostData;
|
|
129
|
+
if (import.meta.env.DEV) {
|
|
130
|
+
const { schemas } = await import("./api.schemas");
|
|
131
|
+
const r = schemas["authRefreshPost"].data.safeParse(data);
|
|
132
|
+
if (!r.success)
|
|
133
|
+
throw new ContractApiError(-1, `[契约违例] authRefreshPost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
134
|
+
}
|
|
105
135
|
return data;
|
|
106
136
|
}
|
|
107
137
|
catch (e) {
|
|
@@ -110,15 +140,22 @@ export async function authRefreshPost(): Promise<unknown> {
|
|
|
110
140
|
}
|
|
111
141
|
|
|
112
142
|
export type AuthPasswordPutBody = z.input<(typeof schemas)["authPasswordPut"]["body"]>;
|
|
143
|
+
export type AuthPasswordPutData = z.infer<(typeof schemas)["authPasswordPut"]["data"]>;
|
|
113
144
|
|
|
114
|
-
export async function authPasswordPut(body: AuthPasswordPutBody): Promise<
|
|
145
|
+
export async function authPasswordPut(body: AuthPasswordPutBody): Promise<AuthPasswordPutData> {
|
|
115
146
|
const client = ensureReq();
|
|
116
147
|
try {
|
|
117
|
-
const env = await client.put(`auth/password`, { json: body }).json<OjEnvelope<
|
|
148
|
+
const env = await client.put(`auth/password`, { json: body }).json<OjEnvelope<AuthPasswordPutData>>();
|
|
118
149
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
119
150
|
if (typeof env.code === "number" && env.code !== 0)
|
|
120
151
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
121
|
-
const data = env.data as
|
|
152
|
+
const data = env.data as AuthPasswordPutData;
|
|
153
|
+
if (import.meta.env.DEV) {
|
|
154
|
+
const { schemas } = await import("./api.schemas");
|
|
155
|
+
const r = schemas["authPasswordPut"].data.safeParse(data);
|
|
156
|
+
if (!r.success)
|
|
157
|
+
throw new ContractApiError(-1, `[契约违例] authPasswordPut 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
158
|
+
}
|
|
122
159
|
return data;
|
|
123
160
|
}
|
|
124
161
|
catch (e) {
|
|
@@ -126,14 +163,23 @@ export async function authPasswordPut(body: AuthPasswordPutBody): Promise<unknow
|
|
|
126
163
|
}
|
|
127
164
|
}
|
|
128
165
|
|
|
129
|
-
export
|
|
166
|
+
export type AuthLdapLoginPostBody = z.input<(typeof schemas)["authLdapLoginPost"]["body"]>;
|
|
167
|
+
export type AuthLdapLoginPostData = z.infer<(typeof schemas)["authLdapLoginPost"]["data"]>;
|
|
168
|
+
|
|
169
|
+
export async function authLdapLoginPost(body: AuthLdapLoginPostBody): Promise<AuthLdapLoginPostData> {
|
|
130
170
|
const client = ensureReq();
|
|
131
171
|
try {
|
|
132
|
-
const env = await client.post(`auth/ldap-login
|
|
172
|
+
const env = await client.post(`auth/ldap-login`, { json: body }).json<OjEnvelope<AuthLdapLoginPostData>>();
|
|
133
173
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
134
174
|
if (typeof env.code === "number" && env.code !== 0)
|
|
135
175
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
136
|
-
const data = env.data as
|
|
176
|
+
const data = env.data as AuthLdapLoginPostData;
|
|
177
|
+
if (import.meta.env.DEV) {
|
|
178
|
+
const { schemas } = await import("./api.schemas");
|
|
179
|
+
const r = schemas["authLdapLoginPost"].data.safeParse(data);
|
|
180
|
+
if (!r.success)
|
|
181
|
+
throw new ContractApiError(-1, `[契约违例] authLdapLoginPost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
182
|
+
}
|
|
137
183
|
return data;
|
|
138
184
|
}
|
|
139
185
|
catch (e) {
|
|
@@ -164,6 +210,29 @@ export async function authWecomAdminAppsGet(): Promise<AuthWecomAdminAppsGetData
|
|
|
164
210
|
}
|
|
165
211
|
}
|
|
166
212
|
|
|
213
|
+
export type AuthWecomAdminOverviewGetData = z.infer<(typeof schemas)["authWecomAdminOverviewGet"]["data"]>;
|
|
214
|
+
|
|
215
|
+
export async function authWecomAdminOverviewGet(): Promise<AuthWecomAdminOverviewGetData> {
|
|
216
|
+
const client = ensureReq();
|
|
217
|
+
try {
|
|
218
|
+
const env = await client.get(`auth/wecom/admin/overview`).json<OjEnvelope<AuthWecomAdminOverviewGetData>>();
|
|
219
|
+
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
220
|
+
if (typeof env.code === "number" && env.code !== 0)
|
|
221
|
+
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
222
|
+
const data = env.data as AuthWecomAdminOverviewGetData;
|
|
223
|
+
if (import.meta.env.DEV) {
|
|
224
|
+
const { schemas } = await import("./api.schemas");
|
|
225
|
+
const r = schemas["authWecomAdminOverviewGet"].data.safeParse(data);
|
|
226
|
+
if (!r.success)
|
|
227
|
+
throw new ContractApiError(-1, `[契约违例] authWecomAdminOverviewGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
228
|
+
}
|
|
229
|
+
return data;
|
|
230
|
+
}
|
|
231
|
+
catch (e) {
|
|
232
|
+
throw await toApiError(e);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
167
236
|
export type AuthWecomAdminStatusPostBody = z.input<(typeof schemas)["authWecomAdminStatusPost"]["body"]>;
|
|
168
237
|
export type AuthWecomAdminStatusPostData = z.infer<(typeof schemas)["authWecomAdminStatusPost"]["data"]>;
|
|
169
238
|
|
|
@@ -211,21 +280,21 @@ export async function authWecomAdminInstallGet(): Promise<AuthWecomAdminInstallG
|
|
|
211
280
|
}
|
|
212
281
|
}
|
|
213
282
|
|
|
214
|
-
export type
|
|
283
|
+
export type AuthWecomAdminConnectPostData = z.infer<(typeof schemas)["authWecomAdminConnectPost"]["data"]>;
|
|
215
284
|
|
|
216
|
-
export async function
|
|
285
|
+
export async function authWecomAdminConnectPost(): Promise<AuthWecomAdminConnectPostData> {
|
|
217
286
|
const client = ensureReq();
|
|
218
287
|
try {
|
|
219
|
-
const env = await client.
|
|
288
|
+
const env = await client.post(`auth/wecom/admin/connect`).json<OjEnvelope<AuthWecomAdminConnectPostData>>();
|
|
220
289
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
221
290
|
if (typeof env.code === "number" && env.code !== 0)
|
|
222
291
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
223
|
-
const data = env.data as
|
|
292
|
+
const data = env.data as AuthWecomAdminConnectPostData;
|
|
224
293
|
if (import.meta.env.DEV) {
|
|
225
294
|
const { schemas } = await import("./api.schemas");
|
|
226
|
-
const r = schemas["
|
|
295
|
+
const r = schemas["authWecomAdminConnectPost"].data.safeParse(data);
|
|
227
296
|
if (!r.success)
|
|
228
|
-
throw new ContractApiError(-1, `[契约违例]
|
|
297
|
+
throw new ContractApiError(-1, `[契约违例] authWecomAdminConnectPost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
229
298
|
}
|
|
230
299
|
return data;
|
|
231
300
|
}
|
|
@@ -234,21 +303,46 @@ export async function authWecomAdminOverviewGet(): Promise<AuthWecomAdminOvervie
|
|
|
234
303
|
}
|
|
235
304
|
}
|
|
236
305
|
|
|
237
|
-
export type
|
|
306
|
+
export type AuthWecomAdminTenantAdminGetQuery = z.input<(typeof schemas)["authWecomAdminTenantAdminGet"]["query"]>;
|
|
307
|
+
export type AuthWecomAdminTenantAdminGetData = z.infer<(typeof schemas)["authWecomAdminTenantAdminGet"]["data"]>;
|
|
238
308
|
|
|
239
|
-
export async function
|
|
309
|
+
export async function authWecomAdminTenantAdminGet(query: AuthWecomAdminTenantAdminGetQuery): Promise<AuthWecomAdminTenantAdminGetData> {
|
|
240
310
|
const client = ensureReq();
|
|
241
311
|
try {
|
|
242
|
-
const env = await client.
|
|
312
|
+
const env = await client.get(`auth/wecom/admin/tenant-admin`, { searchParams: query as Record<string, string | number | boolean> }).json<OjEnvelope<AuthWecomAdminTenantAdminGetData>>();
|
|
243
313
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
244
314
|
if (typeof env.code === "number" && env.code !== 0)
|
|
245
315
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
246
|
-
const data = env.data as
|
|
316
|
+
const data = env.data as AuthWecomAdminTenantAdminGetData;
|
|
247
317
|
if (import.meta.env.DEV) {
|
|
248
318
|
const { schemas } = await import("./api.schemas");
|
|
249
|
-
const r = schemas["
|
|
319
|
+
const r = schemas["authWecomAdminTenantAdminGet"].data.safeParse(data);
|
|
250
320
|
if (!r.success)
|
|
251
|
-
throw new ContractApiError(-1, `[契约违例]
|
|
321
|
+
throw new ContractApiError(-1, `[契约违例] authWecomAdminTenantAdminGet 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
322
|
+
}
|
|
323
|
+
return data;
|
|
324
|
+
}
|
|
325
|
+
catch (e) {
|
|
326
|
+
throw await toApiError(e);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
export type AuthWecomAdminTenantAdminPasswordPostBody = z.input<(typeof schemas)["authWecomAdminTenantAdminPasswordPost"]["body"]>;
|
|
331
|
+
export type AuthWecomAdminTenantAdminPasswordPostData = z.infer<(typeof schemas)["authWecomAdminTenantAdminPasswordPost"]["data"]>;
|
|
332
|
+
|
|
333
|
+
export async function authWecomAdminTenantAdminPasswordPost(body: AuthWecomAdminTenantAdminPasswordPostBody): Promise<AuthWecomAdminTenantAdminPasswordPostData> {
|
|
334
|
+
const client = ensureReq();
|
|
335
|
+
try {
|
|
336
|
+
const env = await client.post(`auth/wecom/admin/tenant-admin/password`, { json: body }).json<OjEnvelope<AuthWecomAdminTenantAdminPasswordPostData>>();
|
|
337
|
+
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
338
|
+
if (typeof env.code === "number" && env.code !== 0)
|
|
339
|
+
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
340
|
+
const data = env.data as AuthWecomAdminTenantAdminPasswordPostData;
|
|
341
|
+
if (import.meta.env.DEV) {
|
|
342
|
+
const { schemas } = await import("./api.schemas");
|
|
343
|
+
const r = schemas["authWecomAdminTenantAdminPasswordPost"].data.safeParse(data);
|
|
344
|
+
if (!r.success)
|
|
345
|
+
throw new ContractApiError(-1, `[契约违例] authWecomAdminTenantAdminPasswordPost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
252
346
|
}
|
|
253
347
|
return data;
|
|
254
348
|
}
|
|
@@ -288,15 +382,22 @@ export async function authWecomCallbackGet(): Promise<unknown> {
|
|
|
288
382
|
}
|
|
289
383
|
|
|
290
384
|
export type AuthWecomTicketPostBody = z.input<(typeof schemas)["authWecomTicketPost"]["body"]>;
|
|
385
|
+
export type AuthWecomTicketPostData = z.infer<(typeof schemas)["authWecomTicketPost"]["data"]>;
|
|
291
386
|
|
|
292
|
-
export async function authWecomTicketPost(body: AuthWecomTicketPostBody): Promise<
|
|
387
|
+
export async function authWecomTicketPost(body: AuthWecomTicketPostBody): Promise<AuthWecomTicketPostData> {
|
|
293
388
|
const client = ensureReq();
|
|
294
389
|
try {
|
|
295
|
-
const env = await client.post(`auth/wecom/ticket`, { json: body }).json<OjEnvelope<
|
|
390
|
+
const env = await client.post(`auth/wecom/ticket`, { json: body }).json<OjEnvelope<AuthWecomTicketPostData>>();
|
|
296
391
|
// 2xx + code!==0 也是业务错误(§6.2 通道 a):oj 不会这么发,但契约机制的价值恰是防漂移
|
|
297
392
|
if (typeof env.code === "number" && env.code !== 0)
|
|
298
393
|
throw new ContractApiError(env.code, env.msg ?? "业务错误(信封 code 非 0)");
|
|
299
|
-
const data = env.data as
|
|
394
|
+
const data = env.data as AuthWecomTicketPostData;
|
|
395
|
+
if (import.meta.env.DEV) {
|
|
396
|
+
const { schemas } = await import("./api.schemas");
|
|
397
|
+
const r = schemas["authWecomTicketPost"].data.safeParse(data);
|
|
398
|
+
if (!r.success)
|
|
399
|
+
throw new ContractApiError(-1, `[契约违例] authWecomTicketPost 响应与契约不符:${r.error.issues.map(i => `${i.path.join(".") || "(root)"}: ${i.message}`).join("; ")}`);
|
|
400
|
+
}
|
|
300
401
|
return data;
|
|
301
402
|
}
|
|
302
403
|
catch (e) {
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { ModuleContext, ModuleI18n } from "@oj-module/runtime";
|
|
2
|
+
import { defineModule } from "@oj-module/runtime";
|
|
3
|
+
|
|
4
|
+
import { routes as homeRoutes } from "./home/routes";
|
|
5
|
+
import { onInit as loginOnInit, routes as loginRoutes } from "./login/routes";
|
|
6
|
+
import { onInit as notificationOnInit, routes as notificationRoutes } from "./notification/routes";
|
|
7
|
+
import { onInit as personalCenterOnInit, routes as personalCenterRoutes } from "./personal-center/routes";
|
|
8
|
+
import { onInit as systemOnInit, routes as systemRoutes } from "./system/routes";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 应用模块(多根聚合):一个 entry 承载六个业务根,各根独立成一级菜单。
|
|
12
|
+
*
|
|
13
|
+
* 为什么聚合:这六个根(首页/登录/个人中心/通知/系统管理)是脚手架的框架内置页面,
|
|
14
|
+
* 同版本发布、同生命周期、缺一不可,拆成六个模块只会把工程目录、web.config 登记、
|
|
15
|
+
* modules.json 与首屏模块入口请求都放大六倍。聚合后仍是「一目录一模块」,但模块内
|
|
16
|
+
* 按根分目录(`<root>/routes.ts` + `pages/` + `__client/`),页面相对导入不变。
|
|
17
|
+
*
|
|
18
|
+
* 结构约定(多根模块):
|
|
19
|
+
* - 顶层路由首段去重 > 1 → runtime 判为多根(`isMultiRoot`),各根按 entry 里的
|
|
20
|
+
* **绝对路径**原样注册,不被 `routePrefix` 改写——URL 与菜单 key 都不变;
|
|
21
|
+
* - 菜单顺序仍由各根 `handle.order` 决定(≥0 主区升序、<0 底部固定区),与聚合前
|
|
22
|
+
* 逐项一致;改顺序只改 order,不要依赖 routes 数组下标(缺省 order 会按数组下标兜底);
|
|
23
|
+
* - 门禁挂根路由:`/system` 的 `handle.roles` 等价于原先的模块级 requiredRoles。
|
|
24
|
+
*
|
|
25
|
+
* i18n 用 `i18nNamespaces` 沿用各根**原命名空间**(home / login / personal-center /
|
|
26
|
+
* notification / system),因此 `t("system:menu.users")`、`useTranslation("system")`
|
|
27
|
+
* 与菜单标题 `<ns>:menu.<key>` 全部零改动。
|
|
28
|
+
*/
|
|
29
|
+
const i18nNamespaces: Record<string, ModuleI18n> = {
|
|
30
|
+
"home": {
|
|
31
|
+
"zh-CN": () => import("./home/locales/zh-CN.json"),
|
|
32
|
+
"en-US": () => import("./home/locales/en-US.json"),
|
|
33
|
+
},
|
|
34
|
+
"login": {
|
|
35
|
+
"zh-CN": () => import("./login/locales/zh-CN.json"),
|
|
36
|
+
"en-US": () => import("./login/locales/en-US.json"),
|
|
37
|
+
},
|
|
38
|
+
"personal-center": {
|
|
39
|
+
"zh-CN": () => import("./personal-center/locales/zh-CN.json"),
|
|
40
|
+
"en-US": () => import("./personal-center/locales/en-US.json"),
|
|
41
|
+
},
|
|
42
|
+
"notification": {
|
|
43
|
+
"zh-CN": () => import("./notification/locales/zh-CN.json"),
|
|
44
|
+
"en-US": () => import("./notification/locales/en-US.json"),
|
|
45
|
+
},
|
|
46
|
+
"system": {
|
|
47
|
+
"zh-CN": () => import("./system/locales/zh-CN.json"),
|
|
48
|
+
"en-US": () => import("./system/locales/en-US.json"),
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default defineModule({
|
|
53
|
+
name: "app",
|
|
54
|
+
description: "应用模块:框架内置页面(首页/登录/个人中心/通知/系统管理),多根聚合",
|
|
55
|
+
version: "0.1.0",
|
|
56
|
+
peerRuntime: ">=0.0.0",
|
|
57
|
+
routes: [
|
|
58
|
+
...homeRoutes,
|
|
59
|
+
...loginRoutes,
|
|
60
|
+
...personalCenterRoutes,
|
|
61
|
+
...notificationRoutes,
|
|
62
|
+
...systemRoutes,
|
|
63
|
+
],
|
|
64
|
+
i18nNamespaces,
|
|
65
|
+
lifecycle: {
|
|
66
|
+
/**
|
|
67
|
+
* 各根的 onInit 按原模块加载顺序串行——login 必须最先(认证 provider 要在任何
|
|
68
|
+
* 登录动作前就位),其余是前缀登记/API provider 注入,顺序无相互依赖。
|
|
69
|
+
*/
|
|
70
|
+
async onInit(ctx: ModuleContext) {
|
|
71
|
+
await loginOnInit(ctx);
|
|
72
|
+
await personalCenterOnInit(ctx);
|
|
73
|
+
await notificationOnInit(ctx);
|
|
74
|
+
await systemOnInit(ctx);
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
});
|
|
@@ -17,6 +17,9 @@ export const API_PREFIX = "/home";
|
|
|
17
17
|
/** 认领身份前缀(契约 apiPrefix,字面等于模块目录名):跨模块认领护栏对比基准 */
|
|
18
18
|
export const MODULE_PREFIX = "/home";
|
|
19
19
|
|
|
20
|
+
/** 认领方模块(web.config clientOwners 指定):跨模块认领护栏对比基准 */
|
|
21
|
+
export const MODULE_OWNER = "/app";
|
|
22
|
+
|
|
20
23
|
/**
|
|
21
24
|
* 模块 entry 的 onInit 里一行创建(构造即 install):完成 apiPrefix 登记 +
|
|
22
25
|
* scoped request 绑定,返回绑好前缀的端点函数集合。一模块一 client;
|
|
@@ -28,8 +31,8 @@ export function createHomeClient(ctx: ModuleContext) {
|
|
|
28
31
|
// 单槽、卸载互相耦合;跨模块需求应由本模块创建后经 provider 暴露。
|
|
29
32
|
// 注意对比基准是 MODULE_PREFIX(目录名)而非 API_PREFIX——D-M8 映射时线上前缀
|
|
30
33
|
// 属于别的命名空间,认领身份仍按目录名。
|
|
31
|
-
if (import.meta.env.DEV && ctx.module.name !==
|
|
32
|
-
console.warn(`[ojm-api] 模块 "${ctx.module.name}" 正在认领 ${MODULE_PREFIX} 的 client——跨模块认领会共享 request 单槽、卸载互相耦合;应由 "${
|
|
34
|
+
if (import.meta.env.DEV && ctx.module.name !== MODULE_OWNER.slice(1)) {
|
|
35
|
+
console.warn(`[ojm-api] 模块 "${ctx.module.name}" 正在认领 ${MODULE_PREFIX} 的 client——跨模块认领会共享 request 单槽、卸载互相耦合;应由 "${MODULE_OWNER.slice(1)}" 模块在自身 onInit 创建,跨模块需求经 provider 暴露。`);
|
|
33
36
|
}
|
|
34
37
|
ctx.register.apiPrefix(API_PREFIX);
|
|
35
38
|
bindRequest(ctx.utils.request);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { AppRouteRecordRaw } from "@oj-module/runtime";
|
|
2
|
+
|
|
3
|
+
import { HomeOutlined } from "@ant-design/icons";
|
|
4
|
+
|
|
5
|
+
import { createElement, lazy } from "react";
|
|
6
|
+
|
|
7
|
+
const Home = lazy(() => import("./pages/index"));
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* 首页根 `/home`。
|
|
11
|
+
*
|
|
12
|
+
* 为什么必须有:shell 预构建产物把 `VITE_BASE_HOME_PATH` 定为 `/home`
|
|
13
|
+
* (登录成功回跳、logo 点击、tabbar 首页、403/404 回首页都指向它)。
|
|
14
|
+
* 工程缺 `/home` 路由时这些跳转会落到错误边界。
|
|
15
|
+
*
|
|
16
|
+
* 结构对齐 playground-oj/web/src/home;页面用统计卡片 + 折线/柱/饼图
|
|
17
|
+
* 演示宿主共享依赖矩阵(echarts / echarts-for-react / react-countup / dayjs /
|
|
18
|
+
* antd / @ant-design/icons / react-i18next,均由宿主 importmap 提供单例)。
|
|
19
|
+
* 图表数据为静态演示值——真实业务走模块契约 + `ojm api` 生成的 client。
|
|
20
|
+
*/
|
|
21
|
+
export const routes: AppRouteRecordRaw[] = [
|
|
22
|
+
{
|
|
23
|
+
path: "/home",
|
|
24
|
+
handle: {
|
|
25
|
+
layout: "container",
|
|
26
|
+
order: 1,
|
|
27
|
+
title: "home:menu.home",
|
|
28
|
+
icon: createElement(HomeOutlined),
|
|
29
|
+
},
|
|
30
|
+
children: [
|
|
31
|
+
{
|
|
32
|
+
index: true,
|
|
33
|
+
Component: Home,
|
|
34
|
+
handle: {
|
|
35
|
+
title: "home:menu.home",
|
|
36
|
+
icon: createElement(HomeOutlined),
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
];
|