@reportwright/cli 0.13.2-rc.1 → 0.13.2-rc.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  All `@reportwright/*` packages (formerly `@pagewrightjs/*`) share one version. The versioning policy is in [CONTRIBUTING.md](CONTRIBUTING.md#versioning-semver).
4
4
 
5
+ ## 0.13.2-rc.2 — 2026-10-09 (release candidate)
6
+
7
+ ### Fixed (from the rc.1 release gate)
8
+ - **E11 Viewer accessibility:** the scrolling page area (`div.vpages`) is keyboard-focusable (`tabindex="0"`), a named `region`, with a visible inset focus ring; the arrow keys scroll it (axe `scrollable-region-focusable`).
9
+ - **E12 Designer arrow keys on pages with margins:** Arrow and Shift+Arrow move the selection by the whole step (1/10 pt, or 1/10 grid steps with Snap to grid). The step used to be clamped to the band's leftover width, so an item as wide as an A4 body with 36 pt margins (523.28 pt) moved 0.28 pt and then not at all. A keyboard nudge still stops at the band's start; overflow past its end shows in the Issues panel. Dragging still keeps items inside the band.
10
+ - **E10 webpack and Next.js builds:** `@reportwright/viewer` (`dist/`, `dist/peer/`) and `@reportwright/cli` ship `pdfstreamworker.js` next to the bundles that name it with `new URL('./pdfstreamworker.js', import.meta.url)`, so bundlers resolve it. The parallel PDF paint worker itself is `@reportwright/engine`'s (Node only); the stand-ins answer that `exportPdfStream` with `parallel` needs the engine.
11
+ - **E13 missing HarfBuzz subset WASM:** when `harfbuzz-subset.wasm` cannot be loaded (fonts then embed in full, PDFs many times larger), `exportPdf` and `exportPdfStream` warn once on the console and add a warning to the result (the model's `warnings`, the stream result's `warnings`), naming the expected path (`@reportwright/fonts/public/harfbuzz-subset.wasm`) and the fix: install `@reportwright/fonts`, or pass `subset: createSubsetter(() => wasmBytes)`.
12
+ - **E09 importer:**
13
+ - files are read in their own encoding: a UTF-16 LE/BE or UTF-8 byte-order mark, else the XML declaration's `encoding` (ISO-8859-1, Latin-1, windows-1252, …), else UTF-8. `Straße` and `Grüße` survive. Applies to `pw import`, `pw import <folder>` and `POST /api/reports/import`.
14
+ - a compiled `.jasper` file gets "This is a compiled JasperReports file; import the .jrxml source instead."
15
+ - `pw import` prints each error once (it printed it twice, the second time cut short).
16
+ - **E07 SQL connection pool:** a PostgreSQL or MySQL query that cannot get a pooled connection within `PW_DB_ACQUIRE_MS` (default 5000) fails with 503 and `Retry-After` instead of a 500; a connection that frees later goes back to the pool. A streaming query whose reader aborts frees its connection at once (the backend is terminated and the connection discarded) instead of holding it until the deadline. PostgreSQL queries run under `statement_timeout` from their first statement.
17
+
5
18
  ## 0.13.2-rc.1 — 2026-10-09 (release candidate)
6
19
 
7
20
  ### Changed
@@ -0,0 +1,4 @@
1
+ // The streaming PDF's parallel paint worker is @reportwright/engine's (dist/pdfstreamworker.js). This stand-in ships so
2
+ // bundlers resolve new URL('./pdfstreamworker.js', import.meta.url) in this package.
3
+ const { parentPort } = globalThis.process.getBuiltinModule('node:worker_threads');
4
+ parentPort.on('message', (job) => parentPort.postMessage({ id: job.id, error: { message: 'exportPdfStream with parallel needs @reportwright/engine' } }));
package/dist/pw.mjs CHANGED
@@ -17500,6 +17500,7 @@ var init_birt = __esm({
17500
17500
  // src/importers/index.js
17501
17501
  var importers_exports = {};
17502
17502
  __export(importers_exports, {
17503
+ decodeXml: () => decodeXml,
17503
17504
  importXmlReport: () => importXmlReport,
17504
17505
  rootName: () => rootName
17505
17506
  });
@@ -17519,6 +17520,21 @@ function rootName(s) {
17519
17520
  }
17520
17521
  return "";
17521
17522
  }
17523
+ function decodeXml(bytes) {
17524
+ const b = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
17525
+ if (b[0] === 172 && b[1] === 237) throw new Error("This is a compiled JasperReports file; import the .jrxml source instead.");
17526
+ if (b[0] === 255 && b[1] === 254) return new TextDecoder("utf-16le").decode(b.subarray(2));
17527
+ if (b[0] === 254 && b[1] === 255) return new TextDecoder("utf-16be").decode(b.subarray(2));
17528
+ if (b[0] === 239 && b[1] === 187 && b[2] === 191) return new TextDecoder("utf-8").decode(b.subarray(3));
17529
+ const decl = /^\s*<\?xml[^>]*?\sencoding\s*=\s*["']([A-Za-z0-9._-]+)["']/.exec(String.fromCharCode(...b.subarray(0, 200)));
17530
+ let enc = decl ? decl[1].toLowerCase() : "utf-8";
17531
+ if (enc === "utf-16" || enc === "unicode") enc = "utf-8";
17532
+ try {
17533
+ return new TextDecoder(enc).decode(b);
17534
+ } catch {
17535
+ return new TextDecoder("utf-8").decode(b);
17536
+ }
17537
+ }
17522
17538
  function importXmlReport(text2, opts = {}) {
17523
17539
  const root = rootName(String(text2 ?? ""));
17524
17540
  if (root === "jasperReport") return importJrxml(text2, opts);
@@ -17670,7 +17686,7 @@ async function importFolder(input, output, opts = {}) {
17670
17686
  }
17671
17687
  const readText = (f4) => {
17672
17688
  if (f4.size > maxBytes) throw new Error(`${f4.rel} is larger than ${maxBytes} bytes`);
17673
- return fs.readFileSync(f4.abs, "utf8");
17689
+ return decodeXml(fs.readFileSync(f4.abs));
17674
17690
  };
17675
17691
  const reports = files.filter((f4) => REPORT.test(f4.rel));
17676
17692
  const taken = /* @__PURE__ */ new Set();
@@ -35997,7 +36013,7 @@ var THEME = `${XML2}<a:theme xmlns:a="http://schemas.openxmlformats.org/drawingm
35997
36013
  // package.json
35998
36014
  var package_default = {
35999
36015
  name: "reportwright",
36000
- version: "0.13.2-rc.1",
36016
+ version: "0.13.2-rc.2",
36001
36017
  license: "MIT",
36002
36018
  private: true,
36003
36019
  engines: { node: "22.x" },
@@ -36417,10 +36433,13 @@ async function cmdImport(args) {
36417
36433
  const file = positionals[0];
36418
36434
  if (fs2.statSync(file, { throwIfNoEntry: false })?.isDirectory()) return importFolderCmd(file, values);
36419
36435
  if (values.recursive || values.force || values.verify || values.report) usage("--recursive, --force, --verify and --report are for a folder");
36420
- const { importXmlReport: importXmlReport2 } = await Promise.resolve().then(() => (init_importers(), importers_exports));
36421
- const r = importXmlReport2(fs2.readFileSync(file, "utf8"), { name: path2.basename(file).replace(/\.[^.]+$/, "") });
36436
+ const { importXmlReport: importXmlReport2, decodeXml: decodeXml2 } = await Promise.resolve().then(() => (init_importers(), importers_exports));
36437
+ const r = importXmlReport2(decodeXml2(fs2.readFileSync(file)), { name: path2.basename(file).replace(/\.[^.]+$/, "") });
36422
36438
  for (const w of r.warnings) console.error(`pw: ${w}`);
36423
- if (r.error) fail(r.error);
36439
+ if (r.error) {
36440
+ if (r.warnings.some((w) => w.startsWith(r.error))) process.exit(1);
36441
+ fail(r.error);
36442
+ }
36424
36443
  const out = values.o || file.replace(/\.[^.]+$/, ".pw.json");
36425
36444
  const json = JSON.stringify(r.definition, null, 2) + "\n";
36426
36445
  if (out === "-") process.stdout.write(json);