@agile-team/mach-report 2.8.4 → 2.9.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 (94) hide show
  1. package/README.md +27 -9
  2. package/dist/ExcelBindingWizard-DiaxvWpQ.cjs +1 -0
  3. package/dist/ExcelBindingWizard-RLJIXKKG.js +816 -0
  4. package/dist/{ReportPreview-DTWiCH5a.js → ReportPreview-B5ZNEasW.js} +22 -21
  5. package/dist/ReportPreview-DRtVPUYo.cjs +6 -0
  6. package/dist/RuleEditor-N4qnMZ-Z.cjs +1 -0
  7. package/dist/RuleEditor-ynnUEK0s.js +1575 -0
  8. package/dist/TemplateReviewPanel-C_Lmzis6.cjs +1 -0
  9. package/dist/TemplateReviewPanel-Cn32OY4_.js +173 -0
  10. package/dist/analytics.cjs +1 -1
  11. package/dist/analytics.d.cts +188 -5
  12. package/dist/analytics.d.ts +188 -5
  13. package/dist/analytics.js +68 -202
  14. package/dist/{assets-B9qJku3V.js → assets-DDsfEi8R.js} +3 -3
  15. package/dist/{assets-RZan7EyL.cjs → assets-ahTRUXRk.cjs} +1 -1
  16. package/dist/binding-preview-B5834rml.cjs +2 -0
  17. package/dist/binding-preview-ChXjN5L5.js +649 -0
  18. package/dist/{capabilities-joSutDF8.js → capabilities-Cm9hZ3uV.js} +5 -5
  19. package/dist/{capabilities-xGTpnPjJ.cjs → capabilities-DYzWL7KS.cjs} +1 -1
  20. package/dist/dataset-BkRmwgeJ.cjs +1 -0
  21. package/dist/dataset-H5pFuQGU.js +121 -0
  22. package/dist/defaults-DXhiM1ZD.js +10 -0
  23. package/dist/defaults-xhmcLLrf.cjs +1 -0
  24. package/dist/designer.cjs +2 -1
  25. package/dist/designer.d.cts +1373 -6
  26. package/dist/designer.d.ts +1373 -6
  27. package/dist/designer.js +2495 -767
  28. package/dist/grid-geometry-BNptEcMm.js +65 -0
  29. package/dist/grid-geometry-CZ_cYB6O.cjs +1 -0
  30. package/dist/import-template-CNMLJSQw.js +23030 -0
  31. package/dist/import-template-CpxunKVp.cjs +29 -0
  32. package/dist/index.cjs +7 -7
  33. package/dist/index.d.cts +202 -3
  34. package/dist/index.d.ts +202 -3
  35. package/dist/index.js +554 -535
  36. package/dist/matrix-CNPDJxED.js +745 -0
  37. package/dist/matrix-Div9Ilh3.cjs +1 -0
  38. package/dist/pdf.cjs +46 -46
  39. package/dist/pdf.d.cts +2 -0
  40. package/dist/pdf.d.ts +2 -0
  41. package/dist/pdf.js +17 -16
  42. package/dist/{plugin-CQmJXNcA.js → plugin-BWwIgZXV.js} +1 -1
  43. package/dist/{plugin-DSFu51Ua.cjs → plugin-Dg-J1Rbm.cjs} +1 -1
  44. package/dist/progress-7OSZbFok.js +39 -0
  45. package/dist/progress-BnLiS5eH.cjs +1 -0
  46. package/dist/render-plan-7xpGrCEl.cjs +1 -0
  47. package/dist/render-plan-Ck6koX9L.js +13 -0
  48. package/dist/server/node.d.cts +62 -0
  49. package/dist/server/node.d.ts +62 -0
  50. package/dist/server-node.cjs +1 -1
  51. package/dist/server-node.js +373 -145
  52. package/dist/server.cjs +1 -1
  53. package/dist/server.d.cts +311 -0
  54. package/dist/server.d.ts +311 -0
  55. package/dist/server.js +590 -186
  56. package/dist/{style-Dv5o_x6b.js → style-CQ1PK8ZB.js} +5 -5
  57. package/dist/style-UgIJSA1F.cjs +1 -0
  58. package/dist/style.css +1 -1
  59. package/dist/template-registry-CHMYZ7SD.cjs +1 -0
  60. package/dist/template-registry-R61AMCr0.js +433 -0
  61. package/dist/template-review-hvWWQFsi.js +1027 -0
  62. package/dist/template-review-jEcOfmGr.cjs +1 -0
  63. package/dist/textwrap-CWHyzkBH.cjs +4 -0
  64. package/dist/{textwrap-DOl04hCQ.js → textwrap-DE1kgcJB.js} +1 -1
  65. package/dist/{validate-DfHPD8wX.cjs → validate-BDiMqkJC.cjs} +1 -1
  66. package/dist/{validate-S6CgIm5d.js → validate-DWPF7icl.js} +13 -13
  67. package/dist/vue/async.d.cts +186 -0
  68. package/dist/vue/async.d.ts +186 -0
  69. package/dist/vue/index.d.cts +271 -3
  70. package/dist/vue/index.d.ts +271 -3
  71. package/dist/vue-async.cjs +1 -1
  72. package/dist/vue-async.js +3 -3
  73. package/dist/vue.cjs +1 -1
  74. package/dist/vue.js +4 -4
  75. package/dist/worker.cjs +1 -1
  76. package/dist/worker.d.cts +2 -0
  77. package/dist/worker.d.ts +2 -0
  78. package/dist/worker.js +1 -1
  79. package/dist/xlsx.cjs +2 -30
  80. package/dist/xlsx.d.cts +268 -0
  81. package/dist/xlsx.d.ts +268 -0
  82. package/dist/xlsx.js +220 -23440
  83. package/package.json +1 -1
  84. package/dist/ReportPreview-DjGeWHY-.cjs +0 -6
  85. package/dist/progress-DD964VAB.js +0 -102
  86. package/dist/progress-KvhwXZ1Q.cjs +0 -1
  87. package/dist/render-plan-CckPEQyf.cjs +0 -1
  88. package/dist/render-plan-uzZYYSy1.js +0 -19
  89. package/dist/report-source-BXHNy_AD.js +0 -755
  90. package/dist/report-source-CCAvFE3t.cjs +0 -1
  91. package/dist/style-CpwiOPyB.cjs +0 -1
  92. package/dist/template-registry-DWExx0gU.cjs +0 -1
  93. package/dist/template-registry-NpOakidD.js +0 -354
  94. package/dist/textwrap-CnGsEum6.cjs +0 -4
package/dist/pdf.d.cts CHANGED
@@ -165,6 +165,8 @@ export declare interface PdfRenderResult {
165
165
  }
166
166
 
