@nocobase/plugin-multi-portal 3.0.0-alpha.2 → 3.0.0-alpha.3
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/dist/externalVersion.js +8 -8
- package/dist/node_modules/tar/package.json +1 -1
- package/dist/server/plugin.d.ts +1 -1
- package/dist/server/plugin.js +21 -55
- package/dist/swagger/index.d.ts +152 -0
- package/dist/swagger/index.js +142 -0
- package/package.json +3 -3
package/dist/externalVersion.js
CHANGED
|
@@ -8,19 +8,19 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
module.exports = {
|
|
11
|
-
"@nocobase/flow-engine": "3.0.0-alpha.
|
|
12
|
-
"@nocobase/client": "3.0.0-alpha.
|
|
13
|
-
"@nocobase/client-v2": "3.0.0-alpha.
|
|
11
|
+
"@nocobase/flow-engine": "3.0.0-alpha.3",
|
|
12
|
+
"@nocobase/client": "3.0.0-alpha.3",
|
|
13
|
+
"@nocobase/client-v2": "3.0.0-alpha.3",
|
|
14
14
|
"antd": "5.24.2",
|
|
15
15
|
"react": "18.2.0",
|
|
16
16
|
"react-router-dom": "6.30.1",
|
|
17
|
-
"@nocobase/database": "3.0.0-alpha.
|
|
18
|
-
"@nocobase/server": "3.0.0-alpha.
|
|
19
|
-
"@nocobase/resourcer": "3.0.0-alpha.
|
|
20
|
-
"@nocobase/utils": "3.0.0-alpha.
|
|
17
|
+
"@nocobase/database": "3.0.0-alpha.3",
|
|
18
|
+
"@nocobase/server": "3.0.0-alpha.3",
|
|
19
|
+
"@nocobase/resourcer": "3.0.0-alpha.3",
|
|
20
|
+
"@nocobase/utils": "3.0.0-alpha.3",
|
|
21
21
|
"ahooks": "3.7.8",
|
|
22
22
|
"antd-style": "3.7.1",
|
|
23
|
-
"@nocobase/plugin-ui-layout": "3.0.0-alpha.
|
|
23
|
+
"@nocobase/plugin-ui-layout": "3.0.0-alpha.3",
|
|
24
24
|
"@ant-design/icons": "5.6.1",
|
|
25
25
|
"sequelize": "6.35.2"
|
|
26
26
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"author":"Isaac Z. Schlueter","name":"tar","description":"tar for node","version":"7.5.15","repository":{"type":"git","url":"https://github.com/isaacs/node-tar.git"},"scripts":{"genparse":"node scripts/generate-parse-fixtures.js","snap":"tap","test":"tap","pretest":"npm run prepare","presnap":"npm run prepare","prepare":"tshy && bash scripts/build.sh","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags","format":"prettier --write . --log-level warn","typedoc":"typedoc --tsconfig .tshy/esm.json ./src/*.ts","lint":"oxlint --fix src test","postsnap":"npm run lint","postlint":"npm run format"},"dependencies":{"@isaacs/fs-minipass":"^4.0.0","chownr":"^3.0.0","minipass":"^7.1.2","minizlib":"^3.1.0","yallist":"^5.0.0"},"devDependencies":{"@types/node":"^25.5.0","chmodr":"^2.0.2","end-of-stream":"^1.4.3","esbuild":"^0.27.4","events-to-array":"^2.0.3","mutate-fs":"^2.1.1","nock":"^13.5.4","oxlint":"^1.57.0","oxlint-tsgolint":"^0.17.3","prettier":"^3.8.1","rimraf":"^6.1.2","tap":"^21.6.2","tshy":"^3.3.2","typedoc":"^0.28.18"},"license":"BlueOak-1.0.0","engines":{"node":">=18"},"files":["dist"],"tshy":{"exports":{"./package.json":"./package.json",".":{"import":{"types":"./dist/esm/index.d.ts","default":"./dist/esm/index.min.js"},"require":{"types":"./dist/commonjs/index.d.ts","default":"./dist/commonjs/index.min.js"}},"./raw":"./src/index.ts","./c":"./src/create.ts","./create":"./src/create.ts","./replace":"./src/create.ts","./r":"./src/create.ts","./list":"./src/list.ts","./t":"./src/list.ts","./update":"./src/update.ts","./u":"./src/update.ts","./extract":"./src/extract.ts","./x":"./src/extract.ts","./pack":"./src/pack.ts","./unpack":"./src/unpack.ts","./parse":"./src/parse.ts","./read-entry":"./src/read-entry.ts","./write-entry":"./src/write-entry.ts","./header":"./src/header.ts","./pax":"./src/pax.ts","./types":"./src/types.ts"}},"exports":{"./package.json":"./package.json",".":{"import":{"types":"./dist/esm/index.d.ts","default":"./dist/esm/index.min.js"},"require":{"types":"./dist/commonjs/index.d.ts","default":"./dist/commonjs/index.min.js"}},"./raw":{"import":{"types":"./dist/esm/index.d.ts","default":"./dist/esm/index.js"},"require":{"types":"./dist/commonjs/index.d.ts","default":"./dist/commonjs/index.js"}},"./c":{"import":{"types":"./dist/esm/create.d.ts","default":"./dist/esm/create.js"},"require":{"types":"./dist/commonjs/create.d.ts","default":"./dist/commonjs/create.js"}},"./create":{"import":{"types":"./dist/esm/create.d.ts","default":"./dist/esm/create.js"},"require":{"types":"./dist/commonjs/create.d.ts","default":"./dist/commonjs/create.js"}},"./replace":{"import":{"types":"./dist/esm/create.d.ts","default":"./dist/esm/create.js"},"require":{"types":"./dist/commonjs/create.d.ts","default":"./dist/commonjs/create.js"}},"./r":{"import":{"types":"./dist/esm/create.d.ts","default":"./dist/esm/create.js"},"require":{"types":"./dist/commonjs/create.d.ts","default":"./dist/commonjs/create.js"}},"./list":{"import":{"types":"./dist/esm/list.d.ts","default":"./dist/esm/list.js"},"require":{"types":"./dist/commonjs/list.d.ts","default":"./dist/commonjs/list.js"}},"./t":{"import":{"types":"./dist/esm/list.d.ts","default":"./dist/esm/list.js"},"require":{"types":"./dist/commonjs/list.d.ts","default":"./dist/commonjs/list.js"}},"./update":{"import":{"types":"./dist/esm/update.d.ts","default":"./dist/esm/update.js"},"require":{"types":"./dist/commonjs/update.d.ts","default":"./dist/commonjs/update.js"}},"./u":{"import":{"types":"./dist/esm/update.d.ts","default":"./dist/esm/update.js"},"require":{"types":"./dist/commonjs/update.d.ts","default":"./dist/commonjs/update.js"}},"./extract":{"import":{"types":"./dist/esm/extract.d.ts","default":"./dist/esm/extract.js"},"require":{"types":"./dist/commonjs/extract.d.ts","default":"./dist/commonjs/extract.js"}},"./x":{"import":{"types":"./dist/esm/extract.d.ts","default":"./dist/esm/extract.js"},"require":{"types":"./dist/commonjs/extract.d.ts","default":"./dist/commonjs/extract.js"}},"./pack":{"import":{"types":"./dist/esm/pack.d.ts","default":"./dist/esm/pack.js"},"require":{"types":"./dist/commonjs/pack.d.ts","default":"./dist/commonjs/pack.js"}},"./unpack":{"import":{"types":"./dist/esm/unpack.d.ts","default":"./dist/esm/unpack.js"},"require":{"types":"./dist/commonjs/unpack.d.ts","default":"./dist/commonjs/unpack.js"}},"./parse":{"import":{"types":"./dist/esm/parse.d.ts","default":"./dist/esm/parse.js"},"require":{"types":"./dist/commonjs/parse.d.ts","default":"./dist/commonjs/parse.js"}},"./read-entry":{"import":{"types":"./dist/esm/read-entry.d.ts","default":"./dist/esm/read-entry.js"},"require":{"types":"./dist/commonjs/read-entry.d.ts","default":"./dist/commonjs/read-entry.js"}},"./write-entry":{"import":{"types":"./dist/esm/write-entry.d.ts","default":"./dist/esm/write-entry.js"},"require":{"types":"./dist/commonjs/write-entry.d.ts","default":"./dist/commonjs/write-entry.js"}},"./header":{"import":{"types":"./dist/esm/header.d.ts","default":"./dist/esm/header.js"},"require":{"types":"./dist/commonjs/header.d.ts","default":"./dist/commonjs/header.js"}},"./pax":{"import":{"types":"./dist/esm/pax.d.ts","default":"./dist/esm/pax.js"},"require":{"types":"./dist/commonjs/pax.d.ts","default":"./dist/commonjs/pax.js"}},"./types":{"import":{"types":"./dist/esm/types.d.ts","default":"./dist/esm/types.js"},"require":{"types":"./dist/commonjs/types.d.ts","default":"./dist/commonjs/types.js"}}},"type":"module","main":"./dist/commonjs/index.min.js","types":"./dist/commonjs/index.d.ts","module":"./dist/esm/index.min.js","_lastModified":"2026-07-
|
|
1
|
+
{"author":"Isaac Z. Schlueter","name":"tar","description":"tar for node","version":"7.5.15","repository":{"type":"git","url":"https://github.com/isaacs/node-tar.git"},"scripts":{"genparse":"node scripts/generate-parse-fixtures.js","snap":"tap","test":"tap","pretest":"npm run prepare","presnap":"npm run prepare","prepare":"tshy && bash scripts/build.sh","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags","format":"prettier --write . --log-level warn","typedoc":"typedoc --tsconfig .tshy/esm.json ./src/*.ts","lint":"oxlint --fix src test","postsnap":"npm run lint","postlint":"npm run format"},"dependencies":{"@isaacs/fs-minipass":"^4.0.0","chownr":"^3.0.0","minipass":"^7.1.2","minizlib":"^3.1.0","yallist":"^5.0.0"},"devDependencies":{"@types/node":"^25.5.0","chmodr":"^2.0.2","end-of-stream":"^1.4.3","esbuild":"^0.27.4","events-to-array":"^2.0.3","mutate-fs":"^2.1.1","nock":"^13.5.4","oxlint":"^1.57.0","oxlint-tsgolint":"^0.17.3","prettier":"^3.8.1","rimraf":"^6.1.2","tap":"^21.6.2","tshy":"^3.3.2","typedoc":"^0.28.18"},"license":"BlueOak-1.0.0","engines":{"node":">=18"},"files":["dist"],"tshy":{"exports":{"./package.json":"./package.json",".":{"import":{"types":"./dist/esm/index.d.ts","default":"./dist/esm/index.min.js"},"require":{"types":"./dist/commonjs/index.d.ts","default":"./dist/commonjs/index.min.js"}},"./raw":"./src/index.ts","./c":"./src/create.ts","./create":"./src/create.ts","./replace":"./src/create.ts","./r":"./src/create.ts","./list":"./src/list.ts","./t":"./src/list.ts","./update":"./src/update.ts","./u":"./src/update.ts","./extract":"./src/extract.ts","./x":"./src/extract.ts","./pack":"./src/pack.ts","./unpack":"./src/unpack.ts","./parse":"./src/parse.ts","./read-entry":"./src/read-entry.ts","./write-entry":"./src/write-entry.ts","./header":"./src/header.ts","./pax":"./src/pax.ts","./types":"./src/types.ts"}},"exports":{"./package.json":"./package.json",".":{"import":{"types":"./dist/esm/index.d.ts","default":"./dist/esm/index.min.js"},"require":{"types":"./dist/commonjs/index.d.ts","default":"./dist/commonjs/index.min.js"}},"./raw":{"import":{"types":"./dist/esm/index.d.ts","default":"./dist/esm/index.js"},"require":{"types":"./dist/commonjs/index.d.ts","default":"./dist/commonjs/index.js"}},"./c":{"import":{"types":"./dist/esm/create.d.ts","default":"./dist/esm/create.js"},"require":{"types":"./dist/commonjs/create.d.ts","default":"./dist/commonjs/create.js"}},"./create":{"import":{"types":"./dist/esm/create.d.ts","default":"./dist/esm/create.js"},"require":{"types":"./dist/commonjs/create.d.ts","default":"./dist/commonjs/create.js"}},"./replace":{"import":{"types":"./dist/esm/create.d.ts","default":"./dist/esm/create.js"},"require":{"types":"./dist/commonjs/create.d.ts","default":"./dist/commonjs/create.js"}},"./r":{"import":{"types":"./dist/esm/create.d.ts","default":"./dist/esm/create.js"},"require":{"types":"./dist/commonjs/create.d.ts","default":"./dist/commonjs/create.js"}},"./list":{"import":{"types":"./dist/esm/list.d.ts","default":"./dist/esm/list.js"},"require":{"types":"./dist/commonjs/list.d.ts","default":"./dist/commonjs/list.js"}},"./t":{"import":{"types":"./dist/esm/list.d.ts","default":"./dist/esm/list.js"},"require":{"types":"./dist/commonjs/list.d.ts","default":"./dist/commonjs/list.js"}},"./update":{"import":{"types":"./dist/esm/update.d.ts","default":"./dist/esm/update.js"},"require":{"types":"./dist/commonjs/update.d.ts","default":"./dist/commonjs/update.js"}},"./u":{"import":{"types":"./dist/esm/update.d.ts","default":"./dist/esm/update.js"},"require":{"types":"./dist/commonjs/update.d.ts","default":"./dist/commonjs/update.js"}},"./extract":{"import":{"types":"./dist/esm/extract.d.ts","default":"./dist/esm/extract.js"},"require":{"types":"./dist/commonjs/extract.d.ts","default":"./dist/commonjs/extract.js"}},"./x":{"import":{"types":"./dist/esm/extract.d.ts","default":"./dist/esm/extract.js"},"require":{"types":"./dist/commonjs/extract.d.ts","default":"./dist/commonjs/extract.js"}},"./pack":{"import":{"types":"./dist/esm/pack.d.ts","default":"./dist/esm/pack.js"},"require":{"types":"./dist/commonjs/pack.d.ts","default":"./dist/commonjs/pack.js"}},"./unpack":{"import":{"types":"./dist/esm/unpack.d.ts","default":"./dist/esm/unpack.js"},"require":{"types":"./dist/commonjs/unpack.d.ts","default":"./dist/commonjs/unpack.js"}},"./parse":{"import":{"types":"./dist/esm/parse.d.ts","default":"./dist/esm/parse.js"},"require":{"types":"./dist/commonjs/parse.d.ts","default":"./dist/commonjs/parse.js"}},"./read-entry":{"import":{"types":"./dist/esm/read-entry.d.ts","default":"./dist/esm/read-entry.js"},"require":{"types":"./dist/commonjs/read-entry.d.ts","default":"./dist/commonjs/read-entry.js"}},"./write-entry":{"import":{"types":"./dist/esm/write-entry.d.ts","default":"./dist/esm/write-entry.js"},"require":{"types":"./dist/commonjs/write-entry.d.ts","default":"./dist/commonjs/write-entry.js"}},"./header":{"import":{"types":"./dist/esm/header.d.ts","default":"./dist/esm/header.js"},"require":{"types":"./dist/commonjs/header.d.ts","default":"./dist/commonjs/header.js"}},"./pax":{"import":{"types":"./dist/esm/pax.d.ts","default":"./dist/esm/pax.js"},"require":{"types":"./dist/commonjs/pax.d.ts","default":"./dist/commonjs/pax.js"}},"./types":{"import":{"types":"./dist/esm/types.d.ts","default":"./dist/esm/types.js"},"require":{"types":"./dist/commonjs/types.d.ts","default":"./dist/commonjs/types.js"}}},"type":"module","main":"./dist/commonjs/index.min.js","types":"./dist/commonjs/index.d.ts","module":"./dist/esm/index.min.js","_lastModified":"2026-07-30T10:32:21.491Z"}
|
package/dist/server/plugin.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export declare class PluginMultiPortalServer extends Plugin {
|
|
|
31
31
|
private logPortalBuildHtml;
|
|
32
32
|
private getPortalStorageTaskKey;
|
|
33
33
|
private runPortalStorageTask;
|
|
34
|
-
private
|
|
34
|
+
private removePortalStorageIndexHtml;
|
|
35
35
|
private waitForPortalStorageTasks;
|
|
36
36
|
private schedulePortalTemplateCopyAndBuild;
|
|
37
37
|
private ensurePortalStorageItem;
|
package/dist/server/plugin.js
CHANGED
|
@@ -597,12 +597,14 @@ async function buildPortalStorageItem(portalDir, item) {
|
|
|
597
597
|
const buildEnv = getPortalStorageCommandEnv({
|
|
598
598
|
NOCOBASE_API_URL: getPortalStorageApiUrl(item.appName),
|
|
599
599
|
NOCOBASE_PORTAL_BASE: getPortalDeployBasePath(item.appName, item.portalName),
|
|
600
|
+
SKIP_YARN_COREPACK_CHECK: "1",
|
|
601
|
+
COREPACK_ENABLE_STRICT: "0",
|
|
600
602
|
COREPACK_ENABLE_PROJECT_SPEC: "0"
|
|
601
603
|
});
|
|
602
604
|
await appendPortalStorageLog(logPath, `Building portal ${item.appName}/${item.portalName}.`);
|
|
603
605
|
await appendPortalStorageLog(
|
|
604
606
|
logPath,
|
|
605
|
-
`Build environment: NOCOBASE_API_URL=${buildEnv.NOCOBASE_API_URL || ""} NOCOBASE_PORTAL_BASE=${buildEnv.NOCOBASE_PORTAL_BASE || ""} APP_PUBLIC_PATH=${buildEnv.APP_PUBLIC_PATH || ""}`
|
|
607
|
+
`Build environment: NOCOBASE_API_URL=${buildEnv.NOCOBASE_API_URL || ""} NOCOBASE_PORTAL_BASE=${buildEnv.NOCOBASE_PORTAL_BASE || ""} APP_PUBLIC_PATH=${buildEnv.APP_PUBLIC_PATH || ""} SKIP_YARN_COREPACK_CHECK=${buildEnv.SKIP_YARN_COREPACK_CHECK || ""} COREPACK_ENABLE_STRICT=${buildEnv.COREPACK_ENABLE_STRICT || ""} COREPACK_ENABLE_PROJECT_SPEC=${buildEnv.COREPACK_ENABLE_PROJECT_SPEC || ""}`
|
|
606
608
|
);
|
|
607
609
|
await runPortalStorageCommandOnce("yarn", ["build:html"], {
|
|
608
610
|
cwd: portalDir,
|
|
@@ -1095,39 +1097,6 @@ async function seedHistoricalMultiPortals(db) {
|
|
|
1095
1097
|
}
|
|
1096
1098
|
await repairFixedLayoutMultiPortalRecords(db);
|
|
1097
1099
|
}
|
|
1098
|
-
async function preventUiLayoutRouteNameConflict(ctx, next) {
|
|
1099
|
-
const targets = await getMultiPortalWriteTargets(ctx, ["uid", "portalName", "uiLayoutUid"]);
|
|
1100
|
-
for (const { existing, values } of targets) {
|
|
1101
|
-
const existingUid = trimString(existing == null ? void 0 : existing.get("uid"));
|
|
1102
|
-
const uid = trimString(values.uid ?? existingUid);
|
|
1103
|
-
const portalName = trimString(values.portalName ?? (existing == null ? void 0 : existing.get("portalName")));
|
|
1104
|
-
const uiLayoutUid = trimString(values.uiLayoutUid ?? (existing == null ? void 0 : existing.get("uiLayoutUid")));
|
|
1105
|
-
const fixedPortal = getFixedLayoutMultiPortalRecord(existingUid) || getFixedLayoutMultiPortalRecord(uid);
|
|
1106
|
-
const canonicalPortal = (fixedPortal == null ? void 0 : fixedPortal.uid) === uid && (!existingUid || fixedPortal.uid === existingUid) && fixedPortal.portalName === portalName && fixedPortal.uiLayoutUid === uiLayoutUid;
|
|
1107
|
-
if (fixedPortal && !canonicalPortal) {
|
|
1108
|
-
ctx.throw(400, "Reserved Portal UID must match its canonical route and UI layout");
|
|
1109
|
-
return;
|
|
1110
|
-
}
|
|
1111
|
-
if (!portalName) {
|
|
1112
|
-
continue;
|
|
1113
|
-
}
|
|
1114
|
-
if (portalName === "admin" || portalName === "mobile") {
|
|
1115
|
-
continue;
|
|
1116
|
-
}
|
|
1117
|
-
const existingInitPortal = (existing == null ? void 0 : existing.get("uid")) === DEFAULT_MULTI_PORTAL_UID && existing.get("portalName") === portalName;
|
|
1118
|
-
const uiLayout = await ctx.db.getRepository("uiLayouts").findOne({
|
|
1119
|
-
filter: {
|
|
1120
|
-
routeName: portalName
|
|
1121
|
-
},
|
|
1122
|
-
fields: ["uid"]
|
|
1123
|
-
});
|
|
1124
|
-
if (uiLayout && !existingInitPortal) {
|
|
1125
|
-
ctx.throw(400, "Portal route name conflicts with an existing UI layout");
|
|
1126
|
-
return;
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
await next();
|
|
1130
|
-
}
|
|
1131
1100
|
async function preventMultiPortalBackingLayoutChange(ctx, next) {
|
|
1132
1101
|
const targets = await getMultiPortalWriteTargets(ctx, ["uiLayoutUid"]);
|
|
1133
1102
|
for (const { existing, values } of targets) {
|
|
@@ -1242,7 +1211,6 @@ async function assertDesktopRouteParentsBelongToScope(ctx, scope, values = ((_a)
|
|
|
1242
1211
|
id: parentIds,
|
|
1243
1212
|
...scope.filter
|
|
1244
1213
|
},
|
|
1245
|
-
...transaction ? { lock: transaction.LOCK.UPDATE } : {},
|
|
1246
1214
|
transaction
|
|
1247
1215
|
});
|
|
1248
1216
|
if (new Set(normalizeDesktopRouteTargetIds(parents)).size !== new Set(parentIds.map(String)).size) {
|
|
@@ -1276,7 +1244,6 @@ async function assertDesktopRouteUpsertMatchesBelongToScope(ctx, scope, values =
|
|
|
1276
1244
|
...filter,
|
|
1277
1245
|
...scope.filter
|
|
1278
1246
|
},
|
|
1279
|
-
...transaction ? { lock: transaction.LOCK.UPDATE } : {},
|
|
1280
1247
|
transaction
|
|
1281
1248
|
});
|
|
1282
1249
|
const allMatchIds = normalizeDesktopRouteTargetIds(allMatches);
|
|
@@ -1691,7 +1658,7 @@ async function findDesktopRouteMutationTargets(ctx, scopeFilter, transaction, se
|
|
|
1691
1658
|
...filter ?? {},
|
|
1692
1659
|
...scopeFilter ?? {}
|
|
1693
1660
|
},
|
|
1694
|
-
...transaction ? { lock: transaction.LOCK.UPDATE } : {},
|
|
1661
|
+
...transaction && !scopeFilter ? { lock: transaction.LOCK.UPDATE } : {},
|
|
1695
1662
|
transaction
|
|
1696
1663
|
});
|
|
1697
1664
|
}
|
|
@@ -1843,7 +1810,6 @@ async function guardDesktopRouteMoveScope(ctx, next) {
|
|
|
1843
1810
|
id: routeIds,
|
|
1844
1811
|
...scope.filter
|
|
1845
1812
|
},
|
|
1846
|
-
lock: transaction.LOCK.UPDATE,
|
|
1847
1813
|
transaction
|
|
1848
1814
|
});
|
|
1849
1815
|
if (normalizeDesktopRouteTargetIds(allRoutes).join(",") !== normalizeDesktopRouteTargetIds(scopedRoutes).join(",") || scopedRoutes.length !== routeIds.length) {
|
|
@@ -1873,7 +1839,6 @@ async function guardDesktopRouteMoveScope(ctx, next) {
|
|
|
1873
1839
|
id: parentIds,
|
|
1874
1840
|
...scope.filter
|
|
1875
1841
|
},
|
|
1876
|
-
lock: transaction.LOCK.UPDATE,
|
|
1877
1842
|
transaction
|
|
1878
1843
|
});
|
|
1879
1844
|
if (normalizeDesktopRouteTargetIds(parents).join(",") !== parentIds.map(String).sort().join(",")) {
|
|
@@ -1921,7 +1886,6 @@ async function guardDesktopRouteMoveScope(ctx, next) {
|
|
|
1921
1886
|
$gte: targetSort
|
|
1922
1887
|
}
|
|
1923
1888
|
},
|
|
1924
|
-
lock: transaction.LOCK.UPDATE,
|
|
1925
1889
|
transaction
|
|
1926
1890
|
});
|
|
1927
1891
|
const affectedRouteIds = affectedRoutes.map((route) => route.get("id"));
|
|
@@ -2019,7 +1983,7 @@ async function findDesktopRouteDestroyRoots(ctx, transaction, scopeFilter) {
|
|
|
2019
1983
|
...scopeFilter ?? {},
|
|
2020
1984
|
...filterByTk.length ? { id: filterByTk } : {}
|
|
2021
1985
|
},
|
|
2022
|
-
lock: transaction.LOCK.UPDATE,
|
|
1986
|
+
...scopeFilter ? {} : { lock: transaction.LOCK.UPDATE },
|
|
2023
1987
|
transaction
|
|
2024
1988
|
});
|
|
2025
1989
|
return collectDesktopRouteIds(records);
|
|
@@ -2085,13 +2049,20 @@ async function detachDesktopRouteTreeOwner(ctx, routeIds, scope, transaction) {
|
|
|
2085
2049
|
}
|
|
2086
2050
|
async function detachOwnerAndFindDestroyRoots(ctx, routeIds, scope, transaction) {
|
|
2087
2051
|
var _a;
|
|
2052
|
+
await ctx.db.getRepository("desktopRoutes").find({
|
|
2053
|
+
fields: ["id"],
|
|
2054
|
+
filter: {
|
|
2055
|
+
id: routeIds
|
|
2056
|
+
},
|
|
2057
|
+
lock: transaction.LOCK.UPDATE,
|
|
2058
|
+
transaction
|
|
2059
|
+
});
|
|
2088
2060
|
const routes = await ctx.db.getRepository("desktopRoutes").find({
|
|
2089
2061
|
fields: ["id", "parentId"],
|
|
2090
2062
|
appends: ["multiPortals", "uiLayouts"],
|
|
2091
2063
|
filter: {
|
|
2092
2064
|
id: routeIds
|
|
2093
2065
|
},
|
|
2094
|
-
lock: transaction.LOCK.UPDATE,
|
|
2095
2066
|
transaction
|
|
2096
2067
|
});
|
|
2097
2068
|
const routesById = new Map(routes.map((route) => [String(route.get("id")), route]));
|
|
@@ -2399,10 +2370,9 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2399
2370
|
}
|
|
2400
2371
|
await run();
|
|
2401
2372
|
}
|
|
2402
|
-
async
|
|
2403
|
-
await import_fs.default.promises.rm((0, import_utils.storagePathJoin)("portals", item.appName, item.portalName, "dist"), {
|
|
2404
|
-
force: true
|
|
2405
|
-
recursive: true
|
|
2373
|
+
async removePortalStorageIndexHtml(item) {
|
|
2374
|
+
await import_fs.default.promises.rm((0, import_utils.storagePathJoin)("portals", item.appName, item.portalName, "dist", "index.html"), {
|
|
2375
|
+
force: true
|
|
2406
2376
|
});
|
|
2407
2377
|
}
|
|
2408
2378
|
waitForPortalStorageTasks() {
|
|
@@ -2446,8 +2416,8 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2446
2416
|
return;
|
|
2447
2417
|
}
|
|
2448
2418
|
this.logPortalBuildHtml(item, "skipped", "the portal is disabled");
|
|
2449
|
-
await this.
|
|
2450
|
-
await appendPortalStorageLog(logPath, `Portal
|
|
2419
|
+
await this.removePortalStorageIndexHtml(item);
|
|
2420
|
+
await appendPortalStorageLog(logPath, `Portal index.html removed for ${item.appName}/${item.portalName}.`);
|
|
2451
2421
|
} catch (error) {
|
|
2452
2422
|
await appendPortalStorageLog(
|
|
2453
2423
|
logPath,
|
|
@@ -2489,15 +2459,15 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2489
2459
|
return;
|
|
2490
2460
|
}
|
|
2491
2461
|
this.logPortalBuildHtml(item, "skipped", "the portal is disabled");
|
|
2492
|
-
await this.
|
|
2493
|
-
await appendPortalStorageLog(logPath, `Portal
|
|
2462
|
+
await this.removePortalStorageIndexHtml(item);
|
|
2463
|
+
await appendPortalStorageLog(logPath, `Portal index.html removed for ${item.appName}/${item.portalName}.`);
|
|
2494
2464
|
}
|
|
2495
2465
|
async syncMultiPortalStorageItem(multiPortal, options, syncPrevious = false, forceBuild = false) {
|
|
2496
2466
|
const currentItem = this.getMultiPortalStorageItem(multiPortal);
|
|
2497
2467
|
const previousItem = syncPrevious ? this.getMultiPortalStorageItem(multiPortal, true) : null;
|
|
2498
2468
|
await this.runPortalStorageTask(async () => {
|
|
2499
2469
|
if (previousItem && (!currentItem || previousItem.appName !== currentItem.appName || previousItem.portalName !== currentItem.portalName || !currentItem.enabled)) {
|
|
2500
|
-
await this.
|
|
2470
|
+
await this.removePortalStorageIndexHtml(previousItem);
|
|
2501
2471
|
}
|
|
2502
2472
|
if (currentItem) {
|
|
2503
2473
|
await this.ensurePortalStorageItem(currentItem, { forceBuild });
|
|
@@ -2849,24 +2819,20 @@ class PluginMultiPortalServer extends import_server.Plugin {
|
|
|
2849
2819
|
);
|
|
2850
2820
|
this.app.resourceManager.registerPreActionHandler("multiPortals:create", captureSkipCreatePortalDirectory);
|
|
2851
2821
|
this.app.resourceManager.registerPreActionHandler("multiPortals:create", normalizeMultiPortalSlugValues);
|
|
2852
|
-
this.app.resourceManager.registerPreActionHandler("multiPortals:create", preventUiLayoutRouteNameConflict);
|
|
2853
2822
|
this.app.resourceManager.registerPreActionHandler("multiPortals:update", preventMultiPortalBackingLayoutChange);
|
|
2854
2823
|
this.app.resourceManager.registerPreActionHandler("multiPortals:update", normalizeMultiPortalSlugValues);
|
|
2855
|
-
this.app.resourceManager.registerPreActionHandler("multiPortals:update", preventUiLayoutRouteNameConflict);
|
|
2856
2824
|
this.app.resourceManager.registerPreActionHandler(
|
|
2857
2825
|
"multiPortals:firstOrCreate",
|
|
2858
2826
|
preventMultiPortalBackingLayoutChange
|
|
2859
2827
|
);
|
|
2860
2828
|
this.app.resourceManager.registerPreActionHandler("multiPortals:firstOrCreate", captureSkipCreatePortalDirectory);
|
|
2861
2829
|
this.app.resourceManager.registerPreActionHandler("multiPortals:firstOrCreate", normalizeMultiPortalSlugValues);
|
|
2862
|
-
this.app.resourceManager.registerPreActionHandler("multiPortals:firstOrCreate", preventUiLayoutRouteNameConflict);
|
|
2863
2830
|
this.app.resourceManager.registerPreActionHandler(
|
|
2864
2831
|
"multiPortals:updateOrCreate",
|
|
2865
2832
|
preventMultiPortalBackingLayoutChange
|
|
2866
2833
|
);
|
|
2867
2834
|
this.app.resourceManager.registerPreActionHandler("multiPortals:updateOrCreate", captureSkipCreatePortalDirectory);
|
|
2868
2835
|
this.app.resourceManager.registerPreActionHandler("multiPortals:updateOrCreate", normalizeMultiPortalSlugValues);
|
|
2869
|
-
this.app.resourceManager.registerPreActionHandler("multiPortals:updateOrCreate", preventUiLayoutRouteNameConflict);
|
|
2870
2836
|
this.app.resourceManager.registerPreActionHandler("desktopRoutes:create", addDesktopRouteCreateMultiPortal, {
|
|
2871
2837
|
after: UI_LAYOUT_DESKTOP_ROUTE_WRITE_LAYOUT_HANDLER_TAG
|
|
2872
2838
|
});
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
declare const _default: {
|
|
10
|
+
openapi: string;
|
|
11
|
+
info: {
|
|
12
|
+
title: string;
|
|
13
|
+
version: string;
|
|
14
|
+
};
|
|
15
|
+
paths: {
|
|
16
|
+
'/roles/{roleName}/multiPortals:list': {
|
|
17
|
+
get: {
|
|
18
|
+
tags: string[];
|
|
19
|
+
summary: string;
|
|
20
|
+
description: string;
|
|
21
|
+
parameters: {
|
|
22
|
+
$ref: string;
|
|
23
|
+
}[];
|
|
24
|
+
responses: {
|
|
25
|
+
200: {
|
|
26
|
+
description: string;
|
|
27
|
+
content: {
|
|
28
|
+
'application/json': {
|
|
29
|
+
schema: {
|
|
30
|
+
type: string;
|
|
31
|
+
properties: {
|
|
32
|
+
data: {
|
|
33
|
+
type: string;
|
|
34
|
+
items: {
|
|
35
|
+
$ref: string;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
'/roles/{roleName}/multiPortals:add': {
|
|
47
|
+
post: {
|
|
48
|
+
tags: string[];
|
|
49
|
+
summary: string;
|
|
50
|
+
description: string;
|
|
51
|
+
parameters: {
|
|
52
|
+
$ref: string;
|
|
53
|
+
}[];
|
|
54
|
+
requestBody: {
|
|
55
|
+
required: boolean;
|
|
56
|
+
content: {
|
|
57
|
+
'application/json': {
|
|
58
|
+
schema: {
|
|
59
|
+
$ref: string;
|
|
60
|
+
};
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
responses: {
|
|
65
|
+
200: {
|
|
66
|
+
description: string;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
'/roles/{roleName}/multiPortals:remove': {
|
|
72
|
+
post: {
|
|
73
|
+
tags: string[];
|
|
74
|
+
summary: string;
|
|
75
|
+
description: string;
|
|
76
|
+
parameters: {
|
|
77
|
+
$ref: string;
|
|
78
|
+
}[];
|
|
79
|
+
requestBody: {
|
|
80
|
+
required: boolean;
|
|
81
|
+
content: {
|
|
82
|
+
'application/json': {
|
|
83
|
+
schema: {
|
|
84
|
+
$ref: string;
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
responses: {
|
|
90
|
+
200: {
|
|
91
|
+
description: string;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
components: {
|
|
98
|
+
parameters: {
|
|
99
|
+
RoleNamePath: {
|
|
100
|
+
name: string;
|
|
101
|
+
in: string;
|
|
102
|
+
description: string;
|
|
103
|
+
required: boolean;
|
|
104
|
+
schema: {
|
|
105
|
+
type: string;
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
schemas: {
|
|
110
|
+
PortalAccessWrite: {
|
|
111
|
+
type: string;
|
|
112
|
+
properties: {
|
|
113
|
+
values: {
|
|
114
|
+
type: string;
|
|
115
|
+
description: string;
|
|
116
|
+
items: {
|
|
117
|
+
type: string;
|
|
118
|
+
};
|
|
119
|
+
minItems: number;
|
|
120
|
+
uniqueItems: boolean;
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
required: string[];
|
|
124
|
+
};
|
|
125
|
+
PortalAccessTarget: {
|
|
126
|
+
type: string;
|
|
127
|
+
additionalProperties: boolean;
|
|
128
|
+
properties: {
|
|
129
|
+
uid: {
|
|
130
|
+
type: string;
|
|
131
|
+
};
|
|
132
|
+
title: {
|
|
133
|
+
type: string;
|
|
134
|
+
};
|
|
135
|
+
portalName: {
|
|
136
|
+
type: string;
|
|
137
|
+
};
|
|
138
|
+
routePath: {
|
|
139
|
+
type: string;
|
|
140
|
+
};
|
|
141
|
+
portalType: {
|
|
142
|
+
type: string;
|
|
143
|
+
};
|
|
144
|
+
enabled: {
|
|
145
|
+
type: string;
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
};
|
|
152
|
+
export default _default;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __export = (target, all) => {
|
|
15
|
+
for (var name in all)
|
|
16
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
17
|
+
};
|
|
18
|
+
var __copyProps = (to, from, except, desc) => {
|
|
19
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
20
|
+
for (let key of __getOwnPropNames(from))
|
|
21
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
22
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
23
|
+
}
|
|
24
|
+
return to;
|
|
25
|
+
};
|
|
26
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
27
|
+
var swagger_exports = {};
|
|
28
|
+
__export(swagger_exports, {
|
|
29
|
+
default: () => swagger_default
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(swagger_exports);
|
|
32
|
+
var swagger_default = {
|
|
33
|
+
openapi: "3.0.2",
|
|
34
|
+
info: {
|
|
35
|
+
title: "NocoBase API - Multi-portal plugin",
|
|
36
|
+
version: "1.0.0"
|
|
37
|
+
},
|
|
38
|
+
paths: {
|
|
39
|
+
"/roles/{roleName}/multiPortals:list": {
|
|
40
|
+
get: {
|
|
41
|
+
tags: ["roles.multiPortals"],
|
|
42
|
+
summary: "List Portals granted to a role",
|
|
43
|
+
description: "List existing custom Portals that the role is explicitly allowed to enter.",
|
|
44
|
+
parameters: [{ $ref: "#/components/parameters/RoleNamePath" }],
|
|
45
|
+
responses: {
|
|
46
|
+
200: {
|
|
47
|
+
description: "OK",
|
|
48
|
+
content: {
|
|
49
|
+
"application/json": {
|
|
50
|
+
schema: {
|
|
51
|
+
type: "object",
|
|
52
|
+
properties: {
|
|
53
|
+
data: {
|
|
54
|
+
type: "array",
|
|
55
|
+
items: { $ref: "#/components/schemas/PortalAccessTarget" }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"/roles/{roleName}/multiPortals:add": {
|
|
66
|
+
post: {
|
|
67
|
+
tags: ["roles.multiPortals"],
|
|
68
|
+
summary: "Grant Portal entry access to a role",
|
|
69
|
+
description: "Allow the role to enter one or more existing custom Portals by uid.",
|
|
70
|
+
parameters: [{ $ref: "#/components/parameters/RoleNamePath" }],
|
|
71
|
+
requestBody: {
|
|
72
|
+
required: true,
|
|
73
|
+
content: {
|
|
74
|
+
"application/json": {
|
|
75
|
+
schema: { $ref: "#/components/schemas/PortalAccessWrite" }
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
responses: {
|
|
80
|
+
200: { description: "OK" }
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"/roles/{roleName}/multiPortals:remove": {
|
|
85
|
+
post: {
|
|
86
|
+
tags: ["roles.multiPortals"],
|
|
87
|
+
summary: "Revoke Portal entry access from a role",
|
|
88
|
+
description: "Prevent the role from entering one or more existing custom Portals by uid.",
|
|
89
|
+
parameters: [{ $ref: "#/components/parameters/RoleNamePath" }],
|
|
90
|
+
requestBody: {
|
|
91
|
+
required: true,
|
|
92
|
+
content: {
|
|
93
|
+
"application/json": {
|
|
94
|
+
schema: { $ref: "#/components/schemas/PortalAccessWrite" }
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
responses: {
|
|
99
|
+
200: { description: "OK" }
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
components: {
|
|
105
|
+
parameters: {
|
|
106
|
+
RoleNamePath: {
|
|
107
|
+
name: "roleName",
|
|
108
|
+
in: "path",
|
|
109
|
+
description: "Role name.",
|
|
110
|
+
required: true,
|
|
111
|
+
schema: { type: "string" }
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
schemas: {
|
|
115
|
+
PortalAccessWrite: {
|
|
116
|
+
type: "object",
|
|
117
|
+
properties: {
|
|
118
|
+
values: {
|
|
119
|
+
type: "array",
|
|
120
|
+
description: "Portal uids.",
|
|
121
|
+
items: { type: "string" },
|
|
122
|
+
minItems: 1,
|
|
123
|
+
uniqueItems: true
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
required: ["values"]
|
|
127
|
+
},
|
|
128
|
+
PortalAccessTarget: {
|
|
129
|
+
type: "object",
|
|
130
|
+
additionalProperties: true,
|
|
131
|
+
properties: {
|
|
132
|
+
uid: { type: "string" },
|
|
133
|
+
title: { type: "string" },
|
|
134
|
+
portalName: { type: "string" },
|
|
135
|
+
routePath: { type: "string" },
|
|
136
|
+
portalType: { type: "string" },
|
|
137
|
+
enabled: { type: "boolean" }
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/plugin-multi-portal",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.3",
|
|
4
4
|
"main": "dist/server/index.js",
|
|
5
5
|
"nocobase": {
|
|
6
6
|
"supportedVersions": [
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"description.zh-CN": "为 Client V2 提供内置 Portal 注册、入口访问与路由权限管理。",
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@ant-design/icons": "5.x",
|
|
16
|
-
"@nocobase/plugin-ui-layout": "3.0.0-alpha.
|
|
16
|
+
"@nocobase/plugin-ui-layout": "3.0.0-alpha.3",
|
|
17
17
|
"ahooks": "3.x",
|
|
18
18
|
"antd": "5.x",
|
|
19
19
|
"react": "^18.2.0",
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
"@nocobase/server": "2.x",
|
|
30
30
|
"@nocobase/test": "2.x"
|
|
31
31
|
},
|
|
32
|
-
"gitHead": "
|
|
32
|
+
"gitHead": "9899cd799c070c7bd85140148ea5b100b046bdc7"
|
|
33
33
|
}
|