@frontmcp/uipack 0.6.3 → 0.7.2

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 (56) hide show
  1. package/CLAUDE.md +0 -14
  2. package/adapters/index.js +50 -47
  3. package/adapters/platform-meta.d.ts.map +1 -1
  4. package/adapters/response-builder.d.ts +16 -3
  5. package/adapters/response-builder.d.ts.map +1 -1
  6. package/bridge-runtime/iife-generator.d.ts.map +1 -1
  7. package/bridge-runtime/index.js +4 -0
  8. package/build/index.d.ts +1 -1
  9. package/build/index.d.ts.map +1 -1
  10. package/build/index.js +61 -69
  11. package/bundler/index.js +35 -34
  12. package/dependency/import-map.d.ts.map +1 -1
  13. package/dependency/index.js +22 -29
  14. package/esm/adapters/index.mjs +52 -42
  15. package/esm/bridge-runtime/index.mjs +4 -0
  16. package/esm/build/index.mjs +30 -32
  17. package/esm/bundler/index.mjs +19 -11
  18. package/esm/dependency/index.mjs +18 -18
  19. package/esm/handlebars/index.mjs +9 -8
  20. package/esm/index.mjs +107 -126
  21. package/esm/package.json +3 -2
  22. package/esm/registry/index.mjs +53 -49
  23. package/esm/renderers/index.mjs +15 -21
  24. package/esm/runtime/index.mjs +16 -15
  25. package/esm/theme/index.mjs +8 -0
  26. package/esm/tool-template/index.mjs +23 -15
  27. package/esm/typings/index.mjs +4 -0
  28. package/esm/utils/index.mjs +9 -56
  29. package/esm/validation/index.mjs +9 -8
  30. package/handlebars/index.js +4 -10
  31. package/index.js +186 -211
  32. package/package.json +3 -2
  33. package/preview/generic-preview.d.ts +4 -5
  34. package/preview/generic-preview.d.ts.map +1 -1
  35. package/preview/types.d.ts +15 -1
  36. package/preview/types.d.ts.map +1 -1
  37. package/registry/index.js +61 -63
  38. package/registry/render-template.d.ts.map +1 -1
  39. package/renderers/index.js +16 -28
  40. package/renderers/utils/detect.d.ts.map +1 -1
  41. package/runtime/index.js +20 -25
  42. package/runtime/sanitizer.d.ts.map +1 -1
  43. package/theme/css-to-theme.d.ts +0 -27
  44. package/theme/css-to-theme.d.ts.map +1 -1
  45. package/theme/index.js +8 -0
  46. package/tool-template/index.js +30 -28
  47. package/typings/dts-parser.d.ts.map +1 -1
  48. package/typings/index.js +4 -0
  49. package/utils/index.d.ts +2 -3
  50. package/utils/index.d.ts.map +1 -1
  51. package/utils/index.js +7 -63
  52. package/validation/index.js +6 -12
  53. package/utils/escape-html.d.ts +0 -102
  54. package/utils/escape-html.d.ts.map +0 -1
  55. package/utils/safe-stringify.d.ts +0 -30
  56. package/utils/safe-stringify.d.ts.map +0 -1
@@ -1192,23 +1192,8 @@ function getImportStats(source) {
1192
1192
  };
1193
1193
  }
1194
1194
 
