@frontmcp/uipack 0.12.2 → 1.0.0-beta.10

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 (298) hide show
  1. package/CLAUDE.md +56 -154
  2. package/README.md +367 -62
  3. package/adapters/base-template.d.ts +30 -0
  4. package/adapters/base-template.d.ts.map +1 -0
  5. package/adapters/cdn-info.d.ts +34 -0
  6. package/adapters/cdn-info.d.ts.map +1 -0
  7. package/adapters/constants.d.ts +18 -0
  8. package/adapters/constants.d.ts.map +1 -0
  9. package/adapters/content-detector.d.ts +19 -0
  10. package/adapters/content-detector.d.ts.map +1 -0
  11. package/adapters/content-renderers.d.ts +27 -0
  12. package/adapters/content-renderers.d.ts.map +1 -0
  13. package/adapters/index.d.ts +14 -7
  14. package/adapters/index.d.ts.map +1 -1
  15. package/adapters/index.js +2343 -426
  16. package/adapters/render-failure.d.ts +18 -0
  17. package/adapters/render-failure.d.ts.map +1 -0
  18. package/adapters/response-builder.d.ts +34 -104
  19. package/adapters/response-builder.d.ts.map +1 -1
  20. package/adapters/serving-mode.d.ts +28 -91
  21. package/adapters/serving-mode.d.ts.map +1 -1
  22. package/adapters/template-renderer.d.ts +50 -0
  23. package/adapters/template-renderer.d.ts.map +1 -0
  24. package/adapters/type-detector.d.ts +18 -0
  25. package/adapters/type-detector.d.ts.map +1 -0
  26. package/bridge-runtime/index.js +1 -1
  27. package/component/index.d.ts +14 -0
  28. package/component/index.d.ts.map +1 -0
  29. package/component/index.js +2043 -0
  30. package/component/loader.d.ts +36 -0
  31. package/component/loader.d.ts.map +1 -0
  32. package/component/renderer.d.ts +30 -0
  33. package/component/renderer.d.ts.map +1 -0
  34. package/component/transpiler.d.ts +49 -0
  35. package/component/transpiler.d.ts.map +1 -0
  36. package/component/types.d.ts +82 -0
  37. package/component/types.d.ts.map +1 -0
  38. package/esm/adapters/index.mjs +2337 -422
  39. package/esm/bridge-runtime/index.mjs +1 -1
  40. package/esm/component/index.mjs +2013 -0
  41. package/esm/index.mjs +3446 -13935
  42. package/esm/package.json +4 -13
  43. package/esm/resolver/index.mjs +661 -0
  44. package/esm/shell/index.mjs +1406 -0
  45. package/esm/types/index.mjs +11 -11
  46. package/esm/utils/index.mjs +53 -8
  47. package/index.d.ts +12 -40
  48. package/index.d.ts.map +1 -1
  49. package/index.js +3579 -14218
  50. package/package.json +4 -13
  51. package/resolver/cdn-registry.d.ts +39 -0
  52. package/resolver/cdn-registry.d.ts.map +1 -0
  53. package/resolver/esm-sh.resolver.d.ts +54 -0
  54. package/resolver/esm-sh.resolver.d.ts.map +1 -0
  55. package/resolver/import-map.d.ts +47 -0
  56. package/resolver/import-map.d.ts.map +1 -0
  57. package/resolver/import-parser.d.ts +28 -0
  58. package/resolver/import-parser.d.ts.map +1 -0
  59. package/resolver/import-rewriter.d.ts +29 -0
  60. package/resolver/import-rewriter.d.ts.map +1 -0
  61. package/resolver/index.d.ts +15 -0
  62. package/resolver/index.d.ts.map +1 -0
  63. package/resolver/index.js +708 -0
  64. package/resolver/types.d.ts +191 -0
  65. package/resolver/types.d.ts.map +1 -0
  66. package/shell/builder.d.ts +31 -0
  67. package/shell/builder.d.ts.map +1 -0
  68. package/shell/csp.d.ts +37 -0
  69. package/shell/csp.d.ts.map +1 -0
  70. package/shell/custom-shell-applier.d.ts +33 -0
  71. package/shell/custom-shell-applier.d.ts.map +1 -0
  72. package/shell/custom-shell-resolver.d.ts +47 -0
  73. package/shell/custom-shell-resolver.d.ts.map +1 -0
  74. package/shell/custom-shell-types.d.ts +75 -0
  75. package/shell/custom-shell-types.d.ts.map +1 -0
  76. package/shell/custom-shell-validator.d.ts +26 -0
  77. package/shell/custom-shell-validator.d.ts.map +1 -0
  78. package/shell/data-injector.d.ts +40 -0
  79. package/shell/data-injector.d.ts.map +1 -0
  80. package/shell/index.d.ts +19 -0
  81. package/shell/index.d.ts.map +1 -0
  82. package/shell/index.js +1453 -0
  83. package/shell/types.d.ts +54 -0
  84. package/shell/types.d.ts.map +1 -0
  85. package/types/index.d.ts +1 -3
  86. package/types/index.d.ts.map +1 -1
  87. package/types/index.js +11 -11
  88. package/types/ui-config.d.ts +50 -11
  89. package/types/ui-config.d.ts.map +1 -1
  90. package/types/ui-runtime.d.ts +8 -82
  91. package/types/ui-runtime.d.ts.map +1 -1
  92. package/utils/index.d.ts +9 -3
  93. package/utils/index.d.ts.map +1 -1
  94. package/utils/index.js +59 -7
  95. package/adapters/platform-meta.constants.d.ts +0 -26
  96. package/adapters/platform-meta.constants.d.ts.map +0 -1
  97. package/adapters/platform-meta.d.ts +0 -234
  98. package/adapters/platform-meta.d.ts.map +0 -1
  99. package/base-template/bridge.d.ts +0 -90
  100. package/base-template/bridge.d.ts.map +0 -1
  101. package/base-template/default-base-template.d.ts +0 -91
  102. package/base-template/default-base-template.d.ts.map +0 -1
  103. package/base-template/index.d.ts +0 -15
  104. package/base-template/index.d.ts.map +0 -1
  105. package/base-template/index.js +0 -1393
  106. package/base-template/polyfills.d.ts +0 -31
  107. package/base-template/polyfills.d.ts.map +0 -1
  108. package/base-template/theme-styles.d.ts +0 -74
  109. package/base-template/theme-styles.d.ts.map +0 -1
  110. package/build/builders/base-builder.d.ts +0 -124
  111. package/build/builders/base-builder.d.ts.map +0 -1
  112. package/build/builders/esbuild-config.d.ts +0 -94
  113. package/build/builders/esbuild-config.d.ts.map +0 -1
  114. package/build/builders/hybrid-builder.d.ts +0 -93
  115. package/build/builders/hybrid-builder.d.ts.map +0 -1
  116. package/build/builders/index.d.ts +0 -17
  117. package/build/builders/index.d.ts.map +0 -1
  118. package/build/builders/inline-builder.d.ts +0 -83
  119. package/build/builders/inline-builder.d.ts.map +0 -1
  120. package/build/builders/static-builder.d.ts +0 -78
  121. package/build/builders/static-builder.d.ts.map +0 -1
  122. package/build/builders/types.d.ts +0 -341
  123. package/build/builders/types.d.ts.map +0 -1
  124. package/build/cdn-resources.d.ts +0 -244
  125. package/build/cdn-resources.d.ts.map +0 -1
  126. package/build/hybrid-data.d.ts +0 -127
  127. package/build/hybrid-data.d.ts.map +0 -1
  128. package/build/index.d.ts +0 -299
  129. package/build/index.d.ts.map +0 -1
  130. package/build/index.js +0 -8699
  131. package/build/ui-components-browser.d.ts +0 -64
  132. package/build/ui-components-browser.d.ts.map +0 -1
  133. package/build/widget-manifest.d.ts +0 -362
  134. package/build/widget-manifest.d.ts.map +0 -1
  135. package/bundler/cache.d.ts +0 -173
  136. package/bundler/cache.d.ts.map +0 -1
  137. package/bundler/file-cache/component-builder.d.ts +0 -167
  138. package/bundler/file-cache/component-builder.d.ts.map +0 -1
  139. package/bundler/file-cache/hash-calculator.d.ts +0 -155
  140. package/bundler/file-cache/hash-calculator.d.ts.map +0 -1
  141. package/bundler/file-cache/index.d.ts +0 -12
  142. package/bundler/file-cache/index.d.ts.map +0 -1
  143. package/bundler/file-cache/storage/filesystem.d.ts +0 -149
  144. package/bundler/file-cache/storage/filesystem.d.ts.map +0 -1
  145. package/bundler/file-cache/storage/index.d.ts +0 -11
  146. package/bundler/file-cache/storage/index.d.ts.map +0 -1
  147. package/bundler/file-cache/storage/interface.d.ts +0 -152
  148. package/bundler/file-cache/storage/interface.d.ts.map +0 -1
  149. package/bundler/file-cache/storage/redis.d.ts +0 -139
  150. package/bundler/file-cache/storage/redis.d.ts.map +0 -1
  151. package/bundler/index.d.ts +0 -35
  152. package/bundler/index.d.ts.map +0 -1
  153. package/bundler/index.js +0 -2953
  154. package/bundler/sandbox/enclave-adapter.d.ts +0 -121
  155. package/bundler/sandbox/enclave-adapter.d.ts.map +0 -1
  156. package/bundler/sandbox/executor.d.ts +0 -14
  157. package/bundler/sandbox/executor.d.ts.map +0 -1
  158. package/bundler/sandbox/policy.d.ts +0 -62
  159. package/bundler/sandbox/policy.d.ts.map +0 -1
  160. package/bundler/types.d.ts +0 -702
  161. package/bundler/types.d.ts.map +0 -1
  162. package/dependency/cdn-registry.d.ts +0 -98
  163. package/dependency/cdn-registry.d.ts.map +0 -1
  164. package/dependency/import-map.d.ts +0 -186
  165. package/dependency/import-map.d.ts.map +0 -1
  166. package/dependency/import-parser.d.ts +0 -82
  167. package/dependency/import-parser.d.ts.map +0 -1
  168. package/dependency/index.d.ts +0 -17
  169. package/dependency/index.d.ts.map +0 -1
  170. package/dependency/index.js +0 -3180
  171. package/dependency/resolver.d.ts +0 -164
  172. package/dependency/resolver.d.ts.map +0 -1
  173. package/dependency/schemas.d.ts +0 -486
  174. package/dependency/schemas.d.ts.map +0 -1
  175. package/dependency/template-loader.d.ts +0 -204
  176. package/dependency/template-loader.d.ts.map +0 -1
  177. package/dependency/template-processor.d.ts +0 -118
  178. package/dependency/template-processor.d.ts.map +0 -1
  179. package/dependency/types.d.ts +0 -739
  180. package/dependency/types.d.ts.map +0 -1
  181. package/esm/base-template/index.mjs +0 -1359
  182. package/esm/build/index.mjs +0 -8601
  183. package/esm/bundler/index.mjs +0 -2895
  184. package/esm/dependency/index.mjs +0 -3068
  185. package/esm/handlebars/index.mjs +0 -587
  186. package/esm/registry/index.mjs +0 -6305
  187. package/esm/renderers/index.mjs +0 -1557
  188. package/esm/runtime/index.mjs +0 -5361
  189. package/esm/styles/index.mjs +0 -171
  190. package/esm/theme/index.mjs +0 -756
  191. package/esm/tool-template/index.mjs +0 -3652
  192. package/esm/validation/index.mjs +0 -542
  193. package/handlebars/expression-extractor.d.ts +0 -147
  194. package/handlebars/expression-extractor.d.ts.map +0 -1
  195. package/handlebars/helpers.d.ts +0 -339
  196. package/handlebars/helpers.d.ts.map +0 -1
  197. package/handlebars/index.d.ts +0 -195
  198. package/handlebars/index.d.ts.map +0 -1
  199. package/handlebars/index.js +0 -659
  200. package/preview/claude-preview.d.ts +0 -67
  201. package/preview/claude-preview.d.ts.map +0 -1
  202. package/preview/generic-preview.d.ts +0 -66
  203. package/preview/generic-preview.d.ts.map +0 -1
  204. package/preview/index.d.ts +0 -36
  205. package/preview/index.d.ts.map +0 -1
  206. package/preview/openai-preview.d.ts +0 -70
  207. package/preview/openai-preview.d.ts.map +0 -1
  208. package/preview/types.d.ts +0 -199
  209. package/preview/types.d.ts.map +0 -1
  210. package/registry/index.d.ts +0 -46
  211. package/registry/index.d.ts.map +0 -1
  212. package/registry/index.js +0 -6342
  213. package/registry/render-template.d.ts +0 -91
  214. package/registry/render-template.d.ts.map +0 -1
  215. package/registry/tool-ui.registry.d.ts +0 -294
  216. package/registry/tool-ui.registry.d.ts.map +0 -1
  217. package/registry/uri-utils.d.ts +0 -56
  218. package/registry/uri-utils.d.ts.map +0 -1
  219. package/renderers/cache.d.ts +0 -145
  220. package/renderers/cache.d.ts.map +0 -1
  221. package/renderers/html.renderer.d.ts +0 -123
  222. package/renderers/html.renderer.d.ts.map +0 -1
  223. package/renderers/index.d.ts +0 -36
  224. package/renderers/index.d.ts.map +0 -1
  225. package/renderers/index.js +0 -1603
  226. package/renderers/mdx-client.renderer.d.ts +0 -124
  227. package/renderers/mdx-client.renderer.d.ts.map +0 -1
  228. package/renderers/registry.d.ts +0 -133
  229. package/renderers/registry.d.ts.map +0 -1
  230. package/renderers/types.d.ts +0 -343
  231. package/renderers/types.d.ts.map +0 -1
  232. package/renderers/utils/detect.d.ts +0 -107
  233. package/renderers/utils/detect.d.ts.map +0 -1
  234. package/renderers/utils/hash.d.ts +0 -40
  235. package/renderers/utils/hash.d.ts.map +0 -1
  236. package/renderers/utils/index.d.ts +0 -9
  237. package/renderers/utils/index.d.ts.map +0 -1
  238. package/renderers/utils/transpiler.d.ts +0 -70
  239. package/renderers/utils/transpiler.d.ts.map +0 -1
  240. package/runtime/adapters/html.adapter.d.ts +0 -59
  241. package/runtime/adapters/html.adapter.d.ts.map +0 -1
  242. package/runtime/adapters/index.d.ts +0 -26
  243. package/runtime/adapters/index.d.ts.map +0 -1
  244. package/runtime/adapters/mdx.adapter.d.ts +0 -73
  245. package/runtime/adapters/mdx.adapter.d.ts.map +0 -1
  246. package/runtime/adapters/types.d.ts +0 -95
  247. package/runtime/adapters/types.d.ts.map +0 -1
  248. package/runtime/csp.d.ts +0 -48
  249. package/runtime/csp.d.ts.map +0 -1
  250. package/runtime/index.d.ts +0 -17
  251. package/runtime/index.d.ts.map +0 -1
  252. package/runtime/index.js +0 -5432
  253. package/runtime/mcp-bridge.d.ts +0 -101
  254. package/runtime/mcp-bridge.d.ts.map +0 -1
  255. package/runtime/renderer-runtime.d.ts +0 -133
  256. package/runtime/renderer-runtime.d.ts.map +0 -1
  257. package/runtime/sanitizer.d.ts +0 -180
  258. package/runtime/sanitizer.d.ts.map +0 -1
  259. package/runtime/types.d.ts +0 -415
  260. package/runtime/types.d.ts.map +0 -1
  261. package/runtime/wrapper.d.ts +0 -421
  262. package/runtime/wrapper.d.ts.map +0 -1
  263. package/styles/index.d.ts +0 -8
  264. package/styles/index.d.ts.map +0 -1
  265. package/styles/index.js +0 -222
  266. package/styles/variants.d.ts +0 -51
  267. package/styles/variants.d.ts.map +0 -1
  268. package/theme/cdn.d.ts +0 -195
  269. package/theme/cdn.d.ts.map +0 -1
  270. package/theme/css-to-theme.d.ts +0 -64
  271. package/theme/css-to-theme.d.ts.map +0 -1
  272. package/theme/index.d.ts +0 -19
  273. package/theme/index.d.ts.map +0 -1
  274. package/theme/index.js +0 -814
  275. package/theme/platforms.d.ts +0 -102
  276. package/theme/platforms.d.ts.map +0 -1
  277. package/theme/presets/github-openai.d.ts +0 -50
  278. package/theme/presets/github-openai.d.ts.map +0 -1
  279. package/theme/presets/index.d.ts +0 -11
  280. package/theme/presets/index.d.ts.map +0 -1
  281. package/theme/theme.d.ts +0 -396
  282. package/theme/theme.d.ts.map +0 -1
  283. package/tool-template/builder.d.ts +0 -213
  284. package/tool-template/builder.d.ts.map +0 -1
  285. package/tool-template/index.d.ts +0 -16
  286. package/tool-template/index.d.ts.map +0 -1
  287. package/tool-template/index.js +0 -3690
  288. package/validation/error-box.d.ts +0 -56
  289. package/validation/error-box.d.ts.map +0 -1
  290. package/validation/index.d.ts +0 -13
  291. package/validation/index.d.ts.map +0 -1
  292. package/validation/index.js +0 -576
  293. package/validation/schema-paths.d.ts +0 -118
  294. package/validation/schema-paths.d.ts.map +0 -1
  295. package/validation/template-validator.d.ts +0 -143
  296. package/validation/template-validator.d.ts.map +0 -1
  297. package/validation/wrapper.d.ts +0 -97
  298. package/validation/wrapper.d.ts.map +0 -1
