@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.
- package/README.md +27 -9
- package/dist/ExcelBindingWizard-DiaxvWpQ.cjs +1 -0
- package/dist/ExcelBindingWizard-RLJIXKKG.js +816 -0
- package/dist/{ReportPreview-DTWiCH5a.js → ReportPreview-B5ZNEasW.js} +22 -21
- package/dist/ReportPreview-DRtVPUYo.cjs +6 -0
- package/dist/RuleEditor-N4qnMZ-Z.cjs +1 -0
- package/dist/RuleEditor-ynnUEK0s.js +1575 -0
- package/dist/TemplateReviewPanel-C_Lmzis6.cjs +1 -0
- package/dist/TemplateReviewPanel-Cn32OY4_.js +173 -0
- package/dist/analytics.cjs +1 -1
- package/dist/analytics.d.cts +188 -5
- package/dist/analytics.d.ts +188 -5
- package/dist/analytics.js +68 -202
- package/dist/{assets-B9qJku3V.js → assets-DDsfEi8R.js} +3 -3
- package/dist/{assets-RZan7EyL.cjs → assets-ahTRUXRk.cjs} +1 -1
- package/dist/binding-preview-B5834rml.cjs +2 -0
- package/dist/binding-preview-ChXjN5L5.js +649 -0
- package/dist/{capabilities-joSutDF8.js → capabilities-Cm9hZ3uV.js} +5 -5
- package/dist/{capabilities-xGTpnPjJ.cjs → capabilities-DYzWL7KS.cjs} +1 -1
- package/dist/dataset-BkRmwgeJ.cjs +1 -0
- package/dist/dataset-H5pFuQGU.js +121 -0
- package/dist/defaults-DXhiM1ZD.js +10 -0
- package/dist/defaults-xhmcLLrf.cjs +1 -0
- package/dist/designer.cjs +2 -1
- package/dist/designer.d.cts +1373 -6
- package/dist/designer.d.ts +1373 -6
- package/dist/designer.js +2495 -767
- package/dist/grid-geometry-BNptEcMm.js +65 -0
- package/dist/grid-geometry-CZ_cYB6O.cjs +1 -0
- package/dist/import-template-CNMLJSQw.js +23030 -0
- package/dist/import-template-CpxunKVp.cjs +29 -0
- package/dist/index.cjs +7 -7
- package/dist/index.d.cts +202 -3
- package/dist/index.d.ts +202 -3
- package/dist/index.js +554 -535
- package/dist/matrix-CNPDJxED.js +745 -0
- package/dist/matrix-Div9Ilh3.cjs +1 -0
- package/dist/pdf.cjs +46 -46
- package/dist/pdf.d.cts +2 -0
- package/dist/pdf.d.ts +2 -0
- package/dist/pdf.js +17 -16
- package/dist/{plugin-CQmJXNcA.js → plugin-BWwIgZXV.js} +1 -1
- package/dist/{plugin-DSFu51Ua.cjs → plugin-Dg-J1Rbm.cjs} +1 -1
- package/dist/progress-7OSZbFok.js +39 -0
- package/dist/progress-BnLiS5eH.cjs +1 -0
- package/dist/render-plan-7xpGrCEl.cjs +1 -0
- package/dist/render-plan-Ck6koX9L.js +13 -0
- package/dist/server/node.d.cts +62 -0
- package/dist/server/node.d.ts +62 -0
- package/dist/server-node.cjs +1 -1
- package/dist/server-node.js +373 -145
- package/dist/server.cjs +1 -1
- package/dist/server.d.cts +311 -0
- package/dist/server.d.ts +311 -0
- package/dist/server.js +590 -186
- package/dist/{style-Dv5o_x6b.js → style-CQ1PK8ZB.js} +5 -5
- package/dist/style-UgIJSA1F.cjs +1 -0
- package/dist/style.css +1 -1
- package/dist/template-registry-CHMYZ7SD.cjs +1 -0
- package/dist/template-registry-R61AMCr0.js +433 -0
- package/dist/template-review-hvWWQFsi.js +1027 -0
- package/dist/template-review-jEcOfmGr.cjs +1 -0
- package/dist/textwrap-CWHyzkBH.cjs +4 -0
- package/dist/{textwrap-DOl04hCQ.js → textwrap-DE1kgcJB.js} +1 -1
- package/dist/{validate-DfHPD8wX.cjs → validate-BDiMqkJC.cjs} +1 -1
- package/dist/{validate-S6CgIm5d.js → validate-DWPF7icl.js} +13 -13
- package/dist/vue/async.d.cts +186 -0
- package/dist/vue/async.d.ts +186 -0
- package/dist/vue/index.d.cts +271 -3
- package/dist/vue/index.d.ts +271 -3
- package/dist/vue-async.cjs +1 -1
- package/dist/vue-async.js +3 -3
- package/dist/vue.cjs +1 -1
- package/dist/vue.js +4 -4
- package/dist/worker.cjs +1 -1
- package/dist/worker.d.cts +2 -0
- package/dist/worker.d.ts +2 -0
- package/dist/worker.js +1 -1
- package/dist/xlsx.cjs +2 -30
- package/dist/xlsx.d.cts +268 -0
- package/dist/xlsx.d.ts +268 -0
- package/dist/xlsx.js +220 -23440
- package/package.json +1 -1
- package/dist/ReportPreview-DjGeWHY-.cjs +0 -6
- package/dist/progress-DD964VAB.js +0 -102
- package/dist/progress-KvhwXZ1Q.cjs +0 -1
- package/dist/render-plan-CckPEQyf.cjs +0 -1
- package/dist/render-plan-uzZYYSy1.js +0 -19
- package/dist/report-source-BXHNy_AD.js +0 -755
- package/dist/report-source-CCAvFE3t.cjs +0 -1
- package/dist/style-CpwiOPyB.cjs +0 -1
- package/dist/template-registry-DWExx0gU.cjs +0 -1
- package/dist/template-registry-NpOakidD.js +0 -354
- package/dist/textwrap-CnGsEum6.cjs +0 -4
package/dist/server-node.js
CHANGED
|
@@ -1,35 +1,38 @@
|
|
|
1
|
-
import { parentPort as
|
|
2
|
-
|
|
1
|
+
import { parentPort as K, Worker as L } from "node:worker_threads";
|
|
2
|
+
import { randomUUID as T, createHash as W } from "node:crypto";
|
|
3
|
+
import { promises as d } from "node:fs";
|
|
4
|
+
import N from "node:path";
|
|
5
|
+
function U(e, t, r) {
|
|
3
6
|
if (!r?.aborted)
|
|
4
7
|
try {
|
|
5
|
-
const
|
|
6
|
-
|
|
8
|
+
const n = e?.({ ...t });
|
|
9
|
+
n && typeof n.then == "function" && Promise.resolve(n).catch(() => {
|
|
7
10
|
});
|
|
8
11
|
} catch {
|
|
9
12
|
}
|
|
10
13
|
}
|
|
11
|
-
function
|
|
14
|
+
function B(e, t, r) {
|
|
12
15
|
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" });
|
|
13
16
|
}
|
|
14
|
-
function
|
|
15
|
-
|
|
17
|
+
function H(e, t, r) {
|
|
18
|
+
B(e, t, r), F(e.source, `${t}.source`, r, !0), e.formula !== void 0 && typeof e.formula != "string" && r.push({ path: `${t}.formula`, message: "单元格公式应为字符串" });
|
|
16
19
|
}
|
|
17
|
-
function
|
|
20
|
+
function F(e, t, r, n = !1) {
|
|
18
21
|
if (e === void 0) return;
|
|
19
22
|
if (!e || typeof e != "object" || Array.isArray(e)) {
|
|
20
23
|
r.push({ path: t, message: "业务来源应为对象" });
|
|
21
24
|
return;
|
|
22
25
|
}
|
|
23
|
-
const
|
|
24
|
-
for (const
|
|
25
|
-
(typeof s
|
|
26
|
-
for (const
|
|
27
|
-
const i = s
|
|
28
|
-
i === void 0 && !(
|
|
26
|
+
const o = e;
|
|
27
|
+
for (const s of ["datasetId", ...n ? ["field"] : []])
|
|
28
|
+
(typeof o[s] != "string" || !o[s].trim()) && r.push({ path: `${t}.${s}`, message: "业务标识应为非空字符串" });
|
|
29
|
+
for (const s of ["rowKey", "revision"]) {
|
|
30
|
+
const i = o[s];
|
|
31
|
+
i === void 0 && !(n && s === "rowKey") || typeof i != "string" && !(typeof i == "number" && Number.isFinite(i)) && r.push({ path: `${t}.${s}`, message: "业务键及修订号应为字符串或有限数字" });
|
|
29
32
|
}
|
|
30
|
-
|
|
33
|
+
o.sourceToken !== void 0 && typeof o.sourceToken != "string" && r.push({ path: `${t}.sourceToken`, message: "来源令牌应为字符串" });
|
|
31
34
|
}
|
|
32
|
-
const
|
|
35
|
+
const G = /* @__PURE__ */ new Set([
|
|
33
36
|
"text",
|
|
34
37
|
"image",
|
|
35
38
|
"barcode",
|
|
@@ -39,149 +42,149 @@ const S = /* @__PURE__ */ new Set([
|
|
|
39
42
|
"rect",
|
|
40
43
|
"ellipse"
|
|
41
44
|
]);
|
|
42
|
-
function
|
|
45
|
+
function $(e) {
|
|
43
46
|
return typeof e == "object" && e !== null && !Array.isArray(e);
|
|
44
47
|
}
|
|
45
|
-
function
|
|
46
|
-
const
|
|
47
|
-
(typeof
|
|
48
|
+
function X(e, t, r, n) {
|
|
49
|
+
const o = e[t];
|
|
50
|
+
(typeof o != "number" || !Number.isFinite(o)) && n.push({ path: `${r}.${t}`, message: `应为有限数字,实际 ${JSON.stringify(o)}` });
|
|
48
51
|
}
|
|
49
|
-
function
|
|
52
|
+
function Z(e, t, r) {
|
|
50
53
|
if (e !== void 0) {
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
54
|
+
const n = `${t}.table`;
|
|
55
|
+
if (!$(e)) r.push({ path: n, message: "逻辑表来源应为对象" });
|
|
53
56
|
else {
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
["header", "body", "group-header", "subtotal", "grand-total"].includes(
|
|
57
|
-
const
|
|
58
|
-
(typeof
|
|
57
|
+
F(e.source, `${n}.source`, r), (typeof e.id != "string" || !e.id.trim()) && r.push({ path: `${n}.id`, message: "逻辑表 ID 应为非空字符串" });
|
|
58
|
+
const o = e.role;
|
|
59
|
+
["header", "body", "group-header", "subtotal", "grand-total"].includes(o) || r.push({ path: `${n}.role`, message: "未知逻辑表行角色" });
|
|
60
|
+
const s = e.rowIndex;
|
|
61
|
+
(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: "逻辑表名称应为字符串" });
|
|
59
62
|
}
|
|
60
63
|
}
|
|
61
64
|
}
|
|
62
|
-
function
|
|
65
|
+
function V(e, t, r, n) {
|
|
63
66
|
if (e !== void 0)
|
|
64
|
-
if (
|
|
67
|
+
if (!$(e) || !Array.isArray(e.cells))
|
|
65
68
|
r.push({ path: `${t}.grid.cells`, message: "grid.cells 应为二维数组" });
|
|
66
69
|
else {
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
if (!Array.isArray(
|
|
70
|
+
const o = e.paddingMm;
|
|
71
|
+
o !== void 0 && (typeof o != "number" || !Number.isFinite(o) || o < 0) && r.push({ path: `${t}.grid.paddingMm`, message: "单元格内距应为有限非负数" }), e.cells.forEach((s, i) => {
|
|
72
|
+
if (!Array.isArray(s)) {
|
|
70
73
|
r.push({ path: `${t}.grid.cells.${i}`, message: "行应为数组" });
|
|
71
74
|
return;
|
|
72
75
|
}
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
const
|
|
76
|
-
if (
|
|
77
|
-
r.push({ path:
|
|
76
|
+
s.forEach((u, l) => {
|
|
77
|
+
if (u == null) return;
|
|
78
|
+
const c = `${t}.grid.cells.${i}.${l}`;
|
|
79
|
+
if (!$(u)) {
|
|
80
|
+
r.push({ path: c, message: "网格单元格应为对象或 null" });
|
|
78
81
|
return;
|
|
79
82
|
}
|
|
80
|
-
|
|
81
|
-
|
|
83
|
+
H(u, c, r), Array.isArray(u.children) && u.children.forEach((a, m) => {
|
|
84
|
+
D(a, `${t}.grid.cells.${i}.${l}.children.${m}`, r, n);
|
|
82
85
|
});
|
|
83
86
|
});
|
|
84
87
|
});
|
|
85
88
|
}
|
|
86
89
|
}
|
|
87
|
-
function
|
|
88
|
-
e !== void 0 && (Array.isArray(e) ? e.forEach((
|
|
89
|
-
(
|
|
90
|
+
function Q(e, t, r) {
|
|
91
|
+
e !== void 0 && (Array.isArray(e) ? e.forEach((n, o) => {
|
|
92
|
+
(!$(n) || !Array.isArray(n.segments)) && r.push({ path: `${t}.richParagraphs.${o}`, message: "段落缺少 segments 数组" });
|
|
90
93
|
}) : r.push({ path: `${t}.richParagraphs`, message: "richParagraphs 应为数组" }));
|
|
91
94
|
}
|
|
92
|
-
function
|
|
93
|
-
if (
|
|
95
|
+
function D(e, t, r, n = []) {
|
|
96
|
+
if (!$(e)) {
|
|
94
97
|
r.push({ path: t, message: "组件应为对象" });
|
|
95
98
|
return;
|
|
96
99
|
}
|
|
97
|
-
const
|
|
98
|
-
typeof
|
|
100
|
+
const o = e.kind;
|
|
101
|
+
typeof o != "string" ? r.push({ path: `${t}.kind`, message: "组件缺少 kind 字符串" }) : G.has(o) || n.push({
|
|
99
102
|
path: `${t}.kind`,
|
|
100
|
-
message: `未知组件类型 ${JSON.stringify(
|
|
103
|
+
message: `未知组件类型 ${JSON.stringify(o)},将以兜底方式渲染`
|
|
101
104
|
});
|
|
102
|
-
for (const
|
|
103
|
-
|
|
105
|
+
for (const s of ["leftMm", "topMm", "widthMm", "heightMm"])
|
|
106
|
+
X(e, s, t, r);
|
|
104
107
|
typeof e.leftMm == "number" && e.leftMm < -100 && r.push({ path: `${t}.leftMm`, message: "几何数值异常(leftMm<-100)" });
|
|
105
|
-
for (const
|
|
106
|
-
typeof e[
|
|
107
|
-
|
|
108
|
+
for (const s of ["widthMm", "heightMm"])
|
|
109
|
+
typeof e[s] == "number" && e[s] < 0 && r.push({ path: `${t}.${s}`, message: "组件尺寸不能为负数" });
|
|
110
|
+
Z(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" }), V(e.grid, t, r, n), Q(e.richParagraphs, t, r);
|
|
108
111
|
}
|
|
109
|
-
function
|
|
110
|
-
if (
|
|
112
|
+
function Y(e, t, r, n = []) {
|
|
113
|
+
if (!$(e)) {
|
|
111
114
|
r.push({ path: t, message: "页应为对象" });
|
|
112
115
|
return;
|
|
113
116
|
}
|
|
114
|
-
const
|
|
115
|
-
(typeof
|
|
117
|
+
const o = e.pageWidthMm, s = e.pageHeightMm;
|
|
118
|
+
(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" });
|
|
116
119
|
const i = e.components;
|
|
117
120
|
Array.isArray(i) ? Array.isArray(i) && i.forEach(
|
|
118
|
-
(
|
|
121
|
+
(u, l) => D(u, `${t}.components.${l}`, r, n)
|
|
119
122
|
) : r.push({ path: `${t}.components`, message: "components 应为数组" });
|
|
120
123
|
}
|
|
121
|
-
function
|
|
122
|
-
const t = [], r = [],
|
|
123
|
-
if (!Array.isArray(
|
|
124
|
+
function ee(e) {
|
|
125
|
+
const t = [], r = [], n = $(e) ? e.pages : void 0;
|
|
126
|
+
if (!Array.isArray(n))
|
|
124
127
|
t.push({
|
|
125
128
|
path: "$.pages",
|
|
126
129
|
message: e == null ? "渲染计划为空" : "渲染计划缺少 pages 数组"
|
|
127
130
|
});
|
|
128
131
|
else {
|
|
129
|
-
|
|
132
|
+
n.forEach((s, i) => Y(s, `$.pages.${i}`, t, r)), n.length > 2e3 && r.push({
|
|
130
133
|
path: "$.pages",
|
|
131
|
-
message: `页数异常大(${
|
|
134
|
+
message: `页数异常大(${n.length} 页),渲染与打印耗时可能显著增加`
|
|
132
135
|
});
|
|
133
|
-
const
|
|
134
|
-
(
|
|
136
|
+
const o = n.reduce(
|
|
137
|
+
(s, i) => s + ($(i) && Array.isArray(i.components) ? i.components.length : 0),
|
|
135
138
|
0
|
|
136
139
|
);
|
|
137
|
-
|
|
140
|
+
o > 5e4 && r.push({
|
|
138
141
|
path: "$.pages",
|
|
139
|
-
message: `组件总数异常大(${
|
|
142
|
+
message: `组件总数异常大(${o} 个),可能触发浏览器性能限制`
|
|
140
143
|
});
|
|
141
144
|
}
|
|
142
145
|
return { ok: t.length === 0, errors: t, warnings: r };
|
|
143
146
|
}
|
|
144
|
-
const
|
|
145
|
-
class
|
|
147
|
+
const x = "mach-report-worker/1";
|
|
148
|
+
class J extends Error {
|
|
146
149
|
constructor(t) {
|
|
147
150
|
super(t.message), this.name = t.name, this.code = t.code, this.path = t.path, this.issues = t.issues, this.diagnostics = t.diagnostics;
|
|
148
151
|
}
|
|
149
152
|
}
|
|
150
|
-
function
|
|
153
|
+
function E(e) {
|
|
151
154
|
return !!e && typeof e == "object" && !Array.isArray(e);
|
|
152
155
|
}
|
|
153
|
-
function
|
|
154
|
-
return
|
|
156
|
+
function te(e) {
|
|
157
|
+
return E(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;
|
|
155
158
|
}
|
|
156
|
-
function
|
|
157
|
-
return Array.isArray(e) && e.every((t) =>
|
|
159
|
+
function re(e) {
|
|
160
|
+
return Array.isArray(e) && e.every((t) => E(t) && typeof t.code == "string" && typeof t.message == "string" && ["info", "warning", "error"].includes(t.severity));
|
|
158
161
|
}
|
|
159
|
-
function
|
|
160
|
-
return
|
|
162
|
+
function ne(e) {
|
|
163
|
+
return E(e) && Object.values(e).every((t) => E(t) && (t.revision === void 0 || typeof t.revision == "string") && (t.sourceToken === void 0 || typeof t.sourceToken == "string"));
|
|
161
164
|
}
|
|
162
|
-
function
|
|
163
|
-
if (!
|
|
164
|
-
if (t === "prepare") return
|
|
165
|
+
function oe(e, t) {
|
|
166
|
+
if (!E(e) || !te(e.stats) || !re(e.diagnostics) || !ne(e.revisions)) return !1;
|
|
167
|
+
if (t === "prepare") return ee(e.plan).ok;
|
|
165
168
|
const r = e.format === "pdf" ? "application/pdf" : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
|
166
169
|
return e.bytes instanceof Uint8Array && (e.format === "pdf" || e.format === "xlsx") && e.contentType === r;
|
|
167
170
|
}
|
|
168
|
-
function
|
|
171
|
+
function _(e) {
|
|
169
172
|
if (!e || typeof e != "object") return { message: String(e) };
|
|
170
173
|
const t = {};
|
|
171
174
|
for (const r of ["code", "path", "field", "message"]) {
|
|
172
|
-
const
|
|
173
|
-
typeof
|
|
175
|
+
const n = e[r];
|
|
176
|
+
typeof n == "string" && (t[r] = n);
|
|
174
177
|
}
|
|
175
178
|
return t;
|
|
176
179
|
}
|
|
177
|
-
function
|
|
178
|
-
const t =
|
|
179
|
-
if (!
|
|
180
|
+
function se(e) {
|
|
181
|
+
const t = _(e);
|
|
182
|
+
if (!E(e)) return t;
|
|
180
183
|
for (const r of ["format", "severity", "kind", "nid"]) typeof e[r] == "string" && (t[r] = e[r]);
|
|
181
184
|
for (const r of ["pageIndex", "componentIndex"]) Number.isSafeInteger(e[r]) && e[r] >= 0 && (t[r] = e[r]);
|
|
182
185
|
return Array.isArray(e.componentPath) && e.componentPath.every((r) => Number.isSafeInteger(r) && r >= 0) && (t.componentPath = e.componentPath), t;
|
|
183
186
|
}
|
|
184
|
-
function
|
|
187
|
+
function ie(e) {
|
|
185
188
|
if (!(e instanceof Error)) return { name: "Error", message: String(e) };
|
|
186
189
|
const t = e;
|
|
187
190
|
return {
|
|
@@ -189,115 +192,340 @@ function B(e) {
|
|
|
189
192
|
message: e.message,
|
|
190
193
|
...typeof t.code == "string" ? { code: t.code } : {},
|
|
191
194
|
...typeof t.path == "string" ? { path: t.path } : {},
|
|
192
|
-
...Array.isArray(t.issues) ? { issues: t.issues.map(
|
|
193
|
-
...Array.isArray(t.diagnostics) ? { diagnostics: t.diagnostics.map(
|
|
195
|
+
...Array.isArray(t.issues) ? { issues: t.issues.map(_) } : {},
|
|
196
|
+
...Array.isArray(t.diagnostics) ? { diagnostics: t.diagnostics.map(se) } : {}
|
|
194
197
|
};
|
|
195
198
|
}
|
|
196
|
-
function
|
|
199
|
+
function ae(e) {
|
|
197
200
|
if (!e || typeof e != "object") return !1;
|
|
198
201
|
const t = e;
|
|
199
|
-
return t.protocol ===
|
|
202
|
+
return t.protocol === x && typeof t.id == "string" && (t.operation === "prepare" || t.operation === "export") && !!t.input && typeof t.input == "object";
|
|
200
203
|
}
|
|
201
|
-
async function
|
|
204
|
+
async function ce(e, t, r) {
|
|
202
205
|
try {
|
|
203
|
-
const
|
|
204
|
-
return { protocol:
|
|
205
|
-
} catch (
|
|
206
|
-
return { protocol:
|
|
206
|
+
const n = t.operation === "prepare" ? await e.prepare({ ...t.input, onEvent: r }) : await e.export({ ...t.input, onEvent: r });
|
|
207
|
+
return { protocol: x, id: t.id, result: n };
|
|
208
|
+
} catch (n) {
|
|
209
|
+
return { protocol: x, id: t.id, error: ie(n) };
|
|
207
210
|
}
|
|
208
211
|
}
|
|
209
|
-
function
|
|
212
|
+
function fe(e) {
|
|
210
213
|
const t = e.result;
|
|
211
214
|
return !t || !("bytes" in t) || !(t.bytes.buffer instanceof ArrayBuffer) ? [] : [t.bytes.buffer];
|
|
212
215
|
}
|
|
213
|
-
function
|
|
214
|
-
if (!
|
|
216
|
+
function ue(e, t) {
|
|
217
|
+
if (!E(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;
|
|
215
218
|
for (const r of ["completed", "total"]) if (e[r] !== void 0 && (typeof e[r] != "number" || !Number.isFinite(e[r]) || e[r] < 0)) return !1;
|
|
216
219
|
return e.completed === void 0 || e.total === void 0 || e.completed <= e.total;
|
|
217
220
|
}
|
|
218
|
-
let
|
|
219
|
-
function
|
|
221
|
+
let pe = 0;
|
|
222
|
+
function j(e) {
|
|
220
223
|
const t = new Error("报表 Worker 任务已取消");
|
|
221
224
|
return t.name = "AbortError", Object.defineProperty(t, "cause", { value: e }), t;
|
|
222
225
|
}
|
|
223
|
-
function
|
|
226
|
+
function de(e, t) {
|
|
224
227
|
if (!e || typeof e != "object") return;
|
|
225
228
|
const r = e;
|
|
226
|
-
return r.protocol ===
|
|
229
|
+
return r.protocol === x && r.id === t ? r : void 0;
|
|
227
230
|
}
|
|
228
|
-
function
|
|
231
|
+
function le(e, t = {}) {
|
|
229
232
|
const r = t.timeoutMs ?? 12e4;
|
|
230
233
|
if (!Number.isFinite(r) || r <= 0 || r > 2147483647) throw new RangeError("Worker timeoutMs 应为正有限数字,且不能超过 2147483647");
|
|
231
|
-
const
|
|
232
|
-
let
|
|
234
|
+
const n = (o, s, i, u) => i?.aborted ? Promise.reject(j(i.reason)) : new Promise((l, c) => {
|
|
235
|
+
let a;
|
|
233
236
|
try {
|
|
234
|
-
|
|
235
|
-
} catch (
|
|
236
|
-
|
|
237
|
+
a = e();
|
|
238
|
+
} catch (h) {
|
|
239
|
+
c(h);
|
|
237
240
|
return;
|
|
238
241
|
}
|
|
239
|
-
const
|
|
240
|
-
let
|
|
241
|
-
},
|
|
242
|
-
const
|
|
243
|
-
|
|
244
|
-
() =>
|
|
245
|
-
(
|
|
242
|
+
const m = `mach-report-${Date.now()}-${++pe}`;
|
|
243
|
+
let y = !1, b = () => {
|
|
244
|
+
}, g;
|
|
245
|
+
const w = (h, p) => {
|
|
246
|
+
y || (y = !0, g && clearTimeout(g), b(), i?.removeEventListener("abort", S), Promise.resolve().then(() => a.terminate()).then(
|
|
247
|
+
() => h === void 0 ? l(p) : c(h),
|
|
248
|
+
(k) => c(h ?? k)
|
|
246
249
|
));
|
|
247
|
-
},
|
|
248
|
-
const
|
|
249
|
-
if (!(!
|
|
250
|
-
if ("type" in
|
|
251
|
-
const
|
|
252
|
-
|
|
250
|
+
}, S = () => w(j(i?.reason)), A = (h) => {
|
|
251
|
+
const p = de(h, m);
|
|
252
|
+
if (!(!p || y)) {
|
|
253
|
+
if ("type" in p && p.type === "event") {
|
|
254
|
+
const k = "event" in p ? p.event : void 0;
|
|
255
|
+
ue(k, s) ? U(u, k, i) : w(new Error("报表 Worker 返回无效阶段事件"));
|
|
253
256
|
return;
|
|
254
257
|
}
|
|
255
|
-
|
|
258
|
+
p.error && typeof p.error.name == "string" && typeof p.error.message == "string" ? w(new J(p.error)) : oe(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 返回无效响应"));
|
|
256
259
|
}
|
|
257
260
|
};
|
|
258
261
|
try {
|
|
259
|
-
if (
|
|
260
|
-
|
|
262
|
+
if (b = a.subscribe(A, (h) => w(h ?? new Error("报表 Worker 执行失败"))), y) {
|
|
263
|
+
b();
|
|
261
264
|
return;
|
|
262
265
|
}
|
|
263
|
-
if (i?.addEventListener("abort",
|
|
266
|
+
if (i?.addEventListener("abort", S, { once: !0 }), g = setTimeout(() => w(new J({ name: "ReportRuntimeError", code: "timeout", message: `报表 Worker 执行超过 ${r}ms` })), r), i?.aborted) S();
|
|
264
267
|
else {
|
|
265
|
-
const { onEvent:
|
|
266
|
-
|
|
268
|
+
const { onEvent: h, signal: p, ...k } = s;
|
|
269
|
+
a.postMessage({ protocol: x, id: m, operation: o, input: k });
|
|
267
270
|
}
|
|
268
|
-
} catch (
|
|
269
|
-
|
|
271
|
+
} catch (h) {
|
|
272
|
+
w(h);
|
|
270
273
|
}
|
|
271
274
|
});
|
|
272
|
-
return { prepare: (
|
|
275
|
+
return { prepare: (o, s, i) => n("prepare", o, s, i), export: (o, s, i) => n("export", o, s, i) };
|
|
273
276
|
}
|
|
274
|
-
|
|
277
|
+
class f extends Error {
|
|
278
|
+
constructor(t, r) {
|
|
279
|
+
super(r), this.code = t, this.name = "ReportJobError";
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function q(e, t) {
|
|
283
|
+
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位安全标识");
|
|
284
|
+
}
|
|
285
|
+
function ye(e) {
|
|
286
|
+
const t = Array.isArray(e), r = Object.getPrototypeOf(e), n = Object.keys(e);
|
|
287
|
+
if (r !== (t ? Array.prototype : Object.prototype) && !(r === null && !t)) throw new f("input", "任务对象应为普通 JSON 对象");
|
|
288
|
+
if (Object.getOwnPropertySymbols(e).length) throw new f("input", "任务不能包含Symbol");
|
|
289
|
+
if (Object.getOwnPropertyNames(e).filter((s) => !(t && s === "length")).length !== n.length) throw new f("input", "任务不能包含不可枚举属性");
|
|
290
|
+
if (t && (n.length !== e.length || n.some((s) => !/^(0|[1-9]\d*)$/.test(s) || Number(s) >= e.length))) throw new f("input", "任务数组不能稀疏或包含额外属性");
|
|
291
|
+
return n.sort();
|
|
292
|
+
}
|
|
293
|
+
function he(e, t) {
|
|
294
|
+
const r = Object.getOwnPropertyDescriptor(e, t);
|
|
295
|
+
if (["__proto__", "prototype", "constructor"].includes(t) || r.get || r.set) throw new f("input", "任务不能包含危险键或访问器");
|
|
296
|
+
return r.value;
|
|
297
|
+
}
|
|
298
|
+
function O(e, t = {}) {
|
|
299
|
+
const r = t.maxNodes ?? 2e4, n = t.maxCharacters ?? 1e6;
|
|
300
|
+
if (!Number.isSafeInteger(r) || r < 1 || r > 2e4 || !Number.isSafeInteger(n) || n < 1 || n > 1e6) throw new f("input", "任务JSON预算无效");
|
|
301
|
+
let o = 0, s = 0;
|
|
302
|
+
const i = /* @__PURE__ */ new Set();
|
|
303
|
+
function u(c, a) {
|
|
304
|
+
if (++o > r || a > 32) throw new f("input", "任务数据超过节点或深度预算");
|
|
305
|
+
if (typeof c == "string") {
|
|
306
|
+
if (s += c.length, s > n) throw new f("input", "任务文本超过预算");
|
|
307
|
+
return c;
|
|
308
|
+
}
|
|
309
|
+
if (c === null || typeof c == "boolean" || typeof c == "number" && Number.isFinite(c)) return c;
|
|
310
|
+
if (!c || typeof c != "object" || i.has(c)) throw new f("input", "任务只允许无循环的有限 JSON 值");
|
|
311
|
+
const m = Array.isArray(c), y = ye(c);
|
|
312
|
+
i.add(c);
|
|
313
|
+
const b = /* @__PURE__ */ Object.create(null);
|
|
314
|
+
for (const g of y) {
|
|
315
|
+
if (s += g.length, s > n) throw new f("input", "任务文本超过预算");
|
|
316
|
+
b[g] = u(he(c, g), a + 1);
|
|
317
|
+
}
|
|
318
|
+
return i.delete(c), m ? Array.from({ length: c.length }, (g, w) => b[String(w)]) : b;
|
|
319
|
+
}
|
|
320
|
+
const l = JSON.stringify(u(e, 0));
|
|
321
|
+
if (l.length > n) throw new f("input", "任务序列化数据超过字符预算");
|
|
322
|
+
return l;
|
|
323
|
+
}
|
|
324
|
+
function P(e) {
|
|
325
|
+
return JSON.parse(JSON.stringify(e));
|
|
326
|
+
}
|
|
327
|
+
function z(e, t, r, n) {
|
|
328
|
+
if (q(t, r), e.scope !== t || e.id !== r || e.revision !== (n ?? 0) + 1 || !Number.isSafeInteger(e.revision)) throw new f("input", "任务身份或修订不匹配");
|
|
329
|
+
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", "任务状态无效");
|
|
330
|
+
if (e.lease && (!e.lease.owner || !Number.isSafeInteger(e.lease.expiresAt))) throw new f("input", "任务租约无效");
|
|
331
|
+
if (!e.request || typeof e.request.kind != "string" || !e.request.kind.trim() || e.request.kind.length > 128) throw new f("input", "任务类型无效");
|
|
332
|
+
O(e.request.payload, { maxNodes: 19e3, maxCharacters: 75e4 }), O(e);
|
|
333
|
+
}
|
|
334
|
+
function me(e, t) {
|
|
335
|
+
if (e && (e.createdAt !== t.createdAt || O(e.request) !== O(t.request))) throw new f("input", "任务创建时间与请求不可变更,请使用新任务ID");
|
|
336
|
+
}
|
|
337
|
+
function ge(e, t) {
|
|
338
|
+
return e.status === "queued" || e.status === "running" && (e.lease?.expiresAt ?? 0) <= t;
|
|
339
|
+
}
|
|
340
|
+
function v(e) {
|
|
341
|
+
return e?.code;
|
|
342
|
+
}
|
|
343
|
+
function M(e, t) {
|
|
344
|
+
return W("sha256").update(JSON.stringify([e, t])).digest("hex") + ".json";
|
|
345
|
+
}
|
|
346
|
+
async function R(e) {
|
|
347
|
+
try {
|
|
348
|
+
return await d.readFile(e, "utf8");
|
|
349
|
+
} catch (t) {
|
|
350
|
+
if (v(t) === "ENOENT") return;
|
|
351
|
+
throw t;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
async function we(e, t) {
|
|
355
|
+
const r = await R(e);
|
|
356
|
+
if (r === void 0) return;
|
|
357
|
+
let n;
|
|
358
|
+
try {
|
|
359
|
+
n = JSON.parse(r);
|
|
360
|
+
} catch {
|
|
361
|
+
throw new f("conflict", "任务锁尚未完整写入或已损坏,拒绝自动移除");
|
|
362
|
+
}
|
|
363
|
+
if (!n || !Number.isSafeInteger(n.pid) || n.pid < 1) throw new f("conflict", "任务锁身份无效,拒绝自动移除");
|
|
364
|
+
try {
|
|
365
|
+
process.kill(n.pid, 0);
|
|
366
|
+
} catch (o) {
|
|
367
|
+
if (v(o) === "ESRCH") {
|
|
368
|
+
await d.unlink(e);
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
throw o;
|
|
372
|
+
}
|
|
373
|
+
throw new f("conflict", "任务目录的写入进程仍在运行");
|
|
374
|
+
}
|
|
375
|
+
async function be(e, t) {
|
|
376
|
+
if (!t) throw new f("conflict", "任务目录已有写入进程;多实例请使用数据库CAS适配器");
|
|
377
|
+
const r = e + ".recovery";
|
|
378
|
+
let n;
|
|
379
|
+
try {
|
|
380
|
+
n = await d.open(r, "wx", 384);
|
|
381
|
+
} catch (o) {
|
|
382
|
+
throw v(o) === "EEXIST" ? new f("conflict", "任务目录恢复正在进行,请稍后重试") : o;
|
|
383
|
+
}
|
|
384
|
+
try {
|
|
385
|
+
return await n.writeFile(JSON.stringify({ pid: process.pid })), await we(e, !0), await d.open(e, "wx", 384);
|
|
386
|
+
} finally {
|
|
387
|
+
await n.close(), await d.unlink(r);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
async function ke(e, t) {
|
|
391
|
+
const r = N.join(e, ".writer-lock"), n = T();
|
|
392
|
+
let o;
|
|
393
|
+
try {
|
|
394
|
+
o = await d.open(r, "wx", 384);
|
|
395
|
+
} catch (s) {
|
|
396
|
+
if (v(s) !== "EEXIST") throw s;
|
|
397
|
+
o = await be(r, t);
|
|
398
|
+
}
|
|
399
|
+
try {
|
|
400
|
+
await o.writeFile(JSON.stringify({ pid: process.pid, token: n })), await o.sync();
|
|
401
|
+
} catch (s) {
|
|
402
|
+
throw await o.close(), await d.unlink(r).catch(() => {
|
|
403
|
+
}), s;
|
|
404
|
+
}
|
|
405
|
+
return { file: r, token: n, handle: o };
|
|
406
|
+
}
|
|
407
|
+
async function $e(e, t, r) {
|
|
408
|
+
const n = await d.readdir(e);
|
|
409
|
+
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.unlink(N.join(e, u));
|
|
410
|
+
const o = n.filter((u) => /^[a-f0-9]{64}\.json$/.test(u));
|
|
411
|
+
if (o.length > t) throw new f("capacity", "持久任务数量超过目录预算");
|
|
412
|
+
const s = /* @__PURE__ */ new Map();
|
|
413
|
+
let i = 0;
|
|
414
|
+
for (const u of o) {
|
|
415
|
+
const l = N.join(e, u), c = await d.stat(l);
|
|
416
|
+
if (i += c.size, c.size > 4e6 || i > r) throw new f("capacity", "持久任务文件超过容量预算");
|
|
417
|
+
const a = JSON.parse(await d.readFile(l, "utf8"));
|
|
418
|
+
if (z(a, a.scope, a.id, a.revision - 1), M(a.scope, a.id) !== u) throw new f("input", "持久任务文件身份不匹配");
|
|
419
|
+
s.set(u, { record: a, bytes: c.size });
|
|
420
|
+
}
|
|
421
|
+
return { records: s, bytes: i };
|
|
422
|
+
}
|
|
423
|
+
async function Ae(e, t, r) {
|
|
424
|
+
const n = N.join(e, `.pending-${T()}`);
|
|
425
|
+
try {
|
|
426
|
+
const o = await d.open(n, "wx", 384);
|
|
427
|
+
try {
|
|
428
|
+
await o.writeFile(r), await o.sync();
|
|
429
|
+
} finally {
|
|
430
|
+
await o.close();
|
|
431
|
+
}
|
|
432
|
+
await d.rename(n, N.join(e, t));
|
|
433
|
+
const s = await d.open(e, "r");
|
|
434
|
+
try {
|
|
435
|
+
await s.sync();
|
|
436
|
+
} finally {
|
|
437
|
+
await s.close();
|
|
438
|
+
}
|
|
439
|
+
} finally {
|
|
440
|
+
await d.unlink(n).catch((o) => {
|
|
441
|
+
if (v(o) !== "ENOENT") throw o;
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
async function Oe(e) {
|
|
446
|
+
const t = N.resolve(e.directory), r = e.maxRecords ?? 1e4, n = e.maxBytes ?? 64 * 1024 * 1024;
|
|
447
|
+
if (![r, n].every((a) => Number.isSafeInteger(a) && a > 0)) throw new f("input", "持久任务预算应为正整数");
|
|
448
|
+
await d.mkdir(t, { recursive: !0, mode: 448 });
|
|
449
|
+
const o = await ke(t, e.recoverDeadOwner ?? !1);
|
|
450
|
+
let s;
|
|
451
|
+
try {
|
|
452
|
+
s = await $e(t, r, n);
|
|
453
|
+
} catch (a) {
|
|
454
|
+
throw await o.handle.close(), await d.unlink(o.file), a;
|
|
455
|
+
}
|
|
456
|
+
let i = !1, u = Promise.resolve();
|
|
457
|
+
const l = () => {
|
|
458
|
+
if (i) throw new f("closed", "持久任务存储已关闭");
|
|
459
|
+
};
|
|
460
|
+
return {
|
|
461
|
+
read: async (a, m) => {
|
|
462
|
+
l(), q(a, m), await u;
|
|
463
|
+
const y = s.records.get(M(a, m));
|
|
464
|
+
return y ? P(y.record) : void 0;
|
|
465
|
+
},
|
|
466
|
+
candidates: async (a, m) => (l(), await u, Array.from(s.records.values(), (y) => y.record).filter((y) => ge(y, a)).sort((y, b) => y.createdAt - b.createdAt).slice(0, m).map(P)),
|
|
467
|
+
compareAndSwap: async (a, m, y, b) => {
|
|
468
|
+
l();
|
|
469
|
+
const g = JSON.parse(O(b));
|
|
470
|
+
z(g, a, m, y);
|
|
471
|
+
let w = !1;
|
|
472
|
+
const S = u.then(async () => {
|
|
473
|
+
if (JSON.parse(await d.readFile(o.file, "utf8")).token !== o.token) throw new f("closed", "持久任务存储写入锁已失效");
|
|
474
|
+
const A = M(a, m), h = s.records.get(A);
|
|
475
|
+
if ((h?.record.revision ?? null) !== y) return;
|
|
476
|
+
me(h?.record, g);
|
|
477
|
+
const p = O(g), k = Buffer.byteLength(p, "utf8"), I = s.bytes - (h?.bytes ?? 0) + k;
|
|
478
|
+
if (I > n || !h && s.records.size >= r) throw new f("capacity", "持久任务容量已满,请归档旧任务或扩大显式预算");
|
|
479
|
+
try {
|
|
480
|
+
await Ae(t, A, p);
|
|
481
|
+
} catch (C) {
|
|
482
|
+
throw await R(N.join(t, A)) === p && (s.records.set(A, { record: g, bytes: k }), s.bytes = I), C;
|
|
483
|
+
}
|
|
484
|
+
s.records.set(A, { record: g, bytes: k }), s.bytes = I, w = !0;
|
|
485
|
+
});
|
|
486
|
+
return u = S.catch(() => {
|
|
487
|
+
}), await S, w;
|
|
488
|
+
},
|
|
489
|
+
close: async () => {
|
|
490
|
+
if (i) return;
|
|
491
|
+
i = !0, await u, await o.handle.close();
|
|
492
|
+
const a = await R(o.file);
|
|
493
|
+
a && JSON.parse(a).token === o.token && await d.unlink(o.file);
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
function ve(e) {
|
|
275
498
|
const t = e.filename ?? e.workerUrl;
|
|
276
499
|
if (!t || e.filename && e.workerUrl) throw new TypeError("请且仅请指定 filename 或 workerUrl");
|
|
277
|
-
return
|
|
278
|
-
const r = new
|
|
500
|
+
return le(() => {
|
|
501
|
+
const r = new L(t, e.workerOptions);
|
|
279
502
|
return {
|
|
280
|
-
postMessage: (
|
|
503
|
+
postMessage: (n) => r.postMessage(n),
|
|
281
504
|
terminate: () => r.terminate(),
|
|
282
|
-
subscribe: (
|
|
283
|
-
const
|
|
284
|
-
return r.on("message",
|
|
285
|
-
r.off("message",
|
|
505
|
+
subscribe: (n, o) => {
|
|
506
|
+
const s = (i) => o(new Error(`报表 Worker 在响应前退出(code ${i})`));
|
|
507
|
+
return r.on("message", n), r.on("error", o), r.on("messageerror", o), r.on("exit", s), () => {
|
|
508
|
+
r.off("message", n), r.off("error", o), r.off("messageerror", o), r.off("exit", s);
|
|
286
509
|
};
|
|
287
510
|
}
|
|
288
511
|
};
|
|
289
512
|
}, e);
|
|
290
513
|
}
|
|
291
|
-
function
|
|
292
|
-
const t =
|
|
514
|
+
function Ie(e) {
|
|
515
|
+
const t = K;
|
|
293
516
|
if (!t) throw new Error("serveNodeReportWorker 只能在 worker_threads 中调用");
|
|
294
|
-
const r = (
|
|
295
|
-
|
|
517
|
+
const r = (n) => {
|
|
518
|
+
ae(n) && ce(e, n, (o) => t.postMessage({ protocol: x, id: n.id, type: "event", event: o })).then((o) => t.postMessage(o, fe(o)));
|
|
296
519
|
};
|
|
297
520
|
return t.on("message", r), () => t.off("message", r);
|
|
298
521
|
}
|
|
522
|
+
function Me(e) {
|
|
523
|
+
return W("sha256").update(e).digest("hex");
|
|
524
|
+
}
|
|
299
525
|
export {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
526
|
+
J as ReportWorkerError,
|
|
527
|
+
ve as createNodeReportExecutor,
|
|
528
|
+
Oe as openFileReportJobStore,
|
|
529
|
+
Me as reportArtifactSha256,
|
|
530
|
+
Ie as serveNodeReportWorker
|
|
303
531
|
};
|