@nocobase/flow-engine 2.0.0-beta.8 → 2.0.0

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 (245) hide show
  1. package/lib/BlockScopedFlowEngine.js +0 -1
  2. package/lib/FlowDefinition.d.ts +2 -0
  3. package/lib/JSRunner.d.ts +6 -0
  4. package/lib/JSRunner.js +32 -2
  5. package/lib/ViewScopedFlowEngine.js +3 -0
  6. package/lib/acl/Acl.js +13 -3
  7. package/lib/components/FlowContextSelector.js +155 -10
  8. package/lib/components/settings/wrappers/component/SwitchWithTitle.js +2 -1
  9. package/lib/components/settings/wrappers/contextual/DefaultSettingsIcon.js +76 -15
  10. package/lib/components/settings/wrappers/contextual/FlowsContextMenu.js +24 -4
  11. package/lib/components/settings/wrappers/contextual/StepSettingsDialog.js +5 -1
  12. package/lib/components/variables/VariableInput.js +9 -4
  13. package/lib/components/variables/VariableTag.js +46 -39
  14. package/lib/components/variables/utils.d.ts +7 -0
  15. package/lib/components/variables/utils.js +42 -2
  16. package/lib/data-source/index.d.ts +7 -27
  17. package/lib/data-source/index.js +81 -51
  18. package/lib/executor/FlowExecutor.d.ts +2 -1
  19. package/lib/executor/FlowExecutor.js +163 -22
  20. package/lib/flowContext.d.ts +230 -7
  21. package/lib/flowContext.js +2267 -148
  22. package/lib/flowEngine.d.ts +21 -0
  23. package/lib/flowEngine.js +56 -8
  24. package/lib/flowI18n.js +6 -4
  25. package/lib/flowSettings.js +17 -11
  26. package/lib/index.d.ts +7 -1
  27. package/lib/index.js +21 -0
  28. package/lib/locale/en-US.json +9 -2
  29. package/lib/locale/index.d.ts +14 -0
  30. package/lib/locale/zh-CN.json +8 -1
  31. package/lib/models/CollectionFieldModel.d.ts +1 -0
  32. package/lib/models/CollectionFieldModel.js +3 -2
  33. package/lib/models/flowModel.js +12 -1
  34. package/lib/provider.js +5 -5
  35. package/lib/resources/baseRecordResource.d.ts +5 -0
  36. package/lib/resources/baseRecordResource.js +24 -0
  37. package/lib/resources/multiRecordResource.d.ts +1 -0
  38. package/lib/resources/multiRecordResource.js +11 -4
  39. package/lib/resources/singleRecordResource.js +2 -0
  40. package/lib/resources/sqlResource.d.ts +4 -3
  41. package/lib/resources/sqlResource.js +8 -3
  42. package/lib/runjs-context/contexts/FormJSFieldItemRunJSContext.js +12 -2
  43. package/lib/runjs-context/contexts/JSBlockRunJSContext.js +2 -2
  44. package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.d.ts +16 -0
  45. package/lib/runjs-context/contexts/JSEditableFieldRunJSContext.js +125 -0
  46. package/lib/runjs-context/contexts/JSItemRunJSContext.js +12 -2
  47. package/lib/runjs-context/contexts/base.js +706 -41
  48. package/lib/runjs-context/contributions.d.ts +33 -0
  49. package/lib/runjs-context/contributions.js +88 -0
  50. package/lib/runjs-context/helpers.js +12 -1
  51. package/lib/runjs-context/setup.js +6 -0
  52. package/lib/runjs-context/snippets/global/api-request.snippet.js +3 -3
  53. package/lib/runjs-context/snippets/global/import-esm.snippet.js +2 -3
  54. package/lib/runjs-context/snippets/global/query-selector.snippet.js +8 -3
  55. package/lib/runjs-context/snippets/global/require-amd.snippet.js +1 -1
  56. package/lib/runjs-context/snippets/index.d.ts +11 -1
  57. package/lib/runjs-context/snippets/index.js +61 -40
  58. package/lib/runjs-context/snippets/scene/block/add-event-listener.snippet.js +10 -7
  59. package/lib/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.js +3 -3
  60. package/lib/runjs-context/snippets/scene/block/chartjs-bar.snippet.js +2 -2
  61. package/lib/runjs-context/snippets/scene/block/echarts-init.snippet.js +2 -2
  62. package/lib/runjs-context/snippets/scene/block/render-iframe.snippet.js +2 -2
  63. package/lib/runjs-context/snippets/scene/block/render-react.snippet.js +1 -1
  64. package/lib/runjs-context/snippets/scene/block/render-statistics.snippet.js +1 -1
  65. package/lib/runjs-context/snippets/scene/block/render-timeline.snippet.js +1 -1
  66. package/lib/runjs-context/snippets/scene/block/resource-example.snippet.js +5 -5
  67. package/lib/runjs-context/snippets/scene/block/three-users-orbit.snippet.js +6 -6
  68. package/lib/runjs-context/snippets/scene/block/vue-component.snippet.js +3 -4
  69. package/lib/runjs-context/snippets/scene/detail/color-by-value.snippet.js +1 -1
  70. package/lib/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.js +20 -3
  71. package/lib/runjs-context/snippets/scene/detail/format-number.snippet.js +1 -1
  72. package/lib/runjs-context/snippets/scene/detail/innerHTML-value.snippet.js +1 -1
  73. package/lib/runjs-context/snippets/scene/detail/percentage-bar.snippet.js +3 -3
  74. package/lib/runjs-context/snippets/scene/detail/relative-time.snippet.js +3 -3
  75. package/lib/runjs-context/snippets/scene/detail/status-tag.snippet.js +2 -2
  76. package/lib/runjs-context/snippets/scene/form/cascade-select.snippet.js +1 -1
  77. package/lib/runjs-context/snippets/scene/form/render-basic.snippet.js +2 -2
  78. package/lib/runjs-context/snippets/scene/table/cell-open-dialog.snippet.js +6 -3
  79. package/lib/runjs-context/snippets/scene/table/concat-fields.snippet.js +3 -1
  80. package/lib/runjsLibs.d.ts +28 -0
  81. package/lib/runjsLibs.js +532 -0
  82. package/lib/scheduler/ModelOperationScheduler.d.ts +2 -0
  83. package/lib/scheduler/ModelOperationScheduler.js +25 -21
  84. package/lib/types.d.ts +27 -0
  85. package/lib/utils/associationObjectVariable.d.ts +2 -2
  86. package/lib/utils/createCollectionContextMeta.js +1 -0
  87. package/lib/utils/createEphemeralContext.js +2 -2
  88. package/lib/utils/dateVariable.d.ts +16 -0
  89. package/lib/utils/dateVariable.js +380 -0
  90. package/lib/utils/exceptions.d.ts +7 -0
  91. package/lib/utils/exceptions.js +10 -0
  92. package/lib/utils/index.d.ts +8 -3
  93. package/lib/utils/index.js +45 -0
  94. package/lib/utils/params-resolvers.js +16 -9
  95. package/lib/utils/resolveModuleUrl.d.ts +58 -0
  96. package/lib/utils/resolveModuleUrl.js +65 -0
  97. package/lib/utils/resolveRunJSObjectValues.d.ts +16 -0
  98. package/lib/utils/resolveRunJSObjectValues.js +61 -0
  99. package/lib/utils/runjsModuleLoader.d.ts +58 -0
  100. package/lib/utils/runjsModuleLoader.js +422 -0
  101. package/lib/utils/runjsTemplateCompat.d.ts +35 -0
  102. package/lib/utils/runjsTemplateCompat.js +743 -0
  103. package/lib/utils/runjsValue.d.ts +29 -0
  104. package/lib/utils/runjsValue.js +275 -0
  105. package/lib/utils/safeGlobals.d.ts +18 -8
  106. package/lib/utils/safeGlobals.js +164 -17
  107. package/lib/utils/schema-utils.d.ts +10 -0
  108. package/lib/utils/schema-utils.js +61 -0
  109. package/lib/views/createViewMeta.d.ts +0 -7
  110. package/lib/views/createViewMeta.js +19 -70
  111. package/lib/views/index.d.ts +1 -2
  112. package/lib/views/index.js +4 -3
  113. package/lib/views/useDialog.js +7 -2
  114. package/lib/views/useDrawer.js +7 -2
  115. package/lib/views/usePage.d.ts +4 -0
  116. package/lib/views/usePage.js +43 -6
  117. package/lib/views/usePopover.js +4 -1
  118. package/lib/views/viewEvents.d.ts +17 -0
  119. package/lib/views/viewEvents.js +90 -0
  120. package/package.json +4 -4
  121. package/src/BlockScopedFlowEngine.ts +2 -5
  122. package/src/JSRunner.ts +44 -2
  123. package/src/ViewScopedFlowEngine.ts +4 -0
  124. package/src/__tests__/JSRunner.test.ts +64 -0
  125. package/src/__tests__/createViewMeta.popup.test.ts +62 -1
  126. package/src/__tests__/flowContext.test.ts +693 -1
  127. package/src/__tests__/flowEngine.dataSourceDirty.test.ts +63 -0
  128. package/src/__tests__/flowModel.openView.navigation.test.ts +28 -0
  129. package/src/__tests__/flowRunJSContextDefine.test.ts +63 -0
  130. package/src/__tests__/flowRuntimeContext.test.ts +2 -1
  131. package/src/__tests__/flowSettings.open.test.tsx +123 -19
  132. package/src/__tests__/runjsContext.test.ts +10 -7
  133. package/src/__tests__/runjsContextImplementations.test.ts +34 -3
  134. package/src/__tests__/runjsContextRuntime.test.ts +3 -3
  135. package/src/__tests__/runjsContributions.test.ts +89 -0
  136. package/src/__tests__/runjsExternalLibs.test.ts +242 -0
  137. package/src/__tests__/runjsLibsLazyLoading.test.ts +44 -0
  138. package/src/__tests__/runjsLocales.test.ts +4 -1
  139. package/src/__tests__/runjsPreprocessDefault.test.ts +49 -0
  140. package/src/__tests__/runjsRuntimeFeatures.test.ts +166 -0
  141. package/src/__tests__/runjsSnippets.test.ts +40 -3
  142. package/src/acl/Acl.tsx +3 -3
  143. package/src/components/FlowContextSelector.tsx +208 -12
  144. package/src/components/settings/wrappers/component/SwitchWithTitle.tsx +2 -1
  145. package/src/components/settings/wrappers/component/__tests__/InlineControls.test.tsx +74 -0
  146. package/src/components/settings/wrappers/contextual/DefaultSettingsIcon.tsx +109 -16
  147. package/src/components/settings/wrappers/contextual/FlowsContextMenu.tsx +41 -7
  148. package/src/components/settings/wrappers/contextual/StepSettingsDialog.tsx +13 -2
  149. package/src/components/settings/wrappers/contextual/__tests__/DefaultSettingsIcon.test.tsx +157 -5
  150. package/src/components/variables/VariableInput.tsx +12 -4
  151. package/src/components/variables/VariableTag.tsx +54 -45
  152. package/src/components/variables/__tests__/FlowContextSelector.test.tsx +260 -3
  153. package/src/components/variables/__tests__/VariableTag.test.tsx +50 -0
  154. package/src/components/variables/__tests__/utils.test.ts +81 -3
  155. package/src/components/variables/utils.ts +67 -6
  156. package/src/data-source/index.ts +85 -110
  157. package/src/executor/FlowExecutor.ts +200 -23
  158. package/src/executor/__tests__/flowExecutor.test.ts +66 -0
  159. package/src/flowContext.ts +2986 -211
  160. package/src/flowEngine.ts +59 -8
  161. package/src/flowI18n.ts +7 -5
  162. package/src/flowSettings.ts +18 -12
  163. package/src/index.ts +14 -1
  164. package/src/locale/en-US.json +9 -2
  165. package/src/locale/zh-CN.json +8 -1
  166. package/src/models/CollectionFieldModel.tsx +3 -1
  167. package/src/models/__tests__/dispatchEvent.when.test.ts +554 -0
  168. package/src/models/__tests__/flowModel.test.ts +20 -4
  169. package/src/models/flowModel.tsx +13 -1
  170. package/src/provider.tsx +7 -6
  171. package/src/resources/__tests__/multiRecordResource.test.ts +44 -0
  172. package/src/resources/__tests__/sqlResource.test.ts +60 -0
  173. package/src/resources/baseRecordResource.ts +31 -0
  174. package/src/resources/multiRecordResource.ts +11 -4
  175. package/src/resources/singleRecordResource.ts +3 -0
  176. package/src/resources/sqlResource.ts +11 -6
  177. package/src/runjs-context/contexts/FormJSFieldItemRunJSContext.ts +10 -0
  178. package/src/runjs-context/contexts/JSBlockRunJSContext.ts +6 -2
  179. package/src/runjs-context/contexts/JSEditableFieldRunJSContext.ts +106 -0
  180. package/src/runjs-context/contexts/JSItemRunJSContext.ts +10 -0
  181. package/src/runjs-context/contexts/base.ts +715 -44
  182. package/src/runjs-context/contributions.ts +88 -0
  183. package/src/runjs-context/helpers.ts +11 -1
  184. package/src/runjs-context/setup.ts +6 -0
  185. package/src/runjs-context/snippets/global/api-request.snippet.ts +3 -3
  186. package/src/runjs-context/snippets/global/import-esm.snippet.ts +2 -3
  187. package/src/runjs-context/snippets/global/query-selector.snippet.ts +8 -3
  188. package/src/runjs-context/snippets/global/require-amd.snippet.ts +1 -1
  189. package/src/runjs-context/snippets/index.ts +75 -41
  190. package/src/runjs-context/snippets/scene/block/add-event-listener.snippet.ts +11 -13
  191. package/src/runjs-context/snippets/scene/block/api-fetch-render-list.snippet.ts +3 -3
  192. package/src/runjs-context/snippets/scene/block/chartjs-bar.snippet.ts +2 -2
  193. package/src/runjs-context/snippets/scene/block/echarts-init.snippet.ts +2 -2
  194. package/src/runjs-context/snippets/scene/block/render-iframe.snippet.ts +2 -2
  195. package/src/runjs-context/snippets/scene/block/render-react.snippet.ts +1 -1
  196. package/src/runjs-context/snippets/scene/block/render-statistics.snippet.ts +1 -1
  197. package/src/runjs-context/snippets/scene/block/render-timeline.snippet.ts +1 -1
  198. package/src/runjs-context/snippets/scene/block/resource-example.snippet.ts +6 -11
  199. package/src/runjs-context/snippets/scene/block/three-users-orbit.snippet.ts +6 -6
  200. package/src/runjs-context/snippets/scene/block/vue-component.snippet.ts +3 -4
  201. package/src/runjs-context/snippets/scene/detail/color-by-value.snippet.ts +1 -1
  202. package/src/runjs-context/snippets/scene/detail/copy-to-clipboard.snippet.ts +20 -3
  203. package/src/runjs-context/snippets/scene/detail/format-number.snippet.ts +1 -1
  204. package/src/runjs-context/snippets/scene/detail/innerHTML-value.snippet.ts +1 -1
  205. package/src/runjs-context/snippets/scene/detail/percentage-bar.snippet.ts +3 -3
  206. package/src/runjs-context/snippets/scene/detail/relative-time.snippet.ts +3 -3
  207. package/src/runjs-context/snippets/scene/detail/status-tag.snippet.ts +2 -2
  208. package/src/runjs-context/snippets/scene/form/cascade-select.snippet.ts +1 -1
  209. package/src/runjs-context/snippets/scene/form/render-basic.snippet.ts +3 -8
  210. package/src/runjs-context/snippets/scene/table/cell-open-dialog.snippet.ts +6 -3
  211. package/src/runjs-context/snippets/scene/table/concat-fields.snippet.ts +3 -1
  212. package/src/runjsLibs.ts +622 -0
  213. package/src/scheduler/ModelOperationScheduler.ts +27 -21
  214. package/src/types.ts +38 -1
  215. package/src/utils/__tests__/dateVariable.test.ts +101 -0
  216. package/src/utils/__tests__/params-resolvers.test.ts +40 -0
  217. package/src/utils/__tests__/runjsRequireAsyncAutoWhitelist.test.ts +38 -0
  218. package/src/utils/__tests__/runjsTemplateCompat.test.ts +159 -0
  219. package/src/utils/__tests__/runjsValue.test.ts +44 -0
  220. package/src/utils/__tests__/safeGlobals.test.ts +57 -2
  221. package/src/utils/__tests__/utils.test.ts +95 -0
  222. package/src/utils/associationObjectVariable.ts +2 -2
  223. package/src/utils/createCollectionContextMeta.ts +1 -0
  224. package/src/utils/createEphemeralContext.ts +5 -4
  225. package/src/utils/dateVariable.ts +397 -0
  226. package/src/utils/exceptions.ts +11 -0
  227. package/src/utils/index.ts +37 -3
  228. package/src/utils/params-resolvers.ts +23 -9
  229. package/src/utils/resolveModuleUrl.ts +91 -0
  230. package/src/utils/resolveRunJSObjectValues.ts +46 -0
  231. package/src/utils/runjsModuleLoader.ts +553 -0
  232. package/src/utils/runjsTemplateCompat.ts +828 -0
  233. package/src/utils/runjsValue.ts +287 -0
  234. package/src/utils/safeGlobals.ts +188 -17
  235. package/src/utils/schema-utils.ts +79 -0
  236. package/src/views/__tests__/FlowView.usePage.test.tsx +54 -1
  237. package/src/views/__tests__/useDialog.closeDestroy.test.tsx +35 -8
  238. package/src/views/__tests__/viewEvents.resolveOpenerEngine.test.ts +28 -0
  239. package/src/views/createViewMeta.ts +22 -75
  240. package/src/views/index.tsx +1 -2
  241. package/src/views/useDialog.tsx +8 -1
  242. package/src/views/useDrawer.tsx +8 -1
  243. package/src/views/usePage.tsx +51 -5
  244. package/src/views/usePopover.tsx +4 -1
  245. package/src/views/viewEvents.ts +55 -0
