@json-to-office/jto 0.38.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/cli.js +51 -40
  2. package/dist/cli.js.map +1 -1
  3. package/dist/client/assets/HomePage-D3vuZyJI.js +106 -0
  4. package/dist/client/assets/HomePage-D3vuZyJI.js.map +1 -0
  5. package/dist/client/assets/{JsonEditorPage-DcXk6s88.js → JsonEditorPage-Cqy_bBQ5.js} +3 -3
  6. package/dist/client/assets/{JsonEditorPage-DcXk6s88.js.map → JsonEditorPage-Cqy_bBQ5.js.map} +1 -1
  7. package/dist/client/assets/{MonacoPluginProvider-iwEEsKo7.js → MonacoPluginProvider-BNFHf2Mg.js} +3 -3
  8. package/dist/client/assets/MonacoPluginProvider-BNFHf2Mg.js.map +1 -0
  9. package/dist/client/assets/{NotFoundPage-SV9cseZ6.js → NotFoundPage-rSUaByPC.js} +2 -2
  10. package/dist/client/assets/{NotFoundPage-SV9cseZ6.js.map → NotFoundPage-rSUaByPC.js.map} +1 -1
  11. package/dist/client/assets/editor-CN0fauKm.js +9 -0
  12. package/dist/client/assets/editor-CN0fauKm.js.map +1 -0
  13. package/dist/client/assets/{editor-monaco-json-Dg4yC3gC.js → editor-monaco-json-HXjjUFz_.js} +2 -2
  14. package/dist/client/assets/{editor-monaco-json-Dg4yC3gC.js.map → editor-monaco-json-HXjjUFz_.js.map} +1 -1
  15. package/dist/client/assets/{editor-refs-store-B2riWLl0.js → editor-refs-store-C7y0QHBG.js} +2 -2
  16. package/dist/client/assets/{editor-refs-store-B2riWLl0.js.map → editor-refs-store-C7y0QHBG.js.map} +1 -1
  17. package/dist/client/assets/index-CNvLzaJ7.css +1 -0
  18. package/dist/client/assets/index-ClBlf8v3.js +5 -0
  19. package/dist/client/assets/index-ClBlf8v3.js.map +1 -0
  20. package/dist/client/assets/{monaco-editor-BcgxPCqT.js → monaco-editor-DJsdM0WK.js} +2 -2
  21. package/dist/client/assets/{monaco-editor-BcgxPCqT.js.map → monaco-editor-DJsdM0WK.js.map} +1 -1
  22. package/dist/client/assets/preview-BoIgsKxW.js +2 -0
  23. package/dist/client/assets/preview-BoIgsKxW.js.map +1 -0
  24. package/dist/client/assets/{query-vendor-Df8-oete.js → query-vendor--rhYD8mC.js} +2 -2
  25. package/dist/client/assets/{query-vendor-Df8-oete.js.map → query-vendor--rhYD8mC.js.map} +1 -1
  26. package/dist/client/assets/radix-ui-DFNP5I4e.js +51 -0
  27. package/dist/client/assets/radix-ui-DFNP5I4e.js.map +1 -0
  28. package/dist/client/assets/{react-vendor-CTFDOf2G.js → react-vendor-BmQ2Ko_D.js} +2 -2
  29. package/dist/client/assets/{react-vendor-CTFDOf2G.js.map → react-vendor-BmQ2Ko_D.js.map} +1 -1
  30. package/dist/client/assets/{state-vendor-ByFYl9bq.js → state-vendor-Cq67_JbF.js} +2 -2
  31. package/dist/client/assets/{state-vendor-ByFYl9bq.js.map → state-vendor-Cq67_JbF.js.map} +1 -1
  32. package/dist/client/assets/{ui-vendor-DyQLnWB8.js → ui-vendor-DpjQWJgX.js} +24 -29
  33. package/dist/client/assets/ui-vendor-DpjQWJgX.js.map +1 -0
  34. package/dist/client/index.html +8 -8
  35. package/package.json +7 -8
  36. package/dist/client/assets/HomePage-C4xj6RnX.js +0 -106
  37. package/dist/client/assets/HomePage-C4xj6RnX.js.map +0 -1
  38. package/dist/client/assets/MonacoPluginProvider-iwEEsKo7.js.map +0 -1
  39. package/dist/client/assets/docx-preview-DQa8jhzH.js +0 -34
  40. package/dist/client/assets/docx-preview-DQa8jhzH.js.map +0 -1
  41. package/dist/client/assets/editor-p__9lo1t.js +0 -9
  42. package/dist/client/assets/editor-p__9lo1t.js.map +0 -1
  43. package/dist/client/assets/index-CboJPFqh.js +0 -5
  44. package/dist/client/assets/index-CboJPFqh.js.map +0 -1
  45. package/dist/client/assets/index-CnUTzeor.css +0 -1
  46. package/dist/client/assets/preview-Qj-FLOiI.js +0 -4
  47. package/dist/client/assets/preview-Qj-FLOiI.js.map +0 -1
  48. package/dist/client/assets/radix-ui-Bq-7y_Sq.js +0 -51
  49. package/dist/client/assets/radix-ui-Bq-7y_Sq.js.map +0 -1
  50. package/dist/client/assets/ui-vendor-DyQLnWB8.js.map +0 -1
  51. package/dist/client/css/preview/docxjs.css +0 -11