1195
- // libs/uipack/src/utils/escape-html.ts
1196
- function escapeHtml(str) {
1197
- if (str === null || str === void 0) {
1198
- return "";
1199
- }
1200
- const s = String(str);
1201
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
1202
- }
1203
- function escapeHtmlAttr(str) {
1204
- return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
1205
- }
1206
- function escapeJsString(str) {
1207
- return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
1208
- }
1209
- function escapeScriptClose(jsonString) {
1210
- return jsonString.replace(/<\//g, "<\\/");
1211
- }
1195
+ // libs/uipack/src/utils/index.ts
1196
+ var import_utils = require("@frontmcp/utils");
1212
1197
 
1213
1198
  // libs/uipack/src/dependency/import-map.ts
1214
1199
  function createImportMap(dependencies) {
@@ -1299,13 +1284,16 @@ function generateUMDShim(dependencies, options = {}) {
1299
1284
  console.warn('UMD shim failed:', e);
1300
1285
  }
1301
1286
  })();` : `window.__esm_shim = ${shimObject};`;
1302
- return minify ? code.replace(/\s+/g, " ").replace(/\s*([{},:])\s*/g, "$1") : code;
1287
+ if (minify && code.length <= 1e5) {
1288
+ return code.replace(/\s+/g, " ").replace(/\s*([{},:])\s*/g, "$1");
1289
+ }
1290
+ return code;
1303
1291
  }
1304
1292
  function generateCDNScriptTags(dependencies) {
1305
1293
  return dependencies.filter((dep) => !dep.esm).map((dep) => {
1306
- const attrs = [`src="${escapeHtmlAttr(dep.cdnUrl)}"`];
1294
+ const attrs = [`src="${(0, import_utils.escapeHtmlAttr)(dep.cdnUrl)}"`];
1307
1295
  if (dep.integrity) {
1308
- attrs.push(`integrity="${escapeHtmlAttr(dep.integrity)}"`);
1296
+ attrs.push(`integrity="${(0, import_utils.escapeHtmlAttr)(dep.integrity)}"`);
1309
1297
  }
1310
1298
  attrs.push('crossorigin="anonymous"');
1311
1299
  return `<script ${attrs.join(" ")}></script>`;
@@ -1313,9 +1301,9 @@ function generateCDNScriptTags(dependencies) {
1313
1301
  }
1314
1302
  function generateESMScriptTags(dependencies) {
1315
1303
  return dependencies.filter((dep) => dep.esm).map((dep) => {
1316
- const attrs = ['type="module"', `src="${escapeHtmlAttr(dep.cdnUrl)}"`];
1304
+ const attrs = ['type="module"', `src="${(0, import_utils.escapeHtmlAttr)(dep.cdnUrl)}"`];
1317
1305
  if (dep.integrity) {
1318
- attrs.push(`integrity="${escapeHtmlAttr(dep.integrity)}"`);
1306
+ attrs.push(`integrity="${(0, import_utils.escapeHtmlAttr)(dep.integrity)}"`);
1319
1307
  }
1320
1308
  attrs.push('crossorigin="anonymous"');
1321
1309
  return `<script ${attrs.join(" ")}></script>`;
@@ -1598,6 +1586,7 @@ var import_path = require("path");
1598
1586
 
1599
1587
  // libs/uipack/src/bundler/file-cache/hash-calculator.ts
1600
1588
  var import_crypto = require("crypto");
1589
+ var import_utils3 = require("@frontmcp/utils");
1601
1590
  function sha256(content) {
1602
1591
  return (0, import_crypto.createHash)("sha256").update(content, "utf8").digest("hex");
1603
1592
  }
@@ -1966,7 +1955,7 @@ function classNames(...classes) {
1966
1955
  }
1967
1956
  var builtinHelpers = {
1968
1957
  // Escaping
1969
- escapeHtml,
1958
+ escapeHtml: import_utils.escapeHtml,
1970
1959
  // Formatting
1971
1960
  formatDate,
1972
1961
  formatCurrency,
@@ -2279,7 +2268,11 @@ function containsHandlebars(template) {
2279
2268
  }
2280
2269
 
2281
2270
  // libs/uipack/src/renderers/utils/detect.ts
2271
+ var MAX_TEMPLATE_LENGTH = 5e4;
2282
2272
  function containsMdxSyntax(source) {
2273
+ if (source.length > MAX_TEMPLATE_LENGTH) {
2274
+ return false;
2275
+ }
2283
2276
  if (/<[A-Z][a-zA-Z0-9]*/.test(source)) {
2284
2277
  return true;
2285
2278
  }
@@ -2566,12 +2559,12 @@ var MdxClientRenderer = class {
2566
2559
  ...outputProps,
2567
2560
  ...props
2568
2561
  };
2569
- const escapedMdx = escapeScriptClose(JSON.stringify(template));
2570
- const escapedProps = escapeScriptClose(JSON.stringify(spreadProps));
2571
- const safeContainerId = escapeJsString(containerId);
2572
- const loadingHtml = showLoading ? `<div class="mdx-loading">${escapeHtml(loadingMessage)}</div>` : "";
2562
+ const escapedMdx = (0, import_utils.escapeScriptClose)(JSON.stringify(template));
2563
+ const escapedProps = (0, import_utils.escapeScriptClose)(JSON.stringify(spreadProps));
2564
+ const safeContainerId = (0, import_utils.escapeJsString)(containerId);
2565
+ const loadingHtml = showLoading ? `<div class="mdx-loading">${(0, import_utils.escapeHtml)(loadingMessage)}</div>` : "";
2573
2566
  return `
