@nocobase/app 2.3.0-alpha.1 → 3.0.0-alpha.1

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.
Files changed (273) hide show
  1. package/__tests__/browserChecker.test.ts +129 -0
  2. package/__tests__/settingsDevProxy.test.ts +96 -0
  3. package/__tests__/settingsPluginImports.test.ts +106 -0
  4. package/client/rsbuild.config.ts +37 -15
  5. package/client-settings/generatePluginImports.ts +36 -0
  6. package/client-settings/index.html +11 -0
  7. package/client-settings/rsbuild.config.ts +270 -0
  8. package/client-settings/src/.plugins/index.ts +4 -0
  9. package/client-settings/src/SettingsPresetPlugin.ts +56 -0
  10. package/client-settings/src/__tests__/runtimePublicPath.test.ts +23 -0
  11. package/client-settings/src/__tests__/runtimeScope.test.ts +29 -0
  12. package/client-settings/src/env.d.ts +22 -0
  13. package/client-settings/src/main.tsx +78 -0
  14. package/client-settings/src/runtimePublicPath.ts +21 -0
  15. package/client-settings/src/runtimeScope.ts +49 -0
  16. package/client-settings/tsconfig.json +19 -0
  17. package/client-v2/public/browser-checker.js +76 -1
  18. package/client-v2/rsbuild.config.ts +31 -9
  19. package/dist/client/assets/{index-800d06ee.js → index-b8e6cdd9.js} +369 -355
  20. package/dist/client/assets/{vendor-antd-f421fb70.js → vendor-antd-b77deb8f.js} +4 -4
  21. package/dist/client/index.html +1 -1
  22. package/dist/client/index.html.tpl +1 -1
  23. package/dist/client/settings/assets/1052-2ed99808.js +1 -0
  24. package/dist/client/settings/assets/108-76a3fdea.js +82 -0
  25. package/dist/client/settings/assets/108-76a3fdea.js.LICENSE.txt +17 -0
  26. package/dist/client/settings/assets/1101-53bb815a.js +1 -0
  27. package/dist/client/settings/assets/1179-1ec4826c.js +1 -0
  28. package/dist/client/settings/assets/1310-c0031389.js +59 -0
  29. package/dist/client/settings/assets/1329-0e47aabd.js +1 -0
  30. package/dist/client/settings/assets/1425-69534606.js +42 -0
  31. package/dist/client/settings/assets/1434-d603f255.js +1 -0
  32. package/dist/client/settings/assets/1463-11b9abe3.js +1 -0
  33. package/dist/client/settings/assets/1469-477cfa59.js +1 -0
  34. package/dist/client/settings/assets/1481-59e4188c.js +1 -0
  35. package/dist/client/settings/assets/1507-9a211af0.js +7 -0
  36. package/dist/client/settings/assets/158-5273dfbb.js +23 -0
  37. package/dist/client/settings/assets/1586-73831f88.js +1 -0
  38. package/dist/client/settings/assets/1667-88ad86eb.js +1 -0
  39. package/dist/client/settings/assets/1675-3cbafc50.js +1 -0
  40. package/dist/client/settings/assets/1676-5db7433e.js +9 -0
  41. package/dist/client/settings/assets/1725-d9ce2582.js +83 -0
  42. package/dist/client/settings/assets/1786-e6c321bb.js +16 -0
  43. package/dist/client/settings/assets/183-963396ee.js +1 -0
  44. package/dist/client/settings/assets/1846-0deb6fc0.js +1 -0
  45. package/dist/client/settings/assets/1848-0ef98f01.js +1 -0
  46. package/dist/client/settings/assets/1863-9160dd98.js +1 -0
  47. package/dist/client/settings/assets/1887-bf619cb3.js +1 -0
  48. package/dist/client/settings/assets/192-c347bb96.js +1 -0
  49. package/dist/client/settings/assets/1951-84be8ebc.js +55 -0
  50. package/dist/client/settings/assets/1979-a893b852.js +1 -0
  51. package/dist/client/settings/assets/1986-01c03982.js +1 -0
  52. package/dist/client/settings/assets/2017-29a9879a.js +26 -0
  53. package/dist/client/settings/assets/2110-961b6f8e.js +1 -0
  54. package/dist/client/settings/assets/212-0f8a26a2.js +18 -0
  55. package/dist/client/settings/assets/2203-9aa79271.js +4 -0
  56. package/dist/client/settings/assets/2258-f667d700.js +1 -0
  57. package/dist/client/settings/assets/2270-ff70d8cb.js +1 -0
  58. package/dist/client/settings/assets/2301-2db05359.js +1 -0
  59. package/dist/client/settings/assets/2322-b9f077c3.js +1 -0
  60. package/dist/client/settings/assets/2335-669f21bd.js +22 -0
  61. package/dist/client/settings/assets/242-c3e15c94.js +1 -0
  62. package/dist/client/settings/assets/2446-ac5fccd3.js +1 -0
  63. package/dist/client/settings/assets/2512-5343dabb.js +1185 -0
  64. package/dist/client/settings/assets/2512-5343dabb.js.LICENSE.txt +9 -0
  65. package/dist/client/settings/assets/2555-4ca49e21.js +31 -0
  66. package/dist/client/settings/assets/2565-ad63e92f.js +1 -0
  67. package/dist/client/settings/assets/2606-c4dcd1e1.js +1 -0
  68. package/dist/client/settings/assets/2613-98648bd2.js +1 -0
  69. package/dist/client/settings/assets/2622-3389992f.js +1 -0
  70. package/dist/client/settings/assets/2702-5ce93acd.js +5 -0
  71. package/dist/client/settings/assets/2710-e7286996.js +36 -0
  72. package/dist/client/settings/assets/2726-4d19faa1.js +23 -0
  73. package/dist/client/settings/assets/2861-48106fd8.js +3 -0
  74. package/dist/client/settings/assets/2898-7656f7f9.js +17 -0
  75. package/dist/client/settings/assets/2913-6b4e6c17.js +1 -0
  76. package/dist/client/settings/assets/2958-93de29a6.js +27 -0
  77. package/dist/client/settings/assets/300-ca09229f.js +1 -0
  78. package/dist/client/settings/assets/3005-1449fc4e.js +56 -0
  79. package/dist/client/settings/assets/3018-fc630932.js +3 -0
  80. package/dist/client/settings/assets/3028-efe6f61f.js +1 -0
  81. package/dist/client/settings/assets/3039-7f273921.js +1 -0
  82. package/dist/client/settings/assets/3102-b985963e.js +1 -0
  83. package/dist/client/settings/assets/3117-cc936eae.js +33 -0
  84. package/dist/client/settings/assets/32-88d3c82f.js +2 -0
  85. package/dist/client/settings/assets/3260-3b3c7cd3.js +1 -0
  86. package/dist/client/settings/assets/3279-8d73fd19.js +1 -0
  87. package/dist/client/settings/assets/3283-654f42f7.js +1 -0
  88. package/dist/client/settings/assets/3309-172e3f79.js +1 -0
  89. package/dist/client/settings/assets/335-da9c4d81.js +1 -0
  90. package/dist/client/settings/assets/338-2f192edd.js +3 -0
  91. package/dist/client/settings/assets/3396-4422ee26.js +1 -0
  92. package/dist/client/settings/assets/3458-2958f051.js +1 -0
  93. package/dist/client/settings/assets/3475-be655098.js +1 -0
  94. package/dist/client/settings/assets/3523-5313a211.js +1 -0
  95. package/dist/client/settings/assets/3526-17f4e8e7.js +1 -0
  96. package/dist/client/settings/assets/3641-c2439c22.js +1 -0
  97. package/dist/client/settings/assets/3646-aa6a2478.js +1 -0
  98. package/dist/client/settings/assets/3660-280439df.js +6 -0
  99. package/dist/client/settings/assets/3662-8dff1ffe.js +28 -0
  100. package/dist/client/settings/assets/3690-4a8bdf43.js +12 -0
  101. package/dist/client/settings/assets/3727-1cfef422.js +44 -0
  102. package/dist/client/settings/assets/3859-fa4f6d5d.js +1 -0
  103. package/dist/client/settings/assets/3898-6236af03.js +1 -0
  104. package/dist/client/settings/assets/3916-3b34f216.js +6 -0
  105. package/dist/client/settings/assets/3937-af967d62.js +3 -0
  106. package/dist/client/settings/assets/3977-3feadc2c.js +1 -0
  107. package/dist/client/settings/assets/3978-29c2602c.js +1 -0
  108. package/dist/client/settings/assets/3989-c8fcfd6c.js +27 -0
  109. package/dist/client/settings/assets/406-497829bb.js +1 -0
  110. package/dist/client/settings/assets/4076-f68c25bd.js +1 -0
  111. package/dist/client/settings/assets/4096-0050f491.js +1 -0
  112. package/dist/client/settings/assets/4171-0710965d.js +2 -0
  113. package/dist/client/settings/assets/4171-0710965d.js.LICENSE.txt +6 -0
  114. package/dist/client/settings/assets/4195-2a00794d.js +1 -0
  115. package/dist/client/settings/assets/4222-29a8147d.js +5 -0
  116. package/dist/client/settings/assets/4223-3821a30e.js +1 -0
  117. package/dist/client/settings/assets/4313-ab774fd9.js +28 -0
  118. package/dist/client/settings/assets/4358-0a504478.js +1 -0
  119. package/dist/client/settings/assets/4419-3ab9c709.js +1 -0
  120. package/dist/client/settings/assets/4456-49679669.js +1 -0
  121. package/dist/client/settings/assets/448-57d6a00d.js +1 -0
  122. package/dist/client/settings/assets/4594-4e72041f.js +1 -0
  123. package/dist/client/settings/assets/4672-573e9a61.js +1 -0
  124. package/dist/client/settings/assets/4686-afbf676f.js +1 -0
  125. package/dist/client/settings/assets/474-ce4285d1.js +1 -0
  126. package/dist/client/settings/assets/4767-8f9d30dc.js +1 -0
  127. package/dist/client/settings/assets/4784-c69aaa68.js +1 -0
  128. package/dist/client/settings/assets/4801-06781ed7.js +1 -0
  129. package/dist/client/settings/assets/492-937af2ba.js +1 -0
  130. package/dist/client/settings/assets/4930-41adc6b7.js +1 -0
  131. package/dist/client/settings/assets/5064-93d8e29e.js +10 -0
  132. package/dist/client/settings/assets/5087-c505a60e.js +1 -0
  133. package/dist/client/settings/assets/5108-a028f8af.js +1 -0
  134. package/dist/client/settings/assets/5122-649463de.js +1 -0
  135. package/dist/client/settings/assets/5123-0bd0a6f2.js +1 -0
  136. package/dist/client/settings/assets/5139-3039fde4.js +1 -0
  137. package/dist/client/settings/assets/5459-c1f208e3.js +1 -0
  138. package/dist/client/settings/assets/5501-387a31be.js +17 -0
  139. package/dist/client/settings/assets/5506-a1f27be3.js +1 -0
  140. package/dist/client/settings/assets/553-1c3126df.js +1 -0
  141. package/dist/client/settings/assets/557-950114e1.js +1 -0
  142. package/dist/client/settings/assets/5640-f846c2a0.js +1 -0
  143. package/dist/client/settings/assets/5642-5c0bab20.js +1 -0
  144. package/dist/client/settings/assets/5674-e33e384f.js +1 -0
  145. package/dist/client/settings/assets/5701-8fe417d1.js +1 -0
  146. package/dist/client/settings/assets/5721-af25e047.js +18 -0
  147. package/dist/client/settings/assets/5757-81a89522.js +1 -0
  148. package/dist/client/settings/assets/5759-2b3bdcc6.js +47 -0
  149. package/dist/client/settings/assets/5761-857b6bbb.js +28 -0
  150. package/dist/client/settings/assets/5791-7c59ba08.js +1 -0
  151. package/dist/client/settings/assets/58-77bfd6c9.js +1 -0
  152. package/dist/client/settings/assets/5815-04fc432a.js +1 -0
  153. package/dist/client/settings/assets/5819-225de680.js +1 -0
  154. package/dist/client/settings/assets/5861-ac056534.js +1 -0
  155. package/dist/client/settings/assets/5870-0c3ecc40.js +1 -0
  156. package/dist/client/settings/assets/5881-b4c942f1.js +1 -0
  157. package/dist/client/settings/assets/5905-a5c3fce6.js +1 -0
  158. package/dist/client/settings/assets/5933-fbe50cd6.js +1 -0
  159. package/dist/client/settings/assets/6062-0e469079.js +1 -0
  160. package/dist/client/settings/assets/6093-641fcafc.js +1 -0
  161. package/dist/client/settings/assets/6157-8e763248.js +1 -0
  162. package/dist/client/settings/assets/6241-55a319df.js +1 -0
  163. package/dist/client/settings/assets/6269-a8a1ea3f.js +1 -0
  164. package/dist/client/settings/assets/630-110e12f4.js +1 -0
  165. package/dist/client/settings/assets/6345-187e76cf.js +1 -0
  166. package/dist/client/settings/assets/6346-94bdf034.js +1 -0
  167. package/dist/client/settings/assets/6373-9d047c6b.js +13 -0
  168. package/dist/client/settings/assets/6437-3865fd7e.js +12 -0
  169. package/dist/client/settings/assets/6581-51c928bf.js +21 -0
  170. package/dist/client/settings/assets/6660-54e08a8d.js +1 -0
  171. package/dist/client/settings/assets/6738-c6598897.js +20 -0
  172. package/dist/client/settings/assets/6870-6a6dba63.js +1 -0
  173. package/dist/client/settings/assets/6914-00d913e7.js +1 -0
  174. package/dist/client/settings/assets/70-f4dc53ad.js +1 -0
  175. package/dist/client/settings/assets/700-e75b7faa.js +15 -0
  176. package/dist/client/settings/assets/7021-4975d54d.js +45 -0
  177. package/dist/client/settings/assets/7095-4f425b85.js +1 -0
  178. package/dist/client/settings/assets/7141-b8e2a787.js +1 -0
  179. package/dist/client/settings/assets/7201-5b49ce84.js +14 -0
  180. package/dist/client/settings/assets/7211-b8c71ed2.js +9 -0
  181. package/dist/client/settings/assets/7245-1058e96e.js +474 -0
  182. package/dist/client/settings/assets/7245-1058e96e.js.LICENSE.txt +2567 -0
  183. package/dist/client/settings/assets/7245-db3cd5c2.css +1 -0
  184. package/dist/client/settings/assets/7318-6e1c7877.js +1 -0
  185. package/dist/client/settings/assets/7386-2f5752d4.js +1 -0
  186. package/dist/client/settings/assets/7413-241d463c.js +1 -0
  187. package/dist/client/settings/assets/7492-5c593f52.js +5 -0
  188. package/dist/client/settings/assets/7507-a015d8cf.js +1 -0
  189. package/dist/client/settings/assets/754-41b763b9.js +17 -0
  190. package/dist/client/settings/assets/7555-f42cdb72.js +1 -0
  191. package/dist/client/settings/assets/7608-2b3f2db0.js +1 -0
  192. package/dist/client/settings/assets/7669-8bd94b73.js +1 -0
  193. package/dist/client/settings/assets/7761-637067c6.js +123 -0
  194. package/dist/client/settings/assets/7876-673cbc3c.js +6 -0
  195. package/dist/client/settings/assets/791-9cfa98c8.js +1 -0
  196. package/dist/client/settings/assets/7946-e07199df.js +13 -0
  197. package/dist/client/settings/assets/7959-f7ef21c6.js +40 -0
  198. package/dist/client/settings/assets/8053-fa93540e.js +1 -0
  199. package/dist/client/settings/assets/8087-90829087.js +1 -0
  200. package/dist/client/settings/assets/8138-e90c290e.js +24 -0
  201. package/dist/client/settings/assets/8217-de1369d7.js +1 -0
  202. package/dist/client/settings/assets/8242-3f880357.js +108 -0
  203. package/dist/client/settings/assets/8252-1153ffdd.js +1 -0
  204. package/dist/client/settings/assets/8262-7a324b59.js +9 -0
  205. package/dist/client/settings/assets/8269-52ea88cd.js +1 -0
  206. package/dist/client/settings/assets/8276-b3dfc452.js +1 -0
  207. package/dist/client/settings/assets/828-55028e33.js +1 -0
  208. package/dist/client/settings/assets/8294-9c81768d.js +1 -0
  209. package/dist/client/settings/assets/8295-447d3bb3.js +1 -0
  210. package/dist/client/settings/assets/8349-82eb3ecd.js +1 -0
  211. package/dist/client/settings/assets/8434-9140d106.js +25 -0
  212. package/dist/client/settings/assets/8438-d2ff6bc1.js +37 -0
  213. package/dist/client/settings/assets/8473-b1118703.js +1 -0
  214. package/dist/client/settings/assets/8480-c16f7ee4.js +1 -0
  215. package/dist/client/settings/assets/8562-ffa35312.js +17 -0
  216. package/dist/client/settings/assets/8624-847569d9.js +1 -0
  217. package/dist/client/settings/assets/8631-b2fd9aac.js +1 -0
  218. package/dist/client/settings/assets/8635-27980c94.js +1 -0
  219. package/dist/client/settings/assets/8676-987fe455.js +1 -0
  220. package/dist/client/settings/assets/8729-9adea5fe.js +1 -0
  221. package/dist/client/settings/assets/8759-4d7f7a69.js +1 -0
  222. package/dist/client/settings/assets/896-d07bab4d.js +1 -0
  223. package/dist/client/settings/assets/9021-ec1b8442.js +1 -0
  224. package/dist/client/settings/assets/9065-5df7b63d.js +1 -0
  225. package/dist/client/settings/assets/9170-efbfcc1e.js +1 -0
  226. package/dist/client/settings/assets/9204-6cb7a01b.js +1 -0
  227. package/dist/client/settings/assets/9217-f27c2dcb.js +1 -0
  228. package/dist/client/settings/assets/9248-ff8e06d0.js +1 -0
  229. package/dist/client/settings/assets/9274-83aa1da2.js +1 -0
  230. package/dist/client/settings/assets/929-a37c623d.js +1 -0
  231. package/dist/client/settings/assets/93-dc732e8a.js +1 -0
  232. package/dist/client/settings/assets/9518-4c8b8805.js +1 -0
  233. package/dist/client/settings/assets/9550-2daf603c.js +1 -0
  234. package/dist/client/settings/assets/9565-2158d75f.js +1 -0
  235. package/dist/client/settings/assets/9578-f64d8970.js +1 -0
  236. package/dist/client/settings/assets/9584-969e1d2b.js +1 -0
  237. package/dist/client/settings/assets/9592-523a3fa6.js +1 -0
  238. package/dist/client/settings/assets/9827-d1f02095.js +9 -0
  239. package/dist/client/settings/assets/9836-fcbb81f6.js +22 -0
  240. package/dist/client/settings/assets/9847-bc9f1ba4.js +1 -0
  241. package/dist/client/settings/assets/9953-407a1cde.js +1 -0
  242. package/dist/client/settings/assets/index-222fdff7.js +1946 -0
  243. package/dist/client/settings/assets/index-222fdff7.js.LICENSE.txt +1 -0
  244. package/dist/client/settings/assets/runtime-6b2f3ebe.js +1 -0
  245. package/dist/client/settings/browser-checker.js +282 -0
  246. package/dist/client/settings/favicon/favicon.ico +0 -0
  247. package/dist/client/settings/file-placeholder/ai-200-200.png +0 -0
  248. package/dist/client/settings/file-placeholder/audio-200-200.png +0 -0
  249. package/dist/client/settings/file-placeholder/docx-200-200.png +0 -0
  250. package/dist/client/settings/file-placeholder/eps-200-200.png +0 -0
  251. package/dist/client/settings/file-placeholder/gif-200-200.png +0 -0
  252. package/dist/client/settings/file-placeholder/jpeg-200-200.png +0 -0
  253. package/dist/client/settings/file-placeholder/pdf-200-200.png +0 -0
  254. package/dist/client/settings/file-placeholder/png-200-200.png +0 -0
  255. package/dist/client/settings/file-placeholder/pptx-200-200.png +0 -0
  256. package/dist/client/settings/file-placeholder/psd-200-200.png +0 -0
  257. package/dist/client/settings/file-placeholder/svg-200-200.png +0 -0
  258. package/dist/client/settings/file-placeholder/unknown-200-200.png +0 -0
  259. package/dist/client/settings/file-placeholder/video-200-200.png +0 -0
  260. package/dist/client/settings/file-placeholder/xlsx-200-200.png +0 -0
  261. package/dist/client/settings/file-placeholder/zip-200-200.png +0 -0
  262. package/dist/client/settings/global.css +63 -0
  263. package/dist/client/settings/index.html +22 -0
  264. package/dist/client/settings/nocobase.png +0 -0
  265. package/dist/client/settings/robots.txt +2 -0
  266. package/dist/client/v/assets/{index-2f7426fe.js → index-b2d53e82.js} +167 -153
  267. package/dist/client/v/assets/index-b2d53e82.js.LICENSE.txt +1 -0
  268. package/dist/client/v/browser-checker.js +76 -1
  269. package/dist/client/v/index.html +1 -1
  270. package/package.json +7 -7
  271. package/settingsDevProxy.ts +52 -0
  272. /package/dist/client/assets/{index-800d06ee.js.LICENSE.txt → index-b8e6cdd9.js.LICENSE.txt} +0 -0
  273. /package/dist/client/{v/assets/index-2f7426fe.js.LICENSE.txt → settings/assets/32-88d3c82f.js.LICENSE.txt} +0 -0