package/dist/cli.js CHANGED
@@ -443,6 +443,7 @@ var init_generator = __esm({
443
443
  );
444
444
  const bypassCache = options?.bypassCache === true || extraEntries.length > 0 || declaresRegistry;
445
445
  const baseDir = typeof options?.baseDir === "string" ? options.baseDir : void 0;
446
+ const renderer = typeof options?.renderer === "string" ? options.renderer : void 0;
446
447
  const cacheKeyData = {
447
448
  config: config2,
448
449
  customThemes: customThemes && Object.keys(customThemes).length > 0 ? customThemes : null,
@@ -450,7 +451,10 @@ var init_generator = __esm({
450
451
  fontSubstitution: fontSubstitution ?? null,
451
452
  fontStrict: callerStrict ?? null,
452
453
  // Same definition, different source directory → different local assets.
453
- baseDir: baseDir ?? null
454
+ baseDir: baseDir ?? null,
455
+ // Same document, different backend → different bytes. Without this,
456
+ // switching backends would serve the other one's cached buffer.
457
+ renderer: renderer ?? null
454
458
  };
455
459
  const cacheKey = this.cacheService.generateCacheKey(cacheKeyData);
456
460
  const hasDynamicContent = this.cacheService.hasDynamicContent(config2);
@@ -492,6 +496,7 @@ var init_generator = __esm({
492
496
  customThemes,
493
497
  fonts: fontOpts,
494
498
  baseDir,
499
+ renderer,
495
500
  warnings: coreWarnings
496
501
  });
497
502
  buffer = await generator.generateBuffer(config2);
@@ -500,6 +505,7 @@ var init_generator = __esm({
500
505
  customThemes,
501
506
  fonts: fontOpts,
502
507
  baseDir,
508
+ renderer,
503
509
  warnings: coreWarnings
504
510
  });
505
511
  }
@@ -1052,6 +1058,10 @@ var init_loose = __esm({
1052
1058
  bypassCache: Type.Optional(Type.Boolean()),
1053
1059
  returnUrl: Type.Optional(Type.Boolean()),
1054
1060
  fonts: Type.Optional(FontOptionsSchema),
1061
+ // Backend to render with. Left as a bounded string rather than an
1062
+ // enum: the registry owns the list, answers an unknown id with the
1063
+ // ids that exist, and the route turns that into a 400.
1064
+ renderer: Type.Optional(Type.String({ maxLength: 64 })),
1055
1065
  // Name of the discovered document this definition came from; the
1056
1066
  // server maps it to that document's directory so relative asset
1057
1067
  // paths resolve against it (#142). Names, never paths — a client
@@ -1938,6 +1948,19 @@ import {
1938
1948
  PluginDiscoveryService
1939
1949
  } from "@json-to-office/jto-cli";
1940
1950
  import { dirname } from "path";
1951
+ function throwIfClientError(error) {
1952
+ const code = error?.code;
1953
+ if (code === "UNSUPPORTED_RENDERER_FEATURE" || code === "UNCOMPILED_COMPONENT" || // An id nobody registered is the caller naming a backend that does not
1954
+ // exist. The message already lists the ones that do.
1955
+ code === "UNKNOWN_RENDERER") {
1956
+ throw new HTTPException4(400, { message: error.message });
1957
+ }
1958
+ if (!(error instanceof Error)) return;
1959
+ const message = error.message.toLowerCase();
1960
+ if (message.includes("invalid") || message.includes("validation") || message.includes("missing required") || message.includes("unknown component")) {
1961
+ throw new HTTPException4(400, { message: error.message });
1962
+ }
1963
+ }
1941
1964
  function createFormatRouter(adapter) {
1942
1965
  const router = new Hono2();
1943
1966
  const assertRequestSources = (value, path5) => {
@@ -2054,12 +2077,7 @@ function createFormatRouter(adapter) {
2054
2077
  error,
2055
2078
  requestId
2056
2079
  });
2057
- if (error instanceof Error) {
2058
- const msg = error.message.toLowerCase();
2059
- if (msg.includes("invalid") || msg.includes("validation") || msg.includes("missing required") || msg.includes("unknown component")) {
2060
- throw new HTTPException4(400, { message: error.message });
2061
- }
2062
- }
2080
+ throwIfClientError(error);
2063
2081
  if (error instanceof HTTPException4) throw error;
2064
2082
  throw new HTTPException4(500, {
2065
2083
  message: `Internal server error during ${adapter.label} generation`
@@ -2299,7 +2317,15 @@ function createFormatRouter(adapter) {
2299
2317
  customThemes,
2300
2318
  options: {
2301
2319
  bypassCache: true,
2302
- ...baseDir !== void 0 && { baseDir }
2320
+ ...baseDir !== void 0 && { baseDir },
2321
+ // The preview has to come from the backend the caller picked.
2322
+ // Regenerating with the default made the picker lie: the PDF on
2323
+ // screen and the bytes on download came from different renderers,
2324
+ // and a capability refusal was invisible until you downloaded
2325
+ // (#255).
2326
+ ...options?.renderer !== void 0 && {
2327
+ renderer: options.renderer
2328
+ }
2303
2329
  }
2304
2330
  });
2305
2331
  const pdfBuffer = await libreOfficeService.convertToPdf(
@@ -2318,6 +2344,7 @@ function createFormatRouter(adapter) {
2318
2344
  requestId
2319
2345
  });
2320
2346
  if (error instanceof HTTPException4) throw error;
2347
+ throwIfClientError(error);
2321
2348
  if (error instanceof LibreOfficeBinaryNotFoundError) {
2322
2349
  throw new HTTPException4(503, {
2323
2350
  message: "LibreOffice is not available. Install LibreOffice or set LIBREOFFICE_PATH."
@@ -2384,23 +2411,30 @@ function createFormatRouter(adapter) {
2384
2411
  requestId
2385
2412
  });
2386
2413
  if (error instanceof HTTPException4) throw error;
2387
- if (error instanceof Error) {
2388
- const msg = error.message.toLowerCase();
2389
- if (msg.includes("invalid") || msg.includes("validation") || msg.includes("missing required") || msg.includes("unknown component")) {
2390
- throw new HTTPException4(400, { message: error.message });
2391
- }
2392
- }
2414
+ throwIfClientError(error);
2393
2415
  throw new HTTPException4(500, {
2394
2416
  message: "Failed to get standard components definition"
2395
2417
  });
2396
2418
  }
2397
2419
  }
2398
2420
  );
2421
+ router.get("/renderers", async (c) => {
2422
+ try {
2423
+ const ids = await adapter.rendererIds();
2424
+ return c.json({
2425
+ success: true,
2426
+ data: { ids, default: ids[0] ?? null },
2427
+ meta: { timestamp: (/* @__PURE__ */ new Date()).toISOString() }
2428
+ });
2429
+ } catch (error) {
2430
+ logger.error("Failed to list renderers", { error });
2431
+ throw new HTTPException4(500, { message: "Failed to list renderers" });
2432
+ }
2433
+ });
2399
2434
  router.get("/cache-stats", async (c) => {
2400
2435
  try {
2401
2436
  const cacheService = getContainer().get("cacheService");
2402
2437
  const stats = cacheService.getStats();
2403
- const components = await adapter.getComponentCacheStats?.() ?? null;
2404
2438
  const rasterizer = await (async () => {
2405
2439
  try {
2406
2440
  const cli = await import("@json-to-office/jto-cli");
@@ -2423,7 +2457,6 @@ function createFormatRouter(adapter) {
2423
2457
  itemCount: stats.itemCount,
2424
2458
  enabled: stats.enabled
2425
2459
  },
2426
- ...components ? { components } : {},
2427
2460
  ...rasterizer ? { rasterizer } : {}
2428
2461
  },
2429
2462
  meta: { timestamp: (/* @__PURE__ */ new Date()).toISOString() }
@@ -2435,35 +2468,13 @@ function createFormatRouter(adapter) {
2435
2468
  });
2436
2469
  }
2437
2470
  });
2438
- router.get("/cache-analytics", async (c) => {
2439
- try {
2440
- const analytics = await adapter.getComponentCacheAnalytics?.();
2441
- if (!analytics) {
2442
- return c.json({
2443
- success: true,
2444
- data: null,
2445
- meta: { timestamp: (/* @__PURE__ */ new Date()).toISOString() }
2446
- });
2447
- }
2448
- return c.json({
2449
- success: true,
2450
- data: analytics,
2451
- meta: { timestamp: (/* @__PURE__ */ new Date()).toISOString() }
2452
- });
2453
- } catch (error) {
2454
- logger.error("Failed to get cache analytics", { error });
2455
- throw new HTTPException4(500, {
2456
- message: "Failed to get cache analytics"
2457
- });
2458
- }
2459
- });
2460
2471
  router.delete("/cache", async (c) => {
2461
2472
  try {
2462
2473
  const cacheService = getContainer().get("cacheService");
2463
2474
  cacheService.clear();
2464
2475
  const cli = await import("@json-to-office/jto-cli");
2465
2476
  cli.invalidateAllCaches();
2466
- await adapter.clearComponentCache?.();
2477
+ await adapter.resetCacheStats?.();
2467
2478
  await cli.clearRasterizerCache?.();
2468
2479
  return c.json({
2469
2480
  success: true,
@@ -4171,7 +4182,7 @@ function createDevCommand(adapter) {
4171
4182
  }
4172
4183
 
4173
4184
  // src/cli.ts
4174
- var PACKAGE_VERSION = true ? "0.38.0" : "dev-mode";
4185
+ var PACKAGE_VERSION = true ? "1.0.0" : "dev-mode";
4175
4186
  var program = new Command2();
4176
4187
  program.name("jto").description("JSON to Office CLI - Generate .docx and .pptx from JSON").version(PACKAGE_VERSION);
4177
4188
  registerCoreCommands(program, {