@@ -409,8 +409,13 @@ export async function preprocessExpression(expression: string, ctx: FlowContext)
409
409
  async function compileExpression<TModel extends FlowModel = FlowModel>(expression: string, ctx: FlowContext) {
410
410
  // 仅点号路径匹配:ctx.a.b.c(不支持括号/函数/索引),用于数组聚合取值
411
411
  const matchDotOnly = (expr: string): string | null => {
412
- const m = expr.trim().match(/^ctx\.([a-zA-Z_$][a-zA-Z0-9_$]*(?:\.[a-zA-Z_$][a-zA-Z0-9_$]*)*)$/);
413
- return m ? m[1] : null;
412
+ // 顶层变量名仍使用 JS 标识符规则(与 ctx.defineProperty 保持一致);
413
+ // 子路径允许包含 '-'(例如 formValues.oho-test.o2m-users)。
414
+ const m = expr
415
+ .trim()
416
+ .match(/^ctx\.([a-zA-Z_$][a-zA-Z0-9_$]*)(?:\.([a-zA-Z_$][a-zA-Z0-9_$-]*(?:\.[a-zA-Z_$][a-zA-Z0-9_$-]*)*))?$/);
417
+ if (!m) return null;
418
+ return m[2] ? `${m[1]}.${m[2]}` : m[1];
414
419
  };
415
420
 
416
421
  // 基于 getValuesByPath 的聚合取值:支持数组扁平化,仅支持 '.' 访问
@@ -423,6 +428,20 @@ async function compileExpression<TModel extends FlowModel = FlowModel>(expressio
423
428
  return getValuesByPath(base as object, segs.join('.'));
424
429
  };
425
430
 
431
+ const resolveInnerExpression = async (innerExpr: string): Promise<any> => {
432
+ const dotPath = matchDotOnly(innerExpr);
433
+ if (dotPath) {
434
+ const resolved = await resolveDotOnlyPath(dotPath);
435
+ // 当 dotPath 含 '-' 时可能与减号运算符存在歧义,例如:ctx.aa.bb-ctx.cc。
436
+ // 若按 path 解析未取到值,则回退到 JS 表达式解析,尽量保持兼容。
437
+ if (resolved === undefined && dotPath.includes('-')) {
438
+ return await processExpression(innerExpr, ctx);
439
+ }
440
+ return resolved;
441
+ }
442
+ return await processExpression(innerExpr, ctx);
443
+ };
444
+
426
445
  /**
427
446
  * 单个表达式模式匹配
428
447
  *
@@ -443,11 +462,7 @@ async function compileExpression<TModel extends FlowModel = FlowModel>(expressio
443
462
  const singleMatch = expression.match(/^\s*\{\{\s*([^{}]+?)\s*\}\}\s*$/);
444
463
  if (singleMatch) {
445
464
  const inner = singleMatch[1];
446
- const dotPath = matchDotOnly(inner);
447
- if (dotPath) {
448
- return await resolveDotOnlyPath(dotPath);
449
- }
450
- return await processExpression(inner, ctx);
465
+ return await resolveInnerExpression(inner);
451
466
  }
452
467
 
453
468
  /**
@@ -470,8 +485,7 @@ async function compileExpression<TModel extends FlowModel = FlowModel>(expressio
470
485
  let result = expression;
471
486
 
472
487
  for (const [fullMatch, innerExpr] of matches) {
473
- const dotPath = matchDotOnly(innerExpr);
474
- const value = dotPath ? await resolveDotOnlyPath(dotPath) : await processExpression(innerExpr, ctx);
488
+ const value = await resolveInnerExpression(innerExpr);
475
489
  if (value !== undefined) {
476
490
  const replacement = typeof value === 'object' && value !== null ? JSON.stringify(value) : String(value);
477
491
  result = result.replace(fullMatch, replacement);
@@ -0,0 +1,91 @@
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
+ /**
11
+ * 解析模块 URL,将相对路径转换为完整的 CDN URL
12
+ *
13
+ * @param url - 模块地址(支持相对路径或完整 URL)
14
+ * @param options - 可选配置
15
+ * @param options.addSuffix - 是否添加 ESM_CDN_SUFFIX 后缀(如 `+esm`),默认为 `true`
16
+ * @returns 解析后的完整 URL
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * // 相对路径会被拼接上 CDN 前缀和后缀(默认添加)
21
+ * // 如果使用 esm.sh(默认),不需要后缀
22
+ * resolveModuleUrl('vue@3.4.0')
23
+ * // => 'https://esm.sh/vue@3.4.0'
24
+ *
25
+ * // 如果使用 jsdelivr,需要配置 ESM_CDN_SUFFIX='/+esm'
26
+ * // resolveModuleUrl('vue@3.4.0') => 'https://cdn.jsdelivr.net/npm/vue@3.4.0/+esm'
27
+ *
28
+ * // 不添加后缀(适用于 UMD 库或 CSS 文件)
29
+ * resolveModuleUrl('vue@3.4.0', { addSuffix: false })
30
+ * // => 'https://esm.sh/vue@3.4.0' (即使配置了 suffix 也不会添加)
31
+ *
32
+ * // 原始 URL(适用于 UMD 库)
33
+ * resolveModuleUrl('lodash@4.17.21/lodash.js', { raw: true })
34
+ * // => 'https://esm.sh/lodash@4.17.21/lodash.js?raw' (即使配置了 suffix 也不会添加)
35
+ *
36
+ * // 完整 URL 保持不变
37
+ * resolveModuleUrl('https://cdn.jsdelivr.net/npm/vue@3.4.0')
38
+ * // => 'https://cdn.jsdelivr.net/npm/vue@3.4.0'
39
+ * ```
40
+ */
41
+ export function resolveModuleUrl(url: string, options?: { addSuffix?: boolean; raw?: boolean }): string {
42
+ if (!url || typeof url !== 'string') {
43
+ throw new Error('invalid url');
44
+ }
45
+
46
+ const u = url.trim();
47
+
48
+ // 如果是完整 URL(http:// 或 https://),直接返回
49
+ if (u.startsWith('http://') || u.startsWith('https://')) {
50
+ return u;
51
+ }
52
+
53
+ // 相对路径:拼接 CDN 前缀和后缀
54
+ const ESM_CDN_BASE_URL = (window as any)['__esm_cdn_base_url__'] || 'https://esm.sh';
55
+ const ESM_CDN_SUFFIX = options?.addSuffix ? (window as any)['__esm_cdn_suffix__'] || '' : '';
56
+
57
+ // 移除 base URL 末尾的斜杠,移除相对路径开头的斜杠
58
+ const base = ESM_CDN_BASE_URL.replace(/\/$/, '');
59
+ const path = u.replace(/^\//, '');
60
+
61
+ if (options?.raw) {
62
+ const sep = path.includes('?') ? '&' : '?';
63
+ return `${base}/${path}${sep}raw`;
64
+ }
65
+
66
+ return `${base}/${path}${ESM_CDN_SUFFIX}`;
67
+ }
68
+
69
+ /**
70
+ * 判断 URL 是否为 CSS 文件
71
+ *
72
+ * @param url - 文件 URL(支持带 query 和 hash,如 `example.css?v=123`)
73
+ * @returns 如果是 CSS 文件返回 `true`,否则返回 `false`
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * isCssFile('style.css') // => true
78
+ * isCssFile('style.css?v=123') // => true
79
+ * isCssFile('style.css#section') // => true
80
+ * isCssFile('script.js') // => false
81
+ * ```
82
+ */
83
+ export function isCssFile(url: string): boolean {
84
+ if (!url || typeof url !== 'string') {
85
+ return false;
86
+ }
87
+
88
+ // 去掉 query 和 hash 后判断文件扩展名
89
+ const pathPart = url.split('?')[0].split('#')[0];
90
+ return pathPart.endsWith('.css');
91
+ }
@@ -0,0 +1,46 @@
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 { isRunJSValue, normalizeRunJSValue } from './runjsValue';
11
+ import { runjsWithSafeGlobals } from './safeGlobals';
12
+
13
+ /**
14
+ * Resolve an object's values, executing any RunJSValue entries via ctx.runjs.
15
+ *
16
+ * - Skips `undefined` values
17
+ * - Skips empty RunJS code (treated as not configured)
18
+ * - Throws when a RunJS execution fails
19
+ */
20
+ export async function resolveRunJSObjectValues(ctx: unknown, raw: unknown): Promise<Record<string, any>> {
21
+ const out: Record<string, any> = {};
22
+
23
+ if (!raw || typeof raw !== 'object') return out;
24
+ if (Array.isArray(raw)) return out;
25
+
26
+ for (const [key, value] of Object.entries(raw as Record<string, any>)) {
27
+ if (typeof value === 'undefined') continue;
28
+
29
+ if (isRunJSValue(value)) {
30
+ const { code, version } = normalizeRunJSValue(value);
31
+ if (!code.trim()) continue;
32
+ const ret = await runjsWithSafeGlobals(ctx, code, { version });
33
+ if (!ret?.success) {
34
+ throw new Error(`RunJS execution failed for "${key}"`);
35
+ }
36
+ if (typeof ret.value !== 'undefined') {
37
+ out[key] = ret.value;
38
+ }
39
+ continue;
40
+ }
41
+
42
+ out[key] = value;
43
+ }
44
+
45
+ return out;
46
+ }