@@ -0,0 +1,270 @@
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
+ import path from 'node:path';
11
+ import { fileURLToPath } from 'node:url';
12
+ import { defineConfig } from '@rsbuild/core';
13
+ import { pluginLess } from '@rsbuild/plugin-less';
14
+ import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill';
15
+ import { pluginReact } from '@rsbuild/plugin-react';
16
+ import { pluginSvgr } from '@rsbuild/plugin-svgr';
17
+ import { getRsbuildBrowserAlias } from '@nocobase/devtools/rsbuildConfig';
18
+ import { generateSettingsPluginImports } from './generatePluginImports';
19
+
20
+ const __filename = fileURLToPath(import.meta.url);
21
+ const __dirname = path.dirname(__filename);
22
+ const SETTINGS_DIST_DIR = 'settings';
23
+
24
+ process.env.APP_PACKAGE_ROOT ||= path.resolve(__dirname, '..');
25
+ generateSettingsPluginImports(path.resolve(__dirname, 'src/.plugins'));
26
+
27
+ function ensurePublicPath(value: string | undefined, fallback = '/') {
28
+ let normalized = value || fallback;
29
+ if (!normalized.startsWith('/')) {
30
+ normalized = `/${normalized}`;
31
+ }
32
+ if (!normalized.endsWith('/')) {
33
+ normalized = `${normalized}/`;
34
+ }
35
+ return normalized.replace(/\/{2,}/g, '/');
36
+ }
37
+
38
+ function toNumber(value: string | undefined, fallback: number) {
39
+ const parsed = Number(value);
40
+ return Number.isFinite(parsed) ? parsed : fallback;
41
+ }
42
+
43
+ function normalizeModernClientPrefix(value: string | undefined) {
44
+ const normalized = String(value || 'v')
45
+ .trim()
46
+ .replace(/^\/+|\/+$/g, '');
47
+ return normalized || 'v';
48
+ }
49
+
50
+ function assertAvailableModernClientPrefix(value: string | undefined) {
51
+ if (normalizeModernClientPrefix(value) === SETTINGS_DIST_DIR) {
52
+ throw new Error('APP_MODERN_CLIENT_PREFIX "settings" is reserved for the standalone Settings application.');
53
+ }
54
+ }
55
+
56
+ function createRuntimeHeadScript(appPublicPath: string, isBuild: boolean) {
57
+ return [
58
+ `window['__nocobase_public_path__'] = window['__nocobase_public_path__'] ?? ${JSON.stringify(appPublicPath)};`,
59
+ `window['__nocobase_modern_client_prefix__'] = window['__nocobase_modern_client_prefix__'] ?? ${JSON.stringify(
60
+ normalizeModernClientPrefix(process.env.APP_MODERN_CLIENT_PREFIX),
61
+ )};`,
62
+ `window['__webpack_public_path__'] = window['__webpack_public_path__'] ?? ${JSON.stringify(
63
+ isBuild ? process.env.CDN_BASE_URL || '' : '',
64
+ )};`,
65
+ `window['__nocobase_api_base_url__'] = window['__nocobase_api_base_url__'] ?? ${JSON.stringify(
66
+ process.env.API_BASE_URL || process.env.API_BASE_PATH || '',
67
+ )};`,
68
+ `window['__nocobase_api_client_storage_prefix__'] = window['__nocobase_api_client_storage_prefix__'] ?? ${JSON.stringify(
69
+ process.env.API_CLIENT_STORAGE_PREFIX || '',
70
+ )};`,
71
+ `window['__nocobase_api_client_storage_type__'] = window['__nocobase_api_client_storage_type__'] ?? ${JSON.stringify(
72
+ process.env.API_CLIENT_STORAGE_TYPE || '',
73
+ )};`,
74
+ `window['__nocobase_api_client_share_token__'] = window['__nocobase_api_client_share_token__'] ?? ${JSON.stringify(
75
+ process.env.API_CLIENT_SHARE_TOKEN || 'false',
76
+ )};`,
77
+ `window['__nocobase_ws_url__'] = window['__nocobase_ws_url__'] ?? ${JSON.stringify(
78
+ process.env.WEBSOCKET_URL || '',
79
+ )};`,
80
+ `window['__nocobase_ws_path__'] = window['__nocobase_ws_path__'] ?? ${JSON.stringify(process.env.WS_PATH || '')};`,
81
+ `window['__nocobase_app_dev__'] = window['__nocobase_app_dev__'] ?? ${JSON.stringify(
82
+ process.env.NOCOBASE_APP_DEV === 'true',
83
+ )};`,
84
+ `window['__esm_cdn_base_url__'] = window['__esm_cdn_base_url__'] ?? ${JSON.stringify(
85
+ process.env.ESM_CDN_BASE_URL || 'https://esm.sh',
86
+ )};`,
87
+ `window['__esm_cdn_suffix__'] = window['__esm_cdn_suffix__'] ?? ${JSON.stringify(
88
+ process.env.ESM_CDN_SUFFIX || '',
89
+ )};`,
90
+ ].join('\n');
91
+ }
92
+
93
+ function createDefineValues(appPublicPath: string) {
94
+ return {
95
+ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
96
+ 'process.env.API_BASE_URL': JSON.stringify(process.env.API_BASE_URL || process.env.API_BASE_PATH || ''),
97
+ 'import.meta.env.APP_PUBLIC_PATH': JSON.stringify(appPublicPath),
98
+ 'import.meta.env.API_BASE_URL': JSON.stringify(process.env.API_BASE_URL || process.env.API_BASE_PATH || ''),
99
+ 'import.meta.env.API_CLIENT_STORAGE_PREFIX': JSON.stringify(process.env.API_CLIENT_STORAGE_PREFIX || ''),
100
+ 'import.meta.env.API_CLIENT_STORAGE_TYPE': JSON.stringify(process.env.API_CLIENT_STORAGE_TYPE || ''),
101
+ 'import.meta.env.API_CLIENT_SHARE_TOKEN': JSON.stringify(process.env.API_CLIENT_SHARE_TOKEN || 'false'),
102
+ 'import.meta.env.WS_URL': JSON.stringify(process.env.WEBSOCKET_URL || ''),
103
+ 'import.meta.env.WS_PATH': JSON.stringify(process.env.WS_PATH || ''),
104
+ };
105
+ }
106
+
107
+ export default defineConfig(({ command }) => {
108
+ const isBuild = command === 'build';
109
+ assertAvailableModernClientPrefix(process.env.APP_MODERN_CLIENT_PREFIX);
110
+
111
+ const appPublicPath = ensurePublicPath(process.env.APP_PUBLIC_PATH, '/');
112
+ const settingsPublicPath = isBuild
113
+ ? `/${SETTINGS_DIST_DIR}/`
114
+ : ensurePublicPath(`${appPublicPath}${SETTINGS_DIST_DIR}/`);
115
+ const apiBasePath = ensurePublicPath(process.env.API_BASE_PATH, '/api/');
116
+ const fileBasePath = ensurePublicPath(`${appPublicPath}files/`);
117
+ const localStorageBasePath = ensurePublicPath(`${appPublicPath}storage/uploads/`);
118
+ const staticBasePath = ensurePublicPath(`${appPublicPath}static/`);
119
+ const wsBasePath = ensurePublicPath(process.env.WS_PATH, '/ws/');
120
+ const appPort = toNumber(process.env.APP_PORT, 13001);
121
+ const settingsPort = toNumber(process.env.APP_SETTINGS_PORT, appPort + 3);
122
+ const hmrClientHost = process.env.RSPACK_HMR_CLIENT_HOST;
123
+ const hmrClientPort = toNumber(process.env.RSPACK_HMR_CLIENT_PORT || process.env.APP_PORT, settingsPort);
124
+ const proxyTargetUrl = process.env.PROXY_TARGET_URL || `http://127.0.0.1:${appPort}`;
125
+ const workspaceAliases = getRsbuildBrowserAlias();
126
+
127
+ return {
128
+ plugins: [pluginReact(), pluginLess(), pluginNodePolyfill(), pluginSvgr()],
129
+ resolve: {
130
+ alias: workspaceAliases,
131
+ },
132
+ source: {
133
+ entry: {
134
+ index: path.resolve(__dirname, 'src/main.tsx'),
135
+ },
136
+ tsconfigPath: path.resolve(__dirname, 'tsconfig.json'),
137
+ define: createDefineValues(appPublicPath),
138
+ },
139
+ html: {
140
+ template: path.resolve(__dirname, 'index.html'),
141
+ scriptLoading: isBuild ? 'module' : 'defer',
142
+ tags: [
143
+ {
144
+ tag: 'link',
145
+ attrs: {
146
+ rel: 'stylesheet',
147
+ href: `${settingsPublicPath}global.css`,
148
+ },
149
+ publicPath: false,
150
+ head: true,
151
+ append: false,
152
+ },
153
+ {
154
+ tag: 'script',
155
+ children: createRuntimeHeadScript(appPublicPath, isBuild),
156
+ head: true,
157
+ append: false,
158
+ },
159
+ {
160
+ tag: 'script',
161
+ attrs: {
162
+ src: `${settingsPublicPath}browser-checker.js?v=1`,
163
+ },
164
+ publicPath: false,
165
+ head: true,
166
+ append: false,
167
+ },
168
+ ],
169
+ },
170
+ output: {
171
+ target: 'web',
172
+ distPath: {
173
+ root: path.resolve(__dirname, '../dist/client/settings'),
174
+ js: 'assets',
175
+ jsAsync: 'assets',
176
+ css: 'assets',
177
+ cssAsync: 'assets',
178
+ svg: 'assets',
179
+ font: 'assets',
180
+ image: 'assets',
181
+ media: 'assets',
182
+ },
183
+ filename: {
184
+ js: '[name]-[contenthash:8].js',
185
+ css: '[name]-[contenthash:8].css',
186
+ svg: '[name]-[contenthash:8][ext][query]',
187
+ font: '[name]-[contenthash:8][ext][query]',
188
+ image: '[name]-[contenthash:8][ext][query]',
189
+ media: '[name]-[contenthash:8][ext][query]',
190
+ },
191
+ assetPrefix: settingsPublicPath,
192
+ cleanDistPath: true,
193
+ sourceMap: {
194
+ js: isBuild ? false : 'eval-cheap-module-source-map',
195
+ css: false,
196
+ },
197
+ },
198
+ server: {
199
+ base: settingsPublicPath,
200
+ host: '0.0.0.0',
201
+ port: settingsPort,
202
+ compress: true,
203
+ publicDir: {
204
+ name: path.resolve(__dirname, '../client-v2/public'),
205
+ },
206
+ proxy: {
207
+ [apiBasePath]: {
208
+ target: proxyTargetUrl,
209
+ changeOrigin: true,
210
+ ws: true,
211
+ xfwd: true,
212
+ },
213
+ [localStorageBasePath]: {
214
+ target: proxyTargetUrl,
215
+ changeOrigin: true,
216
+ },
217
+ [fileBasePath]: {
218
+ target: proxyTargetUrl,
219
+ changeOrigin: true,
220
+ },
221
+ [staticBasePath]: {
222
+ target: proxyTargetUrl,
223
+ changeOrigin: true,
224
+ },
225
+ [wsBasePath]: {
226
+ target: proxyTargetUrl,
227
+ changeOrigin: true,
228
+ ws: true,
229
+ xfwd: true,
230
+ },
231
+ },
232
+ historyApiFallback: {
233
+ disableDotRule: true,
234
+ index: `${settingsPublicPath}index.html`,
235
+ },
236
+ },
237
+ dev: {
238
+ assetPrefix: settingsPublicPath,
239
+ lazyCompilation: false,
240
+ client: {
241
+ overlay: false,
242
+ protocol: 'ws',
243
+ host: hmrClientHost,
244
+ port: hmrClientPort,
245
+ path: `${settingsPublicPath.replace(/\/$/, '')}/__rspack_hmr`,
246
+ },
247
+ progressBar: true,
248
+ },
249
+ tools: {
250
+ rspack(config) {
251
+ config.target = ['web', 'es2020'];
252
+ config.output.module = isBuild;
253
+ config.output.chunkFormat = isBuild ? 'module' : 'array-push';
254
+ config.experiments = {
255
+ ...config.experiments,
256
+ outputModule: isBuild,
257
+ };
258
+ config.optimization = {
259
+ ...config.optimization,
260
+ runtimeChunk: 'single',
261
+ splitChunks: {
262
+ chunks: 'all',
263
+ },
264
+ };
265
+ config.performance = false;
266
+ config.stats = 'errors-warnings';
267
+ },
268
+ },
269
+ };
270
+ });
@@ -0,0 +1,4 @@
1
+
2
+ export default function devDynamicImport(packageName: string): Promise<any> {
3
+ return Promise.resolve(null);
4
+ }
@@ -0,0 +1,56 @@
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
+ import { Plugin, type PluginClass } from '@nocobase/client-v2';
11
+ import { CollectionPluginV2 } from '../../../../presets/nocobase/src/client-v2/CollectionPluginV2';
12
+ import { SettingsApplication } from '../../../client-v2/src/settings-app/SettingsApplication';
13
+ import { SettingsBuildInPlugin } from '../../../client-v2/src/settings-app/SettingsBuildInPlugin';
14
+ import { resolveSettingsRuntimeScope } from './runtimeScope';
15
+
16
+ const CollectionPluginClass = CollectionPluginV2 as unknown as PluginClass;
17
+ const SettingsBuildInPluginClass = SettingsBuildInPlugin as unknown as PluginClass;
18
+
19
+ function offsetToTimeZone(offset: number) {
20
+ const hours = Math.floor(Math.abs(offset));
21
+ const minutes = Math.abs((offset % 1) * 60);
22
+ const formattedHours = String(hours).padStart(2, '0');
23
+ const formattedMinutes = String(minutes).padStart(2, '0');
24
+ const sign = offset >= 0 ? '+' : '-';
25
+ return `${sign}${formattedHours}:${formattedMinutes}`;
26
+ }
27
+
28
+ function getCurrentTimezone() {
29
+ return offsetToTimeZone(new Date().getTimezoneOffset() / -60);
30
+ }
31
+
32
+ export class SettingsPresetPlugin extends Plugin<object, SettingsApplication> {
33
+ private getHostname() {
34
+ if (process.env.API_BASE_URL) {
35
+ try {
36
+ return new URL(process.env.API_BASE_URL).hostname;
37
+ } catch {
38
+ // Fall back to the document hostname when API_BASE_URL is relative or invalid.
39
+ }
40
+ }
41
+ return window.location.hostname;
42
+ }
43
+
44
+ async afterAdd() {
45
+ const { basename } = resolveSettingsRuntimeScope(this.app.getPublicPath(), window.location.pathname);
46
+ this.router.setType('browser');
47
+ this.router.setBasename(basename);
48
+ this.app.apiClient.axios.interceptors.request.use((config) => {
49
+ config.headers['X-Hostname'] = this.getHostname();
50
+ config.headers['X-Timezone'] = getCurrentTimezone();
51
+ return config;
52
+ });
53
+ await this.app.pm.add(CollectionPluginClass, { name: 'builtin-collection-v2' });
54
+ await this.app.pm.add(SettingsBuildInPluginClass, { name: 'builtin-settings-v2' });
55
+ }
56
+ }
@@ -0,0 +1,23 @@
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
+ import { describe, expect, it } from 'vitest';
11
+ import { resolveSettingsAssetPublicPath } from '../runtimePublicPath';
12
+
13
+ describe('Settings runtime asset public path', () => {
14
+ it('uses the Settings asset path without a CDN', () => {
15
+ expect(resolveSettingsAssetPublicPath(undefined, '/nocobase/')).toBe('/nocobase/settings/');
16
+ });
17
+
18
+ it('keeps Settings assets isolated under a CDN', () => {
19
+ expect(resolveSettingsAssetPublicPath('https://cdn.example.com/releases/42/', '/nocobase/')).toBe(
20
+ 'https://cdn.example.com/releases/42/settings/',
21
+ );
22
+ });
23
+ });
@@ -0,0 +1,29 @@
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
+ import { describe, expect, it } from 'vitest';
11
+ import { resolveSettingsRuntimeScope } from '../runtimeScope';
12
+
13
+ describe('Settings runtime scope', () => {
14
+ it('keeps the main application on the configured public path', () => {
15
+ expect(resolveSettingsRuntimeScope('/nocobase/', '/nocobase/settings/system-settings')).toEqual({
16
+ appName: undefined,
17
+ basename: '/nocobase/',
18
+ rootPublicPath: '/nocobase/',
19
+ });
20
+ });
21
+
22
+ it.each(['apps', '_app'])('derives %s application scope from the document path', (scope) => {
23
+ expect(resolveSettingsRuntimeScope('/nocobase/', `/nocobase/settings/${scope}/demo/workflow`)).toEqual({
24
+ appName: 'demo',
25
+ basename: `/nocobase/settings/${scope}/demo/`,
26
+ rootPublicPath: '/nocobase/',
27
+ });
28
+ });
29
+ });
@@ -0,0 +1,22 @@
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
+ interface ImportMetaEnv {
11
+ readonly APP_PUBLIC_PATH?: string;
12
+ readonly API_BASE_URL?: string;
13
+ readonly API_CLIENT_SHARE_TOKEN?: string;
14
+ readonly API_CLIENT_STORAGE_PREFIX?: string;
15
+ readonly API_CLIENT_STORAGE_TYPE?: string;
16
+ readonly WS_URL?: string;
17
+ readonly WS_PATH?: string;
18
+ }
19
+
20
+ interface ImportMeta {
21
+ readonly env: ImportMetaEnv;
22
+ }
@@ -0,0 +1,78 @@
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
+ import devDynamicImport from './.plugins';
11
+ import type { PluginClass } from '@nocobase/client-v2';
12
+ import { SettingsApplication } from '../../../client-v2/src/settings-app/SettingsApplication';
13
+ import { SettingsPresetPlugin } from './SettingsPresetPlugin';
14
+ import { resolveSettingsAssetPublicPath } from './runtimePublicPath';
15
+ import { resolveSettingsRuntimeScope } from './runtimeScope';
16
+
17
+ declare global {
18
+ interface Window {
19
+ __nocobase_public_path__?: string;
20
+ __webpack_public_path__?: string;
21
+ __nocobase_api_base_url__?: string;
22
+ __nocobase_api_client_storage_prefix__?: string;
23
+ __nocobase_api_client_storage_type__?: string;
24
+ __nocobase_api_client_share_token__?: boolean | string;
25
+ __nocobase_ws_url__?: string;
26
+ __nocobase_ws_path__?: string;
27
+ }
28
+ }
29
+
30
+ function parseShareToken(value: boolean | string | undefined) {
31
+ if (typeof value === 'boolean') {
32
+ return value;
33
+ }
34
+ return String(value || '').toLowerCase() === 'true';
35
+ }
36
+
37
+ type ClientStorageType = 'localStorage' | 'sessionStorage' | 'memory';
38
+
39
+ function parseStorageType(value: string | undefined): ClientStorageType {
40
+ if (value === 'sessionStorage' || value === 'memory' || value === 'localStorage') {
41
+ return value;
42
+ }
43
+ return 'localStorage';
44
+ }
45
+
46
+ const configuredPublicPath = window.__nocobase_public_path__ || import.meta.env.APP_PUBLIC_PATH || '/';
47
+ const runtimeScope = resolveSettingsRuntimeScope(configuredPublicPath, window.location.pathname);
48
+ const SettingsPresetPluginClass = SettingsPresetPlugin as unknown as PluginClass;
49
+
50
+ declare let __webpack_public_path__: string;
51
+ // eslint-disable-next-line prefer-const
52
+ __webpack_public_path__ = resolveSettingsAssetPublicPath(window.__webpack_public_path__, runtimeScope.rootPublicPath);
53
+
54
+ const app = new SettingsApplication({
55
+ name: runtimeScope.appName,
56
+ publicPath: runtimeScope.rootPublicPath,
57
+ router: {
58
+ basename: runtimeScope.basename,
59
+ },
60
+ apiClient: {
61
+ shareToken: parseShareToken(window.__nocobase_api_client_share_token__ || import.meta.env.API_CLIENT_SHARE_TOKEN),
62
+ storageType: parseStorageType(
63
+ window.__nocobase_api_client_storage_type__ || import.meta.env.API_CLIENT_STORAGE_TYPE,
64
+ ),
65
+ storagePrefix:
66
+ window.__nocobase_api_client_storage_prefix__ || import.meta.env.API_CLIENT_STORAGE_PREFIX || 'NOCOBASE_',
67
+ baseURL: window.__nocobase_api_base_url__ || import.meta.env.API_BASE_URL || `${runtimeScope.rootPublicPath}api/`,
68
+ },
69
+ ws: {
70
+ url: window.__nocobase_ws_url__ || import.meta.env.WS_URL || '',
71
+ basename: window.__nocobase_ws_path__ || import.meta.env.WS_PATH || `${runtimeScope.rootPublicPath}ws`,
72
+ },
73
+ loadRemotePlugins: true,
74
+ devDynamicImport,
75
+ plugins: [SettingsPresetPluginClass],
76
+ });
77
+
78
+ app.mount('#root');
@@ -0,0 +1,21 @@
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
+ function normalizeBasePath(value: string | undefined, fallback: string) {
11
+ const normalized = String(value || fallback)
12
+ .trim()
13
+ .replace(/\/+$/, '');
14
+ return normalized || fallback.replace(/\/+$/, '');
15
+ }
16
+
17
+ export function resolveSettingsAssetPublicPath(cdnBaseUrl: string | undefined, appPublicPath: string) {
18
+ const basePath = cdnBaseUrl?.trim() ? normalizeBasePath(cdnBaseUrl, '/') : normalizeBasePath(appPublicPath, '/');
19
+
20
+ return `${basePath}/settings/`.replace(/^\/\//, '/');
21
+ }
@@ -0,0 +1,49 @@
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
+ import {
11
+ resolveSettingsDocumentBasename,
12
+ type SettingsAppScope,
13
+ } from '../../../client-v2/src/settings-app/settingsDocumentPath';
14
+
15
+ function ensurePublicPath(value: string) {
16
+ let normalized = value.trim() || '/';
17
+ if (!normalized.startsWith('/')) {
18
+ normalized = `/${normalized}`;
19
+ }
20
+ if (!normalized.endsWith('/')) {
21
+ normalized = `${normalized}/`;
22
+ }
23
+ return normalized.replace(/\/{2,}/g, '/');
24
+ }
25
+
26
+ export function resolveSettingsRuntimeScope(configuredPublicPath: string, pathname: string) {
27
+ const rootPublicPath = ensurePublicPath(configuredPublicPath);
28
+ const normalizedPathname = pathname.startsWith('/') ? pathname : `/${pathname}`;
29
+ const relativePathname = normalizedPathname.startsWith(rootPublicPath)
30
+ ? normalizedPathname.slice(rootPublicPath.length)
31
+ : normalizedPathname.replace(/^\/+/, '');
32
+ const match = /^settings\/(apps|_app)\/([^/]+)(?:\/|$)/.exec(relativePathname);
33
+
34
+ if (!match) {
35
+ return {
36
+ appName: undefined,
37
+ basename: rootPublicPath,
38
+ rootPublicPath,
39
+ };
40
+ }
41
+
42
+ const [, scope, appName] = match;
43
+ const appScope = `/${scope}/${appName}` as SettingsAppScope;
44
+ return {
45
+ appName,
46
+ basename: resolveSettingsDocumentBasename(rootPublicPath, appScope),
47
+ rootPublicPath,
48
+ };
49
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "extends": "../../../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "target": "esnext",
5
+ "module": "esnext",
6
+ "moduleResolution": "node",
7
+ "resolveJsonModule": true,
8
+ "importHelpers": true,
9
+ "jsx": "react-jsx",
10
+ "esModuleInterop": true,
11
+ "sourceMap": true,
12
+ "baseUrl": "../../../../",
13
+ "strict": true,
14
+ "allowSyntheticDefaultImports": true,
15
+ "noEmit": true
16
+ },
17
+ "include": ["src/**/*"],
18
+ "exclude": ["node_modules", "dist"]
19
+ }
@@ -17,11 +17,86 @@ function normalizePublicPath(value) {
17
17
  return ensureTrailingSlash(normalized);
18
18
  }
