@nocobase/plugin-flow-engine 2.3.0-beta.3 → 3.0.0-alpha.11
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 +9 -9
- package/dist/node_modules/@ant-design/icons-svg/package.json +1 -1
- package/dist/node_modules/acorn/package.json +1 -1
- package/dist/node_modules/acorn-jsx/package.json +1 -1
- package/dist/node_modules/acorn-walk/package.json +1 -1
- package/dist/node_modules/ses/package.json +1 -1
- package/dist/node_modules/zod/package.json +1 -1
- package/dist/server/flow-surfaces/navigation-targets.d.ts +7 -0
- package/dist/server/flow-surfaces/navigation-targets.js +176 -88
- package/dist/server/flow-surfaces/service.d.ts +7 -0
- package/dist/server/flow-surfaces/service.js +186 -53
- package/dist/swagger/flow-surfaces.js +5 -5
- package/package.json +2 -2
package/dist/externalVersion.js
CHANGED
|
@@ -8,16 +8,16 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
module.exports = {
|
|
11
|
-
"@nocobase/client": "
|
|
11
|
+
"@nocobase/client": "3.0.0-alpha.11",
|
|
12
12
|
"lodash": "4.18.1",
|
|
13
|
-
"@nocobase/database": "
|
|
14
|
-
"@nocobase/data-source-manager": "
|
|
15
|
-
"@nocobase/resourcer": "
|
|
16
|
-
"@nocobase/server": "
|
|
17
|
-
"@nocobase/utils": "
|
|
18
|
-
"@nocobase/cache": "
|
|
19
|
-
"@nocobase/actions": "
|
|
13
|
+
"@nocobase/database": "3.0.0-alpha.11",
|
|
14
|
+
"@nocobase/data-source-manager": "3.0.0-alpha.11",
|
|
15
|
+
"@nocobase/resourcer": "3.0.0-alpha.11",
|
|
16
|
+
"@nocobase/server": "3.0.0-alpha.11",
|
|
17
|
+
"@nocobase/utils": "3.0.0-alpha.11",
|
|
18
|
+
"@nocobase/cache": "3.0.0-alpha.11",
|
|
19
|
+
"@nocobase/actions": "3.0.0-alpha.11",
|
|
20
20
|
"sequelize": "6.35.2",
|
|
21
21
|
"@formily/json-schema": "2.3.7",
|
|
22
|
-
"@nocobase/ai": "
|
|
22
|
+
"@nocobase/ai": "3.0.0-alpha.11"
|
|
23
23
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@ant-design/icons-svg","version":"4.3.1","sideEffects":false,"description":"Abstract nodes for ant design icons.","contributors":["HeskeyBaozi <hezhiyu233@foxmail.com>"],"homepage":"https://github.com/ant-design/ant-design-icons/","license":"MIT","main":"lib/index.js","module":"es/index.js","files":["lib","es","inline-svg","inline-namespaced-svg"],"repository":{"type":"git","url":"git+https://github.com/ant-design/ant-design-icons.git"},"scripts":{"g":"npm run generate","generate":"cross-env NODE_ENV=production gulp --require ts-node/register/transpile-only","type-check":"tsc --noEmit","build:es":"tsc --project tsconfig.build.json --module esnext --outDir es","build:lib":"tsc --project tsconfig.build.json --module commonjs --outDir lib","build":"cross-env NODE_ENV=production && npm run build:es && npm run build:lib","test":"cross-env NODE_ENV=test && npm run test:unit","test:unit":"jest","prepublishOnly":"npm run test && npm run g && npm run build && npm run type-check && npm run digest","digest":"node scripts/digest.js"},"bugs":{"url":"https://github.com/ant-design/ant-design-icons/issues"},"devDependencies":{"@babel/core":"^7.8.6","@babel/preset-env":"^7.8.6","@babel/preset-typescript":"^7.8.3","@rgrove/parse-xml":"^2.0.2","@types/gulp":"^4.0.6","@types/gulp-concat":"^0.0.32","@types/gulp-rename":"^0.0.33","@types/jest":"^25.1.3","@types/lodash.camelcase":"^4.3.6","@types/lodash.template":"^4.4.6","@types/lodash.upperfirst":"^4.3.6","@types/node":"^13.9.3","@types/ramda":"^0.26.43","@types/rgrove__parse-xml":"^1.1.0","@types/svgo":"^1.3.1","@types/through2":"^2.0.34","@typescript-eslint/eslint-plugin":"^2.21.0","@typescript-eslint/parser":"^2.21.0","babel-jest":"^25.1.0","cross-env":"^7.0.0","del":"^5.1.0","eslint":"^7.16.0","globby":"^11.0.0","gulp":"^4.0.2","gulp-clone":"^2.0.1","gulp-concat":"^2.6.1","gulp-header":"^2.0.9","gulp-rename":"^2.0.0","jest":"^25.1.0","lodash.camelcase":"^4.3.0","lodash.template":"^4.5.0","lodash.upperfirst":"^4.3.1","ramda":"^0.27.0","svgo":"^1.3.2","through2":"^3.0.1","ts-node":"^8.6.2","typescript":"^4.0.0","vinyl":"^2.2.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_lastModified":"2026-08-
|
|
1
|
+
{"name":"@ant-design/icons-svg","version":"4.3.1","sideEffects":false,"description":"Abstract nodes for ant design icons.","contributors":["HeskeyBaozi <hezhiyu233@foxmail.com>"],"homepage":"https://github.com/ant-design/ant-design-icons/","license":"MIT","main":"lib/index.js","module":"es/index.js","files":["lib","es","inline-svg","inline-namespaced-svg"],"repository":{"type":"git","url":"git+https://github.com/ant-design/ant-design-icons.git"},"scripts":{"g":"npm run generate","generate":"cross-env NODE_ENV=production gulp --require ts-node/register/transpile-only","type-check":"tsc --noEmit","build:es":"tsc --project tsconfig.build.json --module esnext --outDir es","build:lib":"tsc --project tsconfig.build.json --module commonjs --outDir lib","build":"cross-env NODE_ENV=production && npm run build:es && npm run build:lib","test":"cross-env NODE_ENV=test && npm run test:unit","test:unit":"jest","prepublishOnly":"npm run test && npm run g && npm run build && npm run type-check && npm run digest","digest":"node scripts/digest.js"},"bugs":{"url":"https://github.com/ant-design/ant-design-icons/issues"},"devDependencies":{"@babel/core":"^7.8.6","@babel/preset-env":"^7.8.6","@babel/preset-typescript":"^7.8.3","@rgrove/parse-xml":"^2.0.2","@types/gulp":"^4.0.6","@types/gulp-concat":"^0.0.32","@types/gulp-rename":"^0.0.33","@types/jest":"^25.1.3","@types/lodash.camelcase":"^4.3.6","@types/lodash.template":"^4.4.6","@types/lodash.upperfirst":"^4.3.6","@types/node":"^13.9.3","@types/ramda":"^0.26.43","@types/rgrove__parse-xml":"^1.1.0","@types/svgo":"^1.3.1","@types/through2":"^2.0.34","@typescript-eslint/eslint-plugin":"^2.21.0","@typescript-eslint/parser":"^2.21.0","babel-jest":"^25.1.0","cross-env":"^7.0.0","del":"^5.1.0","eslint":"^7.16.0","globby":"^11.0.0","gulp":"^4.0.2","gulp-clone":"^2.0.1","gulp-concat":"^2.6.1","gulp-header":"^2.0.9","gulp-rename":"^2.0.0","jest":"^25.1.0","lodash.camelcase":"^4.3.0","lodash.template":"^4.5.0","lodash.upperfirst":"^4.3.1","ramda":"^0.27.0","svgo":"^1.3.2","through2":"^3.0.1","ts-node":"^8.6.2","typescript":"^4.0.0","vinyl":"^2.2.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_lastModified":"2026-08-23T06:22:59.502Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"acorn","description":"ECMAScript parser","homepage":"https://github.com/acornjs/acorn","main":"dist/acorn.js","types":"dist/acorn.d.ts","module":"dist/acorn.mjs","exports":{".":[{"import":"./dist/acorn.mjs","require":"./dist/acorn.js","default":"./dist/acorn.js"},"./dist/acorn.js"],"./package.json":"./package.json"},"version":"8.11.2","engines":{"node":">=0.4.0"},"maintainers":[{"name":"Marijn Haverbeke","email":"marijnh@gmail.com","web":"https://marijnhaverbeke.nl"},{"name":"Ingvar Stepanyan","email":"me@rreverser.com","web":"https://rreverser.com/"},{"name":"Adrian Heine","web":"http://adrianheine.de"}],"repository":{"type":"git","url":"https://github.com/acornjs/acorn.git"},"license":"MIT","scripts":{"prepare":"cd ..; npm run build:main"},"bin":{"acorn":"./bin/acorn"},"_lastModified":"2026-08-
|
|
1
|
+
{"name":"acorn","description":"ECMAScript parser","homepage":"https://github.com/acornjs/acorn","main":"dist/acorn.js","types":"dist/acorn.d.ts","module":"dist/acorn.mjs","exports":{".":[{"import":"./dist/acorn.mjs","require":"./dist/acorn.js","default":"./dist/acorn.js"},"./dist/acorn.js"],"./package.json":"./package.json"},"version":"8.11.2","engines":{"node":">=0.4.0"},"maintainers":[{"name":"Marijn Haverbeke","email":"marijnh@gmail.com","web":"https://marijnhaverbeke.nl"},{"name":"Ingvar Stepanyan","email":"me@rreverser.com","web":"https://rreverser.com/"},{"name":"Adrian Heine","web":"http://adrianheine.de"}],"repository":{"type":"git","url":"https://github.com/acornjs/acorn.git"},"license":"MIT","scripts":{"prepare":"cd ..; npm run build:main"},"bin":{"acorn":"./bin/acorn"},"_lastModified":"2026-08-23T06:23:00.461Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"acorn-jsx","description":"Modern, fast React.js JSX parser","homepage":"https://github.com/acornjs/acorn-jsx","version":"5.3.2","maintainers":[{"name":"Ingvar Stepanyan","email":"me@rreverser.com","web":"http://rreverser.com/"}],"repository":{"type":"git","url":"https://github.com/acornjs/acorn-jsx"},"license":"MIT","scripts":{"test":"node test/run.js"},"peerDependencies":{"acorn":"^6.0.0 || ^7.0.0 || ^8.0.0"},"devDependencies":{"acorn":"^8.0.1"},"_lastModified":"2026-08-
|
|
1
|
+
{"name":"acorn-jsx","description":"Modern, fast React.js JSX parser","homepage":"https://github.com/acornjs/acorn-jsx","version":"5.3.2","maintainers":[{"name":"Ingvar Stepanyan","email":"me@rreverser.com","web":"http://rreverser.com/"}],"repository":{"type":"git","url":"https://github.com/acornjs/acorn-jsx"},"license":"MIT","scripts":{"test":"node test/run.js"},"peerDependencies":{"acorn":"^6.0.0 || ^7.0.0 || ^8.0.0"},"devDependencies":{"acorn":"^8.0.1"},"_lastModified":"2026-08-23T06:23:00.896Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"acorn-walk","description":"ECMAScript (ESTree) AST walker","homepage":"https://github.com/acornjs/acorn","main":"dist/walk.js","types":"dist/walk.d.ts","module":"dist/walk.mjs","exports":{".":[{"import":"./dist/walk.mjs","require":"./dist/walk.js","default":"./dist/walk.js"},"./dist/walk.js"],"./package.json":"./package.json"},"version":"8.3.4","engines":{"node":">=0.4.0"},"dependencies":{"acorn":"^8.11.0"},"maintainers":[{"name":"Marijn Haverbeke","email":"marijnh@gmail.com","web":"https://marijnhaverbeke.nl"},{"name":"Ingvar Stepanyan","email":"me@rreverser.com","web":"https://rreverser.com/"},{"name":"Adrian Heine","web":"http://adrianheine.de"}],"repository":{"type":"git","url":"https://github.com/acornjs/acorn.git"},"scripts":{"prepare":"cd ..; npm run build:walk"},"license":"MIT","_lastModified":"2026-08-
|
|
1
|
+
{"name":"acorn-walk","description":"ECMAScript (ESTree) AST walker","homepage":"https://github.com/acornjs/acorn","main":"dist/walk.js","types":"dist/walk.d.ts","module":"dist/walk.mjs","exports":{".":[{"import":"./dist/walk.mjs","require":"./dist/walk.js","default":"./dist/walk.js"},"./dist/walk.js"],"./package.json":"./package.json"},"version":"8.3.4","engines":{"node":">=0.4.0"},"dependencies":{"acorn":"^8.11.0"},"maintainers":[{"name":"Marijn Haverbeke","email":"marijnh@gmail.com","web":"https://marijnhaverbeke.nl"},{"name":"Ingvar Stepanyan","email":"me@rreverser.com","web":"https://rreverser.com/"},{"name":"Adrian Heine","web":"http://adrianheine.de"}],"repository":{"type":"git","url":"https://github.com/acornjs/acorn.git"},"scripts":{"prepare":"cd ..; npm run build:walk"},"license":"MIT","_lastModified":"2026-08-23T06:23:01.009Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"ses","version":"1.14.0","description":"Hardened JavaScript for Fearless Cooperation","keywords":["lockdown","harden","Compartment","assert","security","confinement","isolation","object capabilities","ocaps","secure execution","third-party code","prototype pollution","supply-chain attack","plugin"],"author":"Agoric","license":"Apache-2.0","homepage":"https://github.com/Agoric/SES-shim/tree/master/packages/ses#readme","repository":{"type":"git","url":"git+https://github.com/endojs/endo.git","directory":"packages/ses"},"bugs":{"url":"https://github.com/endojs/endo/issues"},"type":"module","main":"./dist/ses.cjs","module":"./index.js","unpkg":"./dist/ses.umd.js","types":"./types.d.ts","exports":{".":{"import":{"types":"./types.d.ts","xs":"./src-xs/index.js","default":"./index.js"},"require":{"types":"./dist/types.d.cts","default":"./dist/ses.cjs"}},"./lockdown":{"import":{"types":"./types.d.ts","default":"./index.js"},"require":{"types":"./dist/types.d.cts","default":"./dist/ses.cjs"}},"./hermes":{"require":{"types":"./dist/types.d.cts","default":"./dist/ses-hermes.cjs"}},"./tools.js":"./tools.js","./assert-shim.js":"./assert-shim.js","./lockdown-shim.js":{"xs":"./src-xs/lockdown-shim.js","default":"./lockdown-shim.js"},"./compartment-shim.js":{"xs":"./src-xs/compartment-shim.js","default":"./compartment-shim.js"},"./console-shim.js":"./console-shim.js","./package.json":"./package.json"},"scripts":{"build:vanilla":"node scripts/bundle.js","build:hermes":"node scripts/bundle.js hermes","build":"yarn build:vanilla && yarn build:hermes","clean":"rm -rf dist","cover":"c8 ava","demo":"python3 -m http.server","lint":"yarn lint:types && yarn lint:eslint","lint-fix":"eslint --fix .","lint:eslint":"eslint .","lint:types":"tsc","prepare":"npm run clean && npm run build","qt":"ava","test":"tsd && ava","test:hermes":"./scripts/hermes-test.sh","test:xs":"xst dist/ses.umd.js test/_lockdown-safe.js && node scripts/generate-test-xs.js && xst tmp/test-xs.js && rm -rf tmp","postpack":"git clean -fX \"*.d.ts*\" \"*.d.cts*\" \"*.d.mts*\" \"*.tsbuildinfo\""},"dependencies":{"@endo/cache-map":"^1.1.0","@endo/env-options":"^1.1.11","@endo/immutable-arraybuffer":"^1.1.2"},"devDependencies":{"@babel/generator":"^7.26.3","@babel/parser":"~7.26.2","@babel/traverse":"~7.25.9","@babel/types":"~7.26.0","@endo/compartment-mapper":"^1.6.3","@endo/module-source":"^1.3.3","@endo/test262-runner":"^0.1.48","@types/babel__traverse":"^7.20.5","ava":"^6.1.3","babel-eslint":"^10.1.0","c8":"^7.14.0","core-js":"^3.31.0","eslint":"^8.57.1","eslint-config-airbnb-base":"^15.0.0","eslint-config-prettier":"^9.1.0","eslint-plugin-eslint-comments":"^3.2.0","eslint-plugin-import":"^2.31.0","hermes-engine-cli":"^0.12.0","prettier":"^3.5.3","terser":"^5.16.6","tsd":"^0.31.2","typescript":"~5.8.3"},"files":["./*.d.ts","./*.js","./*.map","LICENSE*","SECURITY*","dist","lib","src","tools"],"publishConfig":{"access":"public"},"eslintConfig":{"extends":["plugin:@endo/ses"]},"ava":{"files":["test/**/*.test.*"],"timeout":"2m"},"typeCoverage":{"atLeast":81.17},"gitHead":"9815aea9541f241389d2135c6097a7442bdffa17","_lastModified":"2026-08-
|
|
1
|
+
{"name":"ses","version":"1.14.0","description":"Hardened JavaScript for Fearless Cooperation","keywords":["lockdown","harden","Compartment","assert","security","confinement","isolation","object capabilities","ocaps","secure execution","third-party code","prototype pollution","supply-chain attack","plugin"],"author":"Agoric","license":"Apache-2.0","homepage":"https://github.com/Agoric/SES-shim/tree/master/packages/ses#readme","repository":{"type":"git","url":"git+https://github.com/endojs/endo.git","directory":"packages/ses"},"bugs":{"url":"https://github.com/endojs/endo/issues"},"type":"module","main":"./dist/ses.cjs","module":"./index.js","unpkg":"./dist/ses.umd.js","types":"./types.d.ts","exports":{".":{"import":{"types":"./types.d.ts","xs":"./src-xs/index.js","default":"./index.js"},"require":{"types":"./dist/types.d.cts","default":"./dist/ses.cjs"}},"./lockdown":{"import":{"types":"./types.d.ts","default":"./index.js"},"require":{"types":"./dist/types.d.cts","default":"./dist/ses.cjs"}},"./hermes":{"require":{"types":"./dist/types.d.cts","default":"./dist/ses-hermes.cjs"}},"./tools.js":"./tools.js","./assert-shim.js":"./assert-shim.js","./lockdown-shim.js":{"xs":"./src-xs/lockdown-shim.js","default":"./lockdown-shim.js"},"./compartment-shim.js":{"xs":"./src-xs/compartment-shim.js","default":"./compartment-shim.js"},"./console-shim.js":"./console-shim.js","./package.json":"./package.json"},"scripts":{"build:vanilla":"node scripts/bundle.js","build:hermes":"node scripts/bundle.js hermes","build":"yarn build:vanilla && yarn build:hermes","clean":"rm -rf dist","cover":"c8 ava","demo":"python3 -m http.server","lint":"yarn lint:types && yarn lint:eslint","lint-fix":"eslint --fix .","lint:eslint":"eslint .","lint:types":"tsc","prepare":"npm run clean && npm run build","qt":"ava","test":"tsd && ava","test:hermes":"./scripts/hermes-test.sh","test:xs":"xst dist/ses.umd.js test/_lockdown-safe.js && node scripts/generate-test-xs.js && xst tmp/test-xs.js && rm -rf tmp","postpack":"git clean -fX \"*.d.ts*\" \"*.d.cts*\" \"*.d.mts*\" \"*.tsbuildinfo\""},"dependencies":{"@endo/cache-map":"^1.1.0","@endo/env-options":"^1.1.11","@endo/immutable-arraybuffer":"^1.1.2"},"devDependencies":{"@babel/generator":"^7.26.3","@babel/parser":"~7.26.2","@babel/traverse":"~7.25.9","@babel/types":"~7.26.0","@endo/compartment-mapper":"^1.6.3","@endo/module-source":"^1.3.3","@endo/test262-runner":"^0.1.48","@types/babel__traverse":"^7.20.5","ava":"^6.1.3","babel-eslint":"^10.1.0","c8":"^7.14.0","core-js":"^3.31.0","eslint":"^8.57.1","eslint-config-airbnb-base":"^15.0.0","eslint-config-prettier":"^9.1.0","eslint-plugin-eslint-comments":"^3.2.0","eslint-plugin-import":"^2.31.0","hermes-engine-cli":"^0.12.0","prettier":"^3.5.3","terser":"^5.16.6","tsd":"^0.31.2","typescript":"~5.8.3"},"files":["./*.d.ts","./*.js","./*.map","LICENSE*","SECURITY*","dist","lib","src","tools"],"publishConfig":{"access":"public"},"eslintConfig":{"extends":["plugin:@endo/ses"]},"ava":{"files":["test/**/*.test.*"],"timeout":"2m"},"typeCoverage":{"atLeast":81.17},"gitHead":"9815aea9541f241389d2135c6097a7442bdffa17","_lastModified":"2026-08-23T06:23:00.045Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"zod","version":"4.3.5","type":"module","license":"MIT","author":"Colin McDonnell <zod@colinhacks.com>","description":"TypeScript-first schema declaration and validation library with static type inference","homepage":"https://zod.dev","llms":"https://zod.dev/llms.txt","llmsFull":"https://zod.dev/llms-full.txt","mcpServer":"https://mcp.inkeep.com/zod/mcp","funding":"https://github.com/sponsors/colinhacks","sideEffects":false,"files":["src","**/*.js","**/*.mjs","**/*.cjs","**/*.d.ts","**/*.d.mts","**/*.d.cts","**/package.json"],"keywords":["typescript","schema","validation","type","inference"],"main":"./index.cjs","types":"./index.d.cts","module":"./index.js","zshy":{"exports":{"./package.json":"./package.json",".":"./src/index.ts","./mini":"./src/mini/index.ts","./locales":"./src/locales/index.ts","./v3":"./src/v3/index.ts","./v4":"./src/v4/index.ts","./v4-mini":"./src/v4-mini/index.ts","./v4/mini":"./src/v4/mini/index.ts","./v4/core":"./src/v4/core/index.ts","./v4/locales":"./src/v4/locales/index.ts","./v4/locales/*":"./src/v4/locales/*"},"conditions":{"@zod/source":"src"}},"exports":{"./package.json":"./package.json",".":{"@zod/source":"./src/index.ts","types":"./index.d.cts","import":"./index.js","require":"./index.cjs"},"./mini":{"@zod/source":"./src/mini/index.ts","types":"./mini/index.d.cts","import":"./mini/index.js","require":"./mini/index.cjs"},"./locales":{"@zod/source":"./src/locales/index.ts","types":"./locales/index.d.cts","import":"./locales/index.js","require":"./locales/index.cjs"},"./v3":{"@zod/source":"./src/v3/index.ts","types":"./v3/index.d.cts","import":"./v3/index.js","require":"./v3/index.cjs"},"./v4":{"@zod/source":"./src/v4/index.ts","types":"./v4/index.d.cts","import":"./v4/index.js","require":"./v4/index.cjs"},"./v4-mini":{"@zod/source":"./src/v4-mini/index.ts","types":"./v4-mini/index.d.cts","import":"./v4-mini/index.js","require":"./v4-mini/index.cjs"},"./v4/mini":{"@zod/source":"./src/v4/mini/index.ts","types":"./v4/mini/index.d.cts","import":"./v4/mini/index.js","require":"./v4/mini/index.cjs"},"./v4/core":{"@zod/source":"./src/v4/core/index.ts","types":"./v4/core/index.d.cts","import":"./v4/core/index.js","require":"./v4/core/index.cjs"},"./v4/locales":{"@zod/source":"./src/v4/locales/index.ts","types":"./v4/locales/index.d.cts","import":"./v4/locales/index.js","require":"./v4/locales/index.cjs"},"./v4/locales/*":{"@zod/source":"./src/v4/locales/*","types":"./v4/locales/*","import":"./v4/locales/*","require":"./v4/locales/*"}},"repository":{"type":"git","url":"git+https://github.com/colinhacks/zod.git"},"bugs":{"url":"https://github.com/colinhacks/zod/issues"},"support":{"backing":{"npm-funding":true}},"scripts":{"clean":"git clean -xdf . -e node_modules","build":"zshy --project tsconfig.build.json","postbuild":"tsx ../../scripts/write-stub-package-jsons.ts && pnpm biome check --write .","test:watch":"pnpm vitest","test":"pnpm vitest run","prepublishOnly":"tsx ../../scripts/check-versions.ts"},"_lastModified":"2026-08-
|
|
1
|
+
{"name":"zod","version":"4.3.5","type":"module","license":"MIT","author":"Colin McDonnell <zod@colinhacks.com>","description":"TypeScript-first schema declaration and validation library with static type inference","homepage":"https://zod.dev","llms":"https://zod.dev/llms.txt","llmsFull":"https://zod.dev/llms-full.txt","mcpServer":"https://mcp.inkeep.com/zod/mcp","funding":"https://github.com/sponsors/colinhacks","sideEffects":false,"files":["src","**/*.js","**/*.mjs","**/*.cjs","**/*.d.ts","**/*.d.mts","**/*.d.cts","**/package.json"],"keywords":["typescript","schema","validation","type","inference"],"main":"./index.cjs","types":"./index.d.cts","module":"./index.js","zshy":{"exports":{"./package.json":"./package.json",".":"./src/index.ts","./mini":"./src/mini/index.ts","./locales":"./src/locales/index.ts","./v3":"./src/v3/index.ts","./v4":"./src/v4/index.ts","./v4-mini":"./src/v4-mini/index.ts","./v4/mini":"./src/v4/mini/index.ts","./v4/core":"./src/v4/core/index.ts","./v4/locales":"./src/v4/locales/index.ts","./v4/locales/*":"./src/v4/locales/*"},"conditions":{"@zod/source":"src"}},"exports":{"./package.json":"./package.json",".":{"@zod/source":"./src/index.ts","types":"./index.d.cts","import":"./index.js","require":"./index.cjs"},"./mini":{"@zod/source":"./src/mini/index.ts","types":"./mini/index.d.cts","import":"./mini/index.js","require":"./mini/index.cjs"},"./locales":{"@zod/source":"./src/locales/index.ts","types":"./locales/index.d.cts","import":"./locales/index.js","require":"./locales/index.cjs"},"./v3":{"@zod/source":"./src/v3/index.ts","types":"./v3/index.d.cts","import":"./v3/index.js","require":"./v3/index.cjs"},"./v4":{"@zod/source":"./src/v4/index.ts","types":"./v4/index.d.cts","import":"./v4/index.js","require":"./v4/index.cjs"},"./v4-mini":{"@zod/source":"./src/v4-mini/index.ts","types":"./v4-mini/index.d.cts","import":"./v4-mini/index.js","require":"./v4-mini/index.cjs"},"./v4/mini":{"@zod/source":"./src/v4/mini/index.ts","types":"./v4/mini/index.d.cts","import":"./v4/mini/index.js","require":"./v4/mini/index.cjs"},"./v4/core":{"@zod/source":"./src/v4/core/index.ts","types":"./v4/core/index.d.cts","import":"./v4/core/index.js","require":"./v4/core/index.cjs"},"./v4/locales":{"@zod/source":"./src/v4/locales/index.ts","types":"./v4/locales/index.d.cts","import":"./v4/locales/index.js","require":"./v4/locales/index.cjs"},"./v4/locales/*":{"@zod/source":"./src/v4/locales/*","types":"./v4/locales/*","import":"./v4/locales/*","require":"./v4/locales/*"}},"repository":{"type":"git","url":"git+https://github.com/colinhacks/zod.git"},"bugs":{"url":"https://github.com/colinhacks/zod/issues"},"support":{"backing":{"npm-funding":true}},"scripts":{"clean":"git clean -xdf . -e node_modules","build":"zshy --project tsconfig.build.json","postbuild":"tsx ../../scripts/write-stub-package-jsons.ts && pnpm biome check --write .","test:watch":"pnpm vitest","test":"pnpm vitest run","prepublishOnly":"tsx ../../scripts/check-versions.ts"},"_lastModified":"2026-08-23T06:23:02.170Z"}
|
|
@@ -12,6 +12,7 @@ export declare const DEFAULT_MOBILE_UI_LAYOUT_UID = "mobile-layout-model";
|
|
|
12
12
|
export declare const DEFAULT_ADMIN_MULTI_PORTAL_UID = "__default_admin__";
|
|
13
13
|
export declare const DEFAULT_MOBILE_MULTI_PORTAL_UID = "__default_mobile__";
|
|
14
14
|
export type FlowSurfaceNavigationRequestRoles = readonly string[] | string;
|
|
15
|
+
type FlowSurfacePortalRouteScopeKind = 'layout' | 'portal';
|
|
15
16
|
export type FlowSurfaceResolvedMultiPortal = {
|
|
16
17
|
uid: string;
|
|
17
18
|
title: string;
|
|
@@ -22,6 +23,8 @@ export type FlowSurfaceResolvedMultiPortal = {
|
|
|
22
23
|
enabled: true;
|
|
23
24
|
layoutUid: string;
|
|
24
25
|
layoutType?: string;
|
|
26
|
+
portalType: 'no-code';
|
|
27
|
+
routeScopeKind: FlowSurfacePortalRouteScopeKind;
|
|
25
28
|
};
|
|
26
29
|
export type FlowSurfaceNavigationTarget = {
|
|
27
30
|
kind: 'layout' | 'portal';
|
|
@@ -56,6 +59,7 @@ export declare class FlowSurfaceNavigationTargetsService {
|
|
|
56
59
|
hasUiLayoutCapability(): boolean;
|
|
57
60
|
normalizePortalUid(value: unknown): string;
|
|
58
61
|
listNavigationTargets(currentRoles?: FlowSurfaceNavigationRequestRoles, transaction?: Transaction): Promise<FlowSurfaceNavigationTargetsResult>;
|
|
62
|
+
resolveDefaultPortal(options: Omit<PortalResolveOptions, 'path'>): Promise<FlowSurfaceResolvedMultiPortal>;
|
|
59
63
|
resolvePortal(portalUidValue: unknown, options: PortalResolveOptions): Promise<FlowSurfaceResolvedMultiPortal>;
|
|
60
64
|
readRoutePortalUids(routeId: unknown, transaction?: Transaction): Promise<string[]>;
|
|
61
65
|
assertRouteBelongsToPortal(actionName: string, routeId: unknown, portalUid: string, path: string, transaction?: Transaction): Promise<void>;
|
|
@@ -64,7 +68,10 @@ export declare class FlowSurfaceNavigationTargetsService {
|
|
|
64
68
|
transaction?: Transaction;
|
|
65
69
|
}): Promise<void>;
|
|
66
70
|
private listLayoutTargets;
|
|
71
|
+
private getEnabledPortalInventory;
|
|
67
72
|
private listAccessiblePortalTargets;
|
|
73
|
+
private comparePortalPriority;
|
|
74
|
+
private getPortalPriority;
|
|
68
75
|
private canAccessPortal;
|
|
69
76
|
private collectRouteTreeIds;
|
|
70
77
|
private removeDefaultLayoutRoutePermissions;
|
|
@@ -38,7 +38,6 @@ const DEFAULT_ADMIN_UI_LAYOUT_UID = "admin-layout-model";
|
|
|
38
38
|
const DEFAULT_MOBILE_UI_LAYOUT_UID = "mobile-layout-model";
|
|
39
39
|
const DEFAULT_ADMIN_MULTI_PORTAL_UID = "__default_admin__";
|
|
40
40
|
const DEFAULT_MOBILE_MULTI_PORTAL_UID = "__default_mobile__";
|
|
41
|
-
const RESERVED_MULTI_PORTAL_UIDS = /* @__PURE__ */ new Set([DEFAULT_ADMIN_MULTI_PORTAL_UID, DEFAULT_MOBILE_MULTI_PORTAL_UID]);
|
|
42
41
|
function readRecordField(record, field) {
|
|
43
42
|
if (!record || typeof record !== "object") {
|
|
44
43
|
return void 0;
|
|
@@ -60,6 +59,17 @@ function normalizeRoles(currentRoles) {
|
|
|
60
59
|
function normalizeRelationRouteId(routeId) {
|
|
61
60
|
return routeId === null || typeof routeId === "undefined" ? void 0 : routeId;
|
|
62
61
|
}
|
|
62
|
+
function isDefaultLayoutMultiPortalUid(uid) {
|
|
63
|
+
return uid === DEFAULT_ADMIN_MULTI_PORTAL_UID || uid === DEFAULT_MOBILE_MULTI_PORTAL_UID;
|
|
64
|
+
}
|
|
65
|
+
function getMultiPortalLayoutType(uiLayoutUid) {
|
|
66
|
+
if (uiLayoutUid === DEFAULT_ADMIN_UI_LAYOUT_UID) {
|
|
67
|
+
return "desktop";
|
|
68
|
+
}
|
|
69
|
+
if (uiLayoutUid === DEFAULT_MOBILE_UI_LAYOUT_UID) {
|
|
70
|
+
return "mobile";
|
|
71
|
+
}
|
|
72
|
+
}
|
|
63
73
|
class FlowSurfaceNavigationTargetsService {
|
|
64
74
|
constructor(db) {
|
|
65
75
|
this.db = db;
|
|
@@ -85,9 +95,17 @@ class FlowSurfaceNavigationTargetsService {
|
|
|
85
95
|
return portalUid || void 0;
|
|
86
96
|
}
|
|
87
97
|
async listNavigationTargets(currentRoles, transaction) {
|
|
88
|
-
|
|
98
|
+
var _a;
|
|
99
|
+
let layoutTargets = await this.listLayoutTargets(transaction);
|
|
89
100
|
const multiPortal = this.hasMultiPortalCapability();
|
|
90
|
-
const
|
|
101
|
+
const portalInventory = multiPortal ? await this.getEnabledPortalInventory(currentRoles, transaction) : { accessible: [] };
|
|
102
|
+
const portalTargets = multiPortal ? await this.listAccessiblePortalTargets(portalInventory.accessible, transaction) : [];
|
|
103
|
+
if (multiPortal) {
|
|
104
|
+
layoutTargets = layoutTargets.map(({ default: _default, ...target }) => target);
|
|
105
|
+
if (portalInventory.accessible.length === 1 && ((_a = portalTargets[0]) == null ? void 0 : _a.uid) === readStringField(portalInventory.accessible[0], "uid")) {
|
|
106
|
+
portalTargets[0] = { ...portalTargets[0], default: true };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
91
109
|
return {
|
|
92
110
|
version: "1",
|
|
93
111
|
capabilities: {
|
|
@@ -96,6 +114,60 @@ class FlowSurfaceNavigationTargetsService {
|
|
|
96
114
|
targets: [...layoutTargets, ...portalTargets]
|
|
97
115
|
};
|
|
98
116
|
}
|
|
117
|
+
async resolveDefaultPortal(options) {
|
|
118
|
+
if (!this.hasMultiPortalCapability()) {
|
|
119
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${options.actionName} requires the Multi-portal capability`, {
|
|
120
|
+
ruleId: "navigation-portal-unsupported",
|
|
121
|
+
path: "navigation"
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
const inventory = await this.getEnabledPortalInventory(options.currentRoles, options.transaction);
|
|
125
|
+
if (!inventory.enabled.length) {
|
|
126
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${options.actionName} requires an enabled portal`, {
|
|
127
|
+
ruleId: "navigation-portal-not-found",
|
|
128
|
+
path: "navigation",
|
|
129
|
+
details: {
|
|
130
|
+
uiBuilderAllowed: false,
|
|
131
|
+
adminLayoutFallbackAllowed: false,
|
|
132
|
+
agentInstruction: "Stop this Flow Surfaces write. Ask the user to create and enable a Portal before retrying; do not fall back to the Admin layout."
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
if (!inventory.accessible.length) {
|
|
137
|
+
(0, import_errors.throwForbidden)(
|
|
138
|
+
`flowSurfaces ${options.actionName} current roles cannot access an enabled portal`,
|
|
139
|
+
"FLOW_SURFACE_NAVIGATION_PORTAL_FORBIDDEN",
|
|
140
|
+
{
|
|
141
|
+
ruleId: "navigation-portal-forbidden",
|
|
142
|
+
path: "navigation"
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
if (inventory.accessible.length > 1) {
|
|
147
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${options.actionName} requires an explicit portal selection`, {
|
|
148
|
+
ruleId: "navigation-portal-selection-required",
|
|
149
|
+
path: "navigation",
|
|
150
|
+
details: {
|
|
151
|
+
candidates: inventory.accessible.map((portal) => {
|
|
152
|
+
const uid = readStringField(portal, "uid");
|
|
153
|
+
return {
|
|
154
|
+
uid,
|
|
155
|
+
portalName: readStringField(portal, "portalName") || null,
|
|
156
|
+
title: readStringField(portal, "title") || uid,
|
|
157
|
+
portalType: readStringField(portal, "portalType") || null
|
|
158
|
+
};
|
|
159
|
+
}),
|
|
160
|
+
uiBuilderAllowed: false,
|
|
161
|
+
adminLayoutFallbackAllowed: false,
|
|
162
|
+
agentInstruction: "Stop this Flow Surfaces write and ask the user to select one candidate before retrying; do not choose by Portal type or fall back to the Admin layout."
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
return this.resolvePortal(readStringField(inventory.accessible[0], "uid"), {
|
|
167
|
+
...options,
|
|
168
|
+
path: "navigation"
|
|
169
|
+
});
|
|
170
|
+
}
|
|
99
171
|
async resolvePortal(portalUidValue, options) {
|
|
100
172
|
const portalUid = this.normalizePortalUid(portalUidValue);
|
|
101
173
|
if (!portalUid) {
|
|
@@ -111,19 +183,9 @@ class FlowSurfaceNavigationTargetsService {
|
|
|
111
183
|
details: { portalUid }
|
|
112
184
|
});
|
|
113
185
|
}
|
|
114
|
-
if (RESERVED_MULTI_PORTAL_UIDS.has(portalUid)) {
|
|
115
|
-
(0, import_errors.throwBadRequest)(
|
|
116
|
-
`flowSurfaces ${options.actionName} ${options.path} cannot use reserved default portal uid '${portalUid}'; use layoutUid semantics instead`,
|
|
117
|
-
{
|
|
118
|
-
ruleId: "navigation-portal-reserved",
|
|
119
|
-
path: options.path,
|
|
120
|
-
details: { portalUid }
|
|
121
|
-
}
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
186
|
const portal = await this.db.getRepository("multiPortals").findOne({
|
|
125
187
|
filter: { uid: portalUid },
|
|
126
|
-
fields: ["uid", "title", "icon", "
|
|
188
|
+
fields: ["uid", "title", "icon", "portalType", "portalName", "routePath", "authCheck", "enabled", "uiLayoutUid"],
|
|
127
189
|
transaction: options.transaction
|
|
128
190
|
});
|
|
129
191
|
if (!portal) {
|
|
@@ -133,6 +195,18 @@ class FlowSurfaceNavigationTargetsService {
|
|
|
133
195
|
details: { portalUid }
|
|
134
196
|
});
|
|
135
197
|
}
|
|
198
|
+
const routeScopeKind = isDefaultLayoutMultiPortalUid(portalUid) ? "layout" : "portal";
|
|
199
|
+
if (routeScopeKind === "portal" && !await this.canAccessPortal(portalUid, options.currentRoles, options.transaction)) {
|
|
200
|
+
(0, import_errors.throwForbidden)(
|
|
201
|
+
`flowSurfaces ${options.actionName} current roles cannot access portal '${portalUid}'`,
|
|
202
|
+
"FLOW_SURFACE_NAVIGATION_PORTAL_FORBIDDEN",
|
|
203
|
+
{
|
|
204
|
+
ruleId: "navigation-portal-forbidden",
|
|
205
|
+
path: options.path,
|
|
206
|
+
details: { portalUid }
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
}
|
|
136
210
|
if (readRecordField(portal, "enabled") !== true) {
|
|
137
211
|
(0, import_errors.throwBadRequest)(`flowSurfaces ${options.actionName} portal '${portalUid}' is disabled`, {
|
|
138
212
|
ruleId: "navigation-portal-disabled",
|
|
@@ -140,60 +214,54 @@ class FlowSurfaceNavigationTargetsService {
|
|
|
140
214
|
details: { portalUid }
|
|
141
215
|
});
|
|
142
216
|
}
|
|
217
|
+
const portalType = readStringField(portal, "portalType");
|
|
218
|
+
if (portalType !== "no-code") {
|
|
219
|
+
if (portalType === "ai") {
|
|
220
|
+
(0, import_errors.throwBadRequest)(
|
|
221
|
+
`flowSurfaces ${options.actionName} cannot use UI Builder or Flow Surfaces for AI Portal '${portalUid}'; stop and implement the request in the Portal source code`,
|
|
222
|
+
{
|
|
223
|
+
ruleId: "navigation-portal-type-unsupported",
|
|
224
|
+
path: options.path,
|
|
225
|
+
details: {
|
|
226
|
+
portalUid,
|
|
227
|
+
portalType,
|
|
228
|
+
portalName: readStringField(portal, "portalName") || null,
|
|
229
|
+
expectedPortalType: "no-code",
|
|
230
|
+
uiBuilderAllowed: false,
|
|
231
|
+
adminLayoutFallbackAllowed: false,
|
|
232
|
+
implementationPath: "ai-portal-source",
|
|
233
|
+
agentInstruction: "Stop this Flow Surfaces write. Run nb portal info <portalName> -j to resolve localPath, then implement the request in that AI Portal source code. Do not retry with an Admin layout."
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${options.actionName} portal '${portalUid}' does not support no-code routes`, {
|
|
239
|
+
ruleId: "navigation-portal-type-unsupported",
|
|
240
|
+
path: options.path,
|
|
241
|
+
details: { portalUid, portalType: portalType || null }
|
|
242
|
+
});
|
|
243
|
+
}
|
|
143
244
|
const layoutUid = readStringField(portal, "uiLayoutUid");
|
|
144
|
-
|
|
145
|
-
|
|
245
|
+
const layoutType = getMultiPortalLayoutType(layoutUid);
|
|
246
|
+
if (!layoutUid || !layoutType) {
|
|
247
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${options.actionName} portal '${portalUid}' has an unsupported UI layout uid`, {
|
|
146
248
|
ruleId: "navigation-portal-layout-not-found",
|
|
147
249
|
path: options.path,
|
|
148
250
|
details: { portalUid, layoutUid: layoutUid || null }
|
|
149
251
|
});
|
|
150
252
|
}
|
|
151
|
-
const layout = await this.db.getRepository("uiLayouts").findOne({
|
|
152
|
-
filter: { uid: layoutUid },
|
|
153
|
-
fields: ["uid", "layoutType", "enabled"],
|
|
154
|
-
transaction: options.transaction
|
|
155
|
-
});
|
|
156
|
-
if (!layout) {
|
|
157
|
-
(0, import_errors.throwBadRequest)(
|
|
158
|
-
`flowSurfaces ${options.actionName} portal '${portalUid}' backing UI layout '${layoutUid}' does not exist`,
|
|
159
|
-
{
|
|
160
|
-
ruleId: "navigation-portal-layout-not-found",
|
|
161
|
-
path: options.path,
|
|
162
|
-
details: { portalUid, layoutUid }
|
|
163
|
-
}
|
|
164
|
-
);
|
|
165
|
-
}
|
|
166
|
-
if (readRecordField(layout, "enabled") !== true) {
|
|
167
|
-
(0, import_errors.throwBadRequest)(
|
|
168
|
-
`flowSurfaces ${options.actionName} portal '${portalUid}' backing UI layout '${layoutUid}' is disabled`,
|
|
169
|
-
{
|
|
170
|
-
ruleId: "navigation-portal-layout-disabled",
|
|
171
|
-
path: options.path,
|
|
172
|
-
details: { portalUid, layoutUid }
|
|
173
|
-
}
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
if (!await this.canAccessPortal(portalUid, options.currentRoles, options.transaction)) {
|
|
177
|
-
(0, import_errors.throwForbidden)(
|
|
178
|
-
`flowSurfaces ${options.actionName} current roles cannot access portal '${portalUid}'`,
|
|
179
|
-
"FLOW_SURFACE_NAVIGATION_PORTAL_FORBIDDEN",
|
|
180
|
-
{
|
|
181
|
-
ruleId: "navigation-portal-forbidden",
|
|
182
|
-
path: options.path,
|
|
183
|
-
details: { portalUid }
|
|
184
|
-
}
|
|
185
|
-
);
|
|
186
|
-
}
|
|
187
253
|
return {
|
|
188
254
|
uid: portalUid,
|
|
189
255
|
title: readStringField(portal, "title") || portalUid,
|
|
190
256
|
icon: readStringField(portal, "icon") || null,
|
|
191
|
-
routeName: readStringField(portal, "
|
|
257
|
+
routeName: readStringField(portal, "portalName"),
|
|
192
258
|
routePath: readStringField(portal, "routePath"),
|
|
193
259
|
authCheck: readRecordField(portal, "authCheck") === true,
|
|
194
260
|
enabled: true,
|
|
195
261
|
layoutUid,
|
|
196
|
-
layoutType
|
|
262
|
+
layoutType,
|
|
263
|
+
portalType,
|
|
264
|
+
routeScopeKind
|
|
197
265
|
};
|
|
198
266
|
}
|
|
199
267
|
async readRoutePortalUids(routeId, transaction) {
|
|
@@ -293,51 +361,53 @@ class FlowSurfaceNavigationTargetsService {
|
|
|
293
361
|
return left.uid.localeCompare(right.uid);
|
|
294
362
|
});
|
|
295
363
|
}
|
|
296
|
-
async
|
|
364
|
+
async getEnabledPortalInventory(currentRoles, transaction) {
|
|
365
|
+
const records = await this.db.getRepository("multiPortals").find({
|
|
366
|
+
filter: { enabled: true },
|
|
367
|
+
fields: ["uid", "title", "icon", "portalType", "portalName", "routePath", "authCheck", "enabled", "uiLayoutUid"],
|
|
368
|
+
sort: ["uid"],
|
|
369
|
+
transaction
|
|
370
|
+
});
|
|
371
|
+
const enabled = records.filter((portal) => {
|
|
372
|
+
const uiLayoutUid = readStringField(portal, "uiLayoutUid");
|
|
373
|
+
return !!getMultiPortalLayoutType(uiLayoutUid);
|
|
374
|
+
});
|
|
375
|
+
enabled.sort(
|
|
376
|
+
(left, right) => String(readStringField(left, "uid") || "").localeCompare(String(readStringField(right, "uid") || ""))
|
|
377
|
+
);
|
|
297
378
|
const roles = normalizeRoles(currentRoles);
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
return [];
|
|
302
|
-
}
|
|
379
|
+
const isRoot = roles.includes("root");
|
|
380
|
+
const accessiblePortalUids = /* @__PURE__ */ new Set();
|
|
381
|
+
if (!isRoot && roles.length && this.db.getCollection("rolesMultiPortals")) {
|
|
303
382
|
const grants = await this.db.getRepository("rolesMultiPortals").find({
|
|
304
|
-
fields: ["multiPortalUid"],
|
|
305
383
|
filter: { roleName: roles },
|
|
384
|
+
fields: ["multiPortalUid"],
|
|
306
385
|
transaction
|
|
307
386
|
});
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
if (!accessiblePortalUids.length) {
|
|
314
|
-
return [];
|
|
387
|
+
for (const grant of grants) {
|
|
388
|
+
const portalUid = readStringField(grant, "multiPortalUid");
|
|
389
|
+
if (portalUid) {
|
|
390
|
+
accessiblePortalUids.add(portalUid);
|
|
391
|
+
}
|
|
315
392
|
}
|
|
316
393
|
}
|
|
317
|
-
const
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
"uid.$notIn": Array.from(RESERVED_MULTI_PORTAL_UIDS)
|
|
321
|
-
};
|
|
322
|
-
const portals = await this.db.getRepository("multiPortals").find({
|
|
323
|
-
filter,
|
|
324
|
-
fields: ["uid", "title", "icon", "routeName", "routePath", "authCheck", "enabled", "uiLayoutUid"],
|
|
325
|
-
sort: ["uid"],
|
|
326
|
-
transaction
|
|
394
|
+
const accessible = enabled.filter((portal) => {
|
|
395
|
+
const portalUid = readStringField(portal, "uid");
|
|
396
|
+
return !!portalUid && (isRoot || isDefaultLayoutMultiPortalUid(portalUid) || accessiblePortalUids.has(portalUid));
|
|
327
397
|
});
|
|
398
|
+
return { enabled, accessible };
|
|
399
|
+
}
|
|
400
|
+
async listAccessiblePortalTargets(portals, _transaction) {
|
|
328
401
|
const targets = [];
|
|
329
402
|
for (const portal of portals) {
|
|
330
403
|
const portalUid = readStringField(portal, "uid");
|
|
331
404
|
const layoutUid = readStringField(portal, "uiLayoutUid");
|
|
332
|
-
|
|
405
|
+
const portalType = readStringField(portal, "portalType");
|
|
406
|
+
if (!portalUid || portalType !== "no-code") {
|
|
333
407
|
continue;
|
|
334
408
|
}
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
fields: ["layoutType"],
|
|
338
|
-
transaction
|
|
339
|
-
});
|
|
340
|
-
if (!layout) {
|
|
409
|
+
const layoutType = getMultiPortalLayoutType(layoutUid);
|
|
410
|
+
if (!layoutUid || !layoutType) {
|
|
341
411
|
continue;
|
|
342
412
|
}
|
|
343
413
|
targets.push({
|
|
@@ -347,13 +417,31 @@ class FlowSurfaceNavigationTargetsService {
|
|
|
347
417
|
title: readStringField(portal, "title") || portalUid,
|
|
348
418
|
icon: readStringField(portal, "icon") || null,
|
|
349
419
|
layoutUid,
|
|
350
|
-
layoutType
|
|
351
|
-
routeName: readStringField(portal, "
|
|
420
|
+
layoutType,
|
|
421
|
+
routeName: readStringField(portal, "portalName"),
|
|
352
422
|
routePath: readStringField(portal, "routePath"),
|
|
353
423
|
authCheck: readRecordField(portal, "authCheck") === true
|
|
354
424
|
});
|
|
355
425
|
}
|
|
356
|
-
return targets;
|
|
426
|
+
return targets.sort((left, right) => this.comparePortalPriority(left, right));
|
|
427
|
+
}
|
|
428
|
+
comparePortalPriority(left, right) {
|
|
429
|
+
const priorityDelta = this.getPortalPriority(left) - this.getPortalPriority(right);
|
|
430
|
+
if (priorityDelta) {
|
|
431
|
+
return priorityDelta;
|
|
432
|
+
}
|
|
433
|
+
return String(readStringField(left, "uid") || "").localeCompare(String(readStringField(right, "uid") || ""));
|
|
434
|
+
}
|
|
435
|
+
getPortalPriority(portal) {
|
|
436
|
+
const uiLayout = readRecordField(portal, "uiLayout");
|
|
437
|
+
const layoutType = readStringField(portal, "layoutType") || readStringField(uiLayout, "layoutType");
|
|
438
|
+
if (readStringField(portal, "uid") === DEFAULT_ADMIN_MULTI_PORTAL_UID) {
|
|
439
|
+
return 0;
|
|
440
|
+
}
|
|
441
|
+
if (layoutType !== "mobile") {
|
|
442
|
+
return 1;
|
|
443
|
+
}
|
|
444
|
+
return 2;
|
|
357
445
|
}
|
|
358
446
|
async canAccessPortal(portalUid, currentRoles, transaction) {
|
|
359
447
|
const roles = normalizeRoles(currentRoles);
|
|
@@ -96,6 +96,12 @@ export declare class FlowSurfacesService {
|
|
|
96
96
|
private resolveDesktopRouteLayoutUidFilter;
|
|
97
97
|
private assertNavigationTargetIsExclusive;
|
|
98
98
|
private readDesktopRouteScope;
|
|
99
|
+
private buildDesktopRouteScopeForPortal;
|
|
100
|
+
private assertAdminLayoutCreateScope;
|
|
101
|
+
private getPortalRouteFilterUid;
|
|
102
|
+
private assertRouteBelongsToResolvedPortal;
|
|
103
|
+
private resolveDefaultDesktopRouteScope;
|
|
104
|
+
private resolveDesktopRouteMatchScope;
|
|
99
105
|
private resolveRequestedDesktopRouteScope;
|
|
100
106
|
private resolveExistingDesktopRouteScope;
|
|
101
107
|
private attachDesktopRouteScopeToRouteAndChildren;
|
|
@@ -227,6 +233,7 @@ export declare class FlowSurfacesService {
|
|
|
227
233
|
private dispatchPlanOnlyAction;
|
|
228
234
|
private resolveApplyBlueprintReplaceTargetInfo;
|
|
229
235
|
private resolveApplyBlueprintCreateNavigationGroup;
|
|
236
|
+
private resolveApplyBlueprintDefaultNavigationTarget;
|
|
230
237
|
private normalizeApplyBlueprintCreateMobileNavigation;
|
|
231
238
|
private assertApplyBlueprintCreateNavigationTarget;
|
|
232
239
|
private resolveApplyBlueprintCreatePageIdentity;
|
|
@@ -1204,6 +1204,83 @@ class FlowSurfacesService {
|
|
|
1204
1204
|
layoutUids: await this.readDesktopRouteUiLayoutUids(routeId, transaction)
|
|
1205
1205
|
};
|
|
1206
1206
|
}
|
|
1207
|
+
buildDesktopRouteScopeForPortal(portal) {
|
|
1208
|
+
return {
|
|
1209
|
+
portalUids: portal.routeScopeKind === "portal" ? [portal.uid] : [],
|
|
1210
|
+
layoutUids: portal.routeScopeKind === "layout" ? [portal.layoutUid] : [],
|
|
1211
|
+
selectedPortal: portal,
|
|
1212
|
+
layoutType: portal.layoutType
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
assertAdminLayoutCreateScope(actionName, scope, path) {
|
|
1216
|
+
if (!this.navigationTargets.hasMultiPortalCapability() || scope.selectedPortal || !scope.layoutUids.includes(import_navigation_targets.DEFAULT_ADMIN_UI_LAYOUT_UID)) {
|
|
1217
|
+
return;
|
|
1218
|
+
}
|
|
1219
|
+
(0, import_errors.throwBadRequest)(`flowSurfaces ${actionName} cannot create navigation directly in the Admin layout`, {
|
|
1220
|
+
ruleId: "navigation-admin-layout-not-portal-target",
|
|
1221
|
+
path,
|
|
1222
|
+
details: {
|
|
1223
|
+
layoutUid: import_navigation_targets.DEFAULT_ADMIN_UI_LAYOUT_UID,
|
|
1224
|
+
uiBuilderAllowed: false,
|
|
1225
|
+
adminLayoutFallbackAllowed: false,
|
|
1226
|
+
agentInstruction: "Resolve the target Portal first. For a no-code Portal, pass portalUid (navigation.portalUid in applyBlueprint); for an AI Portal, stop this Flow Surfaces write and implement the request in the Portal source code."
|
|
1227
|
+
}
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
getPortalRouteFilterUid(portal) {
|
|
1231
|
+
return (portal == null ? void 0 : portal.routeScopeKind) === "portal" ? portal.uid : void 0;
|
|
1232
|
+
}
|
|
1233
|
+
async assertRouteBelongsToResolvedPortal(actionName, route, portal, path, transaction) {
|
|
1234
|
+
if (portal.routeScopeKind === "layout") {
|
|
1235
|
+
await this.assertDesktopRouteBelongsToUiLayout(actionName, route, portal.layoutUid, path, transaction);
|
|
1236
|
+
return;
|
|
1237
|
+
}
|
|
1238
|
+
await this.navigationTargets.assertRouteBelongsToPortal(
|
|
1239
|
+
actionName,
|
|
1240
|
+
this.readRouteField(route, "id"),
|
|
1241
|
+
portal.uid,
|
|
1242
|
+
path,
|
|
1243
|
+
transaction
|
|
1244
|
+
);
|
|
1245
|
+
}
|
|
1246
|
+
async resolveDefaultDesktopRouteScope(actionName, options = {}) {
|
|
1247
|
+
if (this.navigationTargets.hasMultiPortalCapability()) {
|
|
1248
|
+
const portal = await this.navigationTargets.resolveDefaultPortal({
|
|
1249
|
+
actionName,
|
|
1250
|
+
currentRoles: options.currentRoles,
|
|
1251
|
+
transaction: options.transaction
|
|
1252
|
+
});
|
|
1253
|
+
return this.buildDesktopRouteScopeForPortal(portal);
|
|
1254
|
+
}
|
|
1255
|
+
const layoutUids = await this.resolveDefaultDesktopRouteUiLayoutUids(options.transaction);
|
|
1256
|
+
return {
|
|
1257
|
+
portalUids: [],
|
|
1258
|
+
layoutUids,
|
|
1259
|
+
layoutType: layoutUids.length === 1 ? await this.getDesktopRouteUiLayoutTypeByUid(layoutUids[0], options.transaction) : void 0
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
async resolveDesktopRouteMatchScope(layoutUid, portalUid, actionName, options = {}) {
|
|
1263
|
+
if (portalUid) {
|
|
1264
|
+
const portal = await this.navigationTargets.resolvePortal(portalUid, {
|
|
1265
|
+
actionName,
|
|
1266
|
+
path: "values.navigation.portalUid",
|
|
1267
|
+
currentRoles: options.currentRoles,
|
|
1268
|
+
transaction: options.transaction
|
|
1269
|
+
});
|
|
1270
|
+
return {
|
|
1271
|
+
layoutUids: portal.routeScopeKind === "layout" ? [portal.layoutUid] : void 0,
|
|
1272
|
+
portalUid: this.getPortalRouteFilterUid(portal)
|
|
1273
|
+
};
|
|
1274
|
+
}
|
|
1275
|
+
if (this.normalizeDesktopRouteLayoutUidFilter(layoutUid).length) {
|
|
1276
|
+
return { layoutUids: layoutUid, portalUid: void 0 };
|
|
1277
|
+
}
|
|
1278
|
+
const defaultScope = await this.resolveDefaultDesktopRouteScope(actionName, options);
|
|
1279
|
+
return {
|
|
1280
|
+
layoutUids: defaultScope.layoutUids.length ? defaultScope.layoutUids : void 0,
|
|
1281
|
+
portalUid: this.getPortalRouteFilterUid(defaultScope.selectedPortal)
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1207
1284
|
async resolveRequestedDesktopRouteScope(values, parentRoute, actionName, options = {}) {
|
|
1208
1285
|
const layoutUid = this.normalizeExplicitDesktopRouteLayoutUid(values.layoutUid);
|
|
1209
1286
|
const portalUid = this.navigationTargets.normalizePortalUid(values.portalUid);
|
|
@@ -1219,22 +1296,19 @@ class FlowSurfacesService {
|
|
|
1219
1296
|
transaction: options.transaction
|
|
1220
1297
|
});
|
|
1221
1298
|
if (parentRoute) {
|
|
1222
|
-
await this.
|
|
1299
|
+
await this.assertRouteBelongsToResolvedPortal(
|
|
1223
1300
|
actionName,
|
|
1224
|
-
|
|
1225
|
-
portal
|
|
1301
|
+
parentRoute,
|
|
1302
|
+
portal,
|
|
1226
1303
|
"values.parentMenuRouteId",
|
|
1227
1304
|
options.transaction
|
|
1228
1305
|
);
|
|
1229
1306
|
}
|
|
1230
|
-
return
|
|
1231
|
-
portalUids: [portal.uid],
|
|
1232
|
-
layoutUids: [],
|
|
1233
|
-
selectedPortal: portal,
|
|
1234
|
-
layoutType: portal.layoutType
|
|
1235
|
-
};
|
|
1307
|
+
return this.buildDesktopRouteScopeForPortal(portal);
|
|
1236
1308
|
}
|
|
1237
1309
|
if (layoutUid) {
|
|
1310
|
+
const scope2 = { portalUids: [], layoutUids: [layoutUid] };
|
|
1311
|
+
this.assertAdminLayoutCreateScope(actionName, scope2, "values.layoutUid");
|
|
1238
1312
|
await this.assertEnabledDesktopRouteUiLayoutUid(layoutUid, actionName, "values.layoutUid", options.transaction);
|
|
1239
1313
|
if (parentRoute) {
|
|
1240
1314
|
await this.assertDesktopRouteBelongsToUiLayout(
|
|
@@ -1246,8 +1320,7 @@ class FlowSurfacesService {
|
|
|
1246
1320
|
);
|
|
1247
1321
|
}
|
|
1248
1322
|
return {
|
|
1249
|
-
|
|
1250
|
-
layoutUids: [layoutUid],
|
|
1323
|
+
...scope2,
|
|
1251
1324
|
layoutType: await this.getDesktopRouteUiLayoutTypeByUid(layoutUid, options.transaction)
|
|
1252
1325
|
};
|
|
1253
1326
|
}
|
|
@@ -1280,10 +1353,17 @@ class FlowSurfacesService {
|
|
|
1280
1353
|
};
|
|
1281
1354
|
}
|
|
1282
1355
|
}
|
|
1356
|
+
if (!parentRoute) {
|
|
1357
|
+
return this.resolveDefaultDesktopRouteScope(actionName, options);
|
|
1358
|
+
}
|
|
1283
1359
|
const layoutUids = await this.resolveInheritedDesktopRouteUiLayoutUids(parentRoute, options.transaction);
|
|
1284
|
-
|
|
1360
|
+
const scope = {
|
|
1285
1361
|
portalUids: [],
|
|
1286
|
-
layoutUids
|
|
1362
|
+
layoutUids
|
|
1363
|
+
};
|
|
1364
|
+
this.assertAdminLayoutCreateScope(actionName, scope, "values.parentMenuRouteId");
|
|
1365
|
+
return {
|
|
1366
|
+
...scope,
|
|
1287
1367
|
layoutType: layoutUids.length === 1 ? await this.getDesktopRouteUiLayoutTypeByUid(layoutUids[0], options.transaction) : void 0
|
|
1288
1368
|
};
|
|
1289
1369
|
}
|
|
@@ -1302,20 +1382,18 @@ class FlowSurfacesService {
|
|
|
1302
1382
|
currentRoles: options.currentRoles,
|
|
1303
1383
|
transaction: options.transaction
|
|
1304
1384
|
});
|
|
1305
|
-
await this.
|
|
1385
|
+
await this.assertRouteBelongsToResolvedPortal(
|
|
1306
1386
|
actionName,
|
|
1307
|
-
|
|
1308
|
-
portal
|
|
1387
|
+
route,
|
|
1388
|
+
portal,
|
|
1309
1389
|
"values.menuRouteId",
|
|
1310
1390
|
options.transaction
|
|
1311
1391
|
);
|
|
1312
|
-
return
|
|
1313
|
-
...routeScope,
|
|
1314
|
-
selectedPortal: portal,
|
|
1315
|
-
layoutType: portal.layoutType
|
|
1316
|
-
};
|
|
1392
|
+
return this.buildDesktopRouteScopeForPortal(portal);
|
|
1317
1393
|
}
|
|
1318
1394
|
if (layoutUid) {
|
|
1395
|
+
const scope2 = { ...routeScope, layoutUids: [layoutUid] };
|
|
1396
|
+
this.assertAdminLayoutCreateScope(actionName, scope2, "values.layoutUid");
|
|
1319
1397
|
await this.assertEnabledDesktopRouteUiLayoutUid(layoutUid, actionName, "values.layoutUid", options.transaction);
|
|
1320
1398
|
await this.assertDesktopRouteBelongsToUiLayout(
|
|
1321
1399
|
actionName,
|
|
@@ -1325,7 +1403,7 @@ class FlowSurfacesService {
|
|
|
1325
1403
|
options.transaction
|
|
1326
1404
|
);
|
|
1327
1405
|
return {
|
|
1328
|
-
...
|
|
1406
|
+
...scope2,
|
|
1329
1407
|
layoutType: await this.getDesktopRouteUiLayoutTypeByUid(layoutUid, options.transaction)
|
|
1330
1408
|
};
|
|
1331
1409
|
}
|
|
@@ -1355,10 +1433,22 @@ class FlowSurfacesService {
|
|
|
1355
1433
|
layoutType: portal.layoutType
|
|
1356
1434
|
};
|
|
1357
1435
|
}
|
|
1358
|
-
|
|
1359
|
-
|
|
1436
|
+
let layoutUids = routeScope.layoutUids;
|
|
1437
|
+
if (!layoutUids.length) {
|
|
1438
|
+
const parentRouteId = this.readRouteField(route, "parentId");
|
|
1439
|
+
const parentRoute = import_lodash.default.isNil(parentRouteId) ? null : await this.findMenuRouteById(parentRouteId, options.transaction);
|
|
1440
|
+
layoutUids = await this.resolveInheritedDesktopRouteUiLayoutUids(parentRoute, options.transaction);
|
|
1441
|
+
}
|
|
1442
|
+
const scope = {
|
|
1360
1443
|
portalUids: [],
|
|
1361
|
-
layoutUids
|
|
1444
|
+
layoutUids
|
|
1445
|
+
};
|
|
1446
|
+
this.assertAdminLayoutCreateScope(actionName, scope, "values.menuRouteId");
|
|
1447
|
+
if (!routeScope.layoutUids.length) {
|
|
1448
|
+
await this.setDesktopRouteUiLayouts(this.readRouteField(route, "id"), layoutUids, options.transaction);
|
|
1449
|
+
}
|
|
1450
|
+
return {
|
|
1451
|
+
...scope,
|
|
1362
1452
|
layoutType: layoutUids.length === 1 ? await this.getDesktopRouteUiLayoutTypeByUid(layoutUids[0], options.transaction) : void 0
|
|
1363
1453
|
};
|
|
1364
1454
|
}
|
|
@@ -1518,7 +1608,6 @@ class FlowSurfacesService {
|
|
|
1518
1608
|
}
|
|
1519
1609
|
}
|
|
1520
1610
|
async createFlowMenuGroup(values, options = {}) {
|
|
1521
|
-
var _a;
|
|
1522
1611
|
const parentRoute = await this.assertMenuParentIsGroup(values.parentMenuRouteId, options.transaction);
|
|
1523
1612
|
const parentId = this.readRouteField(parentRoute, "id") ?? null;
|
|
1524
1613
|
const routeScope = await this.resolveRequestedDesktopRouteScope(values, parentRoute, "createMenu", options);
|
|
@@ -1528,7 +1617,7 @@ class FlowSurfacesService {
|
|
|
1528
1617
|
title,
|
|
1529
1618
|
options.transaction,
|
|
1530
1619
|
routeScope.layoutUids,
|
|
1531
|
-
(
|
|
1620
|
+
this.getPortalRouteFilterUid(routeScope.selectedPortal)
|
|
1532
1621
|
);
|
|
1533
1622
|
if (existingGroups.length === 1) {
|
|
1534
1623
|
return this.buildMenuResult(existingGroups[0]);
|
|
@@ -3569,7 +3658,7 @@ class FlowSurfacesService {
|
|
|
3569
3658
|
tabs
|
|
3570
3659
|
};
|
|
3571
3660
|
}
|
|
3572
|
-
async resolveApplyBlueprintCreateNavigationGroup(document,
|
|
3661
|
+
async resolveApplyBlueprintCreateNavigationGroup(document, options = {}) {
|
|
3573
3662
|
var _a;
|
|
3574
3663
|
if (document.mode !== "create" || !import_lodash.default.isPlainObject((_a = document.navigation) == null ? void 0 : _a.group)) {
|
|
3575
3664
|
return document;
|
|
@@ -3583,12 +3672,13 @@ class FlowSurfacesService {
|
|
|
3583
3672
|
}
|
|
3584
3673
|
const layoutUid = this.normalizeExplicitDesktopRouteLayoutUid(document.navigation.layoutUid);
|
|
3585
3674
|
const portalUid = this.navigationTargets.normalizePortalUid(document.navigation.portalUid);
|
|
3675
|
+
const matchScope = await this.resolveDesktopRouteMatchScope(layoutUid, portalUid, "applyBlueprint", options);
|
|
3586
3676
|
const matchedRoutes = await this.findMenuGroupRoutesByParentIdAndTitle(
|
|
3587
3677
|
null,
|
|
3588
3678
|
groupTitle,
|
|
3589
|
-
transaction,
|
|
3590
|
-
|
|
3591
|
-
portalUid
|
|
3679
|
+
options.transaction,
|
|
3680
|
+
matchScope.layoutUids,
|
|
3681
|
+
matchScope.portalUid
|
|
3592
3682
|
);
|
|
3593
3683
|
if (!matchedRoutes.length) {
|
|
3594
3684
|
return document;
|
|
@@ -3614,6 +3704,24 @@ class FlowSurfacesService {
|
|
|
3614
3704
|
}
|
|
3615
3705
|
};
|
|
3616
3706
|
}
|
|
3707
|
+
async resolveApplyBlueprintDefaultNavigationTarget(document, options = {}) {
|
|
3708
|
+
var _a, _b, _c, _d;
|
|
3709
|
+
if (document.mode !== "create" || ((_a = document.navigation) == null ? void 0 : _a.layoutUid) || ((_b = document.navigation) == null ? void 0 : _b.portalUid) || !import_lodash.default.isUndefined((_d = (_c = document.navigation) == null ? void 0 : _c.group) == null ? void 0 : _d.routeId) || !this.navigationTargets.hasMultiPortalCapability()) {
|
|
3710
|
+
return document;
|
|
3711
|
+
}
|
|
3712
|
+
const portal = await this.navigationTargets.resolveDefaultPortal({
|
|
3713
|
+
actionName: "applyBlueprint",
|
|
3714
|
+
currentRoles: options.currentRoles,
|
|
3715
|
+
transaction: options.transaction
|
|
3716
|
+
});
|
|
3717
|
+
return {
|
|
3718
|
+
...document,
|
|
3719
|
+
navigation: {
|
|
3720
|
+
...document.navigation,
|
|
3721
|
+
portalUid: portal.uid
|
|
3722
|
+
}
|
|
3723
|
+
};
|
|
3724
|
+
}
|
|
3617
3725
|
async normalizeApplyBlueprintCreateMobileNavigation(document, options = {}) {
|
|
3618
3726
|
var _a, _b;
|
|
3619
3727
|
if (document.mode !== "create") {
|
|
@@ -3669,15 +3777,20 @@ class FlowSurfacesService {
|
|
|
3669
3777
|
return;
|
|
3670
3778
|
}
|
|
3671
3779
|
const groupRoute2 = await this.assertMenuParentIsGroup(groupRouteId2, options.transaction);
|
|
3672
|
-
await this.
|
|
3780
|
+
await this.assertRouteBelongsToResolvedPortal(
|
|
3673
3781
|
"applyBlueprint",
|
|
3674
|
-
|
|
3675
|
-
portal
|
|
3782
|
+
groupRoute2,
|
|
3783
|
+
portal,
|
|
3676
3784
|
"values.navigation.group.routeId",
|
|
3677
3785
|
options.transaction
|
|
3678
3786
|
);
|
|
3679
3787
|
return;
|
|
3680
3788
|
}
|
|
3789
|
+
this.assertAdminLayoutCreateScope(
|
|
3790
|
+
"applyBlueprint",
|
|
3791
|
+
{ portalUids: [], layoutUids: [layoutUid] },
|
|
3792
|
+
"values.navigation.layoutUid"
|
|
3793
|
+
);
|
|
3681
3794
|
await this.assertEnabledDesktopRouteUiLayoutUid(
|
|
3682
3795
|
layoutUid,
|
|
3683
3796
|
"applyBlueprint",
|
|
@@ -3700,7 +3813,7 @@ class FlowSurfacesService {
|
|
|
3700
3813
|
options.transaction
|
|
3701
3814
|
);
|
|
3702
3815
|
}
|
|
3703
|
-
async resolveApplyBlueprintCreatePageIdentity(document,
|
|
3816
|
+
async resolveApplyBlueprintCreatePageIdentity(document, options = {}) {
|
|
3704
3817
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
3705
3818
|
if (document.mode !== "create") {
|
|
3706
3819
|
return document;
|
|
@@ -3713,12 +3826,10 @@ class FlowSurfacesService {
|
|
|
3713
3826
|
if (!pageTitle || !hasGroupRouteId && !layoutUid && !portalUid) {
|
|
3714
3827
|
return document;
|
|
3715
3828
|
}
|
|
3716
|
-
const groupRoute = hasGroupRouteId ? await this.findMenuRouteById(groupRouteId, transaction) : null;
|
|
3829
|
+
const groupRoute = hasGroupRouteId ? await this.findMenuRouteById(groupRouteId, options.transaction) : null;
|
|
3830
|
+
const groupScope = groupRoute && !portalUid ? await this.readDesktopRouteScope(groupRoute, options.transaction) : void 0;
|
|
3717
3831
|
if (!portalUid && groupRoute) {
|
|
3718
|
-
const groupPortalUids =
|
|
3719
|
-
this.readRouteField(groupRoute, "id"),
|
|
3720
|
-
transaction
|
|
3721
|
-
);
|
|
3832
|
+
const groupPortalUids = (groupScope == null ? void 0 : groupScope.portalUids) || [];
|
|
3722
3833
|
if (groupPortalUids.length > 1) {
|
|
3723
3834
|
(0, import_errors.throwBadRequest)(
|
|
3724
3835
|
`flowSurfaces applyBlueprint navigation.group.routeId '${groupRouteId}' belongs to multiple portals; pass navigation.portalUid explicitly`,
|
|
@@ -3734,13 +3845,23 @@ class FlowSurfacesService {
|
|
|
3734
3845
|
}
|
|
3735
3846
|
portalUid = groupPortalUids[0];
|
|
3736
3847
|
}
|
|
3737
|
-
const
|
|
3848
|
+
const portalMatchScope = portalUid ? await this.resolveDesktopRouteMatchScope(layoutUid, portalUid, "applyBlueprint", options) : void 0;
|
|
3849
|
+
let layoutUidFilter = (portalMatchScope == null ? void 0 : portalMatchScope.layoutUids) || layoutUid;
|
|
3850
|
+
if (!portalMatchScope && !layoutUid && groupRoute) {
|
|
3851
|
+
layoutUidFilter = (groupScope == null ? void 0 : groupScope.layoutUids.length) ? groupScope.layoutUids : await this.resolveInheritedDesktopRouteUiLayoutUids(groupRoute, options.transaction);
|
|
3852
|
+
this.assertAdminLayoutCreateScope(
|
|
3853
|
+
"applyBlueprint",
|
|
3854
|
+
{ portalUids: [], layoutUids: this.normalizeDesktopRouteLayoutUidFilter(layoutUidFilter) },
|
|
3855
|
+
"values.navigation.group.routeId"
|
|
3856
|
+
);
|
|
3857
|
+
}
|
|
3858
|
+
const portalUidFilter = portalMatchScope == null ? void 0 : portalMatchScope.portalUid;
|
|
3738
3859
|
const matchedPages = await this.findFlowPageRoutesByParentIdAndTitle(
|
|
3739
3860
|
hasGroupRouteId ? groupRouteId : null,
|
|
3740
3861
|
pageTitle,
|
|
3741
|
-
transaction,
|
|
3862
|
+
options.transaction,
|
|
3742
3863
|
layoutUidFilter,
|
|
3743
|
-
|
|
3864
|
+
portalUidFilter
|
|
3744
3865
|
);
|
|
3745
3866
|
if (!matchedPages.length) {
|
|
3746
3867
|
return document;
|
|
@@ -3769,14 +3890,15 @@ class FlowSurfacesService {
|
|
|
3769
3890
|
}
|
|
3770
3891
|
async prepareApplyBlueprintRequest(values, options = {}, createdKanbanSortFields) {
|
|
3771
3892
|
var _a;
|
|
3772
|
-
const
|
|
3893
|
+
const parsedDocument = (0, import_blueprint.prepareFlowSurfaceApplyBlueprintDocument)(values);
|
|
3894
|
+
const initialDocument = await this.resolveApplyBlueprintDefaultNavigationTarget(parsedDocument, options);
|
|
3773
3895
|
await this.assertApplyBlueprintCreateNavigationTarget(initialDocument, options);
|
|
3774
3896
|
const mobileNormalizedDocument = await this.normalizeApplyBlueprintCreateMobileNavigation(initialDocument, options);
|
|
3775
3897
|
const groupResolvedDocument = await this.resolveApplyBlueprintCreateNavigationGroup(
|
|
3776
3898
|
mobileNormalizedDocument,
|
|
3777
|
-
options
|
|
3899
|
+
options
|
|
3778
3900
|
);
|
|
3779
|
-
const document = await this.resolveApplyBlueprintCreatePageIdentity(groupResolvedDocument, options
|
|
3901
|
+
const document = await this.resolveApplyBlueprintCreatePageIdentity(groupResolvedDocument, options);
|
|
3780
3902
|
await this.prepareApplyBlueprintKanbanBlocks(document, options.transaction, createdKanbanSortFields);
|
|
3781
3903
|
const replaceTarget = document.mode === "replace" && document.target ? await this.resolveApplyBlueprintReplaceTargetInfo(document.target.pageSchemaUid, options.transaction) : void 0;
|
|
3782
3904
|
if (document.mode === "replace" && document.tabs.length > 1 && typeof ((_a = document.page) == null ? void 0 : _a.enableTabs) === "undefined" && (replaceTarget == null ? void 0 : replaceTarget.pageEnableTabs) === false) {
|
|
@@ -4445,7 +4567,18 @@ class FlowSurfacesService {
|
|
|
4445
4567
|
await (0, import_authoring_validation.assertFlowSurfaceAuthoringPayload)("applyBlueprint", values, {
|
|
4446
4568
|
transaction: options.transaction,
|
|
4447
4569
|
enabledPackages,
|
|
4448
|
-
findMenuGroupRoutesByTitle: (title, transaction, targetLayoutUid, targetPortalUid) =>
|
|
4570
|
+
findMenuGroupRoutesByTitle: async (title, transaction, targetLayoutUid, targetPortalUid) => {
|
|
4571
|
+
const matchScope = await this.resolveDesktopRouteMatchScope(
|
|
4572
|
+
targetLayoutUid,
|
|
4573
|
+
targetPortalUid,
|
|
4574
|
+
"applyBlueprint",
|
|
4575
|
+
{
|
|
4576
|
+
transaction,
|
|
4577
|
+
currentRoles: options.currentRoles
|
|
4578
|
+
}
|
|
4579
|
+
);
|
|
4580
|
+
return this.findMenuGroupRoutesByTitle(title, transaction, matchScope.layoutUids, matchScope.portalUid);
|
|
4581
|
+
},
|
|
4449
4582
|
getUiLayoutTypeByUid: (layoutUid2, transaction) => this.getDesktopRouteUiLayoutTypeByUid(layoutUid2, transaction),
|
|
4450
4583
|
getPortalLayoutTypeByUid: async (targetPortalUid, transaction) => {
|
|
4451
4584
|
if ((resolvedPortal == null ? void 0 : resolvedPortal.uid) === targetPortalUid) {
|
|
@@ -6515,18 +6648,18 @@ class FlowSurfacesService {
|
|
|
6515
6648
|
currentRoles: options.currentRoles,
|
|
6516
6649
|
transaction: options.transaction
|
|
6517
6650
|
});
|
|
6518
|
-
await this.
|
|
6651
|
+
await this.assertRouteBelongsToResolvedPortal(
|
|
6519
6652
|
"updateMenu",
|
|
6520
|
-
|
|
6521
|
-
portal
|
|
6653
|
+
route,
|
|
6654
|
+
portal,
|
|
6522
6655
|
"values.menuRouteId",
|
|
6523
6656
|
options.transaction
|
|
6524
6657
|
);
|
|
6525
6658
|
if (nextParentRoute) {
|
|
6526
|
-
await this.
|
|
6659
|
+
await this.assertRouteBelongsToResolvedPortal(
|
|
6527
6660
|
"updateMenu",
|
|
6528
|
-
|
|
6529
|
-
portal
|
|
6661
|
+
nextParentRoute,
|
|
6662
|
+
portal,
|
|
6530
6663
|
"values.parentMenuRouteId",
|
|
6531
6664
|
options.transaction
|
|
6532
6665
|
);
|
|
@@ -621,7 +621,7 @@ const actionDocs = {
|
|
|
621
621
|
},
|
|
622
622
|
listNavigationTargets: {
|
|
623
623
|
tags: [FLOW_SURFACES_TAG],
|
|
624
|
-
summary: "List available UI layouts and role-accessible Multi-portal
|
|
624
|
+
summary: "List available UI layouts and role-accessible Multi-portal entries",
|
|
625
625
|
description: valuesCompatibilityNote(
|
|
626
626
|
`Returns the default Admin target, enabled UI layouts, and enabled custom Multi-portal targets visible to the current roles. capabilities.multiPortal=false and an empty custom-portal set are normal when the commercial Multi-portal capability is not installed. Reserved default portal records are never returned as custom workspaces; Admin and Mobile use their ordinary layout uids. Call this action only when the user explicitly names a workspace or asks to discover navigation targets. ${FLOW_SURFACES_READ_ACL_NOTE}`
|
|
627
627
|
),
|
|
@@ -632,7 +632,7 @@ const actionDocs = {
|
|
|
632
632
|
tags: [FLOW_SURFACES_TAG],
|
|
633
633
|
summary: "Apply a page blueprint to create or replace one Modern page",
|
|
634
634
|
description: valuesCompatibilityNote(
|
|
635
|
-
`In create mode, \`navigation.portalUid\` targets one enabled, role-accessible Multi-portal
|
|
635
|
+
`In create mode, \`navigation.portalUid\` targets one enabled, role-accessible Multi-portal entry and is mutually exclusive with \`navigation.layoutUid\`. Portal-backed mobile layouts ignore \`navigation.group\`, while desktop-backed portals scope group reuse and duplicate-page identity to that portal. If Multi-portal is unavailable, ordinary requests without \`portalUid\` keep their existing Admin behavior. Accepts one simplified JSON page blueprint and compiles it to internal flow-surface operations. The public blueprint describes page structure (\`create\` or \`replace\`, page metadata, ordered tabs, blocks, fields, actions, inline popups, optional reusable assets) and optional top-level \`reaction.items[]\` for whole-page interaction authoring. Each reaction item targets an explicit local key / bind key produced by the same blueprint run. Only explicitly listed reaction items are written. \`rules: []\` clears the targeted slot. Repeating the same \`(type, target)\` reaction slot in one blueprint is invalid. In \`replace\`, reaction targets always bind to the newly produced blueprint result, not historical nodes from the previous page version; if a slot must exist in the resulting surface, include it explicitly instead of relying on omission. Localized reaction edits on an existing surface should use \`getReactionMeta\` + \`set*Rules\` instead of applying a whole page blueprint again. The request body is that page-document JSON object itself and must not be JSON-stringified. Wrong: \`{ "requestBody": "{\\"version\\":\\"1\\"}" }\`. Internal planning details stay hidden. In \`create\`, \`navigation.layoutUid\` optionally scopes menu group reuse, duplicate page identity checks, and newly created routes to an enabled UI layout such as \`admin-layout-model\` or \`mobile-layout-model\`; when the target layout type is mobile, applyBlueprint ignores \`navigation.group\` and creates a root-level mobile tab page. When \`layoutUid\` is omitted, routes keep the existing admin/default inheritance behavior. In non-mobile \`create\`, \`navigation.group.routeId\` has the highest priority when targeting an existing menu group. If \`routeId\` is present, applyBlueprint ignores \`title\`, \`icon\`, \`tooltip\`, and \`hideInMenu\` on \`navigation.group\`; applyBlueprint create mode does not mutate existing group metadata, so callers should use \`updateMenu\` separately when that is required. When \`routeId\` is omitted and \`navigation.group.title\` is provided, applyBlueprint reuses one existing same-title group in the target layout when it is unique, creates a new group when none exists, and rejects ambiguous multi-match cases. Metadata such as \`icon\`, \`tooltip\`, and \`hideInMenu\` is used only when a new group is created and is ignored when an existing group is reused. \`replace\` uses \`target.pageSchemaUid\`, updates only the explicit page-level fields provided in \`page\`, maps blueprint tabs to existing route-backed tab slots by index, rewrites each slot in order, removes trailing old tabs, and appends extra new tabs when needed. Tab and block keys are optional in the public blueprint; omit them unless custom layout or cross-block targeting needs a stable in-document identifier. \`layout\` is only allowed on tabs and inline popup documents; blocks themselves do not accept a \`layout\` property. Public applyBlueprint blocks do not support generic \`form\`; use \`editForm\` or \`createForm\`. AI employee actions use \`type: "aiEmployee"\` plus public \`settings.username\`, \`workContext\`, \`tasks\`, \`auto\`, and \`style\`; work context may target \`self\` or a same-blueprint block key and is persisted as real Flow Model \`uid\` values. For JS blocks/fields/actions, \`script\` is a non-empty string asset key into \`assets.scripts\`; put inline JS in \`settings.code\` and \`settings.version\`. Direct \`table\` / \`list\` / \`gridCard\` / \`calendar\` / \`kanban\` blocks may omit \`defaultFilter\`; the backend generates one from live metadata with up to 4 scalar/filterable fields. Explicit values must contain at least the smaller of 3 and the collection eligible-field count, and values with more than 4 fields are truncated before persistence. A valid explicit or generated block-level value backfills the default \`filter\` action \`settings.defaultFilter\`; explicit filter-action \`settings.defaultFilter\` still wins. ${TREE_TABLE_RECORD_ACTION_DEFAULTS_NOTE} ${APPLY_BLUEPRINT_TREE_TABLE_TITLE_FIELD_NOTE} Inline popup documents may set \`popup.tryTemplate=true\` to ask the backend for the best compatible popup template before falling back to local popup content. Inline popup documents may also combine \`popup.tryTemplate\` with \`popup.saveAsTemplate={ name, description, local? }\`: a hit binds the matched template immediately and lets later inline popups in the same blueprint reuse that final bound template through \`popup.template={ local, mode }\`, while a miss requires explicit local \`popup.blocks\` so the fallback popup can be saved and reused. Custom \`edit\` popups that provide \`popup.blocks\` must include exactly one \`editForm\` block; that \`editForm\` may omit \`resource\` and then inherits the opener's current-record context. When layout is omitted, applyBlueprint auto-generates a simple top-to-bottom layout. When a \`replace\` run expands a page to multiple tabs while the current page still has \`enableTabs=false\`, callers must set \`page.enableTabs=true\` explicitly. The response hides execution internals and returns only the resolved page target and final surface readback.`
|
|
636
636
|
),
|
|
637
637
|
requestBody: {
|
|
638
638
|
required: true,
|
|
@@ -818,7 +818,7 @@ const actionDocs = {
|
|
|
818
818
|
tags: [FLOW_SURFACES_TAG],
|
|
819
819
|
summary: "Create a group menu or a bindable V2 menu item",
|
|
820
820
|
description: valuesCompatibilityNote(
|
|
821
|
-
'Creates a FlowSurfaces menu node. `type="group"` creates a menu group. `type="item"` creates a menu item that can be bound to a modern page (v2), and automatically fills in the flowPage route, the default hidden tab route, and the RootPageModel anchor. Optional `layoutUid` scopes the route to an enabled UI layout. Optional `portalUid` scopes it to one enabled, role-accessible Multi-portal
|
|
821
|
+
'Creates a FlowSurfaces menu node. `type="group"` creates a menu group. `type="item"` creates a menu item that can be bound to a modern page (v2), and automatically fills in the flowPage route, the default hidden tab route, and the RootPageModel anchor. Optional `layoutUid` scopes the route to an enabled UI layout. Optional `portalUid` scopes it to one enabled, role-accessible Multi-portal entry and is mutually exclusive with `layoutUid`. Omitted values keep the existing parent/default admin inheritance.'
|
|
822
822
|
),
|
|
823
823
|
requestBody: requestBody("FlowSurfaceCreateMenuRequest", import_flow_surfaces.flowSurfaceExamples.createMenu),
|
|
824
824
|
responses: responses("FlowSurfaceCreateMenuResult")
|
|
@@ -827,7 +827,7 @@ const actionDocs = {
|
|
|
827
827
|
tags: [FLOW_SURFACES_TAG],
|
|
828
828
|
summary: "Update menu title/icon/tooltip or move it under another group",
|
|
829
829
|
description: valuesCompatibilityNote(
|
|
830
|
-
"Updates menu display information, or moves a group / item to the top level or under another group. Only `group` and `flowPage` menu nodes are supported. Pass `portalUid` when explicitly targeting a Multi-portal
|
|
830
|
+
"Updates menu display information, or moves a group / item to the top level or under another group. Only `group` and `flowPage` menu nodes are supported. Pass `portalUid` when explicitly targeting a Multi-portal entry; the route and new parent must already belong to that portal."
|
|
831
831
|
),
|
|
832
832
|
requestBody: requestBody("FlowSurfaceUpdateMenuRequest", import_flow_surfaces.flowSurfaceExamples.updateMenu),
|
|
833
833
|
responses: responses("FlowSurfaceUpdateMenuResult")
|
|
@@ -836,7 +836,7 @@ const actionDocs = {
|
|
|
836
836
|
tags: [FLOW_SURFACES_TAG],
|
|
837
837
|
summary: "Initialize a modern page for an existing bindable menu item",
|
|
838
838
|
description: valuesCompatibilityNote(
|
|
839
|
-
"Initializes a modern page (v2) for an existing bindable menu item through `menuRouteId` first, and fills in the default BlockGridModel. Optional `layoutUid` asserts that the existing menu route belongs to the target UI layout. Optional `portalUid` asserts that it belongs to one enabled, role-accessible Multi-portal
|
|
839
|
+
"Initializes a modern page (v2) for an existing bindable menu item through `menuRouteId` first, and fills in the default BlockGridModel. Optional `layoutUid` asserts that the existing menu route belongs to the target UI layout. Optional `portalUid` asserts that it belongs to one enabled, role-accessible Multi-portal entry and is mutually exclusive with `layoutUid`. Omitted values preserve the route scope and keep default admin compatibility. In compatibility mode, if `menuRouteId` is omitted, the old behavior still applies and a top-level menu plus page will be created automatically. Before initialization, do not call page/tab lifecycle actions such as `addTab`, `updateTab`, `moveTab`, `removeTab`, or `destroyPage`."
|
|
840
840
|
),
|
|
841
841
|
requestBody: requestBody("FlowSurfaceCreatePageRequest", import_flow_surfaces.flowSurfaceExamples.createPage),
|
|
842
842
|
responses: responses("FlowSurfaceCreatePageResult")
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"displayName.zh-CN": "前端流引擎",
|
|
5
5
|
"description": "",
|
|
6
6
|
"description.zh-CN": "",
|
|
7
|
-
"version": "
|
|
7
|
+
"version": "3.0.0-alpha.11",
|
|
8
8
|
"main": "./dist/server/index.js",
|
|
9
9
|
"license": "Apache-2.0",
|
|
10
10
|
"devDependencies": {
|
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
"@nocobase/test": "2.x",
|
|
27
27
|
"@nocobase/utils": "2.x"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "03574f3a2d10b1ed8469dc7405aa0c4696d6d1d1"
|
|
30
30
|
}
|