@nocobase/app 2.2.0-alpha.10 → 2.2.0-alpha.12

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 +31 -16
  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 +24 -10
  19. package/dist/client/assets/{index-baf26099.js → index-8926ddba.js} +336 -325
  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-16efb5d4.js +1946 -0
  243. package/dist/client/settings/assets/index-16efb5d4.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-372e693c.js → index-9078e942.js} +127 -116
  267. package/dist/client/v/assets/index-9078e942.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-baf26099.js.LICENSE.txt → index-8926ddba.js.LICENSE.txt} +0 -0
  273. /package/dist/client/{v/assets/index-372e693c.js.LICENSE.txt → settings/assets/32-88d3c82f.js.LICENSE.txt} +0 -0
@@ -0,0 +1,129 @@
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 { readFileSync } from 'node:fs';
11
+ import { resolve } from 'node:path';
12
+ import vm from 'node:vm';
13
+ import { describe, expect, it } from 'vitest';
14
+
15
+ const browserCheckerSource = readFileSync(resolve(__dirname, '../client-v2/public/browser-checker.js'), 'utf8');
16
+
17
+ interface RunBrowserCheckerOptions {
18
+ appClientEntryMode?: string;
19
+ currentScriptSrc?: string;
20
+ hash?: string;
21
+ modernPrefix?: string;
22
+ pathname: string;
23
+ publicPath?: string;
24
+ search?: string;
25
+ }
26
+
27
+ function runBrowserChecker(options: RunBrowserCheckerOptions) {
28
+ const replacements: string[] = [];
29
+ const windowObject: Record<string, unknown> = {
30
+ __nocobase_app_client_entry_mode__: options.appClientEntryMode,
31
+ __nocobase_modern_client_prefix__: options.modernPrefix,
32
+ __nocobase_public_path__: options.publicPath ?? '/v/',
33
+ console: {
34
+ log: () => undefined,
35
+ },
36
+ devicePixelRatio: 1,
37
+ location: {
38
+ hash: options.hash ?? '',
39
+ origin: 'https://example.test',
40
+ pathname: options.pathname,
41
+ replace: (url: string) => replacements.push(url),
42
+ search: options.search ?? '',
43
+ },
44
+ outerHeight: 720,
45
+ outerWidth: 1280,
46
+ };
47
+ const documentElement = {
48
+ className: 'no-js',
49
+ clientHeight: 720,
50
+ clientWidth: 1280,
51
+ };
52
+
53
+ vm.runInNewContext(browserCheckerSource, {
54
+ console: {
55
+ debug: () => undefined,
56
+ log: () => undefined,
57
+ },
58
+ document: {
59
+ currentScript: {
60
+ src: options.currentScriptSrc ?? 'https://example.test/v/browser-checker.js',
61
+ },
62
+ documentElement,
63
+ },
64
+ navigator: {
65
+ userAgent:
66
+ 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
67
+ },
68
+ window: windowObject,
69
+ });
70
+
71
+ return {
72
+ className: documentElement.className,
73
+ replacements,
74
+ };
75
+ }
76
+
77
+ describe('v2 browser checker', () => {
78
+ it('redirects the modern client root to Settings only in modern-only mode', () => {
79
+ expect(
80
+ runBrowserChecker({
81
+ appClientEntryMode: 'modern-only',
82
+ pathname: '/v/',
83
+ }).replacements,
84
+ ).toEqual(['https://example.test/settings']);
85
+
86
+ expect(
87
+ runBrowserChecker({
88
+ appClientEntryMode: 'modern-default',
89
+ pathname: '/v/',
90
+ }).replacements,
91
+ ).toEqual([]);
92
+
93
+ expect(
94
+ runBrowserChecker({
95
+ pathname: '/v/',
96
+ }).replacements,
97
+ ).toEqual([]);
98
+ });
99
+
100
+ it('redirects scoped modern client roots to scoped Settings only in modern-only mode', () => {
101
+ expect(
102
+ runBrowserChecker({
103
+ appClientEntryMode: 'modern-only',
104
+ pathname: '/v/apps/demo',
105
+ search: '?from=admin',
106
+ hash: '#portal',
107
+ }).replacements,
108
+ ).toEqual(['https://example.test/settings/apps/demo?from=admin#portal']);
109
+
110
+ expect(
111
+ runBrowserChecker({
112
+ appClientEntryMode: 'modern-default',
113
+ pathname: '/v/apps/demo',
114
+ search: '?from=admin',
115
+ hash: '#portal',
116
+ }).replacements,
117
+ ).toEqual([]);
118
+ });
119
+
120
+ it('keeps Settings scoped trailing slash normalization independent from entry mode', () => {
121
+ expect(
122
+ runBrowserChecker({
123
+ currentScriptSrc: 'https://example.test/settings/browser-checker.js',
124
+ pathname: '/settings/apps/demo',
125
+ publicPath: '/',
126
+ }).replacements,
127
+ ).toEqual(['https://example.test/settings/apps/demo/']);
128
+ });
129
+ });
@@ -0,0 +1,96 @@
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 { createSettingsDevProxyOptions, isSettingsDevPath, rewriteSettingsDevProxyPath } from '../settingsDevProxy';
12
+
13
+ describe('settings dev proxy', () => {
14
+ it.each([
15
+ ['/settings', true],
16
+ ['/settings/signin', true],
17
+ ['/settings/signup', true],
18
+ ['/settings/forgot-password', true],
19
+ ['/settings/reset-password?resetToken=test-token', true],
20
+ ['/settings/2fa?redirect=%2Fsettings%2Fworkflow', true],
21
+ ['/settings/workflow/workflows/1?tab=nodes', true],
22
+ ['/settings/apps/demo/signin', true],
23
+ ['/settings/apps/demo', true],
24
+ ['/settings/apps/demo/workflow/workflows/1', true],
25
+ ['/settings/_app/demo/reset-password?resetToken=test-token', true],
26
+ ['/settings/_app/demo/ai/knowledge-base/detail/k1', true],
27
+ ['/nocobase/settings/assets/index.js', false],
28
+ ['/admin/settings', false],
29
+ ['/v/admin/settings', false],
30
+ ['/apps/demo/settings', false],
31
+ ['/_app/demo/settings', false],
32
+ ['/apps/demo/admin/settings', false],
33
+ ])('matches only standalone Settings paths: %s', (pathname, expected) => {
34
+ expect(isSettingsDevPath(pathname, '/')).toBe(expected);
35
+ });
36
+
37
+ it.each([
38
+ ['/nocobase/settings', true],
39
+ ['/nocobase/settings/signin', true],
40
+ ['/nocobase/settings/2fa?redirect=%2Fnocobase%2Fsettings', true],
41
+ ['/nocobase/settings/workflow/workflows/1', true],
42
+ ['/nocobase/settings/apps/demo/forgot-password', true],
43
+ ['/nocobase/settings/apps/demo', true],
44
+ ['/nocobase/settings/_app/demo/reset-password?resetToken=test-token', true],
45
+ ['/nocobase/settings/_app/demo/ai/knowledge-base/detail/k1', true],
46
+ ['/settings', false],
47
+ ['/nocobase/admin/settings', false],
48
+ ['/nocobase/apps/demo/settings', false],
49
+ ])('honors APP_PUBLIC_PATH: %s', (pathname, expected) => {
50
+ expect(isSettingsDevPath(pathname, '/nocobase/')).toBe(expected);
51
+ });
52
+
53
+ it.each([
54
+ ['/settings', '/', '/settings/'],
55
+ ['/settings?from=admin', '/', '/settings/?from=admin'],
56
+ ['/settings/apps/demo', '/', '/settings/apps/demo'],
57
+ ['/settings/_app/demo?from=admin', '/', '/settings/_app/demo?from=admin'],
58
+ ['/nocobase/settings', '/nocobase/', '/nocobase/settings/'],
59
+ ['/nocobase/settings/apps/demo?from=admin', '/nocobase/', '/nocobase/settings/apps/demo?from=admin'],
60
+ ['/nocobase/settings/_app/demo#portal', '/nocobase/', '/nocobase/settings/_app/demo#portal'],
61
+ ])('normalizes a Settings root to the dev-server base: %s', (pathname, publicPath, expected) => {
62
+ expect(rewriteSettingsDevProxyPath(pathname, publicPath)).toBe(expected);
63
+ });
64
+
65
+ it('preserves application-scoped documents for the Settings dev server', () => {
66
+ expect(rewriteSettingsDevProxyPath('/settings/apps/demo/workflow/workflows/1?tab=nodes', '/')).toBe(
67
+ '/settings/apps/demo/workflow/workflows/1?tab=nodes',
68
+ );
69
+ expect(rewriteSettingsDevProxyPath('/nocobase/settings/apps/demo/a#hash', '/nocobase/')).toBe(
70
+ '/nocobase/settings/apps/demo/a#hash',
71
+ );
72
+ expect(rewriteSettingsDevProxyPath('/settings/assets/index.js', '/')).toBe('/settings/assets/index.js');
73
+ expect(rewriteSettingsDevProxyPath('/settings/__rspack_hmr', '/')).toBe('/settings/__rspack_hmr');
74
+ });
75
+
76
+ it('creates a websocket-capable proxy for the Settings port', () => {
77
+ const options = createSettingsDevProxyOptions('/nocobase/', 13004);
78
+
79
+ expect(options).toMatchObject({
80
+ target: 'http://127.0.0.1:13004',
81
+ changeOrigin: true,
82
+ ws: true,
83
+ xfwd: true,
84
+ });
85
+ expect(options.context?.('/nocobase/settings/__rspack_hmr')).toBe(true);
86
+ expect(options.context?.('/nocobase/settings/signin')).toBe(true);
87
+ expect(options.context?.('/nocobase/settings/apps/demo/workflow')).toBe(true);
88
+ expect(options.context?.('/nocobase/settings/apps/demo/2fa')).toBe(true);
89
+ expect(options.context?.('/nocobase/settings/_app/demo/ai')).toBe(true);
90
+ expect(options.context?.('/nocobase/apps/demo/settings/workflow')).toBe(false);
91
+ expect(options.context?.('/nocobase/admin/settings')).toBe(false);
92
+ expect(options.pathRewrite?.('/nocobase/settings/apps/demo/workflow')).toBe(
93
+ '/nocobase/settings/apps/demo/workflow',
94
+ );
95
+ });
96
+ });
@@ -0,0 +1,106 @@
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 { existsSync, mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
11
+ import { tmpdir } from 'node:os';
12
+ import path from 'node:path';
13
+ import { afterEach, describe, expect, it } from 'vitest';
14
+ import { generateSettingsPluginImports } from '../client-settings/generatePluginImports';
15
+
16
+ const temporaryDirectories: string[] = [];
17
+
18
+ function createTemporaryDirectory() {
19
+ const directory = mkdtempSync(path.join(tmpdir(), 'nocobase-settings-plugin-imports-'));
20
+ temporaryDirectories.push(directory);
21
+ return directory;
22
+ }
23
+
24
+ function createV2Plugin(pluginRoot: string) {
25
+ const pluginDirectory = path.join(pluginRoot, '@example', 'plugin-demo');
26
+ mkdirSync(pluginDirectory, { recursive: true });
27
+ writeFileSync(
28
+ path.join(pluginDirectory, 'package.json'),
29
+ JSON.stringify({ name: '@example/plugin-demo', version: '1.0.0' }),
30
+ );
31
+ writeFileSync(path.join(pluginDirectory, 'client-v2.js'), 'module.exports = {};');
32
+ mkdirSync(path.join(pluginDirectory, 'src', 'client-v2'), { recursive: true });
33
+ writeFileSync(path.join(pluginDirectory, 'src', 'client-v2', 'index.ts'), 'export default class DemoPlugin {}');
34
+ }
35
+
36
+ afterEach(() => {
37
+ for (const directory of temporaryDirectories.splice(0)) {
38
+ rmSync(directory, { recursive: true, force: true });
39
+ }
40
+ });
41
+
42
+ describe('Settings plugin imports', () => {
43
+ it('generates the existing V2 plugin lane into a Settings-owned directory', () => {
44
+ const root = createTemporaryDirectory();
45
+ const pluginRoot = path.join(root, 'plugins');
46
+ const settingsOutput = path.join(root, 'client-settings', 'src', '.plugins');
47
+ const clientV2Output = path.join(root, 'client-v2', 'src', '.plugins');
48
+ createV2Plugin(pluginRoot);
49
+ mkdirSync(clientV2Output, { recursive: true });
50
+ writeFileSync(path.join(clientV2Output, 'index.ts'), 'export const clientV2DevManifest = true;');
51
+
52
+ const localPluginsOnly = process.env.NOCOBASE_DEV_LOCAL_PLUGINS_ONLY;
53
+ process.env.NOCOBASE_DEV_LOCAL_PLUGINS_ONLY = 'true';
54
+ try {
55
+ generateSettingsPluginImports(settingsOutput, [pluginRoot]);
56
+ } finally {
57
+ if (localPluginsOnly === undefined) {
58
+ delete process.env.NOCOBASE_DEV_LOCAL_PLUGINS_ONLY;
59
+ } else {
60
+ process.env.NOCOBASE_DEV_LOCAL_PLUGINS_ONLY = localPluginsOnly;
61
+ }
62
+ }
63
+
64
+ expect(JSON.parse(readFileSync(path.join(settingsOutput, 'packageMap.json'), 'utf8'))).toEqual({
65
+ '@example/plugin-demo': 'example_plugin_demo.ts',
66
+ });
67
+ expect(readFileSync(path.join(clientV2Output, 'index.ts'), 'utf8')).toBe(
68
+ 'export const clientV2DevManifest = true;',
69
+ );
70
+ expect(existsSync(path.join(settingsOutput, 'packages', 'example_plugin_demo.ts'))).toBe(true);
71
+ });
72
+
73
+ it('keeps a production Settings manifest isolated from the Client V2 development manifest', () => {
74
+ const root = createTemporaryDirectory();
75
+ const settingsOutput = path.join(root, 'client-settings', 'src', '.plugins');
76
+ const clientV2Output = path.join(root, 'client-v2', 'src', '.plugins');
77
+ mkdirSync(clientV2Output, { recursive: true });
78
+ writeFileSync(path.join(clientV2Output, 'index.ts'), 'export const clientV2DevManifest = true;');
79
+
80
+ const nodeEnv = process.env.NODE_ENV;
81
+ process.env.NODE_ENV = 'production';
82
+ try {
83
+ generateSettingsPluginImports(settingsOutput, []);
84
+ } finally {
85
+ if (nodeEnv === undefined) {
86
+ delete process.env.NODE_ENV;
87
+ } else {
88
+ process.env.NODE_ENV = nodeEnv;
89
+ }
90
+ }
91
+
92
+ expect(readFileSync(path.join(settingsOutput, 'index.ts'), 'utf8')).toContain('return Promise.resolve(null)');
93
+ expect(readFileSync(path.join(clientV2Output, 'index.ts'), 'utf8')).toBe(
94
+ 'export const clientV2DevManifest = true;',
95
+ );
96
+ });
97
+
98
+ it('wires the Settings config and entry to the Settings-owned generated directory', () => {
99
+ const configSource = readFileSync(path.resolve(__dirname, '../client-settings/rsbuild.config.ts'), 'utf8');
100
+ const entrySource = readFileSync(path.resolve(__dirname, '../client-settings/src/main.tsx'), 'utf8');
101
+
102
+ expect(configSource).not.toContain('generateV2Plugins');
103
+ expect(configSource).toContain("generateSettingsPluginImports(path.resolve(__dirname, 'src/.plugins'))");
104
+ expect(entrySource).toContain("from './.plugins'");
105
+ });
106
+ });
@@ -16,6 +16,7 @@ import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill';
16
16
  import { pluginReact } from '@rsbuild/plugin-react';
17
17
  import { pluginSvgr } from '@rsbuild/plugin-svgr';
18
18
  import { generatePlugins, getRsbuildBrowserAlias } from '@nocobase/devtools/rsbuildConfig';
19
+ import { createSettingsDevProxyOptions } from '../settingsDevProxy';
19
20
 
20
21
  const __filename = fileURLToPath(import.meta.url);
21
22
  const __dirname = path.dirname(__filename);
@@ -46,11 +47,19 @@ function toDefineLiteral(value: string | undefined) {
46
47
  return value === undefined ? 'undefined' : JSON.stringify(value);
47
48
  }
48
49
 
49
- function createRuntimeHeadScript(appPublicPath: string, isBuild: boolean) {
50
- const modernClientPrefix =
51
- String(process.env.APP_MODERN_CLIENT_PREFIX || 'v')
50
+ function normalizeModernClientPrefix(value: string | undefined) {
51
+ const normalized =
52
+ String(value || 'v')
52
53
  .trim()
53
54
  .replace(/^\/+|\/+$/g, '') || 'v';
55
+ if (normalized === 'settings') {
56
+ throw new Error('APP_MODERN_CLIENT_PREFIX "settings" is reserved for the standalone Settings application.');
57
+ }
58
+ return normalized;
59
+ }
60
+
61
+ function createRuntimeHeadScript(appPublicPath: string, isBuild: boolean) {
62
+ const modernClientPrefix = normalizeModernClientPrefix(process.env.APP_MODERN_CLIENT_PREFIX);
54
63
  const appClientEntryMode = process.env.APP_CLIENT_ENTRY_MODE;
55
64
  if (!isBuild) {
56
65
  return [
@@ -109,10 +118,7 @@ export default defineConfig(({ command }) => {
109
118
  const localStorageBasePath = ensurePublicPath(`${resolvedAppPublicPath}storage/uploads/`, '/storage/uploads/');
110
119
  const staticBasePath = ensurePublicPath(`${resolvedAppPublicPath}static/`, '/static/');
111
120
  const wsBasePath = ensurePublicPath(process.env.WS_PATH, '/ws/');
112
- const modernClientPrefix =
113
- String(process.env.APP_MODERN_CLIENT_PREFIX || 'v')
114
- .trim()
115
- .replace(/^\/+|\/+$/g, '') || 'v';
121
+ const modernClientPrefix = normalizeModernClientPrefix(process.env.APP_MODERN_CLIENT_PREFIX);
116
122
  const v2BasePath = ensurePublicPath(
117
123
  `${resolvedAppPublicPath.replace(/\/$/, '')}/${modernClientPrefix}/`,
118
124
  `/${modernClientPrefix}/`,
@@ -120,6 +126,7 @@ export default defineConfig(({ command }) => {
120
126
  const portalBasePath = ensurePublicPath(`${resolvedAppPublicPath.replace(/\/$/, '')}/x/`, '/x/');
121
127
  const clientPort = toNumber(process.env.APP_PORT, 13001);
122
128
  const v2Port = toNumber(process.env.APP_V2_PORT, clientPort + 2);
129
+ const settingsPort = toNumber(process.env.APP_SETTINGS_PORT, clientPort + 3);
123
130
  const hmrPath = `${resolvedAppPublicPath.replace(/\/$/, '')}/__rspack_hmr`;
124
131
  const proxyTargetUrl = process.env.PROXY_TARGET_URL || `http://127.0.0.1:${clientPort + 1}`;
125
132
  const hmrClientHost = process.env.RSPACK_HMR_CLIENT_HOST;
@@ -208,8 +215,10 @@ export default defineConfig(({ command }) => {
208
215
  publicDir: {
209
216
  name: path.resolve(__dirname, 'public'),
210
217
  },
211
- proxy: {
212
- [apiBasePath]: {
218
+ proxy: [
219
+ createSettingsDevProxyOptions(resolvedAppPublicPath, settingsPort),
220
+ {
221
+ context: apiBasePath,
213
222
  target: proxyTargetUrl,
214
223
  changeOrigin: true,
215
224
  ws: true,
@@ -227,25 +236,30 @@ export default defineConfig(({ command }) => {
227
236
  }
228
237
  },
229
238
  },
230
- [localStorageBasePath]: {
239
+ {
240
+ context: localStorageBasePath,
231
241
  target: proxyTargetUrl,
232
242
  changeOrigin: true,
233
243
  },
234
- [fileBasePath]: {
244
+ {
245
+ context: fileBasePath,
235
246
  target: proxyTargetUrl,
236
247
  changeOrigin: true,
237
248
  },
238
- [staticBasePath]: {
249
+ {
250
+ context: staticBasePath,
239
251
  target: proxyTargetUrl,
240
252
  changeOrigin: true,
241
253
  },
242
- [wsBasePath]: {
254
+ {
255
+ context: wsBasePath,
243
256
  target: proxyTargetUrl,
244
257
  changeOrigin: true,
245
258
  ws: true,
246
259
  xfwd: true,
247
260
  },
248
- [v2BasePath]: {
261
+ {
262
+ context: v2BasePath,
249
263
  target: `http://127.0.0.1:${v2Port}`,
250
264
  changeOrigin: true,
251
265
  ws: true,
@@ -254,13 +268,14 @@ export default defineConfig(({ command }) => {
254
268
  },
255
269
  xfwd: true,
256
270
  },
257
- [portalBasePath]: {
271
+ {
272
+ context: portalBasePath,
258
273
  target: proxyTargetUrl,
259
274
  changeOrigin: true,
260
275
  ws: true,
261
276
  xfwd: true,
262
277
  },
263
- },
278
+ ],
264
279
  historyApiFallback: {
265
280
  disableDotRule: true,
266
281
  index: `${resolvedAppPublicPath}index.html`,
@@ -0,0 +1,36 @@
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 { IndexGenerator } from '../../devtools/common.js';
12
+
13
+ type V2PluginIndexGenerator = new (
14
+ outputPath: string,
15
+ pluginPaths: string[],
16
+ options: {
17
+ clientModuleName: string;
18
+ clientRootFile: string;
19
+ clientSourceDir: string;
20
+ },
21
+ ) => { generate(): void };
22
+
23
+ function getPluginDirectories() {
24
+ return (process.env.PLUGIN_PATH || 'packages/plugins/,packages/samples/,packages/pro-plugins/')
25
+ .split(',')
26
+ .map((directory) => path.resolve(process.cwd(), directory));
27
+ }
28
+
29
+ export function generateSettingsPluginImports(outputPath: string, pluginPaths = getPluginDirectories()) {
30
+ const Generator = IndexGenerator as unknown as V2PluginIndexGenerator;
31
+ new Generator(outputPath, pluginPaths, {
32
+ clientModuleName: 'client-v2',
33
+ clientRootFile: 'client-v2.js',
34
+ clientSourceDir: 'client-v2',
35
+ }).generate();
36
+ }
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
6
+ <title>Loading...</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ </body>
11
+ </html>