19
19
 
20
+ function normalizePathname(value) {
21
+ const normalized = ensureLeadingSlash(String(value || '/').trim() || '/').replace(/\/{2,}/g, '/');
22
+ return normalized === '/' ? normalized : normalized.replace(/\/+$/g, '');
23
+ }
24
+
25
+ function resolveSettingsRootPath(publicPath, modernPrefix, pathname) {
26
+ const normalizedPublicPath = normalizePublicPath(publicPath);
27
+ const normalizedModernPrefix =
28
+ String(modernPrefix || 'v')
29
+ .trim()
30
+ .replace(/^\/+|\/+$/g, '') || 'v';
31
+ const modernPublicPathSuffix = `/${normalizedModernPrefix}/`;
32
+ if (!normalizedPublicPath.endsWith(modernPublicPathSuffix)) {
33
+ return null;
34
+ }
35
+
36
+ const modernRootPath = normalizePathname(normalizedPublicPath);
37
+ const normalizedPathname = normalizePathname(pathname);
38
+ let relativePath = '';
39
+ if (normalizedPathname !== modernRootPath) {
40
+ if (!normalizedPathname.startsWith(`${modernRootPath}/`)) {
41
+ return null;
42
+ }
43
+ relativePath = normalizedPathname.slice(modernRootPath.length + 1);
44
+ }
45
+
46
+ let appScope = '';
47
+ if (relativePath) {
48
+ const match = /^(apps|_app)\/([^/]+)$/.exec(relativePath);
49
+ if (!match) {
50
+ return null;
51
+ }
52
+ appScope = `/${match[1]}/${match[2]}`;
53
+ }
54
+
55
+ const rootPublicPath = normalizedPublicPath.slice(0, -(normalizedModernPrefix.length + 1));
56
+ const rootPrefix = rootPublicPath === '/' ? '' : rootPublicPath.replace(/\/+$/g, '');
57
+ return `${rootPrefix}/settings${appScope}`;
58
+ }
59
+
60
+ function isSettingsBrowserCheckerScript(script) {
61
+ const source = String((script && script.src) || '').split(/[?#]/)[0];
62
+ return source.endsWith('/settings/browser-checker.js');
63
+ }
64
+
65
+ function resolveScopedSettingsRootPath(publicPath, pathname) {
66
+ const normalizedPublicPath = normalizePublicPath(publicPath);
67
+ const rootPrefix = normalizedPublicPath === '/' ? '' : normalizedPublicPath.replace(/\/+$/g, '');
68
+ const settingsRootPath = `${rootPrefix}/settings`;
69
+ if (!pathname.startsWith(`${settingsRootPath}/`)) {
70
+ return null;
71
+ }
72
+
73
+ const relativePath = pathname.slice(settingsRootPath.length + 1);
74
+ if (!/^(apps|_app)\/[^/]+$/.test(relativePath)) {
75
+ return null;
76
+ }
77
+
78
+ return `${pathname}/`;
79
+ }
80
+
20
81
  const basename = normalizePublicPath(window['__nocobase_public_path__'] || '/');
21
82
  const currentPath = ensureLeadingSlash(String(window.location.pathname || '/').trim() || '/').replace(/\/{2,}/g, '/');
22
83
  const basenameWithoutTrailingSlash = basename === '/' ? '/' : basename.replace(/\/+$/, '');
84
+ const appClientEntryMode = window['__nocobase_app_client_entry_mode__'];
85
+ const settingsRootPath =
86
+ appClientEntryMode === 'modern-only'
87
+ ? resolveSettingsRootPath(basename, window['__nocobase_modern_client_prefix__'], currentPath)
88
+ : null;
89
+ const scopedSettingsRootPath = isSettingsBrowserCheckerScript(document.currentScript)
90
+ ? resolveScopedSettingsRootPath(basename, currentPath)
91
+ : null;
23
92
 
24
- if (basename !== '/' && currentPath === basenameWithoutTrailingSlash) {
93
+ if (settingsRootPath) {
94
+ const newUrl = `${window.location.origin}${settingsRootPath}${window.location.search}${window.location.hash}`;
95
+ window.location.replace(newUrl);
96
+ } else if (scopedSettingsRootPath) {
97
+ const newUrl = `${window.location.origin}${scopedSettingsRootPath}${window.location.search}${window.location.hash}`;
98
+ window.location.replace(newUrl);
99
+ } else if (basename !== '/' && currentPath === basenameWithoutTrailingSlash) {
25
100
  const newUrl = `${window.location.origin}${basename}${window.location.search}${window.location.hash}`;
26
101
  window.location.replace(newUrl);
27
102
  } else if (basename !== '/' && !currentPath.startsWith(basename)) {