@@ -1,3068 +0,0 @@
1
- // libs/uipack/src/dependency/types.ts
2
- function detectTemplateMode(template) {
3
- if (typeof template === "function") {
4
- return "inline-function";
5
- }
6
- if (typeof template === "string") {
7
- if (template.startsWith("http://") || template.startsWith("https://")) {
8
- return "url";
9
- }
10
- const looksLikeFilePath = (
11
- // Relative paths
12
- template.startsWith("./") || template.startsWith("../") || // Absolute paths (Unix)
13
- template.startsWith("/") || // Windows-style paths (C:\, D:\, etc.)
14
- /^[A-Za-z]:\\/.test(template) || // File extensions (must not contain spaces to avoid false positives)
15
- /\.(tsx?|jsx?|mdx?)$/i.test(template) && !template.includes(" ")
16
- );
17
- if (looksLikeFilePath && template.length < 500 && !template.includes("\n") && !template.includes("<")) {
18
- return "file-path";
19
- }
20
- }
21
- return "inline-string";
22
- }
23
- function detectFormatFromPath(pathOrUrl) {
24
- const lower = pathOrUrl.toLowerCase();
25
- if (lower.endsWith(".tsx") || lower.endsWith(".jsx")) {
26
- return "react";
27
- }
28
- if (lower.endsWith(".mdx")) {
29
- return "mdx";
30
- }
31
- if (lower.endsWith(".md")) {
32
- return "markdown";
33
- }
34
- return "html";
35
- }
36
-
37
- // libs/uipack/src/dependency/schemas.ts
38
- import { z } from "zod";
39
- var cdnProviderSchema = z.enum(["cloudflare", "jsdelivr", "unpkg", "esm.sh", "skypack"]);
40
- var cdnPlatformTypeSchema = z.enum(["claude", "openai", "cursor", "gemini", "continue", "cody", "unknown"]);
41
- var cdnDependencySchema = z.object({
42
- /**
43
- * CDN URL (must be HTTPS).
44
- */
45
- url: z.string().url().refine((url) => url.startsWith("https://"), {
46
- message: "CDN URLs must use HTTPS"
47
- }),
48
- /**
49
- * SRI integrity hash.
50
- */
51
- integrity: z.string().regex(/^sha(256|384|512)-[A-Za-z0-9+/=]+$/, {
52
- message: "Invalid SRI hash format. Must be sha256-, sha384-, or sha512- followed by base64"
53
- }).optional(),
54
- /**
55
- * Global variable name for UMD builds.
56
- */
57
- global: z.string().min(1).optional(),
58
- /**
59
- * Named exports from the library.
60
- */
61
- exports: z.array(z.string().min(1)).optional(),
62
- /**
63
- * Whether this is an ES module.
64
- */
65
- esm: z.boolean().optional(),
66
- /**
67
- * Cross-origin attribute.
68
- */
69
- crossorigin: z.enum(["anonymous", "use-credentials"]).optional(),
70
- /**
71
- * Peer dependencies (npm package names).
72
- */
73
- peerDependencies: z.array(z.string().min(1)).optional()
74
- }).strict();
75
- var bundleTargetSchema = z.enum(["es2018", "es2019", "es2020", "es2021", "es2022", "esnext"]);
76
- var fileBundleOptionsSchema = z.object({
77
- /**
78
- * Minify output.
79
- */
80
- minify: z.boolean().optional(),
81
- /**
82
- * Generate source maps.
83
- */
84
- sourceMaps: z.boolean().optional(),
85
- /**
86
- * Target JavaScript version.
87
- */
88
- target: bundleTargetSchema.optional(),
89
- /**
90
- * Enable tree shaking.
91
- */
92
- treeShake: z.boolean().optional(),
93
- /**
94
- * JSX factory function.
95
- */
96
- jsxFactory: z.string().min(1).optional(),
97
- /**
98
- * JSX fragment factory.
99
- */
100
- jsxFragment: z.string().min(1).optional(),
101
- /**
102
- * JSX import source.
103
- */
104
- jsxImportSource: z.string().min(1).optional()
105
- }).strict();
106
- var fileTemplateConfigSchema = z.object({
107
- /**
108
- * Packages to load from CDN.
109
- */
110
- externals: z.array(z.string().min(1)).optional(),
111
- /**
112
- * Explicit CDN dependency overrides.
113
- */
114
- dependencies: z.record(z.string().min(1), cdnDependencySchema).optional(),
115
- /**
116
- * Bundle options.
117
- */
118
- bundleOptions: fileBundleOptionsSchema.optional()
119
- }).strict();
120
- var importMapSchema = z.object({
121
- /**
122
- * Module specifier to URL mappings.
123
- */
124
- imports: z.record(
125
- z.string().min(1),
126
- z.string().url().refine((url) => url.startsWith("https://"), {
127
- message: "Import map URLs must use HTTPS"
128
- })
129
- ),
130
- /**
131
- * Scoped mappings.
132
- */
133
- scopes: z.record(
134
- z.string().min(1),
135
- z.record(
136
- z.string().min(1),
137
- z.string().url().refine((url) => url.startsWith("https://"), {
138
- message: "Scoped import URLs must use HTTPS"
139
- })
140
- )
141
- ).optional(),
142
- /**
143
- * Integrity hashes.
144
- */
145
- integrity: z.record(z.string().url(), z.string().regex(/^sha(256|384|512)-[A-Za-z0-9+/=]+$/)).optional()
146
- }).strict();
147
- var resolvedDependencySchema = z.object({
148
- packageName: z.string().min(1),
149
- version: z.string().min(1),
150
- cdnUrl: z.string().url(),
151
- integrity: z.string().optional(),
152
- global: z.string().optional(),
153
- esm: z.boolean(),
154
- provider: cdnProviderSchema
155
- }).strict();
156
- var buildManifestMetadataSchema = z.object({
157
- createdAt: z.string().datetime(),
158
- buildTimeMs: z.number().nonnegative(),
159
- totalSize: z.number().nonnegative(),
160
- bundlerVersion: z.string().optional()
161
- }).strict();
162
- var buildManifestOutputsSchema = z.object({
163
- code: z.string(),
164
- sourceMap: z.string().optional(),
165
- ssrHtml: z.string().optional()
166
- }).strict();
167
- var componentBuildManifestSchema = z.object({
168
- version: z.literal("1.0"),
169
- buildId: z.string().uuid(),
170
- toolName: z.string().min(1),
171
- entryPath: z.string().min(1),
172
- contentHash: z.string().regex(/^[a-f0-9]{64}$/, {
173
- message: "Content hash must be a 64-character SHA-256 hex string"
174
- }),
175
- dependencies: z.array(resolvedDependencySchema),
176
- outputs: buildManifestOutputsSchema,
177
- importMap: importMapSchema,
178
- metadata: buildManifestMetadataSchema
179
- }).strict();
180
- var cdnProviderConfigSchema = z.record(cdnProviderSchema, cdnDependencySchema);
181
- var packageMetadataSchema = z.object({
182
- description: z.string().optional(),
183
- homepage: z.string().url().optional(),
184
- license: z.string().optional()
185
- }).strict();
186
- var cdnRegistryEntrySchema = z.object({
187
- packageName: z.string().min(1),
188
- defaultVersion: z.string().min(1),
189
- providers: cdnProviderConfigSchema,
190
- preferredProviders: z.array(cdnProviderSchema).optional(),
191
- metadata: packageMetadataSchema.optional()
192
- }).strict();
193
- var dependencyResolverOptionsSchema = z.object({
194
- platform: cdnPlatformTypeSchema.optional(),
195
- preferredProviders: z.array(cdnProviderSchema).optional(),
196
- customRegistry: z.record(z.string().min(1), cdnRegistryEntrySchema).optional(),
197
- strictMode: z.boolean().optional(),
198
- requireIntegrity: z.boolean().optional()
199
- }).strict();
200
- var importTypeSchema = z.enum(["named", "default", "namespace", "side-effect", "dynamic"]);
201
- var parsedImportSchema = z.object({
202
- statement: z.string(),
203
- specifier: z.string().min(1),
204
- type: importTypeSchema,
205
- namedImports: z.array(z.string().min(1)).optional(),
206
- defaultImport: z.string().min(1).optional(),
207
- namespaceImport: z.string().min(1).optional(),
208
- line: z.number().int().positive(),
209
- column: z.number().int().nonnegative()
210
- }).strict();
211
- var parsedImportResultSchema = z.object({
212
- imports: z.array(parsedImportSchema),
213
- externalImports: z.array(parsedImportSchema),
214
- relativeImports: z.array(parsedImportSchema),
215
- externalPackages: z.array(z.string().min(1))
216
- }).strict();
217
- var cacheStatsSchema = z.object({
218
- entries: z.number().int().nonnegative(),
219
- totalSize: z.number().nonnegative(),
220
- hits: z.number().int().nonnegative(),
221
- misses: z.number().int().nonnegative(),
222
- hitRate: z.number().min(0).max(1)
223
- }).strict();
224
- function validateCDNDependency(data) {
225
- return cdnDependencySchema.parse(data);
226
- }
227
- function safeParseCDNDependency(data) {
228
- return cdnDependencySchema.safeParse(data);
229
- }
230
- function validateFileTemplateConfig(data) {
231
- return fileTemplateConfigSchema.parse(data);
232
- }
233
- function safeParseFileTemplateConfig(data) {
234
- return fileTemplateConfigSchema.safeParse(data);
235
- }
236
- function validateBuildManifest(data) {
237
- return componentBuildManifestSchema.parse(data);
238
- }
239
- function safeParseBuildManifest(data) {
240
- return componentBuildManifestSchema.safeParse(data);
241
- }
242
-
243
- // libs/uipack/src/dependency/cdn-registry.ts
244
- var DEFAULT_CDN_REGISTRY = {
245
- // ============================================
246
- // React Ecosystem
247
- // ============================================
248
- react: {
249
- packageName: "react",
250
- defaultVersion: "18.3.1",
251
- providers: {
252
- cloudflare: {
253
- url: "https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js",
254
- integrity: "sha512-Qp8J4Xr8LBZ5CXNJQc/HmLqFrpXz6lNkbzMYkYHKzQx5p1q1yOqPQHntXKoYgPPE/n9m0QF1OkJdXa2ePpO4fw==",
255
- global: "React",
256
- crossorigin: "anonymous"
257
- },
258
- jsdelivr: {
259
- url: "https://cdn.jsdelivr.net/npm/react@18.3.1/umd/react.production.min.js",
260
- global: "React",
261
- crossorigin: "anonymous"
262
- },
263
- unpkg: {
264
- url: "https://unpkg.com/react@18.3.1/umd/react.production.min.js",
265
- global: "React",
266
- crossorigin: "anonymous"
267
- },
268
- "esm.sh": {
269
- url: "https://esm.sh/react@18.3.1",
270
- esm: true,
271
- crossorigin: "anonymous"
272
- }
273
- },
274
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"],
275
- metadata: {
276
- description: "A JavaScript library for building user interfaces",
277
- homepage: "https://react.dev",
278
- license: "MIT"
279
- }
280
- },
281
- "react-dom": {
282
- packageName: "react-dom",
283
- defaultVersion: "18.3.1",
284
- providers: {
285
- cloudflare: {
286
- url: "https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js",
287
- integrity: "sha512-6s2gVRdS3aT+FDdZTRJSzKlzIPqDXWyYl/5hPQb6hSgzKPGFcQyZhbqjbWVxGrs2dYNrINFXb0k0UD3d+CKPJA==",
288
- global: "ReactDOM",
289
- crossorigin: "anonymous",
290
- peerDependencies: ["react"]
291
- },
292
- jsdelivr: {
293
- url: "https://cdn.jsdelivr.net/npm/react-dom@18.3.1/umd/react-dom.production.min.js",
294
- global: "ReactDOM",
295
- crossorigin: "anonymous",
296
- peerDependencies: ["react"]
297
- },
298
- unpkg: {
299
- url: "https://unpkg.com/react-dom@18.3.1/umd/react-dom.production.min.js",
300
- global: "ReactDOM",
301
- crossorigin: "anonymous",
302
- peerDependencies: ["react"]
303
- },
304
- "esm.sh": {
305
- url: "https://esm.sh/react-dom@18.3.1",
306
- esm: true,
307
- crossorigin: "anonymous",
308
- peerDependencies: ["react"]
309
- }
310
- },
311
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"],
312
- metadata: {
313
- description: "React package for working with the DOM",
314
- homepage: "https://react.dev",
315
- license: "MIT"
316
- }
317
- },
318
- // ============================================
319
- // Charting Libraries
320
- // ============================================
321
- "chart.js": {
322
- packageName: "chart.js",
323
- defaultVersion: "4.4.7",
324
- providers: {
325
- cloudflare: {
326
- url: "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.7/chart.umd.min.js",
327
- integrity: "sha512-dMDjIoZjJD6gs0KPBhFYjLQrH3kIohSEn6HzWs6Y6GiO0+L9kk/bM3cR5KNEDK1KvMNpTIZG6pHK9SZfCJHRpQ==",
328
- global: "Chart",
329
- crossorigin: "anonymous"
330
- },
331
- jsdelivr: {
332
- url: "https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js",
333
- global: "Chart",
334
- crossorigin: "anonymous"
335
- },
336
- unpkg: {
337
- url: "https://unpkg.com/chart.js@4.4.7/dist/chart.umd.min.js",
338
- global: "Chart",
339
- crossorigin: "anonymous"
340
- }
341
- },
342
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
343
- metadata: {
344
- description: "Simple yet flexible JavaScript charting library",
345
- homepage: "https://www.chartjs.org",
346
- license: "MIT"
347
- }
348
- },
349
- "react-chartjs-2": {
350
- packageName: "react-chartjs-2",
351
- defaultVersion: "5.3.0",
352
- providers: {
353
- cloudflare: {
354
- url: "https://cdnjs.cloudflare.com/ajax/libs/react-chartjs-2/5.3.0/react-chartjs-2.min.js",
355
- global: "ReactChartjs2",
356
- crossorigin: "anonymous",
357
- peerDependencies: ["react", "chart.js"]
358
- },
359
- jsdelivr: {
360
- url: "https://cdn.jsdelivr.net/npm/react-chartjs-2@5.3.0/dist/index.umd.js",
361
- global: "ReactChartjs2",
362
- crossorigin: "anonymous",
363
- peerDependencies: ["react", "chart.js"]
364
- },
365
- "esm.sh": {
366
- url: "https://esm.sh/react-chartjs-2@5.3.0",
367
- esm: true,
368
- crossorigin: "anonymous",
369
- peerDependencies: ["react", "chart.js"]
370
- }
371
- },
372
- preferredProviders: ["cloudflare", "jsdelivr", "esm.sh"],
373
- metadata: {
374
- description: "React components for Chart.js",
375
- homepage: "https://react-chartjs-2.js.org",
376
- license: "MIT"
377
- }
378
- },
379
- // ============================================
380
- // D3.js
381
- // ============================================
382
- d3: {
383
- packageName: "d3",
384
- defaultVersion: "7.9.0",
385
- providers: {
386
- cloudflare: {
387
- url: "https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js",
388
- integrity: "sha512-vc58qvvBdrDR4etbxMdlTt4GBQk1qjvyORR2nrsPsFPyrs+/u5c3+1Ct6upOgdZoIl7eq6k3a1UPDSNAQi/32A==",
389
- global: "d3",
390
- crossorigin: "anonymous"
391
- },
392
- jsdelivr: {
393
- url: "https://cdn.jsdelivr.net/npm/d3@7.9.0/dist/d3.min.js",
394
- global: "d3",
395
- crossorigin: "anonymous"
396
- },
397
- unpkg: {
398
- url: "https://unpkg.com/d3@7.9.0/dist/d3.min.js",
399
- global: "d3",
400
- crossorigin: "anonymous"
401
- }
402
- },
403
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
404
- metadata: {
405
- description: "Data-Driven Documents",
406
- homepage: "https://d3js.org",
407
- license: "ISC"
408
- }
409
- },
410
- // ============================================
411
- // Utility Libraries
412
- // ============================================
413
- lodash: {
414
- packageName: "lodash",
415
- defaultVersion: "4.17.21",
416
- providers: {
417
- cloudflare: {
418
- url: "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js",
419
- integrity: "sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==",
420
- global: "_",
421
- crossorigin: "anonymous"
422
- },
423
- jsdelivr: {
424
- url: "https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js",
425
- global: "_",
426
- crossorigin: "anonymous"
427
- },
428
- unpkg: {
429
- url: "https://unpkg.com/lodash@4.17.21/lodash.min.js",
430
- global: "_",
431
- crossorigin: "anonymous"
432
- }
433
- },
434
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
435
- metadata: {
436
- description: "A modern JavaScript utility library",
437
- homepage: "https://lodash.com",
438
- license: "MIT"
439
- }
440
- },
441
- "lodash-es": {
442
- packageName: "lodash-es",
443
- defaultVersion: "4.17.21",
444
- providers: {
445
- "esm.sh": {
446
- url: "https://esm.sh/lodash-es@4.17.21",
447
- esm: true,
448
- crossorigin: "anonymous"
449
- },
450
- jsdelivr: {
451
- url: "https://cdn.jsdelivr.net/npm/lodash-es@4.17.21/+esm",
452
- esm: true,
453
- crossorigin: "anonymous"
454
- }
455
- },
456
- preferredProviders: ["esm.sh", "jsdelivr"],
457
- metadata: {
458
- description: "Lodash exported as ES modules",
459
- homepage: "https://lodash.com",
460
- license: "MIT"
461
- }
462
- },
463
- dayjs: {
464
- packageName: "dayjs",
465
- defaultVersion: "1.11.13",
466
- providers: {
467
- cloudflare: {
468
- url: "https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.13/dayjs.min.js",
469
- integrity: "sha512-Ot7ArUEhJDU0cwoBNNnWe487kjL5wAOsIYig8llY/l0P2TUFwgsAHVmrZMHsT8NGo+HwkjTJsNErS6QqIkBxDw==",
470
- global: "dayjs",
471
- crossorigin: "anonymous"
472
- },
473
- jsdelivr: {
474
- url: "https://cdn.jsdelivr.net/npm/dayjs@1.11.13/dayjs.min.js",
475
- global: "dayjs",
476
- crossorigin: "anonymous"
477
- },
478
- unpkg: {
479
- url: "https://unpkg.com/dayjs@1.11.13/dayjs.min.js",
480
- global: "dayjs",
481
- crossorigin: "anonymous"
482
- }
483
- },
484
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
485
- metadata: {
486
- description: "Fast 2kB alternative to Moment.js with the same modern API",
487
- homepage: "https://day.js.org",
488
- license: "MIT"
489
- }
490
- },
491
- "date-fns": {
492
- packageName: "date-fns",
493
- defaultVersion: "4.1.0",
494
- providers: {
495
- "esm.sh": {
496
- url: "https://esm.sh/date-fns@4.1.0",
497
- esm: true,
498
- crossorigin: "anonymous"
499
- },
500
- jsdelivr: {
501
- url: "https://cdn.jsdelivr.net/npm/date-fns@4.1.0/+esm",
502
- esm: true,
503
- crossorigin: "anonymous"
504
- }
505
- },
506
- preferredProviders: ["esm.sh", "jsdelivr"],
507
- metadata: {
508
- description: "Modern JavaScript date utility library",
509
- homepage: "https://date-fns.org",
510
- license: "MIT"
511
- }
512
- },
513
- // ============================================
514
- // Animation Libraries
515
- // ============================================
516
- "framer-motion": {
517
- packageName: "framer-motion",
518
- defaultVersion: "11.15.0",
519
- providers: {
520
- "esm.sh": {
521
- url: "https://esm.sh/framer-motion@11.15.0",
522
- esm: true,
523
- crossorigin: "anonymous",
524
- peerDependencies: ["react", "react-dom"]
525
- },
526
- jsdelivr: {
527
- url: "https://cdn.jsdelivr.net/npm/framer-motion@11.15.0/dist/framer-motion.js",
528
- global: "Motion",
529
- crossorigin: "anonymous",
530
- peerDependencies: ["react", "react-dom"]
531
- }
532
- },
533
- preferredProviders: ["esm.sh", "jsdelivr"],
534
- metadata: {
535
- description: "Production-ready motion library for React",
536
- homepage: "https://www.framer.com/motion/",
537
- license: "MIT"
538
- }
539
- },
540
- // ============================================
541
- // UI Component Libraries
542
- // ============================================
543
- "lucide-react": {
544
- packageName: "lucide-react",
545
- defaultVersion: "0.468.0",
546
- providers: {
547
- "esm.sh": {
548
- url: "https://esm.sh/lucide-react@0.468.0",
549
- esm: true,
550
- crossorigin: "anonymous",
551
- peerDependencies: ["react"]
552
- },
553
- jsdelivr: {
554
- url: "https://cdn.jsdelivr.net/npm/lucide-react@0.468.0/dist/esm/lucide-react.js",
555
- esm: true,
556
- crossorigin: "anonymous",
557
- peerDependencies: ["react"]
558
- }
559
- },
560
- preferredProviders: ["esm.sh", "jsdelivr"],
561
- metadata: {
562
- description: "Beautiful & consistent icon toolkit for React",
563
- homepage: "https://lucide.dev",
564
- license: "ISC"
565
- }
566
- },
567
- // ============================================
568
- // Markdown/Syntax Highlighting
569
- // ============================================
570
- marked: {
571
- packageName: "marked",
572
- defaultVersion: "15.0.4",
573
- providers: {
574
- cloudflare: {
575
- url: "https://cdnjs.cloudflare.com/ajax/libs/marked/15.0.4/marked.min.js",
576
- integrity: "sha512-Rn/d0sGeizGbk3VJEiYNDt/mMcfuzYoFkia3iBffv+HX8VUrHMo/0cKjZuxWGoZLPh/VxUcC9ais+RBFZW9EBg==",
577
- global: "marked",
578
- crossorigin: "anonymous"
579
- },
580
- jsdelivr: {
581
- url: "https://cdn.jsdelivr.net/npm/marked@15.0.4/marked.min.js",
582
- global: "marked",
583
- crossorigin: "anonymous"
584
- },
585
- unpkg: {
586
- url: "https://unpkg.com/marked@15.0.4/marked.min.js",
587
- global: "marked",
588
- crossorigin: "anonymous"
589
- }
590
- },
591
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
592
- metadata: {
593
- description: "A markdown parser and compiler",
594
- homepage: "https://marked.js.org",
595
- license: "MIT"
596
- }
597
- },
598
- "highlight.js": {
599
- packageName: "highlight.js",
600
- defaultVersion: "11.10.0",
601
- providers: {
602
- cloudflare: {
603
- url: "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.10.0/highlight.min.js",
604
- integrity: "sha512-6yoqbrcLAHDWAdQmiRlHG4+m0g/CT/V9AGyxabG8j7Jk8j3v3k6mIP1iN/PvSofcWet2tf8SRn/j3L/+pb7LRQ==",
605
- global: "hljs",
606
- crossorigin: "anonymous"
607
- },
608
- jsdelivr: {
609
- url: "https://cdn.jsdelivr.net/npm/highlight.js@11.10.0/lib/core.min.js",
610
- global: "hljs",
611
- crossorigin: "anonymous"
612
- },
613
- unpkg: {
614
- url: "https://unpkg.com/highlight.js@11.10.0/lib/core.min.js",
615
- global: "hljs",
616
- crossorigin: "anonymous"
617
- }
618
- },
619
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
620
- metadata: {
621
- description: "Syntax highlighting for the web",
622
- homepage: "https://highlightjs.org",
623
- license: "BSD-3-Clause"
624
- }
625
- },
626
- // ============================================
627
- // Interactive Libraries
628
- // ============================================
629
- "htmx.org": {
630
- packageName: "htmx.org",
631
- defaultVersion: "2.0.4",
632
- providers: {
633
- cloudflare: {
634
- url: "https://cdnjs.cloudflare.com/ajax/libs/htmx/2.0.4/htmx.min.js",
635
- integrity: "sha512-2kIcAizYXhIn5IyXrMC72f2nh0JAtESHRpOieVw5dYPYeHwLCC2eKCqvdZDYRSEgasKrPpEPpRFjL8gqwBZWAA==",
636
- global: "htmx",
637
- crossorigin: "anonymous"
638
- },
639
- jsdelivr: {
640
- url: "https://cdn.jsdelivr.net/npm/htmx.org@2.0.4/dist/htmx.min.js",
641
- global: "htmx",
642
- crossorigin: "anonymous"
643
- },
644
- unpkg: {
645
- url: "https://unpkg.com/htmx.org@2.0.4/dist/htmx.min.js",
646
- global: "htmx",
647
- crossorigin: "anonymous"
648
- }
649
- },
650
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
651
- metadata: {
652
- description: "High power tools for HTML",
653
- homepage: "https://htmx.org",
654
- license: "BSD-2-Clause"
655
- }
656
- },
657
- alpinejs: {
658
- packageName: "alpinejs",
659
- defaultVersion: "3.14.3",
660
- providers: {
661
- cloudflare: {
662
- url: "https://cdnjs.cloudflare.com/ajax/libs/alpinejs/3.14.3/cdn.min.js",
663
- integrity: "sha512-lrQ8FHgsWKFSuQFq8NKPJicjlvJFEIrCqEj8zeX7ZOUlHWltN/Iow4jND+x84jqTdDf9n+hvQpJjGDvOl/eDRA==",
664
- global: "Alpine",
665
- crossorigin: "anonymous"
666
- },
667
- jsdelivr: {
668
- url: "https://cdn.jsdelivr.net/npm/alpinejs@3.14.3/dist/cdn.min.js",
669
- global: "Alpine",
670
- crossorigin: "anonymous"
671
- },
672
- unpkg: {
673
- url: "https://unpkg.com/alpinejs@3.14.3/dist/cdn.min.js",
674
- global: "Alpine",
675
- crossorigin: "anonymous"
676
- }
677
- },
678
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
679
- metadata: {
680
- description: "A rugged, minimal framework for composing behavior directly in your markup",
681
- homepage: "https://alpinejs.dev",
682
- license: "MIT"
683
- }
684
- },
685
- // ============================================
686
- // Templating Libraries
687
- // ============================================
688
- handlebars: {
689
- packageName: "handlebars",
690
- defaultVersion: "4.7.8",
691
- providers: {
692
- cloudflare: {
693
- url: "https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.7.8/handlebars.min.js",
694
- integrity: "sha512-E1dSFxg+wsfJ4HKjutk/WaCzK7S2wv1POn1RRPGh8ZK+ag9l244Vqxji3r6wgz9YBf6+vhQEYJZpSjqWFPg9gg==",
695
- global: "Handlebars",
696
- crossorigin: "anonymous"
697
- },
698
- jsdelivr: {
699
- url: "https://cdn.jsdelivr.net/npm/handlebars@4.7.8/dist/handlebars.min.js",
700
- global: "Handlebars",
701
- crossorigin: "anonymous"
702
- },
703
- unpkg: {
704
- url: "https://unpkg.com/handlebars@4.7.8/dist/handlebars.min.js",
705
- global: "Handlebars",
706
- crossorigin: "anonymous"
707
- }
708
- },
709
- preferredProviders: ["cloudflare", "jsdelivr", "unpkg"],
710
- metadata: {
711
- description: "Minimal templating on steroids",
712
- homepage: "https://handlebarsjs.com",
713
- license: "MIT"
714
- }
715
- }
716
- };
717
- var CDN_PROVIDER_PRIORITY = {
718
- claude: ["cloudflare"],
719
- // ONLY cloudflare for Claude
720
- openai: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"],
721
- cursor: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"],
722
- gemini: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"],
723
- continue: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"],
724
- cody: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"],
725
- unknown: ["cloudflare", "jsdelivr", "unpkg", "esm.sh"]
726
- // Default to cloudflare first
727
- };
728
- function lookupPackage(packageName, registry = DEFAULT_CDN_REGISTRY) {
729
- return registry[packageName];
730
- }
731
- function getPackageCDNUrl(packageName, platform = "unknown", registry = DEFAULT_CDN_REGISTRY) {
732
- const entry = lookupPackage(packageName, registry);
733
- if (!entry) return void 0;
734
- const providerPriority = CDN_PROVIDER_PRIORITY[platform];
735
- for (const provider of providerPriority) {
736
- const config = entry.providers[provider];
737
- if (config?.url) {
738
- return config.url;
739
- }
740
- }
741
- for (const provider of Object.keys(entry.providers)) {
742
- const config = entry.providers[provider];
743
- if (config?.url) {
744
- return config.url;
745
- }
746
- }
747
- return void 0;
748
- }
749
- function getPackageCDNDependency(packageName, platform = "unknown", registry = DEFAULT_CDN_REGISTRY) {
750
- const entry = lookupPackage(packageName, registry);
751
- if (!entry) return void 0;
752
- const providerPriority = CDN_PROVIDER_PRIORITY[platform];
753
- for (const provider of providerPriority) {
754
- const config = entry.providers[provider];
755
- if (config?.url) {
756
- return { provider, dependency: config };
757
- }
758
- }
759
- for (const provider of Object.keys(entry.providers)) {
760
- const config = entry.providers[provider];
761
- if (config?.url) {
762
- return { provider, dependency: config };
763
- }
764
- }
765
- return void 0;
766
- }
767
- function getRegisteredPackages(registry = DEFAULT_CDN_REGISTRY) {
768
- return Object.keys(registry);
769
- }
770
- function isPackageRegistered(packageName, registry = DEFAULT_CDN_REGISTRY) {
771
- return packageName in registry;
772
- }
773
- function mergeRegistries(customRegistry) {
774
- return {
775
- ...DEFAULT_CDN_REGISTRY,
776
- ...customRegistry
777
- };
778
- }
779
- function getPackagePeerDependencies(packageName, registry = DEFAULT_CDN_REGISTRY) {
780
- const entry = lookupPackage(packageName, registry);
781
- if (!entry) return [];
782
- for (const provider of Object.keys(entry.providers)) {
783
- const config = entry.providers[provider];
784
- if (config?.peerDependencies) {
785
- return config.peerDependencies;
786
- }
787
- }
788
- return [];
789
- }
790
- function resolveAllDependencies(packageNames, _platform = "unknown", registry = DEFAULT_CDN_REGISTRY) {
791
- const resolved = /* @__PURE__ */ new Set();
792
- const queue = [...packageNames];
793
- while (queue.length > 0) {
794
- const packageName = queue.shift();
795
- if (!packageName) continue;
796
- if (resolved.has(packageName)) continue;
797
- resolved.add(packageName);
798
- const peers = getPackagePeerDependencies(packageName, registry);
799
- for (const peer of peers) {
800
- if (!resolved.has(peer)) {
801
- queue.push(peer);
802
- }
803
- }
804
- }
805
- const result = [];
806
- const remaining = new Set(resolved);
807
- while (remaining.size > 0) {
808
- let added = false;
809
- for (const pkg of remaining) {
810
- const peers = getPackagePeerDependencies(pkg, registry);
811
- const allPeersResolved = peers.every((peer) => !remaining.has(peer) || result.includes(peer));
812
- if (allPeersResolved) {
813
- if (!result.includes(pkg)) {
814
- result.push(pkg);
815
- }
816
- remaining.delete(pkg);
817
- added = true;
818
- }
819
- }
820
- if (!added && remaining.size > 0) {
821
- const next = remaining.values().next().value;
822
- if (next !== void 0) {
823
- if (!result.includes(next)) {
824
- result.push(next);
825
- }
826
- remaining.delete(next);
827
- }
828
- }
829
- }
830
- return result;
831
- }
832
-
833
- // libs/uipack/src/dependency/import-parser.ts
834
- var IMPORT_PATTERNS = {
835
- /**
836
- * Named imports: import { foo, bar } from 'module'
837
- * Also handles renamed imports: import { foo as f } from 'module'
838
- */
839
- named: /import\s*\{([^}]+)\}\s*from\s*['"]([^'"]+)['"]/g,
840
- /**
841
- * Default imports: import foo from 'module'
842
- */
843
- default: /import\s+(\w+)\s+from\s*['"]([^'"]+)['"]/g,
844
- /**
845
- * Namespace imports: import * as foo from 'module'
846
- */
847
- namespace: /import\s*\*\s*as\s+(\w+)\s+from\s*['"]([^'"]+)['"]/g,
848
- /**
849
- * Side-effect imports: import 'module'
850
- */
851
- sideEffect: /import\s*['"]([^'"]+)['"]/g,
852
- /**
853
- * Dynamic imports: import('module') or await import('module')
854
- */
855
- dynamic: /(?:await\s+)?import\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
856
- /**
857
- * Combined default and named: import foo, { bar } from 'module'
858
- */
859
- defaultAndNamed: /import\s+(\w+)\s*,\s*\{([^}]+)\}\s*from\s*['"]([^'"]+)['"]/g,
860
- /**
861
- * Combined default and namespace: import foo, * as bar from 'module'
862
- */
863
- defaultAndNamespace: /import\s+(\w+)\s*,\s*\*\s*as\s+(\w+)\s+from\s*['"]([^'"]+)['"]/g,
864
- /**
865
- * Re-exports: export { foo } from 'module'
866
- */
867
- reExport: /export\s*\{[^}]+\}\s*from\s*['"]([^'"]+)['"]/g,
868
- /**
869
- * Re-export all: export * from 'module'
870
- */
871
- reExportAll: /export\s*\*\s*from\s*['"]([^'"]+)['"]/g
872
- };
873
- function parseNamedImports(namedString) {
874
- return namedString.split(",").map((s) => s.trim()).filter((s) => s.length > 0).map((s) => {
875
- const asMatch = s.match(/^(\w+)\s+as\s+\w+$/);
876
- return asMatch ? asMatch[1] : s;
877
- });
878
- }
879
- function isRelativeImport(specifier) {
880
- return specifier.startsWith("./") || specifier.startsWith("../") || specifier.startsWith("/");
881
- }
882
- function isExternalImport(specifier) {
883
- return !isRelativeImport(specifier) && !specifier.startsWith("#");
884
- }
885
- function getPackageName(specifier) {
886
- if (specifier.startsWith("@")) {
887
- const parts = specifier.split("/");
888
- if (parts.length >= 2) {
889
- return `${parts[0]}/${parts[1]}`;
890
- }
891
- return specifier;
892
- }
893
- const firstSlash = specifier.indexOf("/");
894
- return firstSlash === -1 ? specifier : specifier.slice(0, firstSlash);
895
- }
896
- function getLineNumber(source, index) {
897
- let line = 1;
898
- for (let i = 0; i < index && i < source.length; i++) {
899
- if (source[i] === "\n") {
900
- line++;
901
- }
902
- }
903
- return line;
904
- }
905
- function getColumnNumber(source, index) {
906
- let column = 0;
907
- for (let i = index - 1; i >= 0 && source[i] !== "\n"; i--) {
908
- column++;
909
- }
910
- return column;
911
- }
912
- function parseImports(source) {
913
- const imports = [];
914
- const seenStatements = /* @__PURE__ */ new Set();
915
- const addImport = (imp) => {
916
- const key = `${imp.type}:${imp.specifier}:${imp.statement}`;
917
- if (!seenStatements.has(key)) {
918
- seenStatements.add(key);
919
- imports.push(imp);
920
- }
921
- };
922
- let match;
923
- const defaultAndNamedRegex = new RegExp(IMPORT_PATTERNS.defaultAndNamed.source, "g");
924
- while ((match = defaultAndNamedRegex.exec(source)) !== null) {
925
- const [statement, defaultName, namedString, specifier] = match;
926
- const namedImports = parseNamedImports(namedString);
927
- addImport({
928
- statement,
929
- specifier,
930
- type: "default",
931
- defaultImport: defaultName,
932
- namedImports,
933
- line: getLineNumber(source, match.index),
934
- column: getColumnNumber(source, match.index)
935
- });
936
- }
937
- const defaultAndNamespaceRegex = new RegExp(IMPORT_PATTERNS.defaultAndNamespace.source, "g");
938
- while ((match = defaultAndNamespaceRegex.exec(source)) !== null) {
939
- const [statement, defaultName, namespaceName, specifier] = match;
940
- addImport({
941
- statement,
942
- specifier,
943
- type: "default",
944
- defaultImport: defaultName,
945
- namespaceImport: namespaceName,
946
- line: getLineNumber(source, match.index),
947
- column: getColumnNumber(source, match.index)
948
- });
949
- }
950
- const namedRegex = new RegExp(IMPORT_PATTERNS.named.source, "g");
951
- while ((match = namedRegex.exec(source)) !== null) {
952
- const [statement, namedString, specifier] = match;
953
- const namedImports = parseNamedImports(namedString);
954
- addImport({
955
- statement,
956
- specifier,
957
- type: "named",
958
- namedImports,
959
- line: getLineNumber(source, match.index),
960
- column: getColumnNumber(source, match.index)
961
- });
962
- }
963
- const defaultRegex = new RegExp(IMPORT_PATTERNS.default.source, "g");
964
- while ((match = defaultRegex.exec(source)) !== null) {
965
- const [statement, defaultName, specifier] = match;
966
- const afterMatch = source.slice(match.index + match[0].length - specifier.length - 2);
967
- if (afterMatch.startsWith(",")) continue;
968
- addImport({
969
- statement,
970
- specifier,
971
- type: "default",
972
- defaultImport: defaultName,
973
- line: getLineNumber(source, match.index),
974
- column: getColumnNumber(source, match.index)
975
- });
976
- }
977
- const namespaceRegex = new RegExp(IMPORT_PATTERNS.namespace.source, "g");
978
- while ((match = namespaceRegex.exec(source)) !== null) {
979
- const [statement, namespaceName, specifier] = match;
980
- addImport({
981
- statement,
982
- specifier,
983
- type: "namespace",
984
- namespaceImport: namespaceName,
985
- line: getLineNumber(source, match.index),
986
- column: getColumnNumber(source, match.index)
987
- });
988
- }
989
- const sideEffectRegex = new RegExp(IMPORT_PATTERNS.sideEffect.source, "g");
990
- while ((match = sideEffectRegex.exec(source)) !== null) {
991
- const [statement, specifier] = match;
992
- const beforeMatch = source.slice(Math.max(0, match.index - 50), match.index);
993
- if (beforeMatch.includes("from")) continue;
994
- addImport({
995
- statement,
996
- specifier,
997
- type: "side-effect",
998
- line: getLineNumber(source, match.index),
999
- column: getColumnNumber(source, match.index)
1000
- });
1001
- }
1002
- const dynamicRegex = new RegExp(IMPORT_PATTERNS.dynamic.source, "g");
1003
- while ((match = dynamicRegex.exec(source)) !== null) {
1004
- const [statement, specifier] = match;
1005
- addImport({
1006
- statement,
1007
- specifier,
1008
- type: "dynamic",
1009
- line: getLineNumber(source, match.index),
1010
- column: getColumnNumber(source, match.index)
1011
- });
1012
- }
1013
- const reExportRegex = new RegExp(IMPORT_PATTERNS.reExport.source, "g");
1014
- while ((match = reExportRegex.exec(source)) !== null) {
1015
- const [statement, specifier] = match;
1016
- addImport({
1017
- statement,
1018
- specifier,
1019
- type: "named",
1020
- line: getLineNumber(source, match.index),
1021
- column: getColumnNumber(source, match.index)
1022
- });
1023
- }
1024
- const reExportAllRegex = new RegExp(IMPORT_PATTERNS.reExportAll.source, "g");
1025
- while ((match = reExportAllRegex.exec(source)) !== null) {
1026
- const [statement, specifier] = match;
1027
- addImport({
1028
- statement,
1029
- specifier,
1030
- type: "namespace",
1031
- line: getLineNumber(source, match.index),
1032
- column: getColumnNumber(source, match.index)
1033
- });
1034
- }
1035
- const externalImports = imports.filter((imp) => isExternalImport(imp.specifier));
1036
- const relativeImports = imports.filter((imp) => isRelativeImport(imp.specifier));
1037
- const externalPackages = [...new Set(externalImports.map((imp) => getPackageName(imp.specifier)))];
1038
- return {
1039
- imports,
1040
- externalImports,
1041
- relativeImports,
1042
- externalPackages
1043
- };
1044
- }
1045
- function extractExternalPackages(source) {
1046
- const result = parseImports(source);
1047
- return result.externalPackages;
1048
- }
1049
- function filterImportsByPackages(result, packages) {
1050
- const packageSet = new Set(packages);
1051
- return result.externalImports.filter((imp) => {
1052
- const pkgName = getPackageName(imp.specifier);
1053
- return packageSet.has(pkgName);
1054
- });
1055
- }
1056
- function getImportStats(source) {
1057
- const result = parseImports(source);
1058
- const byType = {
1059
- named: 0,
1060
- default: 0,
1061
- namespace: 0,
1062
- "side-effect": 0,
1063
- dynamic: 0
1064
- };
1065
- for (const imp of result.imports) {
1066
- byType[imp.type] = (byType[imp.type] || 0) + 1;
1067
- }
1068
- return {
1069
- total: result.imports.length,
1070
- external: result.externalImports.length,
1071
- relative: result.relativeImports.length,
1072
- byType,
1073
- packages: result.externalPackages
1074
- };
1075
- }
1076
-
1077
- // libs/uipack/src/utils/index.ts
1078
- import {
1079
- safeStringify,
1080
- escapeHtml,
1081
- escapeHtmlAttr,
1082
- escapeJsString,
1083
- escapeScriptClose,
1084
- safeJsonForScript
1085
- } from "@frontmcp/utils";
1086
-
1087
- // libs/uipack/src/dependency/import-map.ts
1088
- function createImportMap(dependencies) {
1089
- const imports = {};
1090
- const integrity = {};
1091
- for (const dep of dependencies) {
1092
- imports[dep.packageName] = dep.cdnUrl;
1093
- if (dep.integrity) {
1094
- integrity[dep.cdnUrl] = dep.integrity;
1095
- }
1096
- }
1097
- return {
1098
- imports,
1099
- integrity: Object.keys(integrity).length > 0 ? integrity : void 0
1100
- };
1101
- }
1102
- function createImportMapFromOverrides(dependencies) {
1103
- const imports = {};
1104
- const integrity = {};
1105
- for (const [pkgName, config] of Object.entries(dependencies)) {
1106
- imports[pkgName] = config.url;
1107
- if (config.integrity) {
1108
- integrity[config.url] = config.integrity;
1109
- }
1110
- }
1111
- return {
1112
- imports,
1113
- integrity: Object.keys(integrity).length > 0 ? integrity : void 0
1114
- };
1115
- }
1116
- function mergeImportMaps(...maps) {
1117
- const imports = {};
1118
- const integrity = {};
1119
- const scopes = {};
1120
- for (const map of maps) {
1121
- Object.assign(imports, map.imports);
1122
- if (map.integrity) {
1123
- Object.assign(integrity, map.integrity);
1124
- }
1125
- if (map.scopes) {
1126
- for (const [scope, mappings] of Object.entries(map.scopes)) {
1127
- scopes[scope] = { ...scopes[scope], ...mappings };
1128
- }
1129
- }
1130
- }
1131
- return {
1132
- imports,
1133
- integrity: Object.keys(integrity).length > 0 ? integrity : void 0,
1134
- scopes: Object.keys(scopes).length > 0 ? scopes : void 0
1135
- };
1136
- }
1137
- function addScope(map, scopeUrl, mappings) {
1138
- return {
1139
- ...map,
1140
- scopes: {
1141
- ...map.scopes,
1142
- [scopeUrl]: { ...map.scopes?.[scopeUrl] ?? {}, ...mappings }
1143
- }
1144
- };
1145
- }
1146
- function generateImportMapScriptTag(map) {
1147
- const json2 = JSON.stringify(map, null, 2).replace(/<\//g, "<\\/");
1148
- return `<script type="importmap">
1149
- ${json2}
1150
- </script>`;
1151
- }
1152
- function generateImportMapScriptTagMinified(map) {
1153
- const json2 = JSON.stringify(map).replace(/<\//g, "<\\/");
1154
- return `<script type="importmap">${json2}</script>`;
1155
- }
1156
- function generateUMDShim(dependencies, options = {}) {
1157
- const { safe = true, minify = false } = options;
1158
- const depsWithGlobals = dependencies.filter((d) => d.global && !d.esm);
1159
- if (depsWithGlobals.length === 0) {
1160
- return "";
1161
- }
1162
- const entries = depsWithGlobals.map((dep) => {
1163
- const global = dep.global;
1164
- return `'${dep.packageName}': { default: window.${global}, ...window.${global} }`;
1165
- });
1166
- const shimObject = `{
1167
- ${entries.join(",\n ")}
1168
- }`;
1169
- const code = safe ? `(function() {
1170
- try {
1171
- window.__esm_shim = ${shimObject};
1172
- } catch (e) {
1173
- console.warn('UMD shim failed:', e);
1174
- }
1175
- })();` : `window.__esm_shim = ${shimObject};`;
1176
- if (minify && code.length <= 1e5) {
1177
- return code.replace(/\s+/g, " ").replace(/\s*([{},:])\s*/g, "$1");
1178
- }
1179
- return code;
1180
- }
1181
- function generateCDNScriptTags(dependencies) {
1182
- return dependencies.filter((dep) => !dep.esm).map((dep) => {
1183
- const attrs = [`src="${escapeHtmlAttr(dep.cdnUrl)}"`];
1184
- if (dep.integrity) {
1185
- attrs.push(`integrity="${escapeHtmlAttr(dep.integrity)}"`);
1186
- }
1187
- attrs.push('crossorigin="anonymous"');
1188
- return `<script ${attrs.join(" ")}></script>`;
1189
- });
1190
- }
1191
- function generateESMScriptTags(dependencies) {
1192
- return dependencies.filter((dep) => dep.esm).map((dep) => {
1193
- const attrs = ['type="module"', `src="${escapeHtmlAttr(dep.cdnUrl)}"`];
1194
- if (dep.integrity) {
1195
- attrs.push(`integrity="${escapeHtmlAttr(dep.integrity)}"`);
1196
- }
1197
- attrs.push('crossorigin="anonymous"');
1198
- return `<script ${attrs.join(" ")}></script>`;
1199
- });
1200
- }
1201
- function generateDependencyHTML(dependencies, options = {}) {
1202
- const { minify = false, includeShim = true } = options;
1203
- const parts = [];
1204
- const importMap = createImportMap(dependencies);
1205
- const importMapTag = minify ? generateImportMapScriptTagMinified(importMap) : generateImportMapScriptTag(importMap);
1206
- parts.push(importMapTag);
1207
- const umdTags = generateCDNScriptTags(dependencies);
1208
- parts.push(...umdTags);
1209
- if (includeShim) {
1210
- const shim = generateUMDShim(dependencies, { minify });
1211
- if (shim) {
1212
- parts.push(`<script>${shim}</script>`);
1213
- }
1214
- }
1215
- const esmTags = generateESMScriptTags(dependencies);
1216
- parts.push(...esmTags);
1217
- return parts.join(minify ? "" : "\n");
1218
- }
1219
- function validateImportMap(map) {
1220
- const errors = [];
1221
- if (typeof map !== "object" || map === null) {
1222
- return { valid: false, errors: ["Import map must be an object"] };
1223
- }
1224
- const obj = map;
1225
- if (!obj["imports"]) {
1226
- errors.push('Import map must have an "imports" field');
1227
- } else if (typeof obj["imports"] !== "object" || obj["imports"] === null) {
1228
- errors.push('"imports" must be an object');
1229
- } else {
1230
- const imports = obj["imports"];
1231
- for (const [key, value] of Object.entries(imports)) {
1232
- if (typeof value !== "string") {
1233
- errors.push(`Import "${key}" must map to a string URL`);
1234
- } else if (!value.startsWith("https://")) {
1235
- errors.push(`Import "${key}" URL must use HTTPS: ${value}`);
1236
- }
1237
- }
1238
- }
1239
- if (obj["integrity"] !== void 0) {
1240
- if (typeof obj["integrity"] !== "object" || obj["integrity"] === null) {
1241
- errors.push('"integrity" must be an object');
1242
- } else {
1243
- const integrity = obj["integrity"];
1244
- for (const [url, hash] of Object.entries(integrity)) {
1245
- if (typeof hash !== "string") {
1246
- errors.push(`Integrity for "${url}" must be a string`);
1247
- } else if (!hash.match(/^sha(256|384|512)-/)) {
1248
- errors.push(`Invalid integrity hash format for "${url}": ${hash}`);
1249
- }
1250
- }
1251
- }
1252
- }
1253
- if (obj["scopes"] !== void 0) {
1254
- if (typeof obj["scopes"] !== "object" || obj["scopes"] === null) {
1255
- errors.push('"scopes" must be an object');
1256
- }
1257
- }
1258
- return { valid: errors.length === 0, errors };
1259
- }
1260
-
1261
- // libs/uipack/src/dependency/resolver.ts
1262
- var DependencyResolutionError = class extends Error {
1263
- constructor(packageName, reason) {
1264
- super(`Failed to resolve dependency "${packageName}": ${reason}`);
1265
- this.packageName = packageName;
1266
- this.reason = reason;
1267
- this.name = "DependencyResolutionError";
1268
- }
1269
- };
1270
- var NoProviderError = class extends DependencyResolutionError {
1271
- constructor(packageName, platform) {
1272
- super(packageName, `No CDN provider available for platform "${platform}"`);
1273
- this.platform = platform;
1274
- this.name = "NoProviderError";
1275
- }
1276
- };
1277
- var DependencyResolver = class {
1278
- options;
1279
- registry;
1280
- constructor(options = {}) {
1281
- this.options = {
1282
- platform: options.platform ?? "unknown",
1283
- preferredProviders: options.preferredProviders ?? CDN_PROVIDER_PRIORITY[options.platform ?? "unknown"],
1284
- customRegistry: options.customRegistry ?? {},
1285
- strictMode: options.strictMode ?? true,
1286
- requireIntegrity: options.requireIntegrity ?? false
1287
- };
1288
- this.registry = mergeRegistries(this.options.customRegistry);
1289
- }
1290
- /**
1291
- * Resolve a single package to its CDN dependency.
1292
- *
1293
- * @param packageName - NPM package name
1294
- * @param override - Optional explicit CDN dependency override
1295
- * @returns Resolved dependency, or null in non-strict mode if package is not found (should be bundled)
1296
- * @throws DependencyResolutionError if package cannot be resolved in strict mode
1297
- */
1298
- resolve(packageName, override) {
1299
- if (override) {
1300
- return this.createResolvedDependency(packageName, override, "custom");
1301
- }
1302
- const entry = lookupPackage(packageName, this.registry);
1303
- if (!entry) {
1304
- if (this.options.strictMode) {
1305
- throw new DependencyResolutionError(
1306
- packageName,
1307
- 'Package not found in CDN registry. Add it to "dependencies" for explicit CDN configuration.'
1308
- );
1309
- }
1310
- return null;
1311
- }
1312
- const providerPriority = this.options.preferredProviders;
1313
- for (const provider of providerPriority) {
1314
- const config = entry.providers[provider];
1315
- if (config?.url) {
1316
- if (this.options.requireIntegrity && !config.integrity) {
1317
- continue;
1318
- }
1319
- return this.createResolvedDependency(packageName, config, provider, entry.defaultVersion);
1320
- }
1321
- }
1322
- throw new NoProviderError(packageName, this.options.platform);
1323
- }
1324
- /**
1325
- * Resolve multiple packages.
1326
- *
1327
- * @param packageNames - Array of package names
1328
- * @param overrides - Optional explicit overrides for specific packages
1329
- * @returns Array of resolved dependencies (in dependency order)
1330
- */
1331
- resolveMany(packageNames, overrides) {
1332
- const allPackages = resolveAllDependencies(packageNames, this.options.platform, this.registry);
1333
- const resolved = [];
1334
- for (const pkgName of allPackages) {
1335
- try {
1336
- const override = overrides?.[pkgName];
1337
- const dep = this.resolve(pkgName, override);
1338
- if (dep) {
1339
- resolved.push(dep);
1340
- }
1341
- } catch (error) {
1342
- if (this.options.strictMode) {
1343
- throw error;
1344
- }
1345
- }
1346
- }
1347
- return resolved;
1348
- }
1349
- /**
1350
- * Resolve dependencies from source code.
1351
- *
1352
- * Parses the source to extract imports, then resolves external packages
1353
- * that are in the externals list.
1354
- *
1355
- * @param source - Source code to parse
1356
- * @param externals - Package names to resolve from CDN (others are bundled)
1357
- * @param overrides - Optional explicit CDN overrides
1358
- * @returns Resolved dependencies
1359
- */
1360
- resolveFromSource(source, externals, overrides) {
1361
- const parseResult = parseImports(source);
1362
- const packagesToResolve = parseResult.externalPackages.filter((pkg) => externals.includes(pkg));
1363
- return this.resolveMany(packagesToResolve, overrides);
1364
- }
1365
- /**
1366
- * Generate an import map for resolved dependencies.
1367
- *
1368
- * @param dependencies - Resolved dependencies
1369
- * @returns Browser import map
1370
- */
1371
- generateImportMap(dependencies) {
1372
- return createImportMap(dependencies);
1373
- }
1374
- /**
1375
- * Check if a package can be resolved for the current platform.
1376
- *
1377
- * @param packageName - Package name to check
1378
- * @returns true if the package can be resolved
1379
- */
1380
- canResolve(packageName) {
1381
- try {
1382
- const result = this.resolve(packageName);
1383
- return result !== null;
1384
- } catch {
1385
- return false;
1386
- }
1387
- }
1388
- /**
1389
- * Get the resolved CDN URL for a package.
1390
- *
1391
- * @param packageName - Package name
1392
- * @param override - Optional explicit override
1393
- * @returns CDN URL or undefined if cannot resolve
1394
- */
1395
- getUrl(packageName, override) {
1396
- try {
1397
- const resolved = this.resolve(packageName, override);
1398
- return resolved?.cdnUrl;
1399
- } catch {
1400
- return void 0;
1401
- }
1402
- }
1403
- /**
1404
- * Get peer dependencies for a package.
1405
- */
1406
- getPeerDependencies(packageName) {
1407
- return getPackagePeerDependencies(packageName, this.registry);
1408
- }
1409
- /**
1410
- * Create the current registry (default + custom).
1411
- */
1412
- getRegistry() {
1413
- return this.registry;
1414
- }
1415
- /**
1416
- * Get the current platform.
1417
- */
1418
- getPlatform() {
1419
- return this.options.platform;
1420
- }
1421
- /**
1422
- * Create a resolved dependency object.
1423
- */
1424
- createResolvedDependency(packageName, config, provider, version) {
1425
- return {
1426
- packageName,
1427
- version: version ?? this.extractVersionFromUrl(config.url) ?? "latest",
1428
- cdnUrl: config.url,
1429
- integrity: config.integrity,
1430
- global: config.global,
1431
- esm: config.esm ?? false,
1432
- provider
1433
- };
1434
- }
1435
- /**
1436
- * Try to extract version from CDN URL.
1437
- */
1438
- extractVersionFromUrl(url) {
1439
- const versionMatch = url.match(/@(\d+\.\d+\.\d+(?:-[\w.]+)?)/);
1440
- if (versionMatch) {
1441
- return versionMatch[1];
1442
- }
1443
- const versionMatch2 = url.match(/\/v?(\d+\.\d+\.\d+)\//);
1444
- if (versionMatch2) {
1445
- return versionMatch2[1];
1446
- }
1447
- return void 0;
1448
- }
1449
- };
1450
- function createResolver(platform, options) {
1451
- return new DependencyResolver({
1452
- platform,
1453
- ...options
1454
- });
1455
- }
1456
- function createClaudeResolver(options) {
1457
- return createResolver("claude", options);
1458
- }
1459
- function createOpenAIResolver(options) {
1460
- return createResolver("openai", options);
1461
- }
1462
- function resolveDependencies(source, externals, options) {
1463
- const resolver = new DependencyResolver(options);
1464
- return resolver.resolveFromSource(source, externals);
1465
- }
1466
- function generateImportMapForPackages(externals, options) {
1467
- const resolver = new DependencyResolver(options);
1468
- const resolved = resolver.resolveMany(externals);
1469
- return resolver.generateImportMap(resolved);
1470
- }
1471
-
1472
- // libs/uipack/src/dependency/template-loader.ts
1473
- import { promises as fs } from "fs";
1474
- import { resolve as resolvePath, isAbsolute, sep } from "path";
1475
-
1476
- // libs/uipack/src/bundler/file-cache/hash-calculator.ts
1477
- import { createHash } from "crypto";
1478
- import { readFile, readFileBuffer } from "@frontmcp/utils";
1479
- function sha256(content) {
1480
- return createHash("sha256").update(content, "utf8").digest("hex");
1481
- }
1482
-
1483
- // libs/uipack/src/dependency/template-loader.ts
1484
- var urlCache = /* @__PURE__ */ new Map();
1485
- function getUrlCache() {
1486
- return urlCache;
1487
- }
1488
- function clearUrlCache() {
1489
- urlCache.clear();
1490
- }
1491
- function detectTemplateSource(template) {
1492
- const mode = detectTemplateMode(template);
1493
- switch (mode) {
1494
- case "url":
1495
- return { type: "url", url: template };
1496
- case "file-path":
1497
- return { type: "file", path: template };
1498
- case "inline-string":
1499
- case "inline-function":
1500
- default:
1501
- return { type: "inline", content: template };
1502
- }
1503
- }
1504
- function isFileBasedTemplate(mode) {
1505
- return mode === "file-path" || mode === "url";
1506
- }
1507
- function validateTemplateUrl(url) {
1508
- const parsed = new URL(url);
1509
- if (parsed.protocol !== "https:") {
1510
- throw new Error(`Template URLs must use HTTPS. Got: ${parsed.protocol}`);
1511
- }
1512
- }
1513
- function detectFormatFromUrl(url) {
1514
- const parsed = new URL(url);
1515
- return detectFormatFromPath(parsed.pathname);
1516
- }
1517
- async function fetchTemplateFromUrl(url, options = {}) {
1518
- validateTemplateUrl(url);
1519
- const { timeout = 3e4, skipCache = false, headers: customHeaders = {} } = options;
1520
- if (!skipCache) {
1521
- const cached = urlCache.get(url);
1522
- if (cached?.etag) {
1523
- const headers = {
1524
- ...customHeaders,
1525
- "If-None-Match": cached.etag
1526
- };
1527
- const controller2 = new AbortController();
1528
- const timeoutId2 = setTimeout(() => controller2.abort(), timeout);
1529
- try {
1530
- const response = await fetch(url, {
1531
- headers,
1532
- signal: controller2.signal
1533
- });
1534
- clearTimeout(timeoutId2);
1535
- if (response.status === 304) {
1536
- return cached;
1537
- }
1538
- return await processFetchResponse(url, response);
1539
- } catch (error) {
1540
- clearTimeout(timeoutId2);
1541
- if (error instanceof Error && error.name === "AbortError") {
1542
- throw new Error(`Template fetch timed out after ${timeout}ms: ${url}`);
1543
- }
1544
- throw error;
1545
- }
1546
- }
1547
- }
1548
- const controller = new AbortController();
1549
- const timeoutId = setTimeout(() => controller.abort(), timeout);
1550
- try {
1551
- const response = await fetch(url, {
1552
- headers: customHeaders,
1553
- signal: controller.signal
1554
- });
1555
- clearTimeout(timeoutId);
1556
- return await processFetchResponse(url, response);
1557
- } catch (error) {
1558
- clearTimeout(timeoutId);
1559
- if (error instanceof Error && error.name === "AbortError") {
1560
- throw new Error(`Template fetch timed out after ${timeout}ms: ${url}`);
1561
- }
1562
- throw error;
1563
- }
1564
- }
1565
- async function processFetchResponse(url, response) {
1566
- if (!response.ok) {
1567
- throw new Error(`Failed to fetch template: ${response.status} ${response.statusText} - ${url}`);
1568
- }
1569
- const content = await response.text();
1570
- const etag = response.headers.get("etag") ?? void 0;
1571
- const contentType = response.headers.get("content-type") ?? void 0;
1572
- const result = {
1573
- content,
1574
- etag,
1575
- contentType,
1576
- fetchedAt: (/* @__PURE__ */ new Date()).toISOString()
1577
- };
1578
- urlCache.set(url, result);
1579
- return result;
1580
- }
1581
- async function readTemplateFromFile(filePath, options = {}) {
1582
- const { basePath = process.cwd(), encoding = "utf-8" } = options;
1583
- const absolutePath = isAbsolute(filePath) ? filePath : resolvePath(basePath, filePath);
1584
- const normalizedBase = resolvePath(basePath);
1585
- if (!absolutePath.startsWith(normalizedBase + sep) && absolutePath !== normalizedBase) {
1586
- throw new Error(`Template path escapes base directory: ${filePath}`);
1587
- }
1588
- try {
1589
- return await fs.readFile(absolutePath, encoding);
1590
- } catch (error) {
1591
- const err = error;
1592
- if (err.code === "ENOENT") {
1593
- throw new Error(`Template file not found: ${absolutePath}`);
1594
- }
1595
- if (err.code === "EACCES") {
1596
- throw new Error(`Permission denied reading template file: ${absolutePath}`);
1597
- }
1598
- throw new Error(`Failed to read template file: ${absolutePath} - ${err.message}`);
1599
- }
1600
- }
1601
- function resolveFilePath(filePath, basePath = process.cwd()) {
1602
- return isAbsolute(filePath) ? filePath : resolvePath(basePath, filePath);
1603
- }
1604
- async function resolveTemplate(template, options = {}) {
1605
- const { basePath = process.cwd(), skipCache = false, timeout = 3e4, format: overrideFormat } = options;
1606
- const source = detectTemplateSource(template);
1607
- let content;
1608
- let format;
1609
- let metadata = {};
1610
- switch (source.type) {
1611
- case "inline":
1612
- content = source.content;
1613
- format = overrideFormat ?? "html";
1614
- break;
1615
- case "file": {
1616
- const absolutePath = resolveFilePath(source.path, basePath);
1617
- content = await readTemplateFromFile(absolutePath);
1618
- format = overrideFormat ?? detectFormatFromPath(source.path);
1619
- metadata.resolvedPath = absolutePath;
1620
- break;
1621
- }
1622
- case "url": {
1623
- const fetchResult = await fetchTemplateFromUrl(source.url, {
1624
- skipCache,
1625
- timeout
1626
- });
1627
- content = fetchResult.content;
1628
- format = overrideFormat ?? detectFormatFromUrl(source.url);
1629
- metadata = {
1630
- fetchedAt: fetchResult.fetchedAt,
1631
- etag: fetchResult.etag,
1632
- contentType: fetchResult.contentType
1633
- };
1634
- break;
1635
- }
1636
- }
1637
- const hash = sha256(content);
1638
- return {
1639
- source,
1640
- format,
1641
- content,
1642
- hash,
1643
- metadata: Object.keys(metadata).length > 0 ? metadata : void 0
1644
- };
1645
- }
1646
- var URL_CACHE_TTL_MS = 5 * 60 * 1e3;
1647
- function needsRefetch(resolved) {
1648
- if (resolved.source.type !== "url") {
1649
- return false;
1650
- }
1651
- const cached = urlCache.get(resolved.source.url);
1652
- if (!cached) {
1653
- return true;
1654
- }
1655
- if (cached.etag) {
1656
- return false;
1657
- }
1658
- if (cached.fetchedAt) {
1659
- const fetchedTime = new Date(cached.fetchedAt).getTime();
1660
- const age = Date.now() - fetchedTime;
1661
- return age > URL_CACHE_TTL_MS;
1662
- }
1663
- return true;
1664
- }
1665
- function invalidateUrlCache(url) {
1666
- return urlCache.delete(url);
1667
- }
1668
-
1669
- // libs/uipack/src/handlebars/helpers.ts
1670
- function formatDate(date, format) {
1671
- if (date === null || date === void 0) {
1672
- return "";
1673
- }
1674
- let dateObj;
1675
- if (date instanceof Date) {
1676
- dateObj = date;
1677
- } else if (typeof date === "string" || typeof date === "number") {
1678
- dateObj = new Date(date);
1679
- } else {
1680
- return String(date);
1681
- }
1682
- if (isNaN(dateObj.getTime())) {
1683
- return String(date);
1684
- }
1685
- const options = {};
1686
- switch (format) {
1687
- case "short":
1688
- options.dateStyle = "short";
1689
- break;
1690
- case "medium":
1691
- options.dateStyle = "medium";
1692
- break;
1693
- case "long":
1694
- options.dateStyle = "long";
1695
- break;
1696
- case "full":
1697
- options.dateStyle = "full";
1698
- break;
1699
- case "time":
1700
- options.timeStyle = "short";
1701
- break;
1702
- case "datetime":
1703
- options.dateStyle = "medium";
1704
- options.timeStyle = "short";
1705
- break;
1706
- case "iso":
1707
- return dateObj.toISOString();
1708
- case "relative":
1709
- return formatRelativeDate(dateObj);
1710
- default:
1711
- options.dateStyle = "medium";
1712
- }
1713
- return new Intl.DateTimeFormat("en-US", options).format(dateObj);
1714
- }
1715
- function formatRelativeDate(date) {
1716
- const now = /* @__PURE__ */ new Date();
1717
- const diffMs = now.getTime() - date.getTime();
1718
- const diffSecs = Math.floor(diffMs / 1e3);
1719
- const diffMins = Math.floor(diffSecs / 60);
1720
- const diffHours = Math.floor(diffMins / 60);
1721
- const diffDays = Math.floor(diffHours / 24);
1722
- if (diffSecs < 60) {
1723
- return "just now";
1724
- } else if (diffMins < 60) {
1725
- return `${diffMins} minute${diffMins === 1 ? "" : "s"} ago`;
1726
- } else if (diffHours < 24) {
1727
- return `${diffHours} hour${diffHours === 1 ? "" : "s"} ago`;
1728
- } else if (diffDays < 7) {
1729
- return `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
1730
- } else {
1731
- return formatDate(date, "medium");
1732
- }
1733
- }
1734
- function formatCurrency(amount, currency) {
1735
- if (amount === null || amount === void 0) {
1736
- return "";
1737
- }
1738
- const num = typeof amount === "number" ? amount : parseFloat(String(amount));
1739
- if (isNaN(num)) {
1740
- return String(amount);
1741
- }
1742
- return new Intl.NumberFormat("en-US", {
1743
- style: "currency",
1744
- currency: typeof currency === "string" ? currency : "USD"
1745
- }).format(num);
1746
- }
1747
- function formatNumber(value, decimals) {
1748
- if (value === null || value === void 0) {
1749
- return "";
1750
- }
1751
- const num = typeof value === "number" ? value : parseFloat(String(value));
1752
- if (isNaN(num)) {
1753
- return String(value);
1754
- }
1755
- const options = {};
1756
- if (typeof decimals === "number") {
1757
- options.minimumFractionDigits = decimals;
1758
- options.maximumFractionDigits = decimals;
1759
- }
1760
- return new Intl.NumberFormat("en-US", options).format(num);
1761
- }
1762
- function jsonEmbed(data) {
1763
- const json2 = JSON.stringify(data ?? null);
1764
- return json2.replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
1765
- }
1766
- function json(data, pretty) {
1767
- return JSON.stringify(data ?? null, null, pretty ? 2 : void 0);
1768
- }
1769
- function eq(a, b) {
1770
- return a === b;
1771
- }
1772
- function ne(a, b) {
1773
- return a !== b;
1774
- }
1775
- function gt(a, b) {
1776
- return Number(a) > Number(b);
1777
- }
1778
- function gte(a, b) {
1779
- return Number(a) >= Number(b);
1780
- }
1781
- function lt(a, b) {
1782
- return Number(a) < Number(b);
1783
- }
1784
- function lte(a, b) {
1785
- return Number(a) <= Number(b);
1786
- }
1787
- function and(a, b) {
1788
- return Boolean(a) && Boolean(b);
1789
- }
1790
- function or(a, b) {
1791
- return Boolean(a) || Boolean(b);
1792
- }
1793
- function not(value) {
1794
- return !value;
1795
- }
1796
- function first(arr) {
1797
- if (!Array.isArray(arr)) return void 0;
1798
- return arr[0];
1799
- }
1800
- function last(arr) {
1801
- if (!Array.isArray(arr)) return void 0;
1802
- return arr[arr.length - 1];
1803
- }
1804
- function length(value) {
1805
- if (Array.isArray(value)) return value.length;
1806
- if (typeof value === "string") return value.length;
1807
- return 0;
1808
- }
1809
- function includes(arr, value) {
1810
- if (!Array.isArray(arr)) return false;
1811
- return arr.includes(value);
1812
- }
1813
- function join(arr, separator) {
1814
- if (!Array.isArray(arr)) return "";
1815
- return arr.join(typeof separator === "string" ? separator : ", ");
1816
- }
1817
- function uppercase(str) {
1818
- return String(str ?? "").toUpperCase();
1819
- }
1820
- function lowercase(str) {
1821
- return String(str ?? "").toLowerCase();
1822
- }
1823
- function capitalize(str) {
1824
- const s = String(str ?? "");
1825
- return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
1826
- }
1827
- function truncate(str, maxLength, suffix) {
1828
- const s = String(str ?? "");
1829
- const len = typeof maxLength === "number" ? maxLength : 50;
1830
- const suf = typeof suffix === "string" ? suffix : "...";
1831
- if (s.length <= len) return s;
1832
- return s.slice(0, len - suf.length) + suf;
1833
- }
1834
- function defaultValue(value, defaultValue2) {
1835
- return value || defaultValue2;
1836
- }
1837
- var idCounter = 0;
1838
- function uniqueId(prefix) {
1839
- const id = ++idCounter;
1840
- return prefix ? `${prefix}-${id}` : `id-${id}`;
1841
- }
1842
- function classNames(...classes) {
1843
- return classes.filter(Boolean).map(String).join(" ");
1844
- }
1845
- var builtinHelpers = {
1846
- // Escaping
1847
- escapeHtml,
1848
- // Formatting
1849
- formatDate,
1850
- formatCurrency,
1851
- formatNumber,
1852
- json,
1853
- jsonEmbed,
1854
- // Comparison
1855
- eq,
1856
- ne,
1857
- gt,
1858
- gte,
1859
- lt,
1860
- lte,
1861
- // Logical
1862
- and,
1863
- or,
1864
- not,
1865
- // Array
1866
- first,
1867
- last,
1868
- length,
1869
- includes,
1870
- join,
1871
- // String
1872
- uppercase,
1873
- lowercase,
1874
- capitalize,
1875
- truncate,
1876
- // Utility
1877
- default: defaultValue,
1878
- uniqueId,
1879
- classNames
1880
- };
1881
-
1882
- // libs/uipack/src/handlebars/expression-extractor.ts
1883
- var EXPRESSION_REGEX = /\{\{\{?(?!!)(#|\/)?([^}]+?)\}?\}\}/g;
1884
- var PATH_REGEX = /\b(output|input|structuredContent)(\.[a-zA-Z_$][a-zA-Z0-9_$]*|\.\[[^\]]+\])+/g;
1885
- var KEYWORDS = /* @__PURE__ */ new Set(["this", "else", "@index", "@key", "@first", "@last", "@root"]);
1886
- function extractExpressions(template) {
1887
- const expressions = [];
1888
- const positionMap = buildPositionMap(template);
1889
- let match;
1890
- EXPRESSION_REGEX.lastIndex = 0;
1891
- while ((match = EXPRESSION_REGEX.exec(template)) !== null) {
1892
- const fullExpression = match[0];
1893
- const prefix = match[1];
1894
- const content = match[2].trim();
1895
- const position = positionMap.get(match.index) ?? { line: 1, column: 1 };
1896
- let type = "variable";
1897
- let helperName;
1898
- if (prefix === "/") {
1899
- type = "block-close";
1900
- helperName = content;
1901
- } else if (prefix === "#") {
1902
- type = "block";
1903
- const parts = content.split(/\s+/);
1904
- helperName = parts[0];
1905
- } else {
1906
- const parts = content.split(/\s+/);
1907
- if (parts.length > 1 && !content.startsWith("(")) {
1908
- const firstToken = parts[0];
1909
- if (!firstToken.includes(".") && !KEYWORDS.has(firstToken)) {
1910
- type = "helper";
1911
- helperName = firstToken;
1912
- }
1913
- }
1914
- }
1915
- const paths = extractPathsFromContent(content);
1916
- for (const path of paths) {
1917
- expressions.push({
1918
- path,
1919
- fullExpression,
1920
- line: position.line,
1921
- column: position.column,
1922
- type,
1923
- helperName
1924
- });
1925
- }
1926
- if (paths.length === 0 && type === "variable") {
1927
- const cleanContent = content.trim();
1928
- if (!KEYWORDS.has(cleanContent) && !cleanContent.includes(" ") && !cleanContent.startsWith("(")) {
1929
- }
1930
- }
1931
- }
1932
- return expressions;
1933
- }
1934
- function extractPathsFromContent(content) {
1935
- const paths = [];
1936
- let match;
1937
- const regex = new RegExp(PATH_REGEX.source, "g");
1938
- while ((match = regex.exec(content)) !== null) {
1939
- paths.push(match[0]);
1940
- }
1941
- return paths;
1942
- }
1943
- function buildPositionMap(template) {
1944
- const map = /* @__PURE__ */ new Map();
1945
- let line = 1;
1946
- let column = 1;
1947
- for (let i = 0; i < template.length; i++) {
1948
- map.set(i, { line, column });
1949
- if (template[i] === "\n") {
1950
- line++;
1951
- column = 1;
1952
- } else {
1953
- column++;
1954
- }
1955
- }
1956
- return map;
1957
- }
1958
- function extractAll(template) {
1959
- const expressions = extractExpressions(template);
1960
- const paths = [...new Set(expressions.map((e) => e.path))];
1961
- return {
1962
- expressions,
1963
- paths,
1964
- outputPaths: paths.filter((p) => p.startsWith("output.")),
1965
- inputPaths: paths.filter((p) => p.startsWith("input.")),
1966
- structuredContentPaths: paths.filter((p) => p.startsWith("structuredContent."))
1967
- };
1968
- }
1969
- function normalizePath(path) {
1970
- return path.replace(/\.\d+\./g, ".[].").replace(/\.\d+$/g, ".[]").replace(/\[\d+\]/g, ".[]");
1971
- }
1972
-
1973
- // libs/uipack/src/handlebars/index.ts
1974
- var Handlebars = null;
1975
- async function loadHandlebars() {
1976
- if (Handlebars !== null) {
1977
- return Handlebars;
1978
- }
1979
- try {
1980
- Handlebars = await import("handlebars");
1981
- return Handlebars;
1982
- } catch {
1983
- throw new Error("Handlebars is required for template rendering. Install it: npm install handlebars");
1984
- }
1985
- }
1986
- var HandlebarsRenderer = class {
1987
- options;
1988
- compiledTemplates = /* @__PURE__ */ new Map();
1989
- initialized = false;
1990
- hbs = null;
1991
- constructor(options = {}) {
1992
- this.options = {
1993
- strict: false,
1994
- autoEscape: true,
1995
- ...options
1996
- };
1997
- }
1998
- /**
1999
- * Initialize the renderer with Handlebars.
2000
- */
2001
- async init() {
2002
- if (this.initialized) return;
2003
- this.hbs = await loadHandlebars();
2004
- for (const [name, helper] of Object.entries(builtinHelpers)) {
2005
- this.hbs.registerHelper(name, helper);
2006
- }
2007
- if (this.options.helpers) {
2008
- for (const [name, helper] of Object.entries(this.options.helpers)) {
2009
- this.hbs.registerHelper(name, helper);
2010
- }
2011
- }
2012
- if (this.options.partials) {
2013
- for (const [name, template] of Object.entries(this.options.partials)) {
2014
- this.hbs.registerPartial(name, template);
2015
- }
2016
- }
2017
- this.initialized = true;
2018
- }
2019
- /**
2020
- * Render a Handlebars template.
2021
- *
2022
- * @param template - Template string
2023
- * @param context - Render context with input/output
2024
- * @returns Rendered HTML string
2025
- */
2026
- async render(template, context) {
2027
- await this.init();
2028
- if (!this.hbs) {
2029
- throw new Error("Handlebars not initialized");
2030
- }
2031
- let compiled = this.compiledTemplates.get(template);
2032
- if (!compiled) {
2033
- compiled = this.hbs.compile(template, {
2034
- strict: this.options.strict,
2035
- noEscape: !this.options.autoEscape
2036
- });
2037
- this.compiledTemplates.set(template, compiled);
2038
- }
2039
- const data = {
2040
- input: context.input ?? {},
2041
- output: context.output ?? {},
2042
- structuredContent: context.structuredContent,
2043
- // Also expose at root level for convenience
2044
- ...context.input,
2045
- ...typeof context.output === "object" && context.output !== null ? context.output : {}
2046
- };
2047
- try {
2048
- return compiled(data);
2049
- } catch (error) {
2050
- throw new Error(`Template rendering failed: ${error instanceof Error ? error.message : String(error)}`);
2051
- }
2052
- }
2053
- /**
2054
- * Render a template synchronously.
2055
- *
2056
- * Note: Requires Handlebars to be pre-loaded. Use `render()` for async loading.
2057
- *
2058
- * @param template - Template string
2059
- * @param context - Render context
2060
- * @returns Rendered HTML string
2061
- */
2062
- renderSync(template, context) {
2063
- if (!this.initialized || !this.hbs) {
2064
- throw new Error("HandlebarsRenderer not initialized. Call render() first or use initSync().");
2065
- }
2066
- let compiled = this.compiledTemplates.get(template);
2067
- if (!compiled) {
2068
- compiled = this.hbs.compile(template, {
2069
- strict: this.options.strict,
2070
- noEscape: !this.options.autoEscape
2071
- });
2072
- this.compiledTemplates.set(template, compiled);
2073
- }
2074
- const data = {
2075
- input: context.input ?? {},
2076
- output: context.output ?? {},
2077
- structuredContent: context.structuredContent,
2078
- ...context.input,
2079
- ...typeof context.output === "object" && context.output !== null ? context.output : {}
2080
- };
2081
- return compiled(data);
2082
- }
2083
- /**
2084
- * Initialize synchronously (for environments where Handlebars is already loaded).
2085
- */
2086
- initSync(handlebars) {
2087
- this.hbs = handlebars;
2088
- for (const [name, helper] of Object.entries(builtinHelpers)) {
2089
- this.hbs.registerHelper(name, helper);
2090
- }
2091
- if (this.options.helpers) {
2092
- for (const [name, helper] of Object.entries(this.options.helpers)) {
2093
- this.hbs.registerHelper(name, helper);
2094
- }
2095
- }
2096
- if (this.options.partials) {
2097
- for (const [name, template] of Object.entries(this.options.partials)) {
2098
- this.hbs.registerPartial(name, template);
2099
- }
2100
- }
2101
- this.initialized = true;
2102
- }
2103
- /**
2104
- * Register a custom helper.
2105
- *
2106
- * @param name - Helper name
2107
- * @param fn - Helper function
2108
- */
2109
- registerHelper(name, fn) {
2110
- if (this.hbs) {
2111
- this.hbs.registerHelper(name, fn);
2112
- }
2113
- if (!this.options.helpers) {
2114
- this.options.helpers = {};
2115
- }
2116
- this.options.helpers[name] = fn;
2117
- }
2118
- /**
2119
- * Register a partial template.
2120
- *
2121
- * @param name - Partial name
2122
- * @param template - Partial template string
2123
- */
2124
- registerPartial(name, template) {
2125
- if (this.hbs) {
2126
- this.hbs.registerPartial(name, template);
2127
- }
2128
- if (!this.options.partials) {
2129
- this.options.partials = {};
2130
- }
2131
- this.options.partials[name] = template;
2132
- }
2133
- /**
2134
- * Clear compiled template cache.
2135
- */
2136
- clearCache() {
2137
- this.compiledTemplates.clear();
2138
- }
2139
- /**
2140
- * Check if a template string contains Handlebars syntax.
2141
- *
2142
- * @param template - Template string to check
2143
- * @returns true if contains {{...}} syntax
2144
- */
2145
- static containsHandlebars(template) {
2146
- return /\{\{(?!!)[\s\S]*?\}\}/.test(template);
2147
- }
2148
- /**
2149
- * Check if the renderer is initialized.
2150
- */
2151
- get isInitialized() {
2152
- return this.initialized;
2153
- }
2154
- };
2155
- function containsHandlebars(template) {
2156
- return HandlebarsRenderer.containsHandlebars(template);
2157
- }
2158
-
2159
- // libs/uipack/src/renderers/utils/detect.ts
2160
- var MAX_TEMPLATE_LENGTH = 5e4;
2161
- function containsMdxSyntax(source) {
2162
- if (source.length > MAX_TEMPLATE_LENGTH) {
2163
- return false;
2164
- }
2165
- if (/<[A-Z][a-zA-Z0-9]*/.test(source)) {
2166
- return true;
2167
- }
2168
- if (/^(import|export)\s/m.test(source)) {
2169
- return true;
2170
- }
2171
- if (/\s(className|onClick|onChange|onSubmit|htmlFor|dangerouslySetInnerHTML)=/.test(source)) {
2172
- return true;
2173
- }
2174
- if (/\{[^}"'\n]*\}/.test(source) && !/=\s*["'][^"']*\{/.test(source)) {
2175
- return true;
2176
- }
2177
- if (/^---[\s\S]*?---/m.test(source)) {
2178
- return true;
2179
- }
2180
- if (/<>|<\/>/.test(source)) {
2181
- return true;
2182
- }
2183
- return false;
2184
- }
2185
-
2186
- // libs/uipack/src/renderers/utils/hash.ts
2187
- function hashString(source) {
2188
- let hash = 2166136261;
2189
- for (let i = 0; i < source.length; i++) {
2190
- hash ^= source.charCodeAt(i);
2191
- hash = hash * 16777619 >>> 0;
2192
- }
2193
- return hash.toString(36);
2194
- }
2195
-
2196
- // libs/uipack/src/renderers/cache.ts
2197
- var TranspileCache = class {
2198
- cache = /* @__PURE__ */ new Map();
2199
- maxSize;
2200
- ttl;
2201
- /** Cache statistics */
2202
- stats = {
2203
- hits: 0,
2204
- misses: 0,
2205
- evictions: 0
2206
- };
2207
- constructor(options = {}) {
2208
- this.maxSize = options.maxSize ?? 500;
2209
- this.ttl = options.ttl ?? 0;
2210
- }
2211
- /**
2212
- * Get a cached transpile result by source content.
2213
- *
2214
- * @param source - Source code to look up
2215
- * @returns Cached result or undefined if not found/expired
2216
- */
2217
- get(source) {
2218
- const key = hashString(source);
2219
- return this.getByKey(key);
2220
- }
2221
- /**
2222
- * Get a cached transpile result by hash key.
2223
- *
2224
- * @param key - Hash key
2225
- * @returns Cached result or undefined if not found/expired
2226
- */
2227
- getByKey(key) {
2228
- const entry = this.cache.get(key);
2229
- if (!entry) {
2230
- this.stats.misses++;
2231
- return void 0;
2232
- }
2233
- if (this.ttl > 0 && Date.now() - entry.timestamp > this.ttl) {
2234
- this.cache.delete(key);
2235
- this.stats.misses++;
2236
- return void 0;
2237
- }
2238
- this.cache.delete(key);
2239
- entry.accessCount++;
2240
- this.cache.set(key, entry);
2241
- this.stats.hits++;
2242
- return entry.value;
2243
- }
2244
- /**
2245
- * Store a transpile result.
2246
- *
2247
- * @param source - Source code (used to generate key)
2248
- * @param value - Transpile result to cache
2249
- * @returns The hash key used for storage
2250
- */
2251
- set(source, value) {
2252
- const key = hashString(source);
2253
- this.setByKey(key, value);
2254
- return key;
2255
- }
2256
- /**
2257
- * Store a transpile result by hash key.
2258
- *
2259
- * @param key - Hash key
2260
- * @param value - Transpile result to cache
2261
- */
2262
- setByKey(key, value) {
2263
- if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
2264
- const oldestKey = this.cache.keys().next().value;
2265
- if (oldestKey) {
2266
- this.cache.delete(oldestKey);
2267
- this.stats.evictions++;
2268
- }
2269
- }
2270
- this.cache.set(key, {
2271
- value,
2272
- timestamp: Date.now(),
2273
- accessCount: 1
2274
- });
2275
- }
2276
- /**
2277
- * Check if a source is cached.
2278
- *
2279
- * @param source - Source code to check
2280
- * @returns True if cached and not expired
2281
- */
2282
- has(source) {
2283
- const key = hashString(source);
2284
- return this.hasByKey(key);
2285
- }
2286
- /**
2287
- * Check if a key is cached.
2288
- *
2289
- * @param key - Hash key to check
2290
- * @returns True if cached and not expired
2291
- */
2292
- hasByKey(key) {
2293
- const entry = this.cache.get(key);
2294
- if (!entry) return false;
2295
- if (this.ttl > 0 && Date.now() - entry.timestamp > this.ttl) {
2296
- this.cache.delete(key);
2297
- return false;
2298
- }
2299
- return true;
2300
- }
2301
- /**
2302
- * Delete a cached entry by source.
2303
- *
2304
- * @param source - Source code to delete
2305
- * @returns True if entry was deleted
2306
- */
2307
- delete(source) {
2308
- const key = hashString(source);
2309
- return this.cache.delete(key);
2310
- }
2311
- /**
2312
- * Clear all cached entries.
2313
- */
2314
- clear() {
2315
- this.cache.clear();
2316
- this.stats = { hits: 0, misses: 0, evictions: 0 };
2317
- }
2318
- /**
2319
- * Get current cache size.
2320
- */
2321
- get size() {
2322
- return this.cache.size;
2323
- }
2324
- /**
2325
- * Get cache statistics.
2326
- */
2327
- getStats() {
2328
- const total = this.stats.hits + this.stats.misses;
2329
- return {
2330
- ...this.stats,
2331
- size: this.cache.size,
2332
- hitRate: total > 0 ? this.stats.hits / total : 0
2333
- };
2334
- }
2335
- };
2336
- var transpileCache = new TranspileCache({ maxSize: 500 });
2337
- var renderCache = new TranspileCache({
2338
- maxSize: 1e3,
2339
- ttl: 5 * 60 * 1e3
2340
- // 5 minutes
2341
- });
2342
- var ComponentCache = class {
2343
- cache = /* @__PURE__ */ new Map();
2344
- maxSize;
2345
- constructor(maxSize = 200) {
2346
- this.maxSize = maxSize;
2347
- }
2348
- get(key) {
2349
- const entry = this.cache.get(key);
2350
- if (!entry) return void 0;
2351
- this.cache.delete(key);
2352
- this.cache.set(key, entry);
2353
- return entry.value;
2354
- }
2355
- set(key, value) {
2356
- if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
2357
- const oldestKey = this.cache.keys().next().value;
2358
- if (oldestKey) {
2359
- this.cache.delete(oldestKey);
2360
- }
2361
- }
2362
- this.cache.set(key, { value, timestamp: Date.now() });
2363
- }
2364
- has(key) {
2365
- return this.cache.has(key);
2366
- }
2367
- delete(key) {
2368
- return this.cache.delete(key);
2369
- }
2370
- clear() {
2371
- this.cache.clear();
2372
- }
2373
- get size() {
2374
- return this.cache.size;
2375
- }
2376
- };
2377
- var componentCache = new ComponentCache();
2378
-
2379
- // libs/uipack/src/renderers/mdx-client.renderer.ts
2380
- function buildReactCdnUrls(version = "19") {
2381
- return {
2382
- react: `https://esm.sh/react@${version}`,
2383
- reactDom: `https://esm.sh/react-dom@${version}/client`,
2384
- jsxRuntime: `https://esm.sh/react@${version}/jsx-runtime`
2385
- };
2386
- }
2387
- var DEFAULT_CDN = {
2388
- mdx: "https://esm.sh/@mdx-js/mdx@3",
2389
- ...buildReactCdnUrls("19")
2390
- };
2391
- var MdxClientRenderer = class {
2392
- type = "mdx-client";
2393
- priority = 8;
2394
- // Lower than server-side MDX (10)
2395
- /**
2396
- * Check if this renderer can handle the given template.
2397
- */
2398
- canHandle(template) {
2399
- if (typeof template !== "string") {
2400
- return false;
2401
- }
2402
- return containsMdxSyntax(template);
2403
- }
2404
- /**
2405
- * Prepare MDX template for rendering.
2406
- * Caches the template hash for deduplication. Actual MDX compilation
2407
- * happens client-side via CDN-loaded @mdx-js/mdx in the browser.
2408
- */
2409
- async transpile(template, _options) {
2410
- const hash = hashString(template);
2411
- const cached = transpileCache.getByKey(hash);
2412
- if (cached) {
2413
- return { ...cached, cached: true };
2414
- }
2415
- const transpileResult = {
2416
- code: template,
2417
- hash,
2418
- cached: false
2419
- };
2420
- transpileCache.setByKey(hash, transpileResult);
2421
- return transpileResult;
2422
- }
2423
- /**
2424
- * Render MDX template to HTML with CDN scripts.
2425
- *
2426
- * The returned HTML includes:
2427
- * - A container div for the rendered content
2428
- * - Script tags that load React and MDX from CDN
2429
- * - Inline script that compiles and renders the MDX
2430
- */
2431
- async render(template, context, options) {
2432
- const containerId = options?.containerId || "mdx-content";
2433
- const showLoading = options?.showLoading !== false;
2434
- const loadingMessage = options?.loadingMessage || "Loading...";
2435
- const cdn = {
2436
- ...DEFAULT_CDN,
2437
- ...options?.cdn
2438
- };
2439
- const props = {
2440
- input: context.input,
2441
- output: context.output,
2442
- structuredContent: context.structuredContent,
2443
- helpers: context.helpers
2444
- };
2445
- const reservedProps = /* @__PURE__ */ new Set(["input", "output", "structuredContent", "helpers", "components"]);
2446
- const outputProps = typeof context.output === "object" && context.output !== null ? Object.fromEntries(Object.entries(context.output).filter(([key]) => !reservedProps.has(key))) : {};
2447
- const spreadProps = {
2448
- ...outputProps,
2449
- ...props
2450
- };
2451
- const escapedMdx = escapeScriptClose(JSON.stringify(template));
2452
- const escapedProps = escapeScriptClose(JSON.stringify(spreadProps));
2453
- const safeContainerId = escapeJsString(containerId);
2454
- const loadingHtml = showLoading ? `<div class="mdx-loading">${escapeHtml(loadingMessage)}</div>` : "";
2455
- return `
2456
- <div id="${escapeHtml(containerId)}">${loadingHtml}</div>
2457
- <script type="module">
2458
- (async function() {
2459
- try {
2460
- // Load dependencies from CDN
2461
- const [
2462
- { evaluate },
2463
- runtime,
2464
- React,
2465
- { createRoot }
2466
- ] = await Promise.all([
2467
- import('${cdn.mdx}'),
2468
- import('${cdn.jsxRuntime}'),
2469
- import('${cdn.react}'),
2470
- import('${cdn.reactDom}')
2471
- ]);
2472
-
2473
- // MDX content and props
2474
- const mdxSource = ${escapedMdx};
2475
- const props = ${escapedProps};
2476
-
2477
- // Compile and evaluate MDX
2478
- const { default: Content } = await evaluate(mdxSource, {
2479
- ...runtime,
2480
- Fragment: React.Fragment,
2481
- development: false
2482
- });
2483
-
2484
- // Render to DOM
2485
- const container = document.getElementById('${safeContainerId}');
2486
- if (container) {
2487
- const root = createRoot(container);
2488
- root.render(React.createElement(Content, props));
2489
- }
2490
- } catch (error) {
2491
- console.error('[FrontMCP] MDX client rendering failed:', error);
2492
- const container = document.getElementById('${safeContainerId}');
2493
- if (container) {
2494
- container.innerHTML = '<div class="mdx-error">Failed to render MDX content</div>';
2495
- }
2496
- }
2497
- })();
2498
- </script>
2499
- `;
2500
- }
2501
- /**
2502
- * Get runtime scripts - not needed for client renderer since scripts are inline.
2503
- */
2504
- getRuntimeScripts(platform) {
2505
- if (platform.networkMode === "blocked") {
2506
- return {
2507
- headScripts: "",
2508
- inlineScripts: `console.warn('[FrontMCP] Client-side MDX rendering requires network access. Use @frontmcp/ui for SSR.');`,
2509
- isInline: true
2510
- };
2511
- }
2512
- return {
2513
- headScripts: "",
2514
- isInline: false
2515
- };
2516
- }
2517
- };
2518
- var mdxClientRenderer = new MdxClientRenderer();
2519
-
2520
- // libs/uipack/src/validation/schema-paths.ts
2521
- import { z as z2 } from "zod";
2522
- function extractSchemaPaths(schema, prefix = "output", options = {}) {
2523
- const { maxDepth = 10, includeArrayItems = true } = options;
2524
- const paths = [];
2525
- const visited = /* @__PURE__ */ new Set();
2526
- function recurse(currentSchema, currentPath, depth, isOptional, isNullable, isArrayItem) {
2527
- if (depth > maxDepth) return;
2528
- const pathKey = `${currentPath}:${depth}`;
2529
- if (visited.has(pathKey)) return;
2530
- visited.add(pathKey);
2531
- const description = currentSchema.description;
2532
- const innerType = unwrapType(currentSchema);
2533
- paths.push({
2534
- path: currentPath,
2535
- zodType: currentSchema,
2536
- optional: isOptional,
2537
- nullable: isNullable,
2538
- isArrayItem,
2539
- description
2540
- });
2541
- if (innerType instanceof z2.ZodObject) {
2542
- const shape = innerType.shape;
2543
- for (const [key, value] of Object.entries(shape)) {
2544
- const childSchema = value;
2545
- const childOptional = isOptional || isOptionalType(childSchema);
2546
- const childNullable = isNullable || isNullableType(childSchema);
2547
- recurse(childSchema, `${currentPath}.${key}`, depth + 1, childOptional, childNullable, false);
2548
- }
2549
- } else if (innerType instanceof z2.ZodArray && includeArrayItems) {
2550
- const itemSchema = innerType.element;
2551
- recurse(itemSchema, `${currentPath}.[]`, depth + 1, isOptional, isNullable, true);
2552
- } else if (innerType instanceof z2.ZodUnion || innerType instanceof z2.ZodDiscriminatedUnion) {
2553
- const options2 = "options" in innerType ? innerType.options : [];
2554
- for (const option of options2) {
2555
- recurse(option, currentPath, depth, isOptional, isNullable, isArrayItem);
2556
- }
2557
- } else if (innerType instanceof z2.ZodIntersection) {
2558
- recurse(innerType._def.left, currentPath, depth, isOptional, isNullable, isArrayItem);
2559
- recurse(innerType._def.right, currentPath, depth, isOptional, isNullable, isArrayItem);
2560
- } else if (innerType instanceof z2.ZodRecord) {
2561
- const valueSchema = innerType._def.valueType;
2562
- recurse(valueSchema, `${currentPath}.[]`, depth + 1, isOptional, isNullable, true);
2563
- } else if (innerType instanceof z2.ZodTuple) {
2564
- const items = innerType._def.items;
2565
- items.forEach((item, index) => {
2566
- recurse(item, `${currentPath}.${index}`, depth + 1, isOptional, isNullable, true);
2567
- });
2568
- }
2569
- }
2570
- recurse(schema, prefix, 0, false, false, false);
2571
- const seen = /* @__PURE__ */ new Set();
2572
- return paths.filter((p) => {
2573
- if (seen.has(p.path)) return false;
2574
- seen.add(p.path);
2575
- return true;
2576
- });
2577
- }
2578
- function unwrapType(schema) {
2579
- if (schema instanceof z2.ZodOptional) {
2580
- return unwrapType(schema.unwrap());
2581
- }
2582
- if (schema instanceof z2.ZodNullable) {
2583
- return unwrapType(schema.unwrap());
2584
- }
2585
- if (schema instanceof z2.ZodDefault) {
2586
- return unwrapType(schema._def.innerType);
2587
- }
2588
- if (schema instanceof z2.ZodCatch && "innerType" in schema._def) {
2589
- return unwrapType(schema._def.innerType);
2590
- }
2591
- return schema;
2592
- }
2593
- function isOptionalType(schema) {
2594
- if (schema instanceof z2.ZodOptional) return true;
2595
- if (schema instanceof z2.ZodDefault) return true;
2596
- if (schema instanceof z2.ZodNullable) return isOptionalType(schema.unwrap());
2597
- return false;
2598
- }
2599
- function isNullableType(schema) {
2600
- if (schema instanceof z2.ZodNullable) return true;
2601
- if (schema instanceof z2.ZodOptional) return isNullableType(schema.unwrap());
2602
- return false;
2603
- }
2604
- function getSchemaPathStrings(schema, prefix = "output") {
2605
- const paths = extractSchemaPaths(schema, prefix);
2606
- return new Set(paths.map((p) => p.path));
2607
- }
2608
-
2609
- // libs/uipack/src/validation/template-validator.ts
2610
- function validateTemplate(template, outputSchema, options = {}) {
2611
- const { inputSchema, warnOnOptional = true, suggestSimilar = true, maxSuggestionDistance = 3 } = options;
2612
- const errors = [];
2613
- const warnings = [];
2614
- const extraction = extractAll(template);
2615
- const expressions = extractExpressions(template);
2616
- const outputPaths = getSchemaPathStrings(outputSchema, "output");
2617
- const inputPaths = inputSchema ? getSchemaPathStrings(inputSchema, "input") : /* @__PURE__ */ new Set();
2618
- const outputPathInfos = extractSchemaPaths(outputSchema, "output");
2619
- const inputPathInfos = inputSchema ? extractSchemaPaths(inputSchema, "input") : [];
2620
- const pathInfoMap = /* @__PURE__ */ new Map();
2621
- for (const info of [...outputPathInfos, ...inputPathInfos]) {
2622
- pathInfoMap.set(info.path, info);
2623
- }
2624
- for (const expr of expressions) {
2625
- const { path, fullExpression, line, column } = expr;
2626
- let validPaths;
2627
- let allPaths;
2628
- if (path.startsWith("output.")) {
2629
- validPaths = outputPaths;
2630
- allPaths = Array.from(outputPaths);
2631
- } else if (path.startsWith("input.")) {
2632
- if (!inputSchema) {
2633
- continue;
2634
- }
2635
- validPaths = inputPaths;
2636
- allPaths = Array.from(inputPaths);
2637
- } else if (path.startsWith("structuredContent.")) {
2638
- continue;
2639
- } else {
2640
- continue;
2641
- }
2642
- const normalizedPath = normalizePath(path);
2643
- const isValid = validPaths.has(path) || validPaths.has(normalizedPath);
2644
- if (!isValid) {
2645
- const isArrayAccess = checkArrayAccess(path, validPaths);
2646
- if (!isArrayAccess) {
2647
- const suggestions = suggestSimilar ? findSimilarPaths(path, allPaths, maxSuggestionDistance) : [];
2648
- errors.push({
2649
- type: "missing_field",
2650
- path,
2651
- expression: fullExpression,
2652
- line,
2653
- column,
2654
- message: `Field '${getFieldName(path)}' does not exist in ${getSchemaName(path)} schema`,
2655
- suggestions
2656
- });
2657
- }
2658
- } else {
2659
- const pathInfo = pathInfoMap.get(path) ?? pathInfoMap.get(normalizedPath);
2660
- if (pathInfo && warnOnOptional) {
2661
- if (pathInfo.optional && expr.type === "variable") {
2662
- const hasGuard = hasConditionalGuard(template, path);
2663
- if (!hasGuard) {
2664
- warnings.push({
2665
- type: "optional_field",
2666
- path,
2667
- expression: fullExpression,
2668
- line,
2669
- message: `Accessing optional field '${getFieldName(path)}' without {{#if}} guard`
2670
- });
2671
- }
2672
- }
2673
- }
2674
- }
2675
- }
2676
- return {
2677
- valid: errors.length === 0,
2678
- errors,
2679
- warnings,
2680
- templatePaths: extraction.paths,
2681
- schemaPaths: [...outputPaths, ...inputPaths]
2682
- };
2683
- }
2684
- function checkArrayAccess(path, validPaths) {
2685
- const parts = path.split(".");
2686
- for (let i = 0; i < parts.length; i++) {
2687
- if (/^\d+$/.test(parts[i])) {
2688
- const wildcardParts = [...parts];
2689
- wildcardParts[i] = "[]";
2690
- const wildcardPath = wildcardParts.join(".");
2691
- if (validPaths.has(wildcardPath)) {
2692
- return true;
2693
- }
2694
- }
2695
- }
2696
- return false;
2697
- }
2698
- function getFieldName(path) {
2699
- const parts = path.split(".");
2700
- return parts[parts.length - 1];
2701
- }
2702
- function getSchemaName(path) {
2703
- if (path.startsWith("output.")) return "output";
2704
- if (path.startsWith("input.")) return "input";
2705
- if (path.startsWith("structuredContent.")) return "structuredContent";
2706
- return "unknown";
2707
- }
2708
- function hasConditionalGuard(template, path) {
2709
- const guardPattern = new RegExp(`\\{\\{#if\\s+${escapeRegex(path)}`, "i");
2710
- return guardPattern.test(template);
2711
- }
2712
- function escapeRegex(str) {
2713
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2714
- }
2715
- function findSimilarPaths(path, validPaths, maxDistance) {
2716
- const fieldName = getFieldName(path);
2717
- const prefix = path.substring(0, path.lastIndexOf(".") + 1);
2718
- const suggestions = [];
2719
- for (const validPath of validPaths) {
2720
- if (!validPath.startsWith(prefix)) continue;
2721
- const validFieldName = getFieldName(validPath);
2722
- const distance = levenshteinDistance(fieldName, validFieldName);
2723
- if (distance <= maxDistance && distance > 0) {
2724
- suggestions.push({ path: validPath, distance });
2725
- }
2726
- }
2727
- return suggestions.sort((a, b) => a.distance - b.distance).slice(0, 3).map((s) => s.path);
2728
- }
2729
- function levenshteinDistance(a, b) {
2730
- const matrix = [];
2731
- for (let i = 0; i <= a.length; i++) {
2732
- matrix[i] = [i];
2733
- }
2734
- for (let j = 0; j <= b.length; j++) {
2735
- matrix[0][j] = j;
2736
- }
2737
- for (let i = 1; i <= a.length; i++) {
2738
- for (let j = 1; j <= b.length; j++) {
2739
- const cost = a[i - 1] === b[j - 1] ? 0 : 1;
2740
- matrix[i][j] = Math.min(
2741
- matrix[i - 1][j] + 1,
2742
- // deletion
2743
- matrix[i][j - 1] + 1,
2744
- // insertion
2745
- matrix[i - 1][j - 1] + cost
2746
- // substitution
2747
- );
2748
- }
2749
- }
2750
- return matrix[a.length][b.length];
2751
- }
2752
- function formatValidationWarnings(result, toolName) {
2753
- if (result.valid && result.warnings.length === 0) {
2754
- return "";
2755
- }
2756
- const lines = [];
2757
- if (result.errors.length > 0) {
2758
- lines.push(`[FrontMCP] Template validation warnings for tool "${toolName}":`);
2759
- lines.push("");
2760
- for (const error of result.errors) {
2761
- lines.push(` Line ${error.line}: ${error.expression}`);
2762
- lines.push(` ${error.message}`);
2763
- if (error.suggestions.length > 0) {
2764
- lines.push(` Did you mean: ${error.suggestions.join(", ")}?`);
2765
- }
2766
- lines.push("");
2767
- }
2768
- const outputFields = result.schemaPaths.filter((p) => p.startsWith("output.") && p.split(".").length === 2).map((p) => p.replace("output.", ""));
2769
- if (outputFields.length > 0) {
2770
- lines.push(` Available output fields: ${outputFields.join(", ")}`);
2771
- }
2772
- }
2773
- if (result.warnings.length > 0) {
2774
- if (lines.length > 0) lines.push("");
2775
- lines.push(` Warnings:`);
2776
- for (const warning of result.warnings) {
2777
- lines.push(` Line ${warning.line}: ${warning.message}`);
2778
- }
2779
- }
2780
- return lines.join("\n");
2781
- }
2782
- function logValidationWarnings(result, toolName) {
2783
- const formatted = formatValidationWarnings(result, toolName);
2784
- if (formatted) {
2785
- console.warn(formatted);
2786
- }
2787
- }
2788
-
2789
- // libs/uipack/src/dependency/template-processor.ts
2790
- function safeInputToRecord(input) {
2791
- if (input && typeof input === "object" && !Array.isArray(input)) {
2792
- return input;
2793
- }
2794
- return {};
2795
- }
2796
- var defaultHelpers = {
2797
- escapeHtml,
2798
- formatDate: (date, format) => {
2799
- const d = date instanceof Date ? date : new Date(date);
2800
- if (format === "iso") return d.toISOString();
2801
- if (format === "time") return d.toLocaleTimeString();
2802
- return d.toLocaleDateString();
2803
- },
2804
- formatCurrency: (amount, currency = "USD") => new Intl.NumberFormat("en-US", { style: "currency", currency }).format(amount),
2805
- uniqueId: (prefix = "id") => `${prefix}-${Math.random().toString(36).substring(2, 9)}`,
2806
- jsonEmbed: (data) => JSON.stringify(data).replace(/</g, "\\u003c").replace(/>/g, "\\u003e").replace(/&/g, "\\u0026")
2807
- };
2808
- function getSourceName(source) {
2809
- switch (source.type) {
2810
- case "file":
2811
- return source.path;
2812
- case "url":
2813
- return source.url;
2814
- case "inline":
2815
- return "inline-template";
2816
- }
2817
- }
2818
- var handlebarsRenderer = null;
2819
- async function getHandlebarsRenderer(customHelpers) {
2820
- if (customHelpers) {
2821
- const freshRenderer = new HandlebarsRenderer();
2822
- for (const [name, fn] of Object.entries(customHelpers)) {
2823
- freshRenderer.registerHelper(name, fn);
2824
- }
2825
- return freshRenderer;
2826
- }
2827
- if (!handlebarsRenderer) {
2828
- handlebarsRenderer = new HandlebarsRenderer();
2829
- }
2830
- return handlebarsRenderer;
2831
- }
2832
- function clearHandlebarsCache() {
2833
- if (handlebarsRenderer) {
2834
- handlebarsRenderer.clearCache();
2835
- }
2836
- }
2837
- var markedModule = null;
2838
- async function loadMarked() {
2839
- if (markedModule) {
2840
- return markedModule;
2841
- }
2842
- try {
2843
- const moduleName = "marked";
2844
- markedModule = await import(
2845
- /* webpackIgnore: true */
2846
- moduleName
2847
- );
2848
- return markedModule;
2849
- } catch {
2850
- throw new Error("marked is required for Markdown rendering. Install it: npm install marked");
2851
- }
2852
- }
2853
- async function isMarkedAvailable() {
2854
- try {
2855
- await loadMarked();
2856
- return true;
2857
- } catch {
2858
- return false;
2859
- }
2860
- }
2861
- async function processTemplate(resolved, options) {
2862
- const { format, content } = resolved;
2863
- const { context, handlebarsHelpers, outputSchema, inputSchema, toolName } = options;
2864
- if (format === "react") {
2865
- return {
2866
- code: content,
2867
- format: "react",
2868
- needsBundling: true
2869
- };
2870
- }
2871
- if (outputSchema && process.env["NODE_ENV"] !== "production" && containsHandlebars(content)) {
2872
- const sourceName = getSourceName(resolved.source);
2873
- const validation = validateTemplate(content, outputSchema, {
2874
- inputSchema,
2875
- warnOnOptional: true,
2876
- suggestSimilar: true,
2877
- toolName: toolName ?? sourceName
2878
- });
2879
- if (!validation.valid || validation.warnings.length > 0) {
2880
- logValidationWarnings(validation, toolName ?? sourceName ?? "unknown");
2881
- }
2882
- }
2883
- let processedContent = content;
2884
- if (containsHandlebars(content)) {
2885
- const hbs = await getHandlebarsRenderer(handlebarsHelpers);
2886
- const renderContext = {
2887
- input: safeInputToRecord(context.input),
2888
- output: context.output,
2889
- structuredContent: context.structuredContent
2890
- };
2891
- processedContent = await hbs.render(content, renderContext);
2892
- }
2893
- switch (format) {
2894
- case "html":
2895
- return {
2896
- html: processedContent,
2897
- format: "html"
2898
- };
2899
- case "markdown": {
2900
- const { marked } = await loadMarked();
2901
- const html = await marked.parse(processedContent);
2902
- return {
2903
- html,
2904
- format: "markdown"
2905
- };
2906
- }
2907
- case "mdx": {
2908
- const templateContext = {
2909
- input: context.input,
2910
- output: context.output,
2911
- structuredContent: context.structuredContent,
2912
- helpers: defaultHelpers
2913
- };
2914
- const html = await mdxClientRenderer.render(processedContent, templateContext);
2915
- return {
2916
- html,
2917
- format: "mdx"
2918
- };
2919
- }
2920
- default:
2921
- return {
2922
- html: processedContent,
2923
- format: "html"
2924
- };
2925
- }
2926
- }
2927
- async function processTemplates(items) {
2928
- return Promise.all(items.map(({ resolved, options }) => processTemplate(resolved, options)));
2929
- }
2930
- function supportsHandlebars(format) {
2931
- return format === "html" || format === "markdown" || format === "mdx";
2932
- }
2933
- function producesHtml(format) {
2934
- return format !== "react";
2935
- }
2936
- function requiresBundling(format) {
2937
- return format === "react";
2938
- }
2939
- async function processHtmlTemplate(content, context, helpers) {
2940
- if (!containsHandlebars(content)) {
2941
- return content;
2942
- }
2943
- const hbs = await getHandlebarsRenderer(helpers);
2944
- const renderContext = {
2945
- input: safeInputToRecord(context.input),
2946
- output: context.output,
2947
- structuredContent: context.structuredContent
2948
- };
2949
- return hbs.render(content, renderContext);
2950
- }
2951
- async function processMarkdownTemplate(content, context, helpers) {
2952
- let processed = content;
2953
- if (containsHandlebars(content)) {
2954
- const hbs = await getHandlebarsRenderer(helpers);
2955
- const renderContext = {
2956
- input: safeInputToRecord(context.input),
2957
- output: context.output,
2958
- structuredContent: context.structuredContent
2959
- };
2960
- processed = await hbs.render(content, renderContext);
2961
- }
2962
- const { marked } = await loadMarked();
2963
- return marked.parse(processed);
2964
- }
2965
- async function processMdxTemplate(content, context, helpers) {
2966
- let processed = content;
2967
- if (containsHandlebars(content)) {
2968
- const hbs = await getHandlebarsRenderer(helpers);
2969
- const renderContext = {
2970
- input: safeInputToRecord(context.input),
2971
- output: context.output,
2972
- structuredContent: context.structuredContent
2973
- };
2974
- processed = await hbs.render(content, renderContext);
2975
- }
2976
- const templateContext = {
2977
- input: context.input,
2978
- output: context.output,
2979
- structuredContent: context.structuredContent,
2980
- helpers: defaultHelpers
2981
- };
2982
- return mdxClientRenderer.render(processed, templateContext);
2983
- }
2984
- export {
2985
- CDN_PROVIDER_PRIORITY,
2986
- DEFAULT_CDN_REGISTRY,
2987
- DependencyResolutionError,
2988
- DependencyResolver,
2989
- NoProviderError,
2990
- addScope,
2991
- buildManifestMetadataSchema,
2992
- buildManifestOutputsSchema,
2993
- bundleTargetSchema,
2994
- cacheStatsSchema,
2995
- cdnDependencySchema,
2996
- cdnPlatformTypeSchema,
2997
- cdnProviderConfigSchema,
2998
- cdnProviderSchema,
2999
- cdnRegistryEntrySchema,
3000
- clearHandlebarsCache,
3001
- clearUrlCache,
3002
- componentBuildManifestSchema,
3003
- createClaudeResolver,
3004
- createImportMap,
3005
- createImportMapFromOverrides,
3006
- createOpenAIResolver,
3007
- createResolver,
3008
- dependencyResolverOptionsSchema,
3009
- detectFormatFromPath,
3010
- detectFormatFromUrl,
3011
- detectTemplateMode,
3012
- detectTemplateSource,
3013
- extractExternalPackages,
3014
- fetchTemplateFromUrl,
3015
- fileBundleOptionsSchema,
3016
- fileTemplateConfigSchema,
3017
- filterImportsByPackages,
3018
- generateCDNScriptTags,
3019
- generateDependencyHTML,
3020
- generateESMScriptTags,
3021
- generateImportMapForPackages,
3022
- generateImportMapScriptTag,
3023
- generateImportMapScriptTagMinified,
3024
- generateUMDShim,
3025
- getImportStats,
3026
- getPackageCDNDependency,
3027
- getPackageCDNUrl,
3028
- getPackageName,
3029
- getPackagePeerDependencies,
3030
- getRegisteredPackages,
3031
- getUrlCache,
3032
- importMapSchema,
3033
- importTypeSchema,
3034
- invalidateUrlCache,
3035
- isFileBasedTemplate,
3036
- isMarkedAvailable,
3037
- isPackageRegistered,
3038
- lookupPackage,
3039
- mergeImportMaps,
3040
- mergeRegistries,
3041
- needsRefetch,
3042
- packageMetadataSchema,
3043
- parseImports,
3044
- parsedImportResultSchema,
3045
- parsedImportSchema,
3046
- processHtmlTemplate,
3047
- processMarkdownTemplate,
3048
- processMdxTemplate,
3049
- processTemplate,
3050
- processTemplates,
3051
- producesHtml,
3052
- readTemplateFromFile,
3053
- requiresBundling,
3054
- resolveAllDependencies,
3055
- resolveDependencies,
3056
- resolveFilePath,
3057
- resolveTemplate,
3058
- resolvedDependencySchema,
3059
- safeParseBuildManifest,
3060
- safeParseCDNDependency,
3061
- safeParseFileTemplateConfig,
3062
- supportsHandlebars,
3063
- validateBuildManifest,
3064
- validateCDNDependency,
3065
- validateFileTemplateConfig,
3066
- validateImportMap,
3067
- validateTemplateUrl
3068
- };