2574
- <div id="${escapeHtml(containerId)}">${loadingHtml}</div>
2567
+ <div id="${(0, import_utils.escapeHtml)(containerId)}">${loadingHtml}</div>
2575
2568
  <script type="module">
2576
2569
  (async function() {
2577
2570
  try {
@@ -2912,7 +2905,7 @@ function safeInputToRecord(input) {
2912
2905
  return {};
2913
2906
  }
2914
2907
  var defaultHelpers = {
2915
- escapeHtml,
2908
+ escapeHtml: import_utils.escapeHtml,
2916
2909
  formatDate: (date, format) => {
2917
2910
  const d = date instanceof Date ? date : new Date(date);
2918
2911
  if (format === "iso") return d.toISOString();
@@ -28,16 +28,13 @@ function buildUIMeta(options) {
28
28
  case "generic-mcp":
29
29
  case "gemini":
30
30
  default:
31
- meta["frontmcp/html"] = html;
32
- meta["frontmcp/mimeType"] = "text/html+mcp";
33
- if (rendererType) meta["frontmcp/type"] = rendererType;
34
- if (contentHash) meta["frontmcp/contentHash"] = contentHash;
35
- if (manifestUri) meta["frontmcp/manifestUri"] = manifestUri;
36
- if (token) meta["frontmcp/widgetToken"] = token;
37
- if (directUrl) meta["frontmcp/directUrl"] = directUrl;
38
31
  meta["ui/html"] = html;
39
32
  meta["ui/mimeType"] = "text/html+mcp";
40
33
  if (rendererType) meta["ui/type"] = rendererType;
34
+ if (contentHash) meta["ui/contentHash"] = contentHash;
35
+ if (manifestUri) meta["ui/manifestUri"] = manifestUri;
36
+ if (token) meta["ui/widgetToken"] = token;
37
+ if (directUrl) meta["ui/directUrl"] = directUrl;
41
38
  if (platformType === "claude") {
42
39
  return buildClaudeMeta(meta, uiConfig);
43
40
  } else if (platformType === "gemini") {
@@ -107,23 +104,36 @@ function buildFrontMCPCSP(csp) {
107
104
  return result;
108
105
  }
109
106
  function buildGenericMeta(meta, uiConfig) {
110
- if (uiConfig.widgetAccessible) {
111
- meta["frontmcp/widgetAccessible"] = true;
112
- }
113
107
  if (uiConfig.csp) {
114
- meta["frontmcp/widgetCSP"] = buildFrontMCPCSP(uiConfig.csp);
108
+ const csp = {};
109
+ if (uiConfig.csp.connectDomains?.length) {
110
+ csp.connectDomains = uiConfig.csp.connectDomains;
111
+ }
112
+ if (uiConfig.csp.resourceDomains?.length) {
113
+ csp.resourceDomains = uiConfig.csp.resourceDomains;
114
+ }
115
+ if (Object.keys(csp).length > 0) {
116
+ meta["ui/csp"] = csp;
117
+ }
115
118
  }
116
119
  if (uiConfig.displayMode) {
117
- meta["frontmcp/displayMode"] = uiConfig.displayMode;
118
- }
119
- if (uiConfig.widgetDescription) {
120
- meta["frontmcp/widgetDescription"] = uiConfig.widgetDescription;
120
+ const displayModeMap = {
121
+ inline: "inline",
122
+ fullscreen: "fullscreen",
123
+ pip: "pip",
124
+ widget: "inline",
125
+ panel: "fullscreen"
126
+ };
127
+ const mappedMode = displayModeMap[uiConfig.displayMode];
128
+ if (mappedMode) {
129
+ meta["ui/displayMode"] = mappedMode;
130
+ }
121
131
  }
122
132
  if (uiConfig.prefersBorder !== void 0) {
123
- meta["frontmcp/prefersBorder"] = uiConfig.prefersBorder;
133
+ meta["ui/prefersBorder"] = uiConfig.prefersBorder;
124
134
  }
125
135
  if (uiConfig.sandboxDomain) {
126
- meta["frontmcp/domain"] = uiConfig.sandboxDomain;
136
+ meta["ui/domain"] = uiConfig.sandboxDomain;
127
137
  }
128
138
  return meta;
129
139
  }
@@ -353,25 +363,15 @@ function platformSupportsWidgets(platformType) {
353
363
  return capabilities.supportsWidgets;
354
364
  }
355
365
 
356
- // libs/uipack/src/utils/safe-stringify.ts
357
- function safeStringify(value, space) {
358
- const seen = /* @__PURE__ */ new WeakSet();
359
- try {
360
- return JSON.stringify(
361
- value,
362
- (_key, val) => {
363
- if (typeof val === "object" && val !== null) {
364
- if (seen.has(val)) return "[Circular]";
365
- seen.add(val);
366
- }
367
- return val;
368
- },
369
- space
370
- );
371
- } catch {
372
- return JSON.stringify({ error: "Output could not be serialized" });
373
- }
374
- }
366
+ // libs/uipack/src/utils/index.ts
367
+ import {
368
+ safeStringify,
369
+ escapeHtml,
370
+ escapeHtmlAttr,
371
+ escapeJsString,
372
+ escapeScriptClose,
373
+ safeJsonForScript
374
+ } from "@frontmcp/utils";
375
375
 
376
376
  // libs/uipack/src/adapters/response-builder.ts
377
377
  function buildToolResponseContent(options) {
@@ -394,12 +394,22 @@ function buildToolResponseContent(options) {
394
394
  }
395
395
  if (useStructuredContent) {
396
396
  if (htmlContent) {
397
- return {
398
- content: [{ type: "text", text: htmlContent }],
399
- structuredContent: rawOutput,
400
- contentCleared: false,
401
- format: "structured-content"
402
- };
397
+ const htmlInContent = platformType === "openai" || platformType === "ext-apps";
398
+ if (htmlInContent) {
399
+ return {
400
+ content: [{ type: "text", text: htmlContent }],
401
+ structuredContent: rawOutput,
402
+ contentCleared: false,
403
+ format: "structured-content"
404
+ };
405
+ } else {
406
+ return {
407
+ content: [{ type: "text", text: safeStringify(rawOutput) }],
408
+ structuredContent: rawOutput,
409
+ contentCleared: false,
410
+ format: "structured-content"
411
+ };
412
+ }
403
413
  }
404
414
  return {
405
415
  content: [{ type: "text", text: safeStringify(rawOutput) }],
@@ -823,7 +823,11 @@ FrontMcpBridge.prototype._setupDataToolCallHandler = function() {
823
823
  };
824
824
  `.trim();
825
825
  }
826
+ var MAX_MINIFY_CODE_LENGTH = 5e5;
826
827
  function minifyJS(code) {
828
+ if (code.length > MAX_MINIFY_CODE_LENGTH) {
829
+ return code;
830
+ }
827
831
  return code.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "").replace(/\s+/g, " ").replace(/\s*([{};,:()[\]])\s*/g, "$1").replace(/;\}/g, "}").trim();
828
832
  }
829
833
  function generatePlatformBundle(platform, options = {}) {
@@ -8,34 +8,18 @@ var __export = (target, all) => {
8
8
  __defProp(target, name, { get: all[name], enumerable: true });
9
9
  };
10
10
 
11
- // libs/uipack/src/utils/escape-html.ts
12
- function escapeHtml(str) {
13
- if (str === null || str === void 0) {
14
- return "";
15
- }
16
- const s = String(str);
17
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
18
- }
19
- function escapeHtmlAttr(str) {
20
- return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
21
- }
22
- function escapeJsString(str) {
23
- return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
24
- }
25
- function escapeScriptClose(jsonString) {
26
- return jsonString.replace(/<\//g, "<\\/");
27
- }
28
- var init_escape_html = __esm({
29
- "libs/uipack/src/utils/escape-html.ts"() {
30
- "use strict";
31
- }
32
- });
33
-
34
11
  // libs/uipack/src/utils/index.ts
12
+ import {
13
+ safeStringify,
14
+ escapeHtml,
15
+ escapeHtmlAttr,
16
+ escapeJsString,
17
+ escapeScriptClose,
18
+ safeJsonForScript
19
+ } from "@frontmcp/utils";
35
20
  var init_utils = __esm({
36
21
  "libs/uipack/src/utils/index.ts"() {
37
22
  "use strict";
38
- init_escape_html();
39
23
  }
40
24
  });
41
25
 
@@ -642,9 +626,9 @@ var init_handlebars = __esm({
642
626
 
643
627
  // libs/uipack/src/bundler/file-cache/hash-calculator.ts
644
628
  import { createHash } from "crypto";
645
- import { readFile } from "fs/promises";
646
629
  import { existsSync } from "fs";
647
630
  import { join as join2, dirname, resolve } from "path";
631
+ import { readFile, readFileBuffer } from "@frontmcp/utils";
648
632
  function sha256(content) {
649
633
  return createHash("sha256").update(content, "utf8").digest("hex");
650
634
  }
@@ -653,7 +637,7 @@ function sha256Buffer(buffer) {
653
637
  }
654
638
  async function hashFile(filePath) {
655
639
  try {
656
- const content = await readFile(filePath);
640
+ const content = await readFileBuffer(filePath);
657
641
  return sha256Buffer(content);
658
642
  } catch {
659
643
  return void 0;
@@ -699,7 +683,7 @@ async function collectLocalDependencies(filePath, baseDir, collected, maxDepth,
699
683
  if (!existsSync(filePath)) return;
700
684
  collected.add(filePath);
701
685
  try {
702
- const content = await readFile(filePath, "utf8");
686
+ const content = await readFile(filePath);
703
687
  const imports = extractImportPaths(content);
704
688
  for (const importPath of imports) {
705
689
  if (!importPath.startsWith(".") && !importPath.startsWith("/")) {
@@ -1587,7 +1571,10 @@ function generateUMDShim(dependencies, options = {}) {
1587
1571
  console.warn('UMD shim failed:', e);
1588
1572
  }
1589
1573
  })();` : `window.__esm_shim = ${shimObject};`;
1590
- return minify ? code.replace(/\s+/g, " ").replace(/\s*([{},:])\s*/g, "$1") : code;
1574
+ if (minify && code.length <= 1e5) {
1575
+ return code.replace(/\s+/g, " ").replace(/\s*([{},:])\s*/g, "$1");
1576
+ }
1577
+ return code;
1591
1578
  }
1592
1579
  function generateCDNScriptTags(dependencies) {
1593
1580
  return dependencies.filter((dep) => !dep.esm).map((dep) => {
@@ -1865,10 +1852,10 @@ __export(filesystem_exports, {
1865
1852
  StorageNotInitializedError: () => StorageNotInitializedError,
1866
1853
  createFilesystemStorage: () => createFilesystemStorage
1867
1854
  });
1868
- import { mkdir, readFile as readFile2, writeFile, readdir, unlink, rm } from "fs/promises";
1869
1855
  import { join as join3, dirname as dirname2 } from "path";
1870
1856
  import { existsSync as existsSync2 } from "fs";
1871
1857
  import { createHash as createHash2 } from "crypto";
1858
+ import { mkdir, readFile as readFile2, writeFile, readdir, unlink, rm } from "@frontmcp/utils";
1872
1859
  function createFilesystemStorage(options) {
1873
1860
  return new FilesystemStorage(options);
1874
1861
  }
@@ -2104,7 +2091,7 @@ var init_filesystem = __esm({
2104
2091
  */
2105
2092
  async writeEntry(filePath, entry) {
2106
2093
  await mkdir(dirname2(filePath), { recursive: true });
2107
- await writeFile(filePath, JSON.stringify(entry, null, 2), "utf8");
2094
+ await writeFile(filePath, JSON.stringify(entry, null, 2));
2108
2095
  }
2109
2096
  /**
2110
2097
  * Ensure the storage is initialized.
@@ -2467,10 +2454,10 @@ __export(component_builder_exports, {
2467
2454
  createFilesystemBuilder: () => createFilesystemBuilder,
2468
2455
  createRedisBuilder: () => createRedisBuilder
2469
2456
  });
2470
- import { readFile as readFile3 } from "fs/promises";
2471
2457
  import { existsSync as existsSync3 } from "fs";
2472
2458
  import { resolve as resolve2, extname, basename } from "path";
2473
2459
  import { randomUUID } from "crypto";
2460
+ import { readFile as readFile3 } from "@frontmcp/utils";
2474
2461
  async function createFilesystemBuilder(cacheDir = ".frontmcp-cache/builds") {
2475
2462
  const { FilesystemStorage: FilesystemStorage2 } = await Promise.resolve().then(() => (init_filesystem(), filesystem_exports));
2476
2463
  const storage = new FilesystemStorage2({ cacheDir });
@@ -3561,7 +3548,11 @@ FrontMcpBridge.prototype._setupDataToolCallHandler = function() {
3561
3548
  };
3562
3549
  `.trim();
3563
3550
  }
3551
+ var MAX_MINIFY_CODE_LENGTH = 5e5;
3564
3552
  function minifyJS(code) {
3553
+ if (code.length > MAX_MINIFY_CODE_LENGTH) {
3554
+ return code;
3555
+ }
3565
3556
  return code.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "").replace(/\s+/g, " ").replace(/\s*([{};,:()[\]])\s*/g, "$1").replace(/;\}/g, "}").trim();
3566
3557
  }
3567
3558
  function generatePlatformBundle(platform, options = {}) {
@@ -4374,6 +4365,7 @@ function buildFrameworkRuntimeScriptsUniversal(options) {
4374
4365
  }
4375
4366
 
4376
4367
  // libs/uipack/src/renderers/utils/detect.ts
4368
+ var MAX_TEMPLATE_LENGTH = 5e4;
4377
4369
  function isReactComponent(value) {
4378
4370
  if (typeof value !== "function") {
4379
4371
  return false;
@@ -4402,6 +4394,9 @@ function isTemplateBuilderFunction(fn) {
4402
4394
  return true;
4403
4395
  }
4404
4396
  function containsJsx(source) {
4397
+ if (source.length > MAX_TEMPLATE_LENGTH) {
4398
+ return false;
4399
+ }
4405
4400
  if (/<[A-Z][a-zA-Z0-9]*(\s|>|\/)/.test(source)) {
4406
4401
  return true;
4407
4402
  }
@@ -4426,6 +4421,9 @@ function containsJsx(source) {
4426
4421
  return false;
4427
4422
  }
4428
4423
  function containsMdxSyntax(source) {
4424
+ if (source.length > MAX_TEMPLATE_LENGTH) {
4425
+ return false;
4426
+ }
4429
4427
  if (/<[A-Z][a-zA-Z0-9]*/.test(source)) {
4430
4428
  return true;
4431
4429
  }
@@ -5567,7 +5565,7 @@ function getSchemaPathStrings(schema, prefix = "output") {
5567
5565
  }
5568
5566
 
5569
5567
  // libs/uipack/src/validation/template-validator.ts
5570
- init_expression_extractor();
5568
+ init_handlebars();
5571
5569
  function validateTemplate(template, outputSchema, options = {}) {
5572
5570
  const { inputSchema, warnOnOptional = true, suggestSimilar = true, maxSuggestionDistance = 3 } = options;
5573
5571
  const errors = [];
@@ -40,10 +40,10 @@ __export(filesystem_exports, {
40
40
  StorageNotInitializedError: () => StorageNotInitializedError,
41
41
  createFilesystemStorage: () => createFilesystemStorage
42
42
  });
43
- import { mkdir, readFile, writeFile, readdir, unlink, rm } from "fs/promises";
44
43
  import { join, dirname } from "path";
45
44
  import { existsSync } from "fs";
46
45
  import { createHash } from "crypto";
46
+ import { mkdir, readFile, writeFile, readdir, unlink, rm } from "@frontmcp/utils";
47
47
  function createFilesystemStorage(options) {
48
48
  return new FilesystemStorage(options);
49
49
  }
@@ -279,7 +279,7 @@ var init_filesystem = __esm({
279
279
  */
280
280
  async writeEntry(filePath, entry) {
281
281
  await mkdir(dirname(filePath), { recursive: true });
282
- await writeFile(filePath, JSON.stringify(entry, null, 2), "utf8");
282
+ await writeFile(filePath, JSON.stringify(entry, null, 2));
283
283
  }
284
284
  /**
285
285
  * Ensure the storage is initialized.
@@ -1398,9 +1398,9 @@ init_redis();
1398
1398
 
1399
1399
  // libs/uipack/src/bundler/file-cache/hash-calculator.ts
1400
1400
  import { createHash as createHash2 } from "crypto";
1401
- import { readFile as readFile2 } from "fs/promises";
1402
1401
  import { existsSync as existsSync2 } from "fs";
1403
1402
  import { join as join2, dirname as dirname2, resolve } from "path";
1403
+ import { readFile as readFile2, readFileBuffer } from "@frontmcp/utils";
1404
1404
  function sha256(content) {
1405
1405
  return createHash2("sha256").update(content, "utf8").digest("hex");
1406
1406
  }
@@ -1409,7 +1409,7 @@ function sha256Buffer(buffer) {
1409
1409
  }
1410
1410
  async function hashFile(filePath) {
1411
1411
  try {
1412
- const content = await readFile2(filePath);
1412
+ const content = await readFileBuffer(filePath);
1413
1413
  return sha256Buffer(content);
1414
1414
  } catch {
1415
1415
  return void 0;
@@ -1470,7 +1470,7 @@ async function collectLocalDependencies(filePath, baseDir, collected, maxDepth,
1470
1470
  if (!existsSync2(filePath)) return;
1471
1471
  collected.add(filePath);
1472
1472
  try {
1473
- const content = await readFile2(filePath, "utf8");
1473
+ const content = await readFile2(filePath);
1474
1474
  const imports = extractImportPaths(content);
1475
1475
  for (const importPath of imports) {
1476
1476
  if (!importPath.startsWith(".") && !importPath.startsWith("/")) {
@@ -1544,10 +1544,10 @@ function buildIdFromHash(hash) {
1544
1544
  }
1545
1545
 
1546
1546
  // libs/uipack/src/bundler/file-cache/component-builder.ts
1547
- import { readFile as readFile3 } from "fs/promises";
1548
1547
  import { existsSync as existsSync3 } from "fs";
1549
1548
  import { resolve as resolve2, extname, basename } from "path";
1550
1549
  import { randomUUID } from "crypto";
1550
+ import { readFile as readFile3 } from "@frontmcp/utils";
1551
1551
 
1552
1552
  // libs/uipack/src/dependency/cdn-registry.ts
1553
1553
  var DEFAULT_CDN_REGISTRY = {
@@ -2310,10 +2310,15 @@ function parseImports(source) {
2310
2310
  };
2311
2311
  }
2312
2312
 
2313
- // libs/uipack/src/utils/escape-html.ts
2314
- function escapeHtmlAttr(str) {
2315
- return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
2316
- }
2313
+ // libs/uipack/src/utils/index.ts
2314
+ import {
2315
+ safeStringify,
2316
+ escapeHtml,
2317
+ escapeHtmlAttr,
2318
+ escapeJsString,
2319
+ escapeScriptClose,
2320
+ safeJsonForScript
2321
+ } from "@frontmcp/utils";
2317
2322
 
2318
2323
  // libs/uipack/src/dependency/import-map.ts
2319
2324
  function createImportMap(dependencies) {
@@ -2360,7 +2365,10 @@ function generateUMDShim(dependencies, options = {}) {
2360
2365
  console.warn('UMD shim failed:', e);
2361
2366
  }
2362
2367
  })();` : `window.__esm_shim = ${shimObject};`;
2363
- return minify ? code.replace(/\s+/g, " ").replace(/\s*([{},:])\s*/g, "$1") : code;
2368
+ if (minify && code.length <= 1e5) {
2369
+ return code.replace(/\s+/g, " ").replace(/\s*([{},:])\s*/g, "$1");
2370
+ }
2371
+ return code;
2364
2372
  }
2365
2373
  function generateCDNScriptTags(dependencies) {
2366
2374
  return dependencies.filter((dep) => !dep.esm).map((dep) => {
@@ -1074,23 +1074,15 @@ function getImportStats(source) {
1074
1074
  };
1075
1075
  }
1076
1076
 
1077
- // libs/uipack/src/utils/escape-html.ts
1078
- function escapeHtml(str) {
1079
- if (str === null || str === void 0) {
1080
- return "";
1081
- }
1082
- const s = String(str);
1083
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
1084
- }
1085
- function escapeHtmlAttr(str) {
1086
- return str.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
1087
- }
1088
- function escapeJsString(str) {
1089
- return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
1090
- }
1091
- function escapeScriptClose(jsonString) {
1092
- return jsonString.replace(/<\//g, "<\\/");
1093
- }
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";
1094
1086
 
1095
1087
  // libs/uipack/src/dependency/import-map.ts
1096
1088
  function createImportMap(dependencies) {
@@ -1181,7 +1173,10 @@ function generateUMDShim(dependencies, options = {}) {
1181
1173
  console.warn('UMD shim failed:', e);
1182
1174
  }
1183
1175
  })();` : `window.__esm_shim = ${shimObject};`;
1184
- return minify ? code.replace(/\s+/g, " ").replace(/\s*([{},:])\s*/g, "$1") : code;
1176
+ if (minify && code.length <= 1e5) {
1177
+ return code.replace(/\s+/g, " ").replace(/\s*([{},:])\s*/g, "$1");
1178
+ }
1179
+ return code;
1185
1180
  }
1186
1181
  function generateCDNScriptTags(dependencies) {
1187
1182
  return dependencies.filter((dep) => !dep.esm).map((dep) => {
@@ -1480,6 +1475,7 @@ import { resolve as resolvePath, isAbsolute, sep } from "path";
1480
1475
 
1481
1476
  // libs/uipack/src/bundler/file-cache/hash-calculator.ts
1482
1477
  import { createHash } from "crypto";
1478
+ import { readFile, readFileBuffer } from "@frontmcp/utils";
1483
1479
  function sha256(content) {
1484
1480
  return createHash("sha256").update(content, "utf8").digest("hex");
1485
1481
  }
@@ -2161,7 +2157,11 @@ function containsHandlebars(template) {
2161
2157
  }
2162
2158
 
2163
2159
  // libs/uipack/src/renderers/utils/detect.ts
2160
+ var MAX_TEMPLATE_LENGTH = 5e4;
2164
2161
  function containsMdxSyntax(source) {
2162
+ if (source.length > MAX_TEMPLATE_LENGTH) {
2163
+ return false;
2164
+ }
2165
2165
  if (/<[A-Z][a-zA-Z0-9]*/.test(source)) {
2166
2166
  return true;
2167
2167
  }
@@ -1,11 +1,12 @@
1
- // libs/uipack/src/utils/escape-html.ts
2
- function escapeHtml(str) {
3
- if (str === null || str === void 0) {
4
- return "";
5
- }
6
- const s = String(str);
7
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
8
- }
1
+ // libs/uipack/src/utils/index.ts
2
+ import {
3
+ safeStringify,
4
+ escapeHtml,
5
+ escapeHtmlAttr,
6
+ escapeJsString,
7
+ escapeScriptClose,
8
+ safeJsonForScript
9
+ } from "@frontmcp/utils";
9
10
 
10
11
  // libs/uipack/src/handlebars/helpers.ts
11
12
  function formatDate(date, format) {