167
167
  declare interface PlanComponent {
168
+ /** Template page furniture repeats per page and reserves its vertical band. */
169
+ pageAnchor?: "header" | "footer";
168
170
  kind: ComponentKind;
169
171
  leftMm: number;
170
172
  topMm: number;
package/dist/pdf.d.ts CHANGED
@@ -165,6 +165,8 @@ export declare interface PdfRenderResult {
165
165
  }
166
166
 
167
167
  declare interface PlanComponent {
168
+ /** Template page furniture repeats per page and reserves its vertical band. */
169
+ pageAnchor?: "header" | "footer";
168
170
  kind: ComponentKind;
169
171
  leftMm: number;
170
172
  topMm: number;
package/dist/pdf.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import { g as tg } from "./_commonjsHelpers-DaMA6jEr.js";
2
- import { h as Ud, w as rg } from "./textwrap-DOl04hCQ.js";
3
- import { o as ng, r as ig } from "./progress-DD964VAB.js";
4
- import { r as ag } from "./capabilities-joSutDF8.js";
5
- import { a as og, r as sg } from "./assets-B9qJku3V.js";
6
- import { i as ug, b as fg } from "./render-plan-uzZYYSy1.js";
7
- import { a as uo, b as ac, c as zd, e as cg, d as lg } from "./style-Dv5o_x6b.js";
2
+ import { h as Ud, w as rg } from "./textwrap-DE1kgcJB.js";
3
+ import { o as ng } from "./progress-7OSZbFok.js";
4
+ import { r as ig } from "./capabilities-Cm9hZ3uV.js";
5
+ import { a as ag, r as og } from "./assets-DDsfEi8R.js";
6
+ import { i as sg, a as ug } from "./render-plan-Ck6koX9L.js";
7
+ import { r as fg } from "./grid-geometry-BNptEcMm.js";
8
+ import { r as uo, b as ac, c as zd, e as cg, d as lg } from "./style-CQ1PK8ZB.js";
8
9
  var xu = {}, Sl;
9
10
  function Yn() {
10
11
  return Sl || (Sl = 1, (function(t) {
@@ -35991,7 +35992,7 @@ function _1(t, e, r, n) {
35991
35992
  }, t.measurer) : [];
35992
35993
  }
35993
35994
  function $E(t, e, r) {
35994
- return fg(e) ? (t.fidelityWarnings.push(`${r}: 富文本按纯文本降级导出(内联样式丢失)`), JE(e)) : Array.isArray(e.lines) && e.lines.length ? e.lines : _1(t, e.text ?? "", e.widthMm, e.style ?? {});
35995
+ return ug(e) ? (t.fidelityWarnings.push(`${r}: 富文本按纯文本降级导出(内联样式丢失)`), JE(e)) : Array.isArray(e.lines) && e.lines.length ? e.lines : _1(t, e.text ?? "", e.widthMm, e.style ?? {});
35995
35996
  }
35996
35997
  function Md(t, e, r, n, i) {
35997
35998
  const a = r.style ?? {};
@@ -36032,7 +36033,7 @@ function tT(t, e, r) {
36032
36033
  n.top && gi(t, e, { x: r.x, y: r.yTop }, { x: i, y: r.yTop }), n.right && gi(t, e, { x: i, y: r.yTop }, { x: i, y: a }), n.bottom && gi(t, e, { x: i, y: a }, { x: r.x, y: a }), n.left && gi(t, e, { x: r.x, y: a }, { x: r.x, y: r.yTop });
36033
36034
  }
36034
36035
  function rT(t, e, r, n) {
36035
- for (const i of sg(n, e)) {
36036
+ for (const i of og(n, e)) {
36036
36037
  const a = { borderColor: i.color, lineWidthPt: i.widthPt };
36037
36038
  i.kind === "v" ? gi(
36038
36039
  t,
@@ -36065,7 +36066,7 @@ function nT(t, e, r, n, i, a) {
36065
36066
  h.length > v && t.fidelityWarnings.push(`${a}: 单元格文本超出可用高度,PDF 文本裁切;请增加行高或减少字号(${h.length} 行,可容纳 ${v} 行)`), Q1(t, e, h.slice(0, p), { verticalAlign: "middle", ...o }, l);
36066
36067
  }
36067
36068
  function iT(t, e, r, n, i) {
36068
- const a = ig(r.grid, r.widthMm, r.heightMm);
36069
+ const a = fg(r.grid, r.widthMm, r.heightMm);
36069
36070
  ml(e, n, r.style?.backgroundColor);
36070
36071
  for (const o of a.cells) nT(t, e, r, o, n, `${i} cell ${o.ri + 1}:${o.ci + 1}`);
36071
36072
  rT(e, r, n, a);
@@ -36098,7 +36099,7 @@ function aT(t, e, r) {
36098
36099
  }
36099
36100
  async function oT(t, e, r, n, i) {
36100
36101
  const a = YE(r, n);
36101
- if (ug(r)) {
36102
+ if (sg(r)) {
36102
36103
  const o = await eT(t, r.imageData);
36103
36104
  o ? e.drawImage(o, { x: a.x, y: a.yTop - a.height, width: a.width, height: a.height }) : t.fidelityWarnings.push(`${i}: 图片仅支持 data:image/(png|jpeg) base64,已跳过`);
36104
36105
  } else r.grid ? iT(t, e, r, a, i) : r.kind === "text" ? Md(t, e, r, a, i) : aT(e, r, a) || (r.text ? Md(t, e, r, a, i) : t.fidelityWarnings.push(`${i}: 组件类型 ${r.kind} 缺少可导出的图片或文本,已跳过`));
@@ -36134,10 +36135,10 @@ function $1(t, e, r) {
36134
36135
  let n = r.get(e);
36135
36136
  return n || (n = t.embedFont(e, { subset: !1 }), r.set(e, n)), n;
36136
36137
  }
36137
- async function TT(t, e = {}) {
36138
- const r = await og(t, { ...e, format: "pdf" });
36138
+ async function DT(t, e = {}) {
36139
+ const r = await ag(t, { ...e, format: "pdf" });
36139
36140
  t = r.plan;
36140
- const n = [...r.diagnostics, ...ag(t, "pdf", e)], i = await Xn.create();
36141
+ const n = [...r.diagnostics, ...ig(t, "pdf", e)], i = await Xn.create();
36141
36142
  i.registerFontkit(KE);
36142
36143
  const a = await sT(i, e), o = [];
36143
36144
  for (const [f, l] of t.pages.entries()) {
@@ -36318,7 +36319,7 @@ function Qo(t) {
36318
36319
  function bT(t, e) {
36319
36320
  return e.bold && e.italic ? t.boldItalic ?? t.bold ?? t.italic ?? t.regular : e.bold ? t.bold ?? t.regular : e.italic ? t.italic ?? t.regular : t.regular;
36320
36321
  }
36321
- function DT(t) {
36322
+ function OT(t) {
36322
36323
  const e = {
36323
36324
  regular: Qo(t.regular),
36324
36325
  bold: t.bold ? Qo(t.bold) : void 0,
@@ -36335,8 +36336,8 @@ function DT(t) {
36335
36336
  };
36336
36337
  }
36337
36338
  export {
36338
- DT as createFontBytesMeasurer,
36339
+ OT as createFontBytesMeasurer,
36339
36340
  lT as invalidateFontCache,
36340
36341
  mT as loadFontWithCache,
36341
- TT as renderPlanToPdf
36342
+ DT as renderPlanToPdf
36342
36343
  };
@@ -1,6 +1,6 @@
1
1
  import { defineAsyncComponent as a, computed as s } from "vue";
2
2
  import { g as m } from "./report-params-B_VCihAh.js";
3
- const p = "mach-report/fetcher", l = "mach-report/pdf-exporter", R = "mach-report/config", h = "mach-report/controller", d = a(() => import("./ReportPreview-DTWiCH5a.js").then((r) => r.C)), _ = {
3
+ const p = "mach-report/fetcher", l = "mach-report/pdf-exporter", R = "mach-report/config", h = "mach-report/controller", d = a(() => import("./ReportPreview-B5ZNEasW.js").then((r) => r.C)), _ = {
4
4
  install(r, e = {}) {
5
5
  let t = e.fetcher;
6
6
  if (!t && e.reports) {
@@ -1 +1 @@
1
- "use strict";var l=Object.create;var n=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var d=Object.getPrototypeOf,h=Object.prototype.hasOwnProperty;var m=(r,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let c of p(e))!h.call(r,c)&&c!==t&&n(r,c,{get:()=>e[c],enumerable:!(o=s(e,c))||o.enumerable});return r};var C=(r,e,t)=>(t=r!=null?l(d(r)):{},m(e||!r||!r.__esModule?n(t,"default",{value:r,enumerable:!0}):t,r));const E=require("vue"),O=require("./report-params-CjWrjPl6.cjs"),_="mach-report/fetcher",f="mach-report/pdf-exporter",P="mach-report/config",u="mach-report/controller",a=E.defineAsyncComponent(()=>Promise.resolve().then(()=>require("./ReportPreview-DjGeWHY-.cjs")).then(r=>r.ReportPreview$1)),T={install(r,e={}){let t=e.fetcher;if(!t&&e.reports){const o=e.reports;let c;t=async R=>(c??=import("@agile-team/mach-report").then(({createReportSource:i})=>i(o)),(await c)(R)),t.getParamDefs=R=>O.getReportParamDefs(o,R)}t&&r.provide(_,t),e.pdfExporter&&r.provide(f,e.pdfExporter),r.provide(P,E.computed(()=>{if(e.pdfFontUrl===void 0)return e.config??null;const o=e.config??{defaults:{},presets:{}};return{...o,defaults:{...o.defaults,pdfFontUrl:e.pdfFontUrl}}})),e.globalComponent!==!1&&!r.component("MachReportPreview")&&r.component("MachReportPreview",a)}};exports.MACH_REPORT_CONFIG_KEY=P;exports.MACH_REPORT_CONTROLLER_KEY=u;exports.MACH_REPORT_FETCHER_KEY=_;exports.MACH_REPORT_PDF_EXPORTER_KEY=f;exports.MachReportPreview=a;exports.machReportPlugin=T;
1
+ "use strict";var l=Object.create;var n=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var p=Object.getOwnPropertyNames;var d=Object.getPrototypeOf,h=Object.prototype.hasOwnProperty;var m=(r,e,t,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let c of p(e))!h.call(r,c)&&c!==t&&n(r,c,{get:()=>e[c],enumerable:!(o=s(e,c))||o.enumerable});return r};var C=(r,e,t)=>(t=r!=null?l(d(r)):{},m(e||!r||!r.__esModule?n(t,"default",{value:r,enumerable:!0}):t,r));const E=require("vue"),O=require("./report-params-CjWrjPl6.cjs"),_="mach-report/fetcher",f="mach-report/pdf-exporter",P="mach-report/config",u="mach-report/controller",a=E.defineAsyncComponent(()=>Promise.resolve().then(()=>require("./ReportPreview-DRtVPUYo.cjs")).then(r=>r.ReportPreview$1)),T={install(r,e={}){let t=e.fetcher;if(!t&&e.reports){const o=e.reports;let c;t=async R=>(c??=import("@agile-team/mach-report").then(({createReportSource:i})=>i(o)),(await c)(R)),t.getParamDefs=R=>O.getReportParamDefs(o,R)}t&&r.provide(_,t),e.pdfExporter&&r.provide(f,e.pdfExporter),r.provide(P,E.computed(()=>{if(e.pdfFontUrl===void 0)return e.config??null;const o=e.config??{defaults:{},presets:{}};return{...o,defaults:{...o.defaults,pdfFontUrl:e.pdfFontUrl}}})),e.globalComponent!==!1&&!r.component("MachReportPreview")&&r.component("MachReportPreview",a)}};exports.MACH_REPORT_CONFIG_KEY=P;exports.MACH_REPORT_CONTROLLER_KEY=u;exports.MACH_REPORT_FETCHER_KEY=_;exports.MACH_REPORT_PDF_EXPORTER_KEY=f;exports.MachReportPreview=a;exports.machReportPlugin=T;
@@ -0,0 +1,39 @@
1
+ function i(r) {
2
+ if (r?.aborted) throw r.reason ?? new DOMException("The operation was aborted.", "AbortError");
3
+ }
4
+ function c(r, t, e) {
5
+ i(r.signal);
6
+ try {
7
+ r.onProgress?.(t, e);
8
+ } catch {
9
+ }
10
+ i(r.signal);
11
+ }
12
+ function b(r, t) {
13
+ const e = Promise.resolve(r);
14
+ return t?.aborted ? (e.catch(() => {
15
+ }), Promise.reject(t.reason ?? new DOMException("The operation was aborted.", "AbortError"))) : t ? new Promise((o, u) => {
16
+ const n = () => t.removeEventListener("abort", a), a = () => {
17
+ n(), u(t.reason ?? new DOMException("The operation was aborted.", "AbortError"));
18
+ };
19
+ t.addEventListener("abort", a, { once: !0 }), e.then((s) => {
20
+ n(), o(s);
21
+ }, (s) => {
22
+ n(), u(s);
23
+ }), t.aborted && a();
24
+ }) : e;
25
+ }
26
+ function f(r, t) {
27
+ const e = () => t.abort(r?.reason);
28
+ return r?.addEventListener("abort", e, { once: !0 }), r?.aborted && e(), () => r?.removeEventListener("abort", e);
29
+ }
30
+ async function d(r, t, e) {
31
+ c(r, t, e), (r.signal || r.onProgress) && await new Promise((o) => setTimeout(o, 0)), i(r.signal);
32
+ }
33
+ export {
34
+ i as a,
35
+ f,
36
+ c as n,
37
+ d as o,
38
+ b as w
39
+ };
@@ -0,0 +1 @@
1
+ "use strict";function o(t){if(t?.aborted)throw t.reason??new DOMException("The operation was aborted.","AbortError")}function c(t,r,e){o(t.signal);try{t.onProgress?.(r,e)}catch{}o(t.signal)}function b(t,r){const e=Promise.resolve(t);return r?.aborted?(e.catch(()=>{}),Promise.reject(r.reason??new DOMException("The operation was aborted.","AbortError"))):r?new Promise((n,s)=>{const a=()=>r.removeEventListener("abort",u),u=()=>{a(),s(r.reason??new DOMException("The operation was aborted.","AbortError"))};r.addEventListener("abort",u,{once:!0}),e.then(i=>{a(),n(i)},i=>{a(),s(i)}),r.aborted&&u()}):e}function f(t,r){const e=()=>r.abort(t?.reason);return t?.addEventListener("abort",e,{once:!0}),t?.aborted&&e(),()=>t?.removeEventListener("abort",e)}async function d(t,r,e){c(t,r,e),(t.signal||t.onProgress)&&await new Promise(n=>setTimeout(n,0)),o(t.signal)}exports.assertOutputActive=o;exports.forwardOutputAbort=f;exports.notifyOutputProgress=c;exports.outputCheckpoint=d;exports.waitForOutput=b;
@@ -0,0 +1 @@
1
+ "use strict";const i=require("./defaults-xhmcLLrf.cjs"),r=i.SCHEMA_VERSION_MACH;function a(e){return(e.kind==="image"||e.kind==="barcode"||e.kind==="qrcode"||e.kind==="chart")&&!!e.imageData}function n(e){return e.kind==="text"&&Array.isArray(e.richParagraphs)&&e.richParagraphs.length>0}exports.RENDER_PLAN_SCHEMA_VERSION=r;exports.isImageBackedComponent=a;exports.isRichText=n;
@@ -0,0 +1,13 @@
1
+ import { S as r } from "./defaults-DXhiM1ZD.js";
2
+ const n = r;
3
+ function t(a) {
4
+ return (a.kind === "image" || a.kind === "barcode" || a.kind === "qrcode" || a.kind === "chart") && !!a.imageData;
5
+ }
6
+ function e(a) {
7
+ return a.kind === "text" && Array.isArray(a.richParagraphs) && a.richParagraphs.length > 0;
8
+ }
9
+ export {
10
+ n as R,
11
+ e as a,
12
+ t as i
13
+ };
@@ -31,6 +31,17 @@ declare interface ComponentStyle {
31
31
  /** 独立 worker_threads 适配器;worker 入口注册自己的模板/Provider,不把函数跨线程序列化。 */
32
32
  export declare function createNodeReportExecutor(options: NodeReportExecutorOptions): ReportRuntimeExecutor;
33
33
 
34
+ export declare interface FileReportJobStore extends ReportJobStore {
35
+ close(): Promise<void>;
36
+ }
37
+
38
+ export declare interface FileReportJobStoreOptions {
39
+ directory: string;
40
+ maxRecords?: number;
41
+ maxBytes?: number;
42
+ recoverDeadOwner?: boolean;
43
+ }
44
+
34
45
  declare interface GridCell {
35
46
  text?: string;
36
47
  rawText?: string;
@@ -57,7 +68,12 @@ export declare interface NodeReportExecutorOptions extends ReportWorkerOptions {
57
68
  workerOptions?: WorkerOptions_2;
58
69
  }
59
70
 
71
+ /** Durable local store with one process owner; database adapters provide multi-instance atomic CAS. */
72
+ export declare function openFileReportJobStore(options: FileReportJobStoreOptions): Promise<FileReportJobStore>;
73
+
60
74
  declare interface PlanComponent {
75
+ /** Template page furniture repeats per page and reserves its vertical band. */
76
+ pageAnchor?: "header" | "footer";
61
77
  kind: ComponentKind;
62
78
  leftMm: number;
63
79
  topMm: number;
@@ -134,6 +150,9 @@ declare interface RenderPlan {
134
150
  pages: PlanPage[];
135
151
  }
136
152
 
153
+ /** Optional publication digest for Node hosts; use as reviewReportPublication({ digest }). */
154
+ export declare function reportArtifactSha256(bytes: Uint8Array): string;
155
+
137
156
  /** 可持久化的业务身份与计划坐标独立;权限及并发校验仍由业务服务器执行。 */
138
157
  declare interface ReportCellSource {
139
158
  datasetId: string;
@@ -163,6 +182,49 @@ declare interface ReportDiagnostic {
163
182
  severity: "warning" | "error" | "info";
164
183
  }
165
184
 
185
+ declare type ReportJobJson = null | boolean | number | string | ReportJobJson[] | {
186
+ [key: string]: ReportJobJson;
187
+ };
188
+
189
+ declare interface ReportJobRecord {
190
+ scope: string;
191
+ id: string;
192
+ revision: number;
193
+ request: ReportJobRequest;
194
+ status: ReportJobStatus;
195
+ createdAt: number;
196
+ updatedAt: number;
197
+ attempt: number;
198
+ lease?: {
199
+ owner: string;
200
+ expiresAt: number;
201
+ };
202
+ cancelRequested?: boolean;
203
+ progress?: {
204
+ completed: number;
205
+ total?: number;
206
+ };
207
+ result?: ReportJobJson;
208
+ error?: {
209
+ code: string;
210
+ message: string;
211
+ };
212
+ }
213
+
214
+ declare interface ReportJobRequest {
215
+ kind: string;
216
+ payload: ReportJobJson;
217
+ }
218
+
219
+ declare type ReportJobStatus = "queued" | "running" | "completed" | "failed" | "cancelled";
220
+
221
+ /** CAS must be atomic across all worker instances; candidate enumeration is advisory only. */
222
+ declare interface ReportJobStore {
223
+ read(scope: string, id: string): Promise<ReportJobRecord | undefined>;
224
+ candidates(now: number, limit: number): Promise<ReportJobRecord[]>;
225
+ compareAndSwap(scope: string, id: string, expectedRevision: number | null, next: ReportJobRecord): Promise<boolean>;
226
+ }
227
+
166
228
  /** 报表参数定义(声明式,模板自描述参数面:渲染组件据此生成查询面板) */
167
229
  declare interface ReportParamDef {
168
230
  /** 参数名(传入 params,与数据集 SQL #{field} 绑定对应) */
@@ -31,6 +31,17 @@ declare interface ComponentStyle {
31
31
  /** 独立 worker_threads 适配器;worker 入口注册自己的模板/Provider,不把函数跨线程序列化。 */
32
32
  export declare function createNodeReportExecutor(options: NodeReportExecutorOptions): ReportRuntimeExecutor;
33
33
 
34
+ export declare interface FileReportJobStore extends ReportJobStore {
35
+ close(): Promise<void>;
36
+ }
37
+
38
+ export declare interface FileReportJobStoreOptions {
39
+ directory: string;
40
+ maxRecords?: number;
41
+ maxBytes?: number;
42
+ recoverDeadOwner?: boolean;
43
+ }
44
+
34
45
  declare interface GridCell {
35
46
  text?: string;
36
47
  rawText?: string;
@@ -57,7 +68,12 @@ export declare interface NodeReportExecutorOptions extends ReportWorkerOptions {
57
68
  workerOptions?: WorkerOptions_2;
58
69
  }
59
70
 
71
+ /** Durable local store with one process owner; database adapters provide multi-instance atomic CAS. */
72
+ export declare function openFileReportJobStore(options: FileReportJobStoreOptions): Promise<FileReportJobStore>;
73
+
60
74
  declare interface PlanComponent {
75
+ /** Template page furniture repeats per page and reserves its vertical band. */
76
+ pageAnchor?: "header" | "footer";
61
77
  kind: ComponentKind;
62
78
  leftMm: number;
63
79
  topMm: number;
@@ -134,6 +150,9 @@ declare interface RenderPlan {
134
150
  pages: PlanPage[];
135
151
  }
136
152
 
153
+ /** Optional publication digest for Node hosts; use as reviewReportPublication({ digest }). */
154
+ export declare function reportArtifactSha256(bytes: Uint8Array): string;
155
+
137
156
  /** 可持久化的业务身份与计划坐标独立;权限及并发校验仍由业务服务器执行。 */
138
157
  declare interface ReportCellSource {
139
158
  datasetId: string;
@@ -163,6 +182,49 @@ declare interface ReportDiagnostic {
163
182
  severity: "warning" | "error" | "info";
164
183
  }
165
184
 
185
+ declare type ReportJobJson = null | boolean | number | string | ReportJobJson[] | {
186
+ [key: string]: ReportJobJson;
187
+ };
188
+
189
+ declare interface ReportJobRecord {
190
+ scope: string;
191
+ id: string;
192
+ revision: number;
193
+ request: ReportJobRequest;
194
+ status: ReportJobStatus;
195
+ createdAt: number;
196
+ updatedAt: number;
197
+ attempt: number;
198
+ lease?: {
199
+ owner: string;
200
+ expiresAt: number;
201
+ };
202
+ cancelRequested?: boolean;
203
+ progress?: {
204
+ completed: number;
205
+ total?: number;
206
+ };
207
+ result?: ReportJobJson;
208
+ error?: {
209
+ code: string;
210
+ message: string;
211
+ };
212
+ }
213
+
214
+ declare interface ReportJobRequest {
215
+ kind: string;
216
+ payload: ReportJobJson;
217
+ }
218
+
219
+ declare type ReportJobStatus = "queued" | "running" | "completed" | "failed" | "cancelled";
220
+
221
+ /** CAS must be atomic across all worker instances; candidate enumeration is advisory only. */
222
+ declare interface ReportJobStore {
223
+ read(scope: string, id: string): Promise<ReportJobRecord | undefined>;
224
+ candidates(now: number, limit: number): Promise<ReportJobRecord[]>;
225
+ compareAndSwap(scope: string, id: string, expectedRevision: number | null, next: ReportJobRecord): Promise<boolean>;
226
+ }
227
+
166
228
  /** 报表参数定义(声明式,模板自描述参数面:渲染组件据此生成查询面板) */
167
229
  declare interface ReportParamDef {
168
230
  /** 参数名(传入 params,与数据集 SQL #{field} 绑定对应) */
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const R=require("node:worker_threads");function P(e,t,r){if(!r?.aborted)try{const o=e?.({...t});o&&typeof o.then=="function"&&Promise.resolve(o).catch(()=>{})}catch{}}function T(e,t,r){e.editable!==void 0&&typeof e.editable!="boolean"&&r.push({path:`${t}.editable`,message:"编辑控制应为布尔值"}),e.valueType!==void 0&&!["text","number","boolean"].includes(e.valueType)&&r.push({path:`${t}.valueType`,message:"编辑类型应为 text、number 或 boolean"})}function v(e,t,r){T(e,t,r),x(e.source,`${t}.source`,r,!0),e.formula!==void 0&&typeof e.formula!="string"&&r.push({path:`${t}.formula`,message:"单元格公式应为字符串"})}function x(e,t,r,o=!1){if(e===void 0)return;if(!e||typeof e!="object"||Array.isArray(e)){r.push({path:t,message:"业务来源应为对象"});return}const s=e;for(const n of["datasetId",...o?["field"]:[]])(typeof s[n]!="string"||!s[n].trim())&&r.push({path:`${t}.${n}`,message:"业务标识应为非空字符串"});for(const n of["rowKey","revision"]){const i=s[n];i===void 0&&!(o&&n==="rowKey")||typeof i!="string"&&!(typeof i=="number"&&Number.isFinite(i))&&r.push({path:`${t}.${n}`,message:"业务键及修订号应为字符串或有限数字"})}s.sourceToken!==void 0&&typeof s.sourceToken!="string"&&r.push({path:`${t}.sourceToken`,message:"来源令牌应为字符串"})}const O=new Set(["text","image","barcode","qrcode","chart","line","rect","ellipse"]);function d(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function S(e,t,r,o){const s=e[t];(typeof s!="number"||!Number.isFinite(s))&&o.push({path:`${r}.${t}`,message:`应为有限数字,实际 ${JSON.stringify(s)}`})}function j(e,t,r){if(e!==void 0){const o=`${t}.table`;if(!d(e))r.push({path:o,message:"逻辑表来源应为对象"});else{x(e.source,`${o}.source`,r),(typeof e.id!="string"||!e.id.trim())&&r.push({path:`${o}.id`,message:"逻辑表 ID 应为非空字符串"});const s=e.role;["header","body","group-header","subtotal","grand-total"].includes(s)||r.push({path:`${o}.role`,message:"未知逻辑表行角色"});const n=e.rowIndex;(typeof n!="number"||!Number.isInteger(n)||(s==="header"?n!==-1:n<0))&&r.push({path:`${o}.rowIndex`,message:"表头索引应为 -1,内容行索引应为非负整数"}),(!Array.isArray(e.columnKeys)||e.columnKeys.some(i=>typeof i!="string"))&&r.push({path:`${o}.columnKeys`,message:"逻辑列字段应为字符串数组"}),e.layout!==void 0&&e.layout!=="page"&&e.layout!=="wide"&&r.push({path:`${o}.layout`,message:"布局应为 page 或 wide"}),e.title!==void 0&&typeof e.title!="string"&&r.push({path:`${o}.title`,message:"逻辑表名称应为字符串"})}}}function K(e,t,r,o){if(e!==void 0)if(!d(e)||!Array.isArray(e.cells))r.push({path:`${t}.grid.cells`,message:"grid.cells 应为二维数组"});else{const s=e.paddingMm;s!==void 0&&(typeof s!="number"||!Number.isFinite(s)||s<0)&&r.push({path:`${t}.grid.paddingMm`,message:"单元格内距应为有限非负数"}),e.cells.forEach((n,i)=>{if(!Array.isArray(n)){r.push({path:`${t}.grid.cells.${i}`,message:"行应为数组"});return}n.forEach((c,m)=>{if(c==null)return;const g=`${t}.grid.cells.${i}.${m}`;if(!d(c)){r.push({path:g,message:"网格单元格应为对象或 null"});return}v(c,g,r),Array.isArray(c.children)&&c.children.forEach((y,b)=>{I(y,`${t}.grid.cells.${i}.${m}.children.${b}`,r,o)})})})}}function _(e,t,r){e!==void 0&&(Array.isArray(e)?e.forEach((o,s)=>{(!d(o)||!Array.isArray(o.segments))&&r.push({path:`${t}.richParagraphs.${s}`,message:"段落缺少 segments 数组"})}):r.push({path:`${t}.richParagraphs`,message:"richParagraphs 应为数组"}))}function I(e,t,r,o=[]){if(!d(e)){r.push({path:t,message:"组件应为对象"});return}const s=e.kind;typeof s!="string"?r.push({path:`${t}.kind`,message:"组件缺少 kind 字符串"}):O.has(s)||o.push({path:`${t}.kind`,message:`未知组件类型 ${JSON.stringify(s)},将以兜底方式渲染`});for(const n of["leftMm","topMm","widthMm","heightMm"])S(e,n,t,r);typeof e.leftMm=="number"&&e.leftMm<-100&&r.push({path:`${t}.leftMm`,message:"几何数值异常(leftMm<-100)"});for(const n of["widthMm","heightMm"])typeof e[n]=="number"&&e[n]<0&&r.push({path:`${t}.${n}`,message:"组件尺寸不能为负数"});j(e.table,t,r),e.lineDirection!==void 0&&!["down","up"].includes(e.lineDirection)&&r.push({path:`${t}.lineDirection`,message:"线段方向应为 down 或 up"}),K(e.grid,t,r,o),_(e.richParagraphs,t,r)}function D(e,t,r,o=[]){if(!d(e)){r.push({path:t,message:"页应为对象"});return}const s=e.pageWidthMm,n=e.pageHeightMm;(typeof s!="number"||!Number.isFinite(s)||s<=0)&&r.push({path:`${t}.pageWidthMm`,message:`页宽非法: ${JSON.stringify(s)}`}),(typeof n!="number"||!(n>0&&n<5e3))&&r.push({path:`${t}.pageHeightMm`,message:`页高非法: ${JSON.stringify(n)}`}),e.layout!==void 0&&e.layout!=="page"&&e.layout!=="wide"&&r.push({path:`${t}.layout`,message:"布局应为 page 或 wide"});const i=e.components;Array.isArray(i)?Array.isArray(i)&&i.forEach((c,m)=>I(c,`${t}.components.${m}`,r,o)):r.push({path:`${t}.components`,message:"components 应为数组"})}function F(e){const t=[],r=[],o=d(e)?e.pages:void 0;if(!Array.isArray(o))t.push({path:"$.pages",message:e==null?"渲染计划为空":"渲染计划缺少 pages 数组"});else{o.forEach((n,i)=>D(n,`$.pages.${i}`,t,r)),o.length>2e3&&r.push({path:"$.pages",message:`页数异常大(${o.length} 页),渲染与打印耗时可能显著增加`});const s=o.reduce((n,i)=>n+(d(i)&&Array.isArray(i.components)?i.components.length:0),0);s>5e4&&r.push({path:"$.pages",message:`组件总数异常大(${s} 个),可能触发浏览器性能限制`})}return{ok:t.length===0,errors:t,warnings:r}}const l="mach-report-worker/1";class E extends Error{constructor(t){super(t.message),this.name=t.name,this.code=t.code,this.path=t.path,this.issues=t.issues,this.diagnostics=t.diagnostics}}function u(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function z(e){return u(e)?["rows","pages","cells"].every(t=>typeof e[t]=="number"&&Number.isSafeInteger(e[t])&&e[t]>=0)&&typeof e.durationMs=="number"&&Number.isFinite(e.durationMs)&&e.durationMs>=0:!1}function C(e){return Array.isArray(e)&&e.every(t=>u(t)&&typeof t.code=="string"&&typeof t.message=="string"&&["info","warning","error"].includes(t.severity))}function J(e){return u(e)&&Object.values(e).every(t=>u(t)&&(t.revision===void 0||typeof t.revision=="string")&&(t.sourceToken===void 0||typeof t.sourceToken=="string"))}function L(e,t){if(!u(e)||!z(e.stats)||!C(e.diagnostics)||!J(e.revisions))return!1;if(t==="prepare")return F(e.plan).ok;const r=e.format==="pdf"?"application/pdf":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";return e.bytes instanceof Uint8Array&&(e.format==="pdf"||e.format==="xlsx")&&e.contentType===r}function N(e){if(!e||typeof e!="object")return{message:String(e)};const t={};for(const r of["code","path","field","message"]){const o=e[r];typeof o=="string"&&(t[r]=o)}return t}function U(e){const t=N(e);if(!u(e))return t;for(const r of["format","severity","kind","nid"])typeof e[r]=="string"&&(t[r]=e[r]);for(const r of["pageIndex","componentIndex"])Number.isSafeInteger(e[r])&&e[r]>=0&&(t[r]=e[r]);return Array.isArray(e.componentPath)&&e.componentPath.every(r=>Number.isSafeInteger(r)&&r>=0)&&(t.componentPath=e.componentPath),t}function q(e){if(!(e instanceof Error))return{name:"Error",message:String(e)};const t=e;return{name:e.name,message:e.message,...typeof t.code=="string"?{code:t.code}:{},...typeof t.path=="string"?{path:t.path}:{},...Array.isArray(t.issues)?{issues:t.issues.map(N)}:{},...Array.isArray(t.diagnostics)?{diagnostics:t.diagnostics.map(U)}:{}}}function B(e){if(!e||typeof e!="object")return!1;const t=e;return t.protocol===l&&typeof t.id=="string"&&(t.operation==="prepare"||t.operation==="export")&&!!t.input&&typeof t.input=="object"}async function G(e,t,r){try{const o=t.operation==="prepare"?await e.prepare({...t.input,onEvent:r}):await e.export({...t.input,onEvent:r});return{protocol:l,id:t.id,result:o}}catch(o){return{protocol:l,id:t.id,error:q(o)}}}function H(e){const t=e.result;return!t||!("bytes"in t)||!(t.bytes.buffer instanceof ArrayBuffer)?[]:[t.bytes.buffer]}function Q(e,t){if(!u(e)||typeof e.taskId!="string"||!e.taskId||t.taskId!==void 0&&e.taskId!==t.taskId||e.correlationId!==t.correlationId||e.reportId!==void 0&&(typeof e.reportId!="string"||!t.reportIds.includes(e.reportId))||!["query","validate","layout","encode"].includes(e.stage)||!["started","completed","failed"].includes(e.status))return!1;for(const r of["completed","total"])if(e[r]!==void 0&&(typeof e[r]!="number"||!Number.isFinite(e[r])||e[r]<0))return!1;return e.completed===void 0||e.total===void 0||e.completed<=e.total}let V=0;function M(e){const t=new Error("报表 Worker 任务已取消");return t.name="AbortError",Object.defineProperty(t,"cause",{value:e}),t}function X(e,t){if(!e||typeof e!="object")return;const r=e;return r.protocol===l&&r.id===t?r:void 0}function Y(e,t={}){const r=t.timeoutMs??12e4;if(!Number.isFinite(r)||r<=0||r>2147483647)throw new RangeError("Worker timeoutMs 应为正有限数字,且不能超过 2147483647");const o=(s,n,i,c)=>i?.aborted?Promise.reject(M(i.reason)):new Promise((m,g)=>{let y;try{y=e()}catch(f){g(f);return}const b=`mach-report-${Date.now()}-${++V}`;let $=!1,k=()=>{},w;const p=(f,a)=>{$||($=!0,w&&clearTimeout(w),k(),i?.removeEventListener("abort",A),Promise.resolve().then(()=>y.terminate()).then(()=>f===void 0?m(a):g(f),h=>g(f??h)))},A=()=>p(M(i?.reason)),W=f=>{const a=X(f,b);if(!(!a||$)){if("type"in a&&a.type==="event"){const h="event"in a?a.event:void 0;Q(h,n)?P(c,h,i):p(new Error("报表 Worker 返回无效阶段事件"));return}a.error&&typeof a.error.name=="string"&&typeof a.error.message=="string"?p(new E(a.error)):L(a.result,s)&&(s!=="export"||"format"in a.result&&"format"in n&&a.result.format===n.format)?p(void 0,a.result):p(new Error("报表 Worker 返回无效响应"))}};try{if(k=y.subscribe(W,f=>p(f??new Error("报表 Worker 执行失败"))),$){k();return}if(i?.addEventListener("abort",A,{once:!0}),w=setTimeout(()=>p(new E({name:"ReportRuntimeError",code:"timeout",message:`报表 Worker 执行超过 ${r}ms`})),r),i?.aborted)A();else{const{onEvent:f,signal:a,...h}=n;y.postMessage({protocol:l,id:b,operation:s,input:h})}}catch(f){p(f)}});return{prepare:(s,n,i)=>o("prepare",s,n,i),export:(s,n,i)=>o("export",s,n,i)}}function Z(e){const t=e.filename??e.workerUrl;if(!t||e.filename&&e.workerUrl)throw new TypeError("请且仅请指定 filename 或 workerUrl");return Y(()=>{const r=new R.Worker(t,e.workerOptions);return{postMessage:o=>r.postMessage(o),terminate:()=>r.terminate(),subscribe:(o,s)=>{const n=i=>s(new Error(`报表 Worker 在响应前退出(code ${i})`));return r.on("message",o),r.on("error",s),r.on("messageerror",s),r.on("exit",n),()=>{r.off("message",o),r.off("error",s),r.off("messageerror",s),r.off("exit",n)}}}},e)}function ee(e){const t=R.parentPort;if(!t)throw new Error("serveNodeReportWorker 只能在 worker_threads 中调用");const r=o=>{B(o)&&G(e,o,s=>t.postMessage({protocol:l,id:o.id,type:"event",event:s})).then(s=>t.postMessage(s,H(s)))};return t.on("message",r),()=>t.off("message",r)}exports.ReportWorkerError=E;exports.createNodeReportExecutor=Z;exports.serveNodeReportWorker=ee;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const W=require("node:worker_threads"),I=require("node:crypto"),d=require("node:fs"),N=require("node:path");function K(e,t,r){if(!r?.aborted)try{const n=e?.({...t});n&&typeof n.then=="function"&&Promise.resolve(n).catch(()=>{})}catch{}}function U(e,t,r){e.editable!==void 0&&typeof e.editable!="boolean"&&r.push({path:`${t}.editable`,message:"编辑控制应为布尔值"}),e.valueType!==void 0&&!["text","number","boolean"].includes(e.valueType)&&r.push({path:`${t}.valueType`,message:"编辑类型应为 text、number 或 boolean"})}function L(e,t,r){U(e,t,r),F(e.source,`${t}.source`,r,!0),e.formula!==void 0&&typeof e.formula!="string"&&r.push({path:`${t}.formula`,message:"单元格公式应为字符串"})}function F(e,t,r,n=!1){if(e===void 0)return;if(!e||typeof e!="object"||Array.isArray(e)){r.push({path:t,message:"业务来源应为对象"});return}const o=e;for(const s of["datasetId",...n?["field"]:[]])(typeof o[s]!="string"||!o[s].trim())&&r.push({path:`${t}.${s}`,message:"业务标识应为非空字符串"});for(const s of["rowKey","revision"]){const i=o[s];i===void 0&&!(n&&s==="rowKey")||typeof i!="string"&&!(typeof i=="number"&&Number.isFinite(i))&&r.push({path:`${t}.${s}`,message:"业务键及修订号应为字符串或有限数字"})}o.sourceToken!==void 0&&typeof o.sourceToken!="string"&&r.push({path:`${t}.sourceToken`,message:"来源令牌应为字符串"})}const B=new Set(["text","image","barcode","qrcode","chart","line","rect","ellipse"]);function $(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function H(e,t,r,n){const o=e[t];(typeof o!="number"||!Number.isFinite(o))&&n.push({path:`${r}.${t}`,message:`应为有限数字,实际 ${JSON.stringify(o)}`})}function G(e,t,r){if(e!==void 0){const n=`${t}.table`;if(!$(e))r.push({path:n,message:"逻辑表来源应为对象"});else{F(e.source,`${n}.source`,r),(typeof e.id!="string"||!e.id.trim())&&r.push({path:`${n}.id`,message:"逻辑表 ID 应为非空字符串"});const o=e.role;["header","body","group-header","subtotal","grand-total"].includes(o)||r.push({path:`${n}.role`,message:"未知逻辑表行角色"});const s=e.rowIndex;(typeof s!="number"||!Number.isInteger(s)||(o==="header"?s!==-1:s<0))&&r.push({path:`${n}.rowIndex`,message:"表头索引应为 -1,内容行索引应为非负整数"}),(!Array.isArray(e.columnKeys)||e.columnKeys.some(i=>typeof i!="string"))&&r.push({path:`${n}.columnKeys`,message:"逻辑列字段应为字符串数组"}),e.layout!==void 0&&e.layout!=="page"&&e.layout!=="wide"&&r.push({path:`${n}.layout`,message:"布局应为 page 或 wide"}),e.title!==void 0&&typeof e.title!="string"&&r.push({path:`${n}.title`,message:"逻辑表名称应为字符串"})}}}function X(e,t,r,n){if(e!==void 0)if(!$(e)||!Array.isArray(e.cells))r.push({path:`${t}.grid.cells`,message:"grid.cells 应为二维数组"});else{const o=e.paddingMm;o!==void 0&&(typeof o!="number"||!Number.isFinite(o)||o<0)&&r.push({path:`${t}.grid.paddingMm`,message:"单元格内距应为有限非负数"}),e.cells.forEach((s,i)=>{if(!Array.isArray(s)){r.push({path:`${t}.grid.cells.${i}`,message:"行应为数组"});return}s.forEach((u,l)=>{if(u==null)return;const c=`${t}.grid.cells.${i}.${l}`;if(!$(u)){r.push({path:c,message:"网格单元格应为对象或 null"});return}L(u,c,r),Array.isArray(u.children)&&u.children.forEach((a,m)=>{_(a,`${t}.grid.cells.${i}.${l}.children.${m}`,r,n)})})})}}function Z(e,t,r){e!==void 0&&(Array.isArray(e)?e.forEach((n,o)=>{(!$(n)||!Array.isArray(n.segments))&&r.push({path:`${t}.richParagraphs.${o}`,message:"段落缺少 segments 数组"})}):r.push({path:`${t}.richParagraphs`,message:"richParagraphs 应为数组"}))}function _(e,t,r,n=[]){if(!$(e)){r.push({path:t,message:"组件应为对象"});return}const o=e.kind;typeof o!="string"?r.push({path:`${t}.kind`,message:"组件缺少 kind 字符串"}):B.has(o)||n.push({path:`${t}.kind`,message:`未知组件类型 ${JSON.stringify(o)},将以兜底方式渲染`});for(const s of["leftMm","topMm","widthMm","heightMm"])H(e,s,t,r);typeof e.leftMm=="number"&&e.leftMm<-100&&r.push({path:`${t}.leftMm`,message:"几何数值异常(leftMm<-100)"});for(const s of["widthMm","heightMm"])typeof e[s]=="number"&&e[s]<0&&r.push({path:`${t}.${s}`,message:"组件尺寸不能为负数"});G(e.table,t,r),e.pageAnchor!==void 0&&!["header","footer"].includes(e.pageAnchor)&&r.push({path:`${t}.pageAnchor`,message:"页面锚点应为 header 或 footer"}),e.lineDirection!==void 0&&!["down","up"].includes(e.lineDirection)&&r.push({path:`${t}.lineDirection`,message:"线段方向应为 down 或 up"}),X(e.grid,t,r,n),Z(e.richParagraphs,t,r)}function V(e,t,r,n=[]){if(!$(e)){r.push({path:t,message:"页应为对象"});return}const o=e.pageWidthMm,s=e.pageHeightMm;(typeof o!="number"||!Number.isFinite(o)||o<=0)&&r.push({path:`${t}.pageWidthMm`,message:`页宽非法: ${JSON.stringify(o)}`}),(typeof s!="number"||!(s>0&&s<5e3))&&r.push({path:`${t}.pageHeightMm`,message:`页高非法: ${JSON.stringify(s)}`}),e.layout!==void 0&&e.layout!=="page"&&e.layout!=="wide"&&r.push({path:`${t}.layout`,message:"布局应为 page 或 wide"});const i=e.components;Array.isArray(i)?Array.isArray(i)&&i.forEach((u,l)=>_(u,`${t}.components.${l}`,r,n)):r.push({path:`${t}.components`,message:"components 应为数组"})}function Q(e){const t=[],r=[],n=$(e)?e.pages:void 0;if(!Array.isArray(n))t.push({path:"$.pages",message:e==null?"渲染计划为空":"渲染计划缺少 pages 数组"});else{n.forEach((s,i)=>V(s,`$.pages.${i}`,t,r)),n.length>2e3&&r.push({path:"$.pages",message:`页数异常大(${n.length} 页),渲染与打印耗时可能显著增加`});const o=n.reduce((s,i)=>s+($(i)&&Array.isArray(i.components)?i.components.length:0),0);o>5e4&&r.push({path:"$.pages",message:`组件总数异常大(${o} 个),可能触发浏览器性能限制`})}return{ok:t.length===0,errors:t,warnings:r}}const O="mach-report-worker/1";class M extends Error{constructor(t){super(t.message),this.name=t.name,this.code=t.code,this.path=t.path,this.issues=t.issues,this.diagnostics=t.diagnostics}}function S(e){return!!e&&typeof e=="object"&&!Array.isArray(e)}function Y(e){return S(e)?["rows","pages","cells"].every(t=>typeof e[t]=="number"&&Number.isSafeInteger(e[t])&&e[t]>=0)&&typeof e.durationMs=="number"&&Number.isFinite(e.durationMs)&&e.durationMs>=0:!1}function ee(e){return Array.isArray(e)&&e.every(t=>S(t)&&typeof t.code=="string"&&typeof t.message=="string"&&["info","warning","error"].includes(t.severity))}function te(e){return S(e)&&Object.values(e).every(t=>S(t)&&(t.revision===void 0||typeof t.revision=="string")&&(t.sourceToken===void 0||typeof t.sourceToken=="string"))}function re(e,t){if(!S(e)||!Y(e.stats)||!ee(e.diagnostics)||!te(e.revisions))return!1;if(t==="prepare")return Q(e.plan).ok;const r=e.format==="pdf"?"application/pdf":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";return e.bytes instanceof Uint8Array&&(e.format==="pdf"||e.format==="xlsx")&&e.contentType===r}function q(e){if(!e||typeof e!="object")return{message:String(e)};const t={};for(const r of["code","path","field","message"]){const n=e[r];typeof n=="string"&&(t[r]=n)}return t}function ne(e){const t=q(e);if(!S(e))return t;for(const r of["format","severity","kind","nid"])typeof e[r]=="string"&&(t[r]=e[r]);for(const r of["pageIndex","componentIndex"])Number.isSafeInteger(e[r])&&e[r]>=0&&(t[r]=e[r]);return Array.isArray(e.componentPath)&&e.componentPath.every(r=>Number.isSafeInteger(r)&&r>=0)&&(t.componentPath=e.componentPath),t}function oe(e){if(!(e instanceof Error))return{name:"Error",message:String(e)};const t=e;return{name:e.name,message:e.message,...typeof t.code=="string"?{code:t.code}:{},...typeof t.path=="string"?{path:t.path}:{},...Array.isArray(t.issues)?{issues:t.issues.map(q)}:{},...Array.isArray(t.diagnostics)?{diagnostics:t.diagnostics.map(ne)}:{}}}function se(e){if(!e||typeof e!="object")return!1;const t=e;return t.protocol===O&&typeof t.id=="string"&&(t.operation==="prepare"||t.operation==="export")&&!!t.input&&typeof t.input=="object"}async function ie(e,t,r){try{const n=t.operation==="prepare"?await e.prepare({...t.input,onEvent:r}):await e.export({...t.input,onEvent:r});return{protocol:O,id:t.id,result:n}}catch(n){return{protocol:O,id:t.id,error:oe(n)}}}function ae(e){const t=e.result;return!t||!("bytes"in t)||!(t.bytes.buffer instanceof ArrayBuffer)?[]:[t.bytes.buffer]}function ce(e,t){if(!S(e)||typeof e.taskId!="string"||!e.taskId||t.taskId!==void 0&&e.taskId!==t.taskId||e.correlationId!==t.correlationId||e.reportId!==void 0&&(typeof e.reportId!="string"||!t.reportIds.includes(e.reportId))||!["query","validate","layout","encode"].includes(e.stage)||!["started","completed","failed"].includes(e.status))return!1;for(const r of["completed","total"])if(e[r]!==void 0&&(typeof e[r]!="number"||!Number.isFinite(e[r])||e[r]<0))return!1;return e.completed===void 0||e.total===void 0||e.completed<=e.total}let fe=0;function P(e){const t=new Error("报表 Worker 任务已取消");return t.name="AbortError",Object.defineProperty(t,"cause",{value:e}),t}function ue(e,t){if(!e||typeof e!="object")return;const r=e;return r.protocol===O&&r.id===t?r:void 0}function pe(e,t={}){const r=t.timeoutMs??12e4;if(!Number.isFinite(r)||r<=0||r>2147483647)throw new RangeError("Worker timeoutMs 应为正有限数字,且不能超过 2147483647");const n=(o,s,i,u)=>i?.aborted?Promise.reject(P(i.reason)):new Promise((l,c)=>{let a;try{a=e()}catch(h){c(h);return}const m=`mach-report-${Date.now()}-${++fe}`;let y=!1,b=()=>{},g;const w=(h,p)=>{y||(y=!0,g&&clearTimeout(g),b(),i?.removeEventListener("abort",E),Promise.resolve().then(()=>a.terminate()).then(()=>h===void 0?l(p):c(h),k=>c(h??k)))},E=()=>w(P(i?.reason)),A=h=>{const p=ue(h,m);if(!(!p||y)){if("type"in p&&p.type==="event"){const k="event"in p?p.event:void 0;ce(k,s)?K(u,k,i):w(new Error("报表 Worker 返回无效阶段事件"));return}p.error&&typeof p.error.name=="string"&&typeof p.error.message=="string"?w(new M(p.error)):re(p.result,o)&&(o!=="export"||"format"in p.result&&"format"in s&&p.result.format===s.format)?w(void 0,p.result):w(new Error("报表 Worker 返回无效响应"))}};try{if(b=a.subscribe(A,h=>w(h??new Error("报表 Worker 执行失败"))),y){b();return}if(i?.addEventListener("abort",E,{once:!0}),g=setTimeout(()=>w(new M({name:"ReportRuntimeError",code:"timeout",message:`报表 Worker 执行超过 ${r}ms`})),r),i?.aborted)E();else{const{onEvent:h,signal:p,...k}=s;a.postMessage({protocol:O,id:m,operation:o,input:k})}}catch(h){w(h)}});return{prepare:(o,s,i)=>n("prepare",o,s,i),export:(o,s,i)=>n("export",o,s,i)}}class f extends Error{constructor(t,r){super(r),this.code=t,this.name="ReportJobError"}}function D(e,t){if(typeof e!="string"||!e.trim()||e.length>256||typeof t!="string"||!/^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,127}$/.test(t))throw new f("input","任务范围应非空,ID应为1–128位安全标识")}function de(e){const t=Array.isArray(e),r=Object.getPrototypeOf(e),n=Object.keys(e);if(r!==(t?Array.prototype:Object.prototype)&&!(r===null&&!t))throw new f("input","任务对象应为普通 JSON 对象");if(Object.getOwnPropertySymbols(e).length)throw new f("input","任务不能包含Symbol");if(Object.getOwnPropertyNames(e).filter(s=>!(t&&s==="length")).length!==n.length)throw new f("input","任务不能包含不可枚举属性");if(t&&(n.length!==e.length||n.some(s=>!/^(0|[1-9]\d*)$/.test(s)||Number(s)>=e.length)))throw new f("input","任务数组不能稀疏或包含额外属性");return n.sort()}function le(e,t){const r=Object.getOwnPropertyDescriptor(e,t);if(["__proto__","prototype","constructor"].includes(t)||r.get||r.set)throw new f("input","任务不能包含危险键或访问器");return r.value}function x(e,t={}){const r=t.maxNodes??2e4,n=t.maxCharacters??1e6;if(!Number.isSafeInteger(r)||r<1||r>2e4||!Number.isSafeInteger(n)||n<1||n>1e6)throw new f("input","任务JSON预算无效");let o=0,s=0;const i=new Set;function u(c,a){if(++o>r||a>32)throw new f("input","任务数据超过节点或深度预算");if(typeof c=="string"){if(s+=c.length,s>n)throw new f("input","任务文本超过预算");return c}if(c===null||typeof c=="boolean"||typeof c=="number"&&Number.isFinite(c))return c;if(!c||typeof c!="object"||i.has(c))throw new f("input","任务只允许无循环的有限 JSON 值");const m=Array.isArray(c),y=de(c);i.add(c);const b=Object.create(null);for(const g of y){if(s+=g.length,s>n)throw new f("input","任务文本超过预算");b[g]=u(le(c,g),a+1)}return i.delete(c),m?Array.from({length:c.length},(g,w)=>b[String(w)]):b}const l=JSON.stringify(u(e,0));if(l.length>n)throw new f("input","任务序列化数据超过字符预算");return l}function T(e){return JSON.parse(JSON.stringify(e))}function z(e,t,r,n){if(D(t,r),e.scope!==t||e.id!==r||e.revision!==(n??0)+1||!Number.isSafeInteger(e.revision))throw new f("input","任务身份或修订不匹配");if(![e.createdAt,e.updatedAt,e.attempt].every(o=>Number.isSafeInteger(o)&&o>=0)||!["queued","running","completed","failed","cancelled"].includes(e.status))throw new f("input","任务状态无效");if(e.lease&&(!e.lease.owner||!Number.isSafeInteger(e.lease.expiresAt)))throw new f("input","任务租约无效");if(!e.request||typeof e.request.kind!="string"||!e.request.kind.trim()||e.request.kind.length>128)throw new f("input","任务类型无效");x(e.request.payload,{maxNodes:19e3,maxCharacters:75e4}),x(e)}function ye(e,t){if(e&&(e.createdAt!==t.createdAt||x(e.request)!==x(t.request)))throw new f("input","任务创建时间与请求不可变更,请使用新任务ID")}function he(e,t){return e.status==="queued"||e.status==="running"&&(e.lease?.expiresAt??0)<=t}function v(e){return e?.code}function J(e,t){return I.createHash("sha256").update(JSON.stringify([e,t])).digest("hex")+".json"}async function j(e){try{return await d.promises.readFile(e,"utf8")}catch(t){if(v(t)==="ENOENT")return;throw t}}async function me(e,t){const r=await j(e);if(r===void 0)return;let n;try{n=JSON.parse(r)}catch{throw new f("conflict","任务锁尚未完整写入或已损坏,拒绝自动移除")}if(!n||!Number.isSafeInteger(n.pid)||n.pid<1)throw new f("conflict","任务锁身份无效,拒绝自动移除");try{process.kill(n.pid,0)}catch(o){if(v(o)==="ESRCH"){await d.promises.unlink(e);return}throw o}throw new f("conflict","任务目录的写入进程仍在运行")}async function ge(e,t){if(!t)throw new f("conflict","任务目录已有写入进程;多实例请使用数据库CAS适配器");const r=e+".recovery";let n;try{n=await d.promises.open(r,"wx",384)}catch(o){throw v(o)==="EEXIST"?new f("conflict","任务目录恢复正在进行,请稍后重试"):o}try{return await n.writeFile(JSON.stringify({pid:process.pid})),await me(e,!0),await d.promises.open(e,"wx",384)}finally{await n.close(),await d.promises.unlink(r)}}async function we(e,t){const r=N.join(e,".writer-lock"),n=I.randomUUID();let o;try{o=await d.promises.open(r,"wx",384)}catch(s){if(v(s)!=="EEXIST")throw s;o=await ge(r,t)}try{await o.writeFile(JSON.stringify({pid:process.pid,token:n})),await o.sync()}catch(s){throw await o.close(),await d.promises.unlink(r).catch(()=>{}),s}return{file:r,token:n,handle:o}}async function be(e,t,r){const n=await d.promises.readdir(e);for(const u of n.filter(l=>/^\.pending-[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.test(l)))await d.promises.unlink(N.join(e,u));const o=n.filter(u=>/^[a-f0-9]{64}\.json$/.test(u));if(o.length>t)throw new f("capacity","持久任务数量超过目录预算");const s=new Map;let i=0;for(const u of o){const l=N.join(e,u),c=await d.promises.stat(l);if(i+=c.size,c.size>4e6||i>r)throw new f("capacity","持久任务文件超过容量预算");const a=JSON.parse(await d.promises.readFile(l,"utf8"));if(z(a,a.scope,a.id,a.revision-1),J(a.scope,a.id)!==u)throw new f("input","持久任务文件身份不匹配");s.set(u,{record:a,bytes:c.size})}return{records:s,bytes:i}}async function ke(e,t,r){const n=N.join(e,`.pending-${I.randomUUID()}`);try{const o=await d.promises.open(n,"wx",384);try{await o.writeFile(r),await o.sync()}finally{await o.close()}await d.promises.rename(n,N.join(e,t));const s=await d.promises.open(e,"r");try{await s.sync()}finally{await s.close()}}finally{await d.promises.unlink(n).catch(o=>{if(v(o)!=="ENOENT")throw o})}}async function $e(e){const t=N.resolve(e.directory),r=e.maxRecords??1e4,n=e.maxBytes??64*1024*1024;if(![r,n].every(a=>Number.isSafeInteger(a)&&a>0))throw new f("input","持久任务预算应为正整数");await d.promises.mkdir(t,{recursive:!0,mode:448});const o=await we(t,e.recoverDeadOwner??!1);let s;try{s=await be(t,r,n)}catch(a){throw await o.handle.close(),await d.promises.unlink(o.file),a}let i=!1,u=Promise.resolve();const l=()=>{if(i)throw new f("closed","持久任务存储已关闭")};return{read:async(a,m)=>{l(),D(a,m),await u;const y=s.records.get(J(a,m));return y?T(y.record):void 0},candidates:async(a,m)=>(l(),await u,Array.from(s.records.values(),y=>y.record).filter(y=>he(y,a)).sort((y,b)=>y.createdAt-b.createdAt).slice(0,m).map(T)),compareAndSwap:async(a,m,y,b)=>{l();const g=JSON.parse(x(b));z(g,a,m,y);let w=!1;const E=u.then(async()=>{if(JSON.parse(await d.promises.readFile(o.file,"utf8")).token!==o.token)throw new f("closed","持久任务存储写入锁已失效");const A=J(a,m),h=s.records.get(A);if((h?.record.revision??null)!==y)return;ye(h?.record,g);const p=x(g),k=Buffer.byteLength(p,"utf8"),R=s.bytes-(h?.bytes??0)+k;if(R>n||!h&&s.records.size>=r)throw new f("capacity","持久任务容量已满,请归档旧任务或扩大显式预算");try{await ke(t,A,p)}catch(C){throw await j(N.join(t,A))===p&&(s.records.set(A,{record:g,bytes:k}),s.bytes=R),C}s.records.set(A,{record:g,bytes:k}),s.bytes=R,w=!0});return u=E.catch(()=>{}),await E,w},close:async()=>{if(i)return;i=!0,await u,await o.handle.close();const a=await j(o.file);a&&JSON.parse(a).token===o.token&&await d.promises.unlink(o.file)}}}function Ae(e){const t=e.filename??e.workerUrl;if(!t||e.filename&&e.workerUrl)throw new TypeError("请且仅请指定 filename 或 workerUrl");return pe(()=>{const r=new W.Worker(t,e.workerOptions);return{postMessage:n=>r.postMessage(n),terminate:()=>r.terminate(),subscribe:(n,o)=>{const s=i=>o(new Error(`报表 Worker 在响应前退出(code ${i})`));return r.on("message",n),r.on("error",o),r.on("messageerror",o),r.on("exit",s),()=>{r.off("message",n),r.off("error",o),r.off("messageerror",o),r.off("exit",s)}}}},e)}function Ne(e){const t=W.parentPort;if(!t)throw new Error("serveNodeReportWorker 只能在 worker_threads 中调用");const r=n=>{se(n)&&ie(e,n,o=>t.postMessage({protocol:O,id:n.id,type:"event",event:o})).then(o=>t.postMessage(o,ae(o)))};return t.on("message",r),()=>t.off("message",r)}function Se(e){return I.createHash("sha256").update(e).digest("hex")}exports.ReportWorkerError=M;exports.createNodeReportExecutor=Ae;exports.openFileReportJobStore=$e;exports.reportArtifactSha256=Se;exports.serveNodeReportWorker=Ne;