@oj-module/cli 0.2.66 → 0.2.67
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/bin/.oj-version +1 -0
- package/bin/oj +4 -0
- package/devkit/README.md +15 -7
- package/devkit/SKILL.md +30 -1
- package/devkit/framework-dev.md +10 -4
- package/devkit/manual.md +38 -12
- package/devkit/publish-walkthrough.md +110 -37
- package/devkit/wecom-internal-app.md +7 -2
- package/devkit/wecom-multi-corp-links.md +163 -0
- package/package.json +2 -2
- package/shell-dist/assets/{index.i0kqbxp050.js → index.6alqyx6ae0.js} +21 -1
- package/shell-dist/assets/{runtime.1xfsxcajj0.js → runtime.2dgstpjsu0.js} +3449 -3449
- package/shell-dist/index.html +4 -4
- package/shell-dist/versions.json +3 -3
- package/src/__tests__/publish-keygen.test.ts +157 -0
- package/src/__tests__/templates-migration-schema-parity.test.ts +540 -0
- package/src/__tests__/templates-schema-columns.test.ts +15 -2
- package/src/__tests__/templates-tenant-scope.test.ts +6 -2
- package/src/bundle.ts +8 -3
- package/src/cli.ts +17 -5
- package/src/dev.ts +15 -10
- package/src/install.ts +11 -4
- package/src/keygen.ts +54 -0
- package/src/lifecycle/__tests__/bundle.test.ts +21 -3
- package/src/lifecycle/__tests__/fixtures/fixture-valid/api/src/demo-solution/manifest.yaml +1 -1
- package/src/lifecycle/__tests__/fixtures/fixture-valid/api/src/demo-solution/migrations/0001__init.sql +2 -2
- package/src/lifecycle/__tests__/fixtures/fixture-valid/api/src/demo-solution/schema.yaml +5 -2
- package/src/lifecycle/__tests__/fixtures/fixture-valid/manifest.yaml +1 -1
- package/src/lifecycle/__tests__/manifest-contract.test.ts +75 -3
- package/src/lifecycle/__tests__/smoke.test.ts +2 -2
- package/src/manifest-contract.ts +91 -8
- package/src/market/bootstrap.ts +26 -2
- package/src/market/command.ts +1 -0
- package/src/market/publish.ts +5 -1
- package/src/market/walkthrough.ts +24 -8
- package/src/site.ts +2 -0
- package/src/usage.ts +8 -4
- package/src/vendor.ts +5 -1
- package/templates/config.yaml +4 -2
- package/templates/init.include.yaml +8 -3
- package/templates/openapi.json +460 -1
- package/templates/src/app/api/_platform/_lifecycle/compensate.ts +136 -0
- package/templates/src/app/api/_platform/_lifecycle/installer.ts +71 -22
- package/templates/src/app/api/_platform/_lifecycle/lock.ts +23 -0
- package/templates/src/app/api/_platform/_lifecycle/steps/deploy-web.ts +28 -0
- package/templates/src/app/api/_platform/_lifecycle/steps/preflight.ts +46 -0
- package/templates/src/app/api/_platform/_lifecycle/steps/reload.ts +100 -36
- package/templates/src/app/api/_platform/_lifecycle/steps/smoke.ts +7 -15
- package/templates/src/app/api/_platform/_lifecycle/text-edit.ts +71 -19
- package/templates/src/app/api/_platform/_lifecycle/types.ts +26 -2
- package/templates/src/app/api/_platform/_lifecycle/uninstall.ts +93 -14
- package/templates/src/app/api/_platform/_shared/service/domain/settings.ts +8 -4
- package/templates/src/app/api/_platform/manifest.yaml +1 -0
- package/templates/src/app/api/_platform/market/api.ts +235 -10
- package/templates/src/app/api/_platform/migrations/0001__baseline.mysql.sql +178 -0
- package/templates/src/app/api/_platform/migrations/0001__baseline.pg.sql +173 -0
- package/templates/src/app/api/_platform/migrations/0001__baseline.sql +188 -0
- package/templates/src/app/api/_platform/migrations/0002__market_release.mysql.sql +17 -0
- package/templates/src/app/api/_platform/migrations/0002__market_release.pg.sql +16 -0
- package/templates/src/app/api/_platform/migrations/0002__market_release.sql +33 -0
- package/templates/src/app/api/_platform/schema.yaml +18 -0
- package/templates/src/app/api/_platform/seed.mysql.sql +10 -0
- package/templates/src/app/api/_platform/seed.pg.sql +10 -0
- package/templates/src/app/api/auth/_shared/wecom/client.ts +24 -4
- package/templates/src/app/api/home/migrations/0001__create_home_tables.mysql.sql +14 -0
- package/templates/src/app/api/home/migrations/0001__create_home_tables.pg.sql +14 -0
- package/templates/src/app/api/home/migrations/0002__tenant.pg.sql +4 -0
- package/templates/src/app/api/home/seed.mysql.sql +71 -0
- package/templates/src/app/api/home/seed.pg.sql +71 -0
- package/templates/src/app/api/notification/_shared/notify.ts +6 -6
- package/templates/src/app/api/notification/migrations/0001__create_notifications.mysql.sql +11 -0
- package/templates/src/app/api/notification/migrations/0001__create_notifications.pg.sql +11 -0
- package/templates/src/app/api/notification/migrations/0002__notifications_user.mysql.sql +8 -0
- package/templates/src/app/api/notification/migrations/0003__notifications_broadcast.mysql.sql +21 -0
- package/templates/src/app/api/notification/migrations/0003__notifications_broadcast.pg.sql +22 -0
- package/templates/src/app/api/notification/migrations/0004__notifications_broadcast_hidden.mysql.sql +10 -0
- package/templates/src/app/api/notification/migrations/0004__notifications_broadcast_hidden.pg.sql +11 -0
- package/templates/src/app/api/notification/migrations/0005__tenant.pg.sql +6 -0
- package/templates/src/app/api/notification/seed.mysql.sql +8 -0
- package/templates/src/app/api/notification/seed.pg.sql +11 -0
- package/templates/src/app/api/publish/_shared/identity.ts +69 -0
- package/templates/src/app/api/publish/api.ts +349 -0
- package/templates/src/app/api/publish/manifest.yaml +8 -0
- package/templates/src/app/api/publish/migrations/0001__publish_credential.mysql.sql +23 -0
- package/templates/src/app/api/publish/migrations/0001__publish_credential.pg.sql +23 -0
- package/templates/src/app/api/publish/migrations/0001__publish_credential.sql +39 -0
- package/templates/src/app/api/publish/schema.yaml +33 -0
- package/templates/src/app/api/system/login-methods/api.ts +2 -1
- package/templates/src/app/web/_platform/__client/api.schemas.ts +15 -0
- package/templates/src/app/web/_platform/__client/index.ts +25 -1
- package/templates/src/app/web/entry.ts +9 -5
- package/templates/src/app/web/home/routes.ts +5 -0
- package/templates/src/app/web/login/locales/en-US.json +7 -1
- package/templates/src/app/web/login/locales/zh-CN.json +7 -1
- package/templates/src/app/web/login/pages/login.tsx +79 -86
- package/templates/src/app/web/login/routes.ts +54 -1
- package/templates/src/app/web/personal-center/locales/en-US.json +1 -0
- package/templates/src/app/web/personal-center/locales/zh-CN.json +1 -0
- package/templates/src/app/web/personal-center/pages/my-profile/index.tsx +5 -0
- package/templates/src/app/web/system/__client/api.schemas.ts +2 -1
- package/templates/src/app/web/system/locales/en-US.json +1 -8
- package/templates/src/app/web/system/locales/zh-CN.json +1 -8
- package/templates/src/app/web/system/pages/settings/index.tsx +17 -4
- package/templates/src/app/web/system/routes.ts +0 -6
- package/templates/src/oj-market/web/__tests__/CardGrid.test.tsx +33 -0
- package/templates/src/oj-market/web/__tests__/DetailDrawer.test.tsx +69 -0
- package/templates/src/oj-market/web/__tests__/marketClient.fake.ts +7 -1
- package/templates/src/oj-market/web/api/client.ts +3 -0
- package/templates/src/oj-market/web/api/defaultClient.ts +5 -0
- package/templates/src/oj-market/web/components/CardItem.tsx +44 -1
- package/templates/src/oj-market/web/components/DetailDrawer.tsx +17 -1
- package/templates/src/oj-market/web/entry.ts +31 -2
- package/templates/src/oj-market/web/locales/en-US.json +5 -1
- package/templates/src/oj-market/web/locales/zh-CN.json +5 -1
- package/templates/src/oj-market/web/publish/__client/api.schemas.ts +61 -0
- package/templates/src/oj-market/web/publish/__client/index.ts +164 -0
- package/templates/src/oj-market/web/publish/locales/en-US.json +80 -0
- package/templates/src/oj-market/web/publish/locales/zh-CN.json +80 -0
- package/templates/src/oj-market/web/publish/pages/history.tsx +112 -0
- package/templates/src/oj-market/web/publish/pages/index.tsx +196 -0
- package/templates/src/oj-market/web/publish/pages/model.ts +52 -0
- package/templates/src/oj-market/web/publish/pages/token-modal.tsx +82 -0
- package/templates/src/oj-market/web/publish/routes.ts +41 -0
- package/templates/src/oj-market/web/types.ts +30 -0
- package/templates/tests/lifecycle/compensate.spec.ts +207 -0
- package/templates/tests/lifecycle/deploy-smoke.spec.ts +38 -14
- package/templates/tests/lifecycle/installer.spec.ts +28 -9
- package/templates/tests/lifecycle/market-api.spec.ts +164 -12
- package/templates/tests/lifecycle/preflight.spec.ts +68 -0
- package/templates/tests/lifecycle/role-title-translate.spec.ts +2 -32
- package/templates/tests/lifecycle/text-edit.spec.ts +45 -27
- package/templates/tests/lifecycle/uninstall.spec.ts +36 -0
- package/templates/tests/publish-credential.spec.ts +354 -0
- package/templates/tests/publish-identity.spec.ts +44 -0
- package/templates/tests/wecom-client-timeout.spec.ts +33 -3
- package/templates/tests/wecom-landing.spec.ts +63 -1
- package/templates/tsconfig.paths.json +1 -0
- package/templates/web.config.ts +6 -4
- package/vendor/host-versions.json +3 -3
- package/templates/seed.mysql.sql +0 -6
- package/templates/seed.pg.sql +0 -6
- package/templates/src/app/api/_platform/migrations/0001__create_users.mysql.sql +0 -9
- package/templates/src/app/api/_platform/migrations/0001__create_users.pg.sql +0 -9
- package/templates/src/app/api/_platform/migrations/0001__create_users.sql +0 -7
- package/templates/src/app/api/_platform/migrations/0002__add_users_avatar_base64.mysql.sql +0 -3
- package/templates/src/app/api/_platform/migrations/0002__add_users_avatar_base64.sql +0 -2
- package/templates/src/app/api/_platform/migrations/0003__users_source_display_name.mysql.sql +0 -5
- package/templates/src/app/api/_platform/migrations/0003__users_source_display_name.sql +0 -5
- package/templates/src/app/api/_platform/migrations/0004__sys_rbac.mysql.sql +0 -70
- package/templates/src/app/api/_platform/migrations/0004__sys_rbac.pg.sql +0 -67
- package/templates/src/app/api/_platform/migrations/0004__sys_rbac.sql +0 -67
- package/templates/src/app/api/_platform/migrations/0005__users_must_change.mysql.sql +0 -3
- package/templates/src/app/api/_platform/migrations/0005__users_must_change.sql +0 -2
- package/templates/src/app/api/_platform/migrations/0006__users_is_forbidden.mysql.sql +0 -3
- package/templates/src/app/api/_platform/migrations/0006__users_is_forbidden.sql +0 -3
- package/templates/src/app/api/_platform/migrations/0007__users_email.sql +0 -3
- package/templates/src/app/api/_platform/migrations/0008__sys_refresh_token.mysql.sql +0 -10
- package/templates/src/app/api/_platform/migrations/0008__sys_refresh_token.pg.sql +0 -10
- package/templates/src/app/api/_platform/migrations/0008__sys_refresh_token.sql +0 -11
- package/templates/src/app/api/_platform/migrations/0009__sys_throttle.mysql.sql +0 -12
- package/templates/src/app/api/_platform/migrations/0009__sys_throttle.pg.sql +0 -12
- package/templates/src/app/api/_platform/migrations/0009__sys_throttle.sql +0 -13
- package/templates/src/app/api/_platform/migrations/0010__sys_solution_route.mysql.sql +0 -17
- package/templates/src/app/api/_platform/migrations/0010__sys_solution_route.pg.sql +0 -16
- package/templates/src/app/api/_platform/migrations/0010__sys_solution_route.sql +0 -18
- package/templates/src/app/api/_platform/migrations/0011__sys_setting_group_label.mysql.sql +0 -2
- package/templates/src/app/api/_platform/migrations/0011__sys_setting_group_label.sql +0 -4
- package/templates/src/app/api/_platform/migrations/0012__market_history.mysql.sql +0 -13
- package/templates/src/app/api/_platform/migrations/0012__market_history.pg.sql +0 -12
- package/templates/src/app/api/_platform/migrations/0012__market_history.sql +0 -14
- package/templates/src/app/api/_platform/migrations/0013__users_profile.sql +0 -4
- package/templates/src/app/api/_platform/migrations/0014__reg_source_seq.mysql.sql +0 -9
- package/templates/src/app/api/_platform/migrations/0014__reg_source_seq.pg.sql +0 -7
- package/templates/src/app/api/_platform/migrations/0014__reg_source_seq.sql +0 -8
- package/templates/src/app/api/_platform/migrations/0015__tenant.mysql.sql +0 -12
- package/templates/src/app/api/_platform/migrations/0015__tenant.pg.sql +0 -11
- package/templates/src/app/api/_platform/migrations/0015__tenant.sql +0 -44
- package/templates/src/app/api/_platform/migrations/0016__org.mysql.sql +0 -41
- package/templates/src/app/api/_platform/migrations/0016__org.pg.sql +0 -40
- package/templates/src/app/api/_platform/migrations/0016__org.sql +0 -62
- package/templates/src/app/api/_platform/migrations/0017__users_employee_no.mysql.sql +0 -7
- package/templates/src/app/api/_platform/migrations/0017__users_employee_no.pg.sql +0 -4
- package/templates/src/app/api/_platform/migrations/0017__users_employee_no.sql +0 -8
- package/templates/src/app/api/_platform/migrations/0018__sys_role_title_key.mysql.sql +0 -3
- package/templates/src/app/api/_platform/migrations/0018__sys_role_title_key.pg.sql +0 -3
- package/templates/src/app/api/_platform/migrations/0018__sys_role_title_key.sql +0 -8
- package/templates/src/app/web/system/pages/login-methods/index.tsx +0 -30
package/templates/openapi.json
CHANGED
|
@@ -870,6 +870,96 @@
|
|
|
870
870
|
}
|
|
871
871
|
}
|
|
872
872
|
},
|
|
873
|
+
"/api/_platform/market/releases": {
|
|
874
|
+
"get": {
|
|
875
|
+
"operationId": "_platform_market_releases_get",
|
|
876
|
+
"summary": "GET api/_platform/market/releases",
|
|
877
|
+
"x-oj-file": "app/api/_platform/market/api.ts",
|
|
878
|
+
"tags": [
|
|
879
|
+
"_platform"
|
|
880
|
+
],
|
|
881
|
+
"parameters": [
|
|
882
|
+
{
|
|
883
|
+
"name": "page",
|
|
884
|
+
"in": "query",
|
|
885
|
+
"required": false,
|
|
886
|
+
"schema": {
|
|
887
|
+
"type": "number",
|
|
888
|
+
"minimum": 1
|
|
889
|
+
}
|
|
890
|
+
},
|
|
891
|
+
{
|
|
892
|
+
"name": "limit",
|
|
893
|
+
"in": "query",
|
|
894
|
+
"required": false,
|
|
895
|
+
"schema": {
|
|
896
|
+
"type": "number",
|
|
897
|
+
"minimum": 1,
|
|
898
|
+
"maximum": 200
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
],
|
|
902
|
+
"responses": {
|
|
903
|
+
"200": {
|
|
904
|
+
"description": "OK",
|
|
905
|
+
"x-oj-response-enforced": false,
|
|
906
|
+
"content": {
|
|
907
|
+
"application/json": {
|
|
908
|
+
"schema": {
|
|
909
|
+
"type": "object",
|
|
910
|
+
"required": [
|
|
911
|
+
"code",
|
|
912
|
+
"msg",
|
|
913
|
+
"data"
|
|
914
|
+
],
|
|
915
|
+
"properties": {
|
|
916
|
+
"code": {
|
|
917
|
+
"type": "integer"
|
|
918
|
+
},
|
|
919
|
+
"msg": {
|
|
920
|
+
"type": "string"
|
|
921
|
+
},
|
|
922
|
+
"data": {
|
|
923
|
+
"type": "object",
|
|
924
|
+
"required": [
|
|
925
|
+
"list",
|
|
926
|
+
"total",
|
|
927
|
+
"page",
|
|
928
|
+
"size"
|
|
929
|
+
],
|
|
930
|
+
"properties": {
|
|
931
|
+
"list": {
|
|
932
|
+
"type": "array",
|
|
933
|
+
"items": {
|
|
934
|
+
"type": "object",
|
|
935
|
+
"additionalProperties": true
|
|
936
|
+
}
|
|
937
|
+
},
|
|
938
|
+
"total": {
|
|
939
|
+
"type": "number"
|
|
940
|
+
},
|
|
941
|
+
"page": {
|
|
942
|
+
"type": "number"
|
|
943
|
+
},
|
|
944
|
+
"size": {
|
|
945
|
+
"type": "number"
|
|
946
|
+
},
|
|
947
|
+
"syncError": {
|
|
948
|
+
"type": [
|
|
949
|
+
"string",
|
|
950
|
+
"null"
|
|
951
|
+
]
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
},
|
|
873
963
|
"/api/_platform/org/departments": {
|
|
874
964
|
"get": {
|
|
875
965
|
"operationId": "_platform_org_departments_get",
|
|
@@ -4536,6 +4626,368 @@
|
|
|
4536
4626
|
}
|
|
4537
4627
|
}
|
|
4538
4628
|
},
|
|
4629
|
+
"/api/publish/credential": {
|
|
4630
|
+
"get": {
|
|
4631
|
+
"operationId": "publish_credential_get",
|
|
4632
|
+
"summary": "GET api/publish/credential",
|
|
4633
|
+
"x-oj-file": "app/api/publish/api.ts",
|
|
4634
|
+
"tags": [
|
|
4635
|
+
"publish"
|
|
4636
|
+
],
|
|
4637
|
+
"parameters": [
|
|
4638
|
+
{
|
|
4639
|
+
"name": "page",
|
|
4640
|
+
"in": "query",
|
|
4641
|
+
"required": false,
|
|
4642
|
+
"schema": {
|
|
4643
|
+
"type": "number",
|
|
4644
|
+
"minimum": 1
|
|
4645
|
+
}
|
|
4646
|
+
},
|
|
4647
|
+
{
|
|
4648
|
+
"name": "limit",
|
|
4649
|
+
"in": "query",
|
|
4650
|
+
"required": false,
|
|
4651
|
+
"schema": {
|
|
4652
|
+
"type": "number",
|
|
4653
|
+
"minimum": 1,
|
|
4654
|
+
"maximum": 200
|
|
4655
|
+
}
|
|
4656
|
+
},
|
|
4657
|
+
{
|
|
4658
|
+
"name": "tenant",
|
|
4659
|
+
"in": "query",
|
|
4660
|
+
"required": false,
|
|
4661
|
+
"schema": {
|
|
4662
|
+
"type": "string"
|
|
4663
|
+
}
|
|
4664
|
+
}
|
|
4665
|
+
],
|
|
4666
|
+
"responses": {
|
|
4667
|
+
"200": {
|
|
4668
|
+
"description": "OK",
|
|
4669
|
+
"x-oj-response-enforced": false,
|
|
4670
|
+
"content": {
|
|
4671
|
+
"application/json": {
|
|
4672
|
+
"schema": {
|
|
4673
|
+
"type": "object",
|
|
4674
|
+
"required": [
|
|
4675
|
+
"code",
|
|
4676
|
+
"msg",
|
|
4677
|
+
"data"
|
|
4678
|
+
],
|
|
4679
|
+
"properties": {
|
|
4680
|
+
"code": {
|
|
4681
|
+
"type": "integer"
|
|
4682
|
+
},
|
|
4683
|
+
"msg": {
|
|
4684
|
+
"type": "string"
|
|
4685
|
+
},
|
|
4686
|
+
"data": {
|
|
4687
|
+
"type": "object",
|
|
4688
|
+
"required": [
|
|
4689
|
+
"list",
|
|
4690
|
+
"total"
|
|
4691
|
+
],
|
|
4692
|
+
"properties": {
|
|
4693
|
+
"list": {
|
|
4694
|
+
"type": "array",
|
|
4695
|
+
"items": {
|
|
4696
|
+
"type": "object",
|
|
4697
|
+
"required": [
|
|
4698
|
+
"id",
|
|
4699
|
+
"product",
|
|
4700
|
+
"key_id",
|
|
4701
|
+
"username",
|
|
4702
|
+
"token_hint",
|
|
4703
|
+
"status",
|
|
4704
|
+
"expires_at",
|
|
4705
|
+
"created_at"
|
|
4706
|
+
],
|
|
4707
|
+
"properties": {
|
|
4708
|
+
"id": {
|
|
4709
|
+
"type": "number"
|
|
4710
|
+
},
|
|
4711
|
+
"product": {
|
|
4712
|
+
"type": "string"
|
|
4713
|
+
},
|
|
4714
|
+
"key_id": {
|
|
4715
|
+
"type": "string"
|
|
4716
|
+
},
|
|
4717
|
+
"username": {
|
|
4718
|
+
"type": "string"
|
|
4719
|
+
},
|
|
4720
|
+
"display_name": {
|
|
4721
|
+
"type": [
|
|
4722
|
+
"string",
|
|
4723
|
+
"null"
|
|
4724
|
+
]
|
|
4725
|
+
},
|
|
4726
|
+
"token_hint": {
|
|
4727
|
+
"type": "string"
|
|
4728
|
+
},
|
|
4729
|
+
"status": {
|
|
4730
|
+
"type": "string",
|
|
4731
|
+
"enum": [
|
|
4732
|
+
"active",
|
|
4733
|
+
"used",
|
|
4734
|
+
"revoked",
|
|
4735
|
+
"expired"
|
|
4736
|
+
]
|
|
4737
|
+
},
|
|
4738
|
+
"expires_at": {
|
|
4739
|
+
"type": "number"
|
|
4740
|
+
},
|
|
4741
|
+
"used_at": {
|
|
4742
|
+
"type": [
|
|
4743
|
+
"number",
|
|
4744
|
+
"null"
|
|
4745
|
+
]
|
|
4746
|
+
},
|
|
4747
|
+
"created_at": {
|
|
4748
|
+
"type": "number"
|
|
4749
|
+
},
|
|
4750
|
+
"owner_tenant": {
|
|
4751
|
+
"type": "string"
|
|
4752
|
+
}
|
|
4753
|
+
}
|
|
4754
|
+
}
|
|
4755
|
+
},
|
|
4756
|
+
"total": {
|
|
4757
|
+
"type": "number"
|
|
4758
|
+
}
|
|
4759
|
+
}
|
|
4760
|
+
}
|
|
4761
|
+
}
|
|
4762
|
+
}
|
|
4763
|
+
}
|
|
4764
|
+
}
|
|
4765
|
+
}
|
|
4766
|
+
}
|
|
4767
|
+
},
|
|
4768
|
+
"post": {
|
|
4769
|
+
"operationId": "publish_credential_post",
|
|
4770
|
+
"summary": "POST api/publish/credential",
|
|
4771
|
+
"x-oj-file": "app/api/publish/api.ts",
|
|
4772
|
+
"tags": [
|
|
4773
|
+
"publish"
|
|
4774
|
+
],
|
|
4775
|
+
"requestBody": {
|
|
4776
|
+
"required": true,
|
|
4777
|
+
"content": {
|
|
4778
|
+
"application/json": {
|
|
4779
|
+
"schema": {
|
|
4780
|
+
"type": "object",
|
|
4781
|
+
"required": [
|
|
4782
|
+
"product"
|
|
4783
|
+
],
|
|
4784
|
+
"properties": {
|
|
4785
|
+
"product": {
|
|
4786
|
+
"type": "string"
|
|
4787
|
+
}
|
|
4788
|
+
}
|
|
4789
|
+
}
|
|
4790
|
+
}
|
|
4791
|
+
}
|
|
4792
|
+
},
|
|
4793
|
+
"responses": {
|
|
4794
|
+
"200": {
|
|
4795
|
+
"description": "OK",
|
|
4796
|
+
"x-oj-response-enforced": false,
|
|
4797
|
+
"content": {
|
|
4798
|
+
"application/json": {
|
|
4799
|
+
"schema": {
|
|
4800
|
+
"type": "object",
|
|
4801
|
+
"required": [
|
|
4802
|
+
"code",
|
|
4803
|
+
"msg",
|
|
4804
|
+
"data"
|
|
4805
|
+
],
|
|
4806
|
+
"properties": {
|
|
4807
|
+
"code": {
|
|
4808
|
+
"type": "integer"
|
|
4809
|
+
},
|
|
4810
|
+
"msg": {
|
|
4811
|
+
"type": "string"
|
|
4812
|
+
},
|
|
4813
|
+
"data": {
|
|
4814
|
+
"type": "object",
|
|
4815
|
+
"required": [
|
|
4816
|
+
"token",
|
|
4817
|
+
"key_id",
|
|
4818
|
+
"product",
|
|
4819
|
+
"expires_at"
|
|
4820
|
+
],
|
|
4821
|
+
"properties": {
|
|
4822
|
+
"token": {
|
|
4823
|
+
"type": "string"
|
|
4824
|
+
},
|
|
4825
|
+
"key_id": {
|
|
4826
|
+
"type": "string"
|
|
4827
|
+
},
|
|
4828
|
+
"product": {
|
|
4829
|
+
"type": "string"
|
|
4830
|
+
},
|
|
4831
|
+
"token_hint": {
|
|
4832
|
+
"type": "string"
|
|
4833
|
+
},
|
|
4834
|
+
"expires_at": {
|
|
4835
|
+
"type": "number"
|
|
4836
|
+
}
|
|
4837
|
+
}
|
|
4838
|
+
}
|
|
4839
|
+
}
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4842
|
+
}
|
|
4843
|
+
}
|
|
4844
|
+
}
|
|
4845
|
+
}
|
|
4846
|
+
},
|
|
4847
|
+
"/api/publish/credential/revoke": {
|
|
4848
|
+
"post": {
|
|
4849
|
+
"operationId": "publish_credential_revoke_post",
|
|
4850
|
+
"summary": "POST api/publish/credential/revoke",
|
|
4851
|
+
"x-oj-file": "app/api/publish/api.ts",
|
|
4852
|
+
"tags": [
|
|
4853
|
+
"publish"
|
|
4854
|
+
],
|
|
4855
|
+
"requestBody": {
|
|
4856
|
+
"required": true,
|
|
4857
|
+
"content": {
|
|
4858
|
+
"application/json": {
|
|
4859
|
+
"schema": {
|
|
4860
|
+
"type": "object",
|
|
4861
|
+
"required": [
|
|
4862
|
+
"id"
|
|
4863
|
+
],
|
|
4864
|
+
"properties": {
|
|
4865
|
+
"id": {
|
|
4866
|
+
"type": "number"
|
|
4867
|
+
}
|
|
4868
|
+
}
|
|
4869
|
+
}
|
|
4870
|
+
}
|
|
4871
|
+
}
|
|
4872
|
+
},
|
|
4873
|
+
"responses": {
|
|
4874
|
+
"200": {
|
|
4875
|
+
"description": "OK",
|
|
4876
|
+
"x-oj-response-enforced": false,
|
|
4877
|
+
"content": {
|
|
4878
|
+
"application/json": {
|
|
4879
|
+
"schema": {
|
|
4880
|
+
"type": "object",
|
|
4881
|
+
"required": [
|
|
4882
|
+
"code",
|
|
4883
|
+
"msg",
|
|
4884
|
+
"data"
|
|
4885
|
+
],
|
|
4886
|
+
"properties": {
|
|
4887
|
+
"code": {
|
|
4888
|
+
"type": "integer"
|
|
4889
|
+
},
|
|
4890
|
+
"msg": {
|
|
4891
|
+
"type": "string"
|
|
4892
|
+
},
|
|
4893
|
+
"data": {
|
|
4894
|
+
"type": "object",
|
|
4895
|
+
"required": [
|
|
4896
|
+
"ok"
|
|
4897
|
+
],
|
|
4898
|
+
"properties": {
|
|
4899
|
+
"ok": {
|
|
4900
|
+
"type": "boolean"
|
|
4901
|
+
}
|
|
4902
|
+
}
|
|
4903
|
+
}
|
|
4904
|
+
}
|
|
4905
|
+
}
|
|
4906
|
+
}
|
|
4907
|
+
}
|
|
4908
|
+
}
|
|
4909
|
+
}
|
|
4910
|
+
}
|
|
4911
|
+
},
|
|
4912
|
+
"/api/publish/credential/exchange": {
|
|
4913
|
+
"post": {
|
|
4914
|
+
"operationId": "publish_credential_exchange_post",
|
|
4915
|
+
"summary": "POST api/publish/credential/exchange",
|
|
4916
|
+
"x-oj-file": "app/api/publish/api.ts",
|
|
4917
|
+
"tags": [
|
|
4918
|
+
"publish"
|
|
4919
|
+
],
|
|
4920
|
+
"requestBody": {
|
|
4921
|
+
"required": true,
|
|
4922
|
+
"content": {
|
|
4923
|
+
"application/json": {
|
|
4924
|
+
"schema": {
|
|
4925
|
+
"type": "object",
|
|
4926
|
+
"required": [
|
|
4927
|
+
"token"
|
|
4928
|
+
],
|
|
4929
|
+
"properties": {
|
|
4930
|
+
"token": {
|
|
4931
|
+
"type": "string"
|
|
4932
|
+
}
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4935
|
+
}
|
|
4936
|
+
}
|
|
4937
|
+
},
|
|
4938
|
+
"responses": {
|
|
4939
|
+
"200": {
|
|
4940
|
+
"description": "OK",
|
|
4941
|
+
"x-oj-response-enforced": false,
|
|
4942
|
+
"content": {
|
|
4943
|
+
"application/json": {
|
|
4944
|
+
"schema": {
|
|
4945
|
+
"type": "object",
|
|
4946
|
+
"required": [
|
|
4947
|
+
"code",
|
|
4948
|
+
"msg",
|
|
4949
|
+
"data"
|
|
4950
|
+
],
|
|
4951
|
+
"properties": {
|
|
4952
|
+
"code": {
|
|
4953
|
+
"type": "integer"
|
|
4954
|
+
},
|
|
4955
|
+
"msg": {
|
|
4956
|
+
"type": "string"
|
|
4957
|
+
},
|
|
4958
|
+
"data": {
|
|
4959
|
+
"type": "object",
|
|
4960
|
+
"required": [
|
|
4961
|
+
"key_id",
|
|
4962
|
+
"product",
|
|
4963
|
+
"username"
|
|
4964
|
+
],
|
|
4965
|
+
"properties": {
|
|
4966
|
+
"key_id": {
|
|
4967
|
+
"type": "string"
|
|
4968
|
+
},
|
|
4969
|
+
"product": {
|
|
4970
|
+
"type": "string"
|
|
4971
|
+
},
|
|
4972
|
+
"username": {
|
|
4973
|
+
"type": "string"
|
|
4974
|
+
},
|
|
4975
|
+
"display_name": {
|
|
4976
|
+
"type": [
|
|
4977
|
+
"string",
|
|
4978
|
+
"null"
|
|
4979
|
+
]
|
|
4980
|
+
}
|
|
4981
|
+
}
|
|
4982
|
+
}
|
|
4983
|
+
}
|
|
4984
|
+
}
|
|
4985
|
+
}
|
|
4986
|
+
}
|
|
4987
|
+
}
|
|
4988
|
+
}
|
|
4989
|
+
}
|
|
4990
|
+
},
|
|
4539
4991
|
"/api/system/departments": {
|
|
4540
4992
|
"get": {
|
|
4541
4993
|
"operationId": "system_departments_get",
|
|
@@ -5325,7 +5777,8 @@
|
|
|
5325
5777
|
"data": {
|
|
5326
5778
|
"type": "object",
|
|
5327
5779
|
"required": [
|
|
5328
|
-
"methods"
|
|
5780
|
+
"methods",
|
|
5781
|
+
"site_title"
|
|
5329
5782
|
],
|
|
5330
5783
|
"properties": {
|
|
5331
5784
|
"methods": {
|
|
@@ -5333,6 +5786,9 @@
|
|
|
5333
5786
|
"items": {
|
|
5334
5787
|
"type": "string"
|
|
5335
5788
|
}
|
|
5789
|
+
},
|
|
5790
|
+
"site_title": {
|
|
5791
|
+
"type": "string"
|
|
5336
5792
|
}
|
|
5337
5793
|
}
|
|
5338
5794
|
}
|
|
@@ -6862,6 +7318,9 @@
|
|
|
6862
7318
|
{
|
|
6863
7319
|
"name": "personal-center"
|
|
6864
7320
|
},
|
|
7321
|
+
{
|
|
7322
|
+
"name": "publish"
|
|
7323
|
+
},
|
|
6865
7324
|
{
|
|
6866
7325
|
"name": "system"
|
|
6867
7326
|
},
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// 安装补偿清单(P0 §3.5):锁后失败(registering/deploying_web/reloading/smoke)时,把站点恢复到
|
|
2
|
+
// 「装前代」状态——旧代继续服务,任务标 partial + 可重试。本模块是回滚的唯一入口(SRP:只负责
|
|
3
|
+
// 逆序回滚已落盘资产,不含装前校验/审计/终态文案),各资产回滚原语各自单一函数(OCP:新增资产
|
|
4
|
+
// 类型只需加一个原语 + 在此注册一步)。所有原语幂等(缺则 no-op),故补偿可安全被重试端点反复调用。
|
|
5
|
+
// 与 cancelCleanup 的区别(intentionally 不同):取消 = 回到装前且删版本目录;补偿 = 回到装前代
|
|
6
|
+
// 但**保留版本目录**供重试。两者共用 revertLock(lock.ts)不重复锁回退逻辑(DRY)。
|
|
7
|
+
|
|
8
|
+
import type { ReloadFace } from "./steps/reload";
|
|
9
|
+
import { atomicWriteText, fsFace, isMissingPath } from "./atomic";
|
|
10
|
+
import { revertLock } from "./lock";
|
|
11
|
+
import { removeModulesJsonEntry } from "./steps/deploy-web";
|
|
12
|
+
import { removeAnonymousPaths } from "./text-edit";
|
|
13
|
+
import { revertRegistrations } from "./uninstall";
|
|
14
|
+
|
|
15
|
+
/** 本仓 preview 派生文件名(与 cli preview-config.ts / installer.ts 逐字一致) */
|
|
16
|
+
const PREVIEW_CONFIG_NAME = ".ojm-preview.yaml";
|
|
17
|
+
|
|
18
|
+
/** 与 config 同目录的 preview 派生路径(无目录分隔符 = 同目录裸名);本地化避免与 installer.ts 循环依赖 */
|
|
19
|
+
function previewSiblingOf(configPath: string): string {
|
|
20
|
+
const cut = Math.max(configPath.lastIndexOf("/"), configPath.lastIndexOf("\\"));
|
|
21
|
+
return cut < 0 ? PREVIEW_CONFIG_NAME : `${configPath.slice(0, cut + 1)}${PREVIEW_CONFIG_NAME}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function isObj(v: unknown): v is Record<string, unknown> {
|
|
25
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface CompensateInput {
|
|
29
|
+
/** 方案名 */
|
|
30
|
+
name: string
|
|
31
|
+
/** 本次安装版本 */
|
|
32
|
+
version: string
|
|
33
|
+
/** config.yaml 路径(缺省 "config.yaml") */
|
|
34
|
+
configPath: string
|
|
35
|
+
/** reloading 段真正新增的匿名路径(installer 已写入 req.deferredAnonymous);空 = 未接线,config 步 no-op */
|
|
36
|
+
deferredAnonymous: string[]
|
|
37
|
+
/** 站点 sharedRoot(锁/版本目录所在) */
|
|
38
|
+
sharedRoot: string
|
|
39
|
+
/** 站点 modules.json 路径 */
|
|
40
|
+
modulesJsonPath: string
|
|
41
|
+
/** runInstall 起始捕获的装前锁快照 */
|
|
42
|
+
lockBefore: Record<string, string>
|
|
43
|
+
/** 装前锁文件是否存在(首装 = false → 回退即删锁) */
|
|
44
|
+
lockExisted: boolean
|
|
45
|
+
/** 注入式 reload 面(与 reloadStage 同源) */
|
|
46
|
+
reload: ReloadFace
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface CompensateStep {
|
|
50
|
+
step: string
|
|
51
|
+
ok: boolean
|
|
52
|
+
message: string
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface CompensateResult {
|
|
56
|
+
/** 各步结果(逆序:config → lock → modules.json → db → reload) */
|
|
57
|
+
steps: CompensateStep[]
|
|
58
|
+
/** 是否全部成功(任一步失败即 false,但其余步仍尽力执行) */
|
|
59
|
+
allOk: boolean
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* 执行补偿回滚。每步独立 try/catch:单步失败记录进 steps 并继续其余步,最终 allOk 反映整体;
|
|
64
|
+
* 调用方据 allOk 决定 task 文案(失败步需在 message 中点名,便于运维定位)。
|
|
65
|
+
*/
|
|
66
|
+
export async function compensate(input: CompensateInput): Promise<CompensateResult> {
|
|
67
|
+
const steps: CompensateStep[] = [];
|
|
68
|
+
const run = async (step: string, fn: () => Promise<void>): Promise<void> => {
|
|
69
|
+
try {
|
|
70
|
+
await fn();
|
|
71
|
+
steps.push({ step, ok: true, message: `${step}:已回滚到装前代` });
|
|
72
|
+
}
|
|
73
|
+
catch (e) {
|
|
74
|
+
steps.push({ step, ok: false, message: `${step}回滚失败:${String(e)}` });
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const f = fsFace();
|
|
79
|
+
|
|
80
|
+
// 1. config 匿名移除(源 config + preview 派生,派生缺失即跳过)
|
|
81
|
+
await run("config.anonymous", async () => {
|
|
82
|
+
if (input.deferredAnonymous.length === 0) {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
for (const p of [input.configPath, previewSiblingOf(input.configPath)]) {
|
|
86
|
+
let content: string;
|
|
87
|
+
try {
|
|
88
|
+
content = new TextDecoder().decode(await f.readFile(p));
|
|
89
|
+
}
|
|
90
|
+
catch (e) {
|
|
91
|
+
if (isMissingPath(e)) {
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
throw e;
|
|
95
|
+
}
|
|
96
|
+
const { content: next, removed } = removeAnonymousPaths(content, input.deferredAnonymous);
|
|
97
|
+
if (removed.length > 0) {
|
|
98
|
+
await atomicWriteText(p, next);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// 2. lock 回写装前(首装则删锁;空锁拒启)
|
|
104
|
+
await run("lock", async () => {
|
|
105
|
+
await revertLock(input.sharedRoot, input.lockBefore, input.lockExisted);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// 3. modules.json 条目移除 + 断言(防并发写者插回)
|
|
109
|
+
await run("modules.json", async () => {
|
|
110
|
+
const { removed } = await removeModulesJsonEntry(input.name, { modulesJsonPath: input.modulesJsonPath });
|
|
111
|
+
if (!removed) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const list = JSON.parse(new TextDecoder().decode(await f.readFile(input.modulesJsonPath))) as unknown;
|
|
115
|
+
if (Array.isArray(list) && list.some(e => isObj(e) && e.name === input.name)) {
|
|
116
|
+
throw new Error("回滚后 modules.json 仍存在该模块条目(疑似并发写者插回)");
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
// 4. DB 注册回退(复用卸载事务:删 route + 级联清角色/权限)
|
|
121
|
+
await run("db.registrations", async () => {
|
|
122
|
+
await revertRegistrations(input.name);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// 5. reload 让旧代生效(best-effort 重同步活动代;抛错即记失败,目标=活动代回到装前态)
|
|
126
|
+
// 注:US-1 落地前上游仅按 config sha 判定——回退 config 会产出 applied(移除匿名),非 unchanged;
|
|
127
|
+
// US-1 落地后预期 unchanged===true。两种皆视为成功(只要未抛错)。
|
|
128
|
+
await run("reload", async () => {
|
|
129
|
+
const r = await input.reload.reloadConfig();
|
|
130
|
+
if (typeof r !== "object" || r === null || typeof r.unchanged !== "boolean") {
|
|
131
|
+
throw new Error("reloadConfig 返回形状违约(expected {unchanged:boolean,...})");
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
return { steps, allOk: steps.every(s => s.ok) };
|
|
136
|
+
}
|