@agile-team/mach-report 2.10.0 → 2.11.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 +6 -2
- package/dist/ExcelBindingWizard-CjIiVox-.cjs +1 -0
- package/dist/ExcelBindingWizard-Dxm-K5HL.js +1240 -0
- package/dist/ParamEditor-D-Hf5xfO.cjs +1 -0
- package/dist/ParamEditor-DRGxzxeO.js +381 -0
- package/dist/ReportBatchPanel-BYgg0EDB.cjs +1 -0
- package/dist/ReportBatchPanel-Bby5yLzU.js +287 -0
- package/dist/ReportPreview-DWXROHBP.cjs +6 -0
- package/dist/ReportPreview-DiNXhQI0.js +4138 -0
- package/dist/ReportTemplateLibrary-C6CO7YCT.cjs +1 -0
- package/dist/ReportTemplateLibrary-DfzDXRvr.js +260 -0
- package/dist/RuleEditor-C2QsOHOs.cjs +1 -0
- package/dist/RuleEditor-D9wQHrkf.js +2024 -0
- package/dist/TemplateReviewPanel-BKofGrV9.js +222 -0
- package/dist/TemplateReviewPanel-DwtOcLue.cjs +1 -0
- package/dist/analytics.cjs +1 -1
- package/dist/analytics.d.cts +2 -0
- package/dist/analytics.d.ts +2 -0
- package/dist/analytics.js +29 -29
- package/dist/batch-Bt3Fd27Z.cjs +1 -0
- package/dist/batch-mRqhhhjt.js +364 -0
- package/dist/computed-Bvk0W15F.js +521 -0
- package/dist/computed-CGV2a809.cjs +1 -0
- package/dist/config-B612mw0x.js +525 -0
- package/dist/config-BRoLo2oj.cjs +1 -0
- package/dist/designer.cjs +2 -2
- package/dist/designer.d.cts +659 -9
- package/dist/designer.d.ts +659 -9
- package/dist/designer.js +2030 -1824
- package/dist/index.cjs +8 -8
- package/dist/index.d.cts +147 -3
- package/dist/index.d.ts +147 -3
- package/dist/index.js +639 -592
- package/dist/injection-keys-Db_DyLkm.cjs +1 -0
- package/dist/injection-keys-e85udZCp.js +7 -0
- package/dist/list-cell-BuYn4tGF.cjs +1 -0
- package/dist/{list-cell-Dxyi7DOw.js → list-cell-ClFra1zS.js} +54 -40
- package/dist/matrix-DVyWiYsd.cjs +1 -0
- package/dist/matrix-yZsGnldA.js +227 -0
- package/dist/param-validation-BlHHXs6u.js +153 -0
- package/dist/param-validation-DCK039V1.cjs +1 -0
- package/dist/pdf.cjs +25 -25
- package/dist/pdf.d.cts +3 -0
- package/dist/pdf.d.ts +3 -0
- package/dist/pdf.js +677 -677
- package/dist/plugin-BDTU4D94.cjs +1 -0
- package/dist/plugin-Cd5G2QQn.js +22 -0
- package/dist/region-binding-workflow-CXDmt9Bs.js +977 -0
- package/dist/region-binding-workflow-DhQvu1co.cjs +3 -0
- package/dist/{report-params-B_VCihAh.js → report-params-B44imUd4.js} +1 -1
- package/dist/{report-params-CjWrjPl6.cjs → report-params-SJfhKgaX.cjs} +1 -1
- package/dist/server/node.d.cts +5 -2
- package/dist/server/node.d.ts +5 -2
- package/dist/server-node.cjs +1 -1
- package/dist/server-node.js +87 -87
- package/dist/server.cjs +1 -1
- package/dist/server.d.cts +201 -2
- package/dist/server.d.ts +201 -2
- package/dist/server.js +557 -658
- package/dist/style.css +1 -1
- package/dist/template-registry-WNXdkiET.js +506 -0
- package/dist/template-registry-ukBGlm8N.cjs +1 -0
- package/dist/template-review-BXp2oyqg.cjs +1 -0
- package/dist/template-review-BdcXSYbx.js +1616 -0
- package/dist/tree-BX380Rr7.cjs +1 -0
- package/dist/tree-CqcQ99NM.js +172 -0
- package/dist/{validate-UUy9yP4K.js → validate-7s0yn6ii.js} +44 -44
- package/dist/validate-DsRiNw8h.cjs +1 -0
- package/dist/vue/async.d.cts +93 -4
- package/dist/vue/async.d.ts +93 -4
- package/dist/vue/index.d.cts +145 -7
- package/dist/vue/index.d.ts +145 -7
- package/dist/vue-async.cjs +1 -1
- package/dist/vue-async.js +5 -5
- package/dist/vue.cjs +1 -1
- package/dist/vue.js +116 -113
- package/dist/{workbook-session-B-bW5_yR.js → workbook-session-BKOTwcoq.js} +1 -1
- package/dist/{workbook-session-D7RtdNo0.cjs → workbook-session-CLYLhZWu.cjs} +1 -1
- package/dist/worker.cjs +1 -1
- package/dist/worker.d.cts +5 -2
- package/dist/worker.d.ts +5 -2
- package/dist/worker.js +1 -1
- package/dist/xlsx.cjs +3 -3
- package/dist/xlsx.d.cts +129 -2
- package/dist/xlsx.d.ts +129 -2
- package/dist/xlsx.js +336 -242
- package/package.json +1 -1
- package/dist/ExcelBindingWizard-CF7RplWm.cjs +0 -1
- package/dist/ExcelBindingWizard-qhwEderR.js +0 -842
- package/dist/ReportPreview-BE1tCHqE.js +0 -4604
- package/dist/ReportPreview-QKRKQOe3.cjs +0 -6
- package/dist/RuleEditor-BA36yIV6.js +0 -1723
- package/dist/RuleEditor-CczJ6mJm.cjs +0 -1
- package/dist/TemplateReviewPanel-CHi4Alqa.cjs +0 -1
- package/dist/TemplateReviewPanel-Dz0G5o83.js +0 -217
- package/dist/binding-preview-BWsdf_z2.cjs +0 -2
- package/dist/binding-preview-DILq0-0f.js +0 -649
- package/dist/decimal-CI1OAczk.js +0 -87
- package/dist/decimal-CQA0xJex.cjs +0 -1
- package/dist/list-cell-CyM1ZlRN.cjs +0 -1
- package/dist/matrix-BbXarwyk.js +0 -661
- package/dist/matrix-Cm65WLLP.cjs +0 -1
- package/dist/param-validation-BWNjLcN0.js +0 -116
- package/dist/param-validation-CiTxFeZ8.cjs +0 -1
- package/dist/plugin-CThk42vJ.cjs +0 -1
- package/dist/plugin-tGn7-5oF.js +0 -25
- package/dist/template-registry-CGWTLtIA.cjs +0 -1
- package/dist/template-registry-DzlQs3OF.js +0 -434
- package/dist/template-review-D1RoNCPw.cjs +0 -1
- package/dist/template-review-fnteXRng.js +0 -1473
- package/dist/validate-Bf6ccFr2.cjs +0 -1
package/dist/server.js
CHANGED
|
@@ -1,848 +1,747 @@
|
|
|
1
|
-
import { b as
|
|
2
|
-
import { g as
|
|
3
|
-
import {
|
|
4
|
-
import { c as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (e.reason instanceof x) throw e.reason;
|
|
16
|
-
const t = new Error("报表执行已取消");
|
|
17
|
-
throw t.name = "AbortError", Object.defineProperty(t, "cause", { value: e.reason }), t;
|
|
18
|
-
}
|
|
19
|
-
function R(e, t, r) {
|
|
20
|
-
if (!Number.isFinite(r) || r < 0) throw new x("budget", `${t} 的执行统计无效`, `$.budget.${t}`);
|
|
21
|
-
const s = e[t];
|
|
22
|
-
if (s !== void 0 && r > s) throw new x("budget", `${t} 超出预算 ${s}(实际 ${r})`, `$.budget.${t}`);
|
|
23
|
-
}
|
|
24
|
-
function ge(e) {
|
|
25
|
-
for (const [t, r] of Object.entries(e)) {
|
|
26
|
-
if (r !== void 0 && (!Number.isFinite(r) || r <= 0)) throw new x("budget", `${t} 应为正有限数字`, `$.budget.${t}`);
|
|
27
|
-
if (t !== "maxDurationMs" && r !== void 0 && !Number.isSafeInteger(r)) throw new x("budget", `${t} 应为正安全整数`, `$.budget.${t}`);
|
|
28
|
-
if (t === "maxDurationMs" && r !== void 0 && r > 2147483647) throw new x("budget", "maxDurationMs 不能超过 2147483647", `$.budget.${t}`);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
async function z(e, t, r) {
|
|
32
|
-
const s = new AbortController(), n = () => s.abort(e?.reason);
|
|
33
|
-
e?.addEventListener("abort", n, { once: !0 }), e?.aborted && n();
|
|
34
|
-
const o = Date.now(), c = t === void 0 ? void 0 : setTimeout(() => s.abort(new x("timeout", `报表执行超过 ${t}ms`)), t);
|
|
35
|
-
let m;
|
|
36
|
-
try {
|
|
37
|
-
v(s.signal);
|
|
38
|
-
const p = new Promise((u, i) => {
|
|
39
|
-
m = () => {
|
|
40
|
-
try {
|
|
41
|
-
v(s.signal);
|
|
42
|
-
} catch (d) {
|
|
43
|
-
i(d);
|
|
44
|
-
}
|
|
45
|
-
}, s.signal.addEventListener("abort", m, { once: !0 });
|
|
46
|
-
}), a = await Promise.race([r(s.signal), p]);
|
|
47
|
-
if (v(s.signal), t !== void 0 && Date.now() - o > t) throw new x("timeout", `报表执行超过 ${t}ms`);
|
|
48
|
-
return a;
|
|
49
|
-
} finally {
|
|
50
|
-
c !== void 0 && clearTimeout(c), m && s.signal.removeEventListener("abort", m), e?.removeEventListener("abort", n);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
function ee(e, t) {
|
|
54
|
-
if (t.length === 0) throw new j("config", "缺少报表 ID");
|
|
55
|
-
return t.map((r) => {
|
|
56
|
-
if (!Object.prototype.hasOwnProperty.call(e, r)) throw new j("config", `未注册报表 ${r}`);
|
|
57
|
-
return e[r];
|
|
1
|
+
import { A as oe, b as P, k as ie, B as ce, a as le, P as ue, n as de, y as fe } from "./template-review-BdcXSYbx.js";
|
|
2
|
+
import { g as T } from "./report-params-B44imUd4.js";
|
|
3
|
+
import { d as H, r as pe, R as Y } from "./param-validation-BlHHXs6u.js";
|
|
4
|
+
import { v as ge, c as q, a as R, t as b, R as A, b as v, d as $, s as I, e as D, j as we, f as me } from "./batch-mRqhhhjt.js";
|
|
5
|
+
import { g as et, r as tt, h as rt, i as st, k as nt, l as at } from "./batch-mRqhhhjt.js";
|
|
6
|
+
import { c as ee } from "./validate-7s0yn6ii.js";
|
|
7
|
+
import { r as Q, c as M, n as z } from "./task-events-Dpsvf_t2.js";
|
|
8
|
+
import { T as ye } from "./tree-CqcQ99NM.js";
|
|
9
|
+
import { p as he } from "./template-registry-WNXdkiET.js";
|
|
10
|
+
function te(e, t) {
|
|
11
|
+
if (t.length === 0) throw new P("config", "缺少报表 ID");
|
|
12
|
+
return t.map((s) => {
|
|
13
|
+
if (!Object.prototype.hasOwnProperty.call(e, s)) throw new P("config", `未注册报表 ${s}`);
|
|
14
|
+
return e[s];
|
|
58
15
|
});
|
|
59
16
|
}
|
|
60
|
-
function
|
|
61
|
-
return e.grid?.cells.reduce((t,
|
|
17
|
+
function C(e) {
|
|
18
|
+
return e.grid?.cells.reduce((t, s) => t + s.reduce((a, r) => a + (r ? 1 + (r.children?.reduce((n, i) => n + C(i), 0) ?? 0) : 0), 0), 0) ?? 0;
|
|
62
19
|
}
|
|
63
|
-
function
|
|
64
|
-
return e.pages.reduce((
|
|
20
|
+
function ve(e, t, s) {
|
|
21
|
+
return e.pages.reduce((a, r) => a + r.components.reduce((n, i) => i.kind !== "list" ? n + C(i) : n + de(i, t, s), 0), 0);
|
|
65
22
|
}
|
|
66
|
-
function
|
|
67
|
-
return
|
|
68
|
-
const
|
|
23
|
+
function be(e, t = Object.keys(e)) {
|
|
24
|
+
return te(e, t).map((s, a) => {
|
|
25
|
+
const r = t[a], n = T(e, [r]);
|
|
69
26
|
return {
|
|
70
|
-
id:
|
|
71
|
-
params: JSON.parse(JSON.stringify(
|
|
72
|
-
paramsSchema:
|
|
73
|
-
datasetsSchema: Object.fromEntries(Object.entries(
|
|
27
|
+
id: r,
|
|
28
|
+
params: JSON.parse(JSON.stringify(n)),
|
|
29
|
+
paramsSchema: pe(n),
|
|
30
|
+
datasetsSchema: Object.fromEntries(Object.entries(s.dataSchema ?? {}).map(([i, l]) => [i, oe(typeof s.template == "function" ? void 0 : s.template, i, l)])),
|
|
74
31
|
capabilities: {
|
|
75
|
-
save: !!
|
|
76
|
-
export: !!
|
|
77
|
-
templates: !!
|
|
32
|
+
save: !!s.provider?.save,
|
|
33
|
+
export: !!s.provider?.export,
|
|
34
|
+
templates: !!s.provider?.templates
|
|
78
35
|
}
|
|
79
36
|
};
|
|
80
37
|
});
|
|
81
38
|
}
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
const
|
|
85
|
-
return { ...
|
|
39
|
+
function re(e, t) {
|
|
40
|
+
te(e, t.reportIds);
|
|
41
|
+
const s = H(T(e, t.reportIds), t.params), a = t.reportIds.flatMap((n) => H(T(e, [n]), t.params).issues), r = new Map(a.map((n) => [JSON.stringify(n), n]));
|
|
42
|
+
return { ...s, ok: r.size === 0, issues: [...r.values()] };
|
|
86
43
|
}
|
|
87
|
-
function
|
|
88
|
-
const
|
|
89
|
-
if (!
|
|
90
|
-
const
|
|
91
|
-
return R(t, "maxRows", e.stats.rows), R(t, "maxPages",
|
|
44
|
+
function xe(e, t) {
|
|
45
|
+
const s = ee(e.plan);
|
|
46
|
+
if (!s.ok) throw new P("validate", `执行器返回无效计划:${s.errors[0]?.path}`);
|
|
47
|
+
const a = e.plan.pages.length, r = e.plan.pages.reduce((n, i) => n + i.components.reduce((l, f) => l + C(f), 0), 0);
|
|
48
|
+
return R(t, "maxRows", e.stats.rows), R(t, "maxPages", a), R(t, "maxCells", r), { ...e, stats: { ...e.stats, pages: a, cells: r } };
|
|
92
49
|
}
|
|
93
|
-
function
|
|
94
|
-
const
|
|
95
|
-
if (!
|
|
50
|
+
function X(e, t) {
|
|
51
|
+
const s = re(e.reports, t);
|
|
52
|
+
if (!s.ok) throw new Y(s.issues);
|
|
96
53
|
}
|
|
97
|
-
function
|
|
98
|
-
return e.map(({ code: t, message:
|
|
54
|
+
function G(e = []) {
|
|
55
|
+
return e.map(({ code: t, message: s, severity: a, pageIndex: r, componentIndex: n }) => ({ code: t, message: s, severity: a, path: `$.pages.${r}.components.${n}` }));
|
|
99
56
|
}
|
|
100
|
-
function
|
|
57
|
+
function Se(e) {
|
|
101
58
|
const t = { maxRows: 1e5, maxPages: 1e4, maxCells: 2e6, maxOutputBytes: 1e8, maxDurationMs: 12e4, ...e.budget };
|
|
102
59
|
ge(t);
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
let
|
|
106
|
-
const
|
|
107
|
-
...
|
|
108
|
-
pagination: { ...e.pagination, ...
|
|
60
|
+
const s = async (r, n) => {
|
|
61
|
+
const i = Date.now();
|
|
62
|
+
let l = 0, f = 0;
|
|
63
|
+
const o = [], u = {}, c = Object.fromEntries(Object.entries(e.reports).map(([g, p]) => [g, {
|
|
64
|
+
...p,
|
|
65
|
+
pagination: { ...e.pagination, ...p.pagination, ...n ? { measurer: n } : {} },
|
|
109
66
|
dataValidation: {
|
|
110
|
-
...
|
|
111
|
-
maxRows: Math.min(t.maxRows ?? 1e5,
|
|
112
|
-
maxCells: Math.min(t.maxCells ?? 2e6,
|
|
67
|
+
...p.dataValidation,
|
|
68
|
+
maxRows: Math.min(t.maxRows ?? 1e5, p.dataValidation?.maxRows ?? 1 / 0),
|
|
69
|
+
maxCells: Math.min(t.maxCells ?? 2e6, p.dataValidation?.maxCells ?? 1 / 0)
|
|
113
70
|
}
|
|
114
|
-
}])),
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
71
|
+
}])), m = await ie(c, { maxPages: t.maxPages, maxCells: t.maxCells, onDatasets: (g, p, h) => {
|
|
72
|
+
try {
|
|
73
|
+
l += ce(h, p, { maxRows: t.maxRows, signal: r.signal });
|
|
74
|
+
} catch (S) {
|
|
75
|
+
throw S instanceof ye ? new A("budget", S.message, "$.budget.maxRows") : S;
|
|
76
|
+
}
|
|
77
|
+
R(t, "maxRows", l), f += ve(h, p, c[g]?.pagination), R(t, "maxCells", f);
|
|
78
|
+
} })({ ...r, params: r.params ?? {}, onWarning: (g) => o.push({ code: "layout", message: g, severity: "warning" }), onQueryResult: (g, p) => {
|
|
79
|
+
Object.defineProperty(u, g, { value: { revision: p.revision, sourceToken: p.sourceToken }, enumerable: !0, writable: !0 }), o.push(...p.diagnostics ?? []);
|
|
80
|
+
} }).catch((g) => {
|
|
81
|
+
throw g instanceof P && g.cause instanceof le ? new A("budget", g.cause.message, "$.budget.maxPages") : g instanceof P && g.cause instanceof ue ? new A("budget", g.cause.message, "$.budget.maxCells") : g;
|
|
120
82
|
});
|
|
121
|
-
|
|
122
|
-
const y =
|
|
123
|
-
return R(t, "maxPages",
|
|
124
|
-
},
|
|
125
|
-
const
|
|
126
|
-
if (
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
const u =
|
|
83
|
+
b(r.signal);
|
|
84
|
+
const y = m.pages.reduce((g, p) => g + p.components.reduce((h, S) => h + C(S), 0), 0);
|
|
85
|
+
return R(t, "maxPages", m.pages.length), R(t, "maxCells", y), { plan: m, diagnostics: o, revisions: u, stats: { rows: l, pages: m.pages.length, cells: y, durationMs: Date.now() - i } };
|
|
86
|
+
}, a = async (r) => {
|
|
87
|
+
const n = Date.now();
|
|
88
|
+
if (r.format !== "pdf" && r.format !== "xlsx") throw new P("config", "不支持的报表导出格式");
|
|
89
|
+
const i = r.format === "pdf" ? await import("@agile-team/mach-report/pdf") : void 0;
|
|
90
|
+
b(r.signal);
|
|
91
|
+
const l = r.pdf?.customFontFaces ?? (r.pdf?.customFontBytes ? { regular: r.pdf.customFontBytes } : void 0), f = i && l ? i.createFontBytesMeasurer(l) : void 0, o = await s(r, f);
|
|
92
|
+
b(r.signal);
|
|
93
|
+
const u = M(r), c = await u.run("encode", async () => {
|
|
132
94
|
let y;
|
|
133
|
-
if (
|
|
134
|
-
|
|
135
|
-
const
|
|
136
|
-
y =
|
|
95
|
+
if (r.format === "pdf") {
|
|
96
|
+
b(r.signal);
|
|
97
|
+
const g = await i.renderPlanToPdf(o.plan, { ...r.pdf, ...f ? { measurer: f } : {}, fidelity: r.fidelity, signal: r.signal, onProgress: (p, h) => u.progress("encode", p, h) });
|
|
98
|
+
y = g.bytes, o.diagnostics.push(...G(g.diagnostics)), o.diagnostics.push(...g.fidelityWarnings.map((p) => ({ code: "pdf-fidelity", message: p, severity: "warning" })), ...g.pageErrors.map((p) => ({ code: "pdf-page", message: p, severity: "error" }))), g.unsupportedTextCount && o.diagnostics.push({ code: "pdf-font", message: `${g.unsupportedTextCount} 段文本包含当前字体不支持的字符`, severity: "warning" });
|
|
137
99
|
} else {
|
|
138
|
-
const { renderPlanToXlsx:
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
y = new Uint8Array(
|
|
100
|
+
const { renderPlanToXlsx: g } = await import("@agile-team/mach-report/xlsx");
|
|
101
|
+
b(r.signal);
|
|
102
|
+
const p = await g(o.plan, { ...r.xlsx, fidelity: r.fidelity, signal: r.signal, onProgress: (h, S) => u.progress("encode", h, S) });
|
|
103
|
+
y = new Uint8Array(p.buffer), o.diagnostics.push(...G(p.diagnostics)), o.diagnostics.push(...p.warnings.map((h) => ({ code: "xlsx-fidelity", message: h, severity: "warning" })));
|
|
142
104
|
}
|
|
143
|
-
return
|
|
105
|
+
return b(r.signal), y;
|
|
144
106
|
});
|
|
145
|
-
R(t, "maxOutputBytes",
|
|
146
|
-
const { plan: d, ...
|
|
147
|
-
return { ...
|
|
107
|
+
R(t, "maxOutputBytes", c.byteLength);
|
|
108
|
+
const { plan: d, ...m } = o;
|
|
109
|
+
return { ...m, bytes: c, format: r.format, contentType: r.format === "pdf" ? "application/pdf" : "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", stats: { ...m.stats, durationMs: Date.now() - n, outputBytes: c.byteLength } };
|
|
148
110
|
};
|
|
149
111
|
return {
|
|
150
|
-
describe: (
|
|
151
|
-
validate: (
|
|
152
|
-
prepare: (
|
|
153
|
-
const { signal:
|
|
154
|
-
|
|
155
|
-
const d = e.executor ? await e.executor.prepare(
|
|
156
|
-
return
|
|
112
|
+
describe: (r) => be(e.reports, r),
|
|
113
|
+
validate: (r) => re(e.reports, r),
|
|
114
|
+
prepare: (r) => q(r.signal, t.maxDurationMs, async (n) => {
|
|
115
|
+
const { signal: i, onEvent: l, ...f } = r, o = { ...f, taskId: f.taskId ?? Q() }, u = l ? (m) => z(l, m, n) : void 0, c = { ...o, signal: n, onEvent: u };
|
|
116
|
+
M(c).runSync("validate", () => X(e, o));
|
|
117
|
+
const d = e.executor ? await e.executor.prepare(o, n, u) : await s(c);
|
|
118
|
+
return xe(d, t);
|
|
157
119
|
}),
|
|
158
|
-
export: (
|
|
159
|
-
const { signal:
|
|
160
|
-
if (
|
|
161
|
-
const d = e.executor ? await e.executor.export(
|
|
120
|
+
export: (r) => q(r.signal, t.maxDurationMs, async (n) => {
|
|
121
|
+
const { signal: i, onEvent: l, ...f } = r, o = { ...f, taskId: f.taskId ?? Q() }, u = l ? (m) => z(l, m, n) : void 0, c = { ...o, signal: n, onEvent: u };
|
|
122
|
+
if (M(c).runSync("validate", () => X(e, o)), o.format !== "pdf" && o.format !== "xlsx") throw new P("config", "不支持的报表导出格式");
|
|
123
|
+
const d = e.executor ? await e.executor.export(o, n, u) : await a(c);
|
|
162
124
|
return R(t, "maxRows", d.stats.rows), R(t, "maxPages", d.stats.pages), R(t, "maxCells", d.stats.cells), R(t, "maxOutputBytes", d.bytes.byteLength), { ...d, stats: { ...d.stats, outputBytes: d.bytes.byteLength } };
|
|
163
125
|
})
|
|
164
126
|
};
|
|
165
127
|
}
|
|
166
|
-
function
|
|
167
|
-
const t = e.concurrency ?? 1,
|
|
168
|
-
if (!Number.isSafeInteger(t) || t < 1 || !Number.isSafeInteger(
|
|
169
|
-
const
|
|
170
|
-
let
|
|
171
|
-
const
|
|
172
|
-
for (; !
|
|
128
|
+
function Qe(e = {}) {
|
|
129
|
+
const t = e.concurrency ?? 1, s = e.maxQueued ?? 20;
|
|
130
|
+
if (!Number.isSafeInteger(t) || t < 1 || !Number.isSafeInteger(s) || s < 0) throw new A("budget", "队列并发应为正整数,排队上限应为非负整数");
|
|
131
|
+
const a = [], r = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set();
|
|
132
|
+
let i = !1, l = 0;
|
|
133
|
+
const f = () => {
|
|
134
|
+
for (; !i && r.size < t && a.length; ) a.shift().start();
|
|
173
135
|
};
|
|
174
136
|
return {
|
|
175
137
|
get active() {
|
|
176
|
-
return
|
|
138
|
+
return r.size;
|
|
177
139
|
},
|
|
178
140
|
get pending() {
|
|
179
|
-
return
|
|
141
|
+
return a.length;
|
|
180
142
|
},
|
|
181
|
-
enqueue: (u,
|
|
182
|
-
if (
|
|
183
|
-
if (
|
|
184
|
-
const d =
|
|
185
|
-
if (
|
|
186
|
-
const
|
|
187
|
-
let y = "queued",
|
|
188
|
-
const
|
|
189
|
-
h =
|
|
190
|
-
}),
|
|
191
|
-
|
|
192
|
-
}, E = (
|
|
143
|
+
enqueue: (u, c = {}) => {
|
|
144
|
+
if (i) throw new A("closed", "任务队列已关闭");
|
|
145
|
+
if (b(c.signal), r.size >= t && a.length >= s) throw new A("queue-full", "报表任务队列已满");
|
|
146
|
+
const d = c.id ?? `report-${++l}`;
|
|
147
|
+
if (n.has(d)) throw new A("queue-full", "任务 ID 正在执行或排队");
|
|
148
|
+
const m = new AbortController();
|
|
149
|
+
let y = "queued", g, p, h, S;
|
|
150
|
+
const ne = new Promise((x, O) => {
|
|
151
|
+
h = x, S = O;
|
|
152
|
+
}), F = () => {
|
|
153
|
+
c.signal?.removeEventListener("abort", _), n.delete(d);
|
|
154
|
+
}, E = (x) => {
|
|
193
155
|
if (y !== "queued" && y !== "running") return;
|
|
194
156
|
const O = y === "queued";
|
|
195
|
-
y = "cancelled",
|
|
157
|
+
y = "cancelled", m.abort(x);
|
|
196
158
|
try {
|
|
197
|
-
|
|
198
|
-
} catch (
|
|
199
|
-
|
|
159
|
+
b(m.signal);
|
|
160
|
+
} catch (J) {
|
|
161
|
+
S(J);
|
|
200
162
|
}
|
|
201
163
|
if (O) {
|
|
202
|
-
const
|
|
203
|
-
|
|
164
|
+
const J = a.indexOf(k);
|
|
165
|
+
J >= 0 && a.splice(J, 1), F(), f();
|
|
204
166
|
}
|
|
205
|
-
}, _ = () => E(
|
|
206
|
-
y === "running" && (!Number.isFinite(
|
|
207
|
-
},
|
|
208
|
-
y !== "running" ||
|
|
209
|
-
},
|
|
167
|
+
}, _ = () => E(c.signal?.reason), V = (x, O) => {
|
|
168
|
+
y === "running" && (!Number.isFinite(x) || x < 0 || O !== void 0 && (!Number.isFinite(O) || O < x) || (g = { completed: x, ...O === void 0 ? {} : { total: O } }));
|
|
169
|
+
}, ae = (x) => {
|
|
170
|
+
y !== "running" || m.signal.aborted || (p = { ...x, taskId: d }, x.completed !== void 0 && V(x.completed, x.total), z(c.onEvent, p, m.signal));
|
|
171
|
+
}, k = {
|
|
210
172
|
cancel: E,
|
|
211
173
|
start: () => {
|
|
212
|
-
y === "queued" && (y = "running",
|
|
213
|
-
(
|
|
214
|
-
y === "running" && (y = "completed", h(
|
|
174
|
+
y === "queued" && (y = "running", r.add(k), Promise.resolve().then(() => (b(m.signal), u({ taskId: d, signal: m.signal, reportProgress: V, onEvent: ae }))).then(
|
|
175
|
+
(x) => {
|
|
176
|
+
y === "running" && (y = "completed", h(x));
|
|
215
177
|
},
|
|
216
|
-
(
|
|
217
|
-
y === "running" && (y = "failed",
|
|
178
|
+
(x) => {
|
|
179
|
+
y === "running" && (y = "failed", S(x));
|
|
218
180
|
}
|
|
219
181
|
).finally(() => {
|
|
220
|
-
|
|
182
|
+
r.delete(k), F(), f();
|
|
221
183
|
}));
|
|
222
184
|
}
|
|
223
185
|
};
|
|
224
|
-
return
|
|
186
|
+
return n.add(d), c.signal?.addEventListener("abort", _, { once: !0 }), c.signal?.aborted ? E(c.signal.reason) : r.size < t ? k.start() : a.push(k), { id: d, get status() {
|
|
225
187
|
return y;
|
|
226
188
|
}, get progress() {
|
|
227
|
-
return
|
|
189
|
+
return g;
|
|
228
190
|
}, get event() {
|
|
229
|
-
return
|
|
230
|
-
}, result:
|
|
191
|
+
return p;
|
|
192
|
+
}, result: ne, cancel: E };
|
|
231
193
|
},
|
|
232
194
|
close: (u = {}) => {
|
|
233
|
-
|
|
234
|
-
for (const
|
|
235
|
-
if (u.cancelRunning) for (const
|
|
236
|
-
}
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
const ve = new Uint32Array([
|
|
240
|
-
1116352408,
|
|
241
|
-
1899447441,
|
|
242
|
-
3049323471,
|
|
243
|
-
3921009573,
|
|
244
|
-
961987163,
|
|
245
|
-
1508970993,
|
|
246
|
-
2453635748,
|
|
247
|
-
2870763221,
|
|
248
|
-
3624381080,
|
|
249
|
-
310598401,
|
|
250
|
-
607225278,
|
|
251
|
-
1426881987,
|
|
252
|
-
1925078388,
|
|
253
|
-
2162078206,
|
|
254
|
-
2614888103,
|
|
255
|
-
3248222580,
|
|
256
|
-
3835390401,
|
|
257
|
-
4022224774,
|
|
258
|
-
264347078,
|
|
259
|
-
604807628,
|
|
260
|
-
770255983,
|
|
261
|
-
1249150122,
|
|
262
|
-
1555081692,
|
|
263
|
-
1996064986,
|
|
264
|
-
2554220882,
|
|
265
|
-
2821834349,
|
|
266
|
-
2952996808,
|
|
267
|
-
3210313671,
|
|
268
|
-
3336571891,
|
|
269
|
-
3584528711,
|
|
270
|
-
113926993,
|
|
271
|
-
338241895,
|
|
272
|
-
666307205,
|
|
273
|
-
773529912,
|
|
274
|
-
1294757372,
|
|
275
|
-
1396182291,
|
|
276
|
-
1695183700,
|
|
277
|
-
1986661051,
|
|
278
|
-
2177026350,
|
|
279
|
-
2456956037,
|
|
280
|
-
2730485921,
|
|
281
|
-
2820302411,
|
|
282
|
-
3259730800,
|
|
283
|
-
3345764771,
|
|
284
|
-
3516065817,
|
|
285
|
-
3600352804,
|
|
286
|
-
4094571909,
|
|
287
|
-
275423344,
|
|
288
|
-
430227734,
|
|
289
|
-
506948616,
|
|
290
|
-
659060556,
|
|
291
|
-
883997877,
|
|
292
|
-
958139571,
|
|
293
|
-
1322822218,
|
|
294
|
-
1537002063,
|
|
295
|
-
1747873779,
|
|
296
|
-
1955562222,
|
|
297
|
-
2024104815,
|
|
298
|
-
2227730452,
|
|
299
|
-
2361852424,
|
|
300
|
-
2428436474,
|
|
301
|
-
2756734187,
|
|
302
|
-
3204031479,
|
|
303
|
-
3329325298
|
|
304
|
-
]), P = (e, t) => e >>> t | e << 32 - t;
|
|
305
|
-
function xe(e, t, r) {
|
|
306
|
-
const s = new DataView(e.buffer, e.byteOffset + t, 64);
|
|
307
|
-
for (let n = 0; n < 16; n++) r[n] = s.getUint32(n * 4);
|
|
308
|
-
for (let n = 16; n < 64; n++) {
|
|
309
|
-
const o = r[n - 15], c = r[n - 2], m = P(o, 7) ^ P(o, 18) ^ o >>> 3, p = P(c, 17) ^ P(c, 19) ^ c >>> 10;
|
|
310
|
-
r[n] = r[n - 16] + m + r[n - 7] + p;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
function Ae(e, t) {
|
|
314
|
-
let r = e[0], s = e[1], n = e[2], o = e[3], c = e[4], m = e[5], p = e[6], a = e[7];
|
|
315
|
-
for (let u = 0; u < 64; u++) {
|
|
316
|
-
const i = P(c, 6) ^ P(c, 11) ^ P(c, 25), d = c & m ^ ~c & p, w = a + i + d + ve[u] + t[u] >>> 0, y = P(r, 2) ^ P(r, 13) ^ P(r, 22), l = r & s ^ r & n ^ s & n, f = y + l >>> 0;
|
|
317
|
-
a = p, p = m, m = c, c = o + w >>> 0, o = n, n = s, s = r, r = w + f >>> 0;
|
|
318
|
-
}
|
|
319
|
-
e[0] = e[0] + r, e[1] = e[1] + s, e[2] = e[2] + n, e[3] = e[3] + o, e[4] = e[4] + c, e[5] = e[5] + m, e[6] = e[6] + p, e[7] = e[7] + a;
|
|
320
|
-
}
|
|
321
|
-
function Se(e) {
|
|
322
|
-
const t = new Uint8Array(Math.ceil((e.byteLength + 9) / 64) * 64);
|
|
323
|
-
t.set(e), t[e.byteLength] = 128;
|
|
324
|
-
const r = new DataView(t.buffer);
|
|
325
|
-
return r.setUint32(t.length - 8, Math.floor(e.byteLength / 536870912)), r.setUint32(t.length - 4, e.byteLength * 8 >>> 0), t;
|
|
326
|
-
}
|
|
327
|
-
const Re = () => new Uint32Array([1779033703, 3144134277, 1013904242, 2773480762, 1359893119, 2600822924, 528734635, 1541459225]), Pe = (e) => Array.from(e, (t) => t.toString(16).padStart(8, "0")).join("");
|
|
328
|
-
async function Oe(e) {
|
|
329
|
-
const t = Se(e), r = Re(), s = new Uint32Array(64);
|
|
330
|
-
for (let n = 0; n < t.length; n += 64)
|
|
331
|
-
n > 0 && n % 262144 === 0 && await new Promise((o) => setTimeout(o, 0)), xe(t, n, s), Ae(r, s);
|
|
332
|
-
return Pe(r);
|
|
333
|
-
}
|
|
334
|
-
function Ne(e = {}) {
|
|
335
|
-
const t = {
|
|
336
|
-
maxRecords: e.maxRecords ?? 1e4,
|
|
337
|
-
maxBytes: e.maxBytes ?? 67108864,
|
|
338
|
-
maxResultBytes: e.maxResultBytes ?? 262144,
|
|
339
|
-
controlReserveBytes: e.controlReserveBytes ?? 4096,
|
|
340
|
-
maxTombstones: e.maxTombstones ?? 1e4,
|
|
341
|
-
maxTombstoneBytes: e.maxTombstoneBytes ?? 16777216
|
|
342
|
-
};
|
|
343
|
-
if (!Object.values(t).every((r) => Number.isSafeInteger(r) && r > 0) || t.controlReserveBytes < 4096) throw new g("input", "任务容量应为正整数,控制状态预留至少4096字节");
|
|
344
|
-
return t;
|
|
345
|
-
}
|
|
346
|
-
function q(e) {
|
|
347
|
-
return new TextEncoder().encode(S(e)).byteLength;
|
|
348
|
-
}
|
|
349
|
-
function C(e, t) {
|
|
350
|
-
const r = { scope: e.scope, id: e.id, revision: 1, request: e.request, status: "queued", createdAt: e.createdAt, updatedAt: e.createdAt, attempt: 0 }, s = { ...e };
|
|
351
|
-
delete s.result;
|
|
352
|
-
const n = e.result === void 0 ? 0 : q(e.result);
|
|
353
|
-
if (n > t.maxResultBytes) throw new g("capacity", "任务结果超过独立预算,请保存文件引用");
|
|
354
|
-
return Math.max(q(r) + t.controlReserveBytes, q(s)) + n;
|
|
355
|
-
}
|
|
356
|
-
function re(e) {
|
|
357
|
-
return e.status !== "queued" && e.status !== "running";
|
|
358
|
-
}
|
|
359
|
-
function je(e) {
|
|
360
|
-
const t = { ...e, tombstoneRetentionMs: e.tombstoneRetentionMs ?? 6048e5, limit: e.limit ?? 100 };
|
|
361
|
-
if (![t.now, t.terminalBefore].every((r) => Number.isSafeInteger(r) && r >= 0) || t.terminalBefore > t.now) throw new g("input", "终态清理时间应为不超过当前时间的非负整数");
|
|
362
|
-
if (![t.tombstoneRetentionMs, t.limit].every((r) => Number.isSafeInteger(r) && r > 0) || !Number.isSafeInteger(t.now + t.tombstoneRetentionMs)) throw new g("input", "幂等保留期与清理批量应为正整数");
|
|
363
|
-
return t;
|
|
364
|
-
}
|
|
365
|
-
async function ne(e) {
|
|
366
|
-
const t = new TextEncoder().encode(S(e)), r = globalThis.crypto?.subtle;
|
|
367
|
-
if (!r) return Oe(t);
|
|
368
|
-
const s = await r.digest("SHA-256", t);
|
|
369
|
-
return Array.from(new Uint8Array(s), (n) => n.toString(16).padStart(2, "0")).join("");
|
|
370
|
-
}
|
|
371
|
-
async function qe(e, t) {
|
|
372
|
-
if (!re(e)) throw new g("input", "只能归档终态任务");
|
|
373
|
-
return { scope: e.scope, id: e.id, revision: e.revision, status: e.status, createdAt: e.createdAt, updatedAt: e.updatedAt, attempt: e.attempt, requestHash: await ne(e.request), expiresAt: t };
|
|
374
|
-
}
|
|
375
|
-
class g extends Error {
|
|
376
|
-
constructor(t, r) {
|
|
377
|
-
super(r), this.code = t, this.name = "ReportJobError";
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
function $(e, t) {
|
|
381
|
-
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 g("input", "任务范围应非空,ID应为1–128位安全标识");
|
|
382
|
-
}
|
|
383
|
-
function Ie(e) {
|
|
384
|
-
const t = Array.isArray(e), r = Object.getPrototypeOf(e), s = Object.keys(e);
|
|
385
|
-
if (r !== (t ? Array.prototype : Object.prototype) && !(r === null && !t)) throw new g("input", "任务对象应为普通 JSON 对象");
|
|
386
|
-
if (Object.getOwnPropertySymbols(e).length) throw new g("input", "任务不能包含Symbol");
|
|
387
|
-
if (Object.getOwnPropertyNames(e).filter((o) => !(t && o === "length")).length !== s.length) throw new g("input", "任务不能包含不可枚举属性");
|
|
388
|
-
if (t && (s.length !== e.length || s.some((o) => !/^(0|[1-9]\d*)$/.test(o) || Number(o) >= e.length))) throw new g("input", "任务数组不能稀疏或包含额外属性");
|
|
389
|
-
return s.sort();
|
|
390
|
-
}
|
|
391
|
-
function Be(e, t) {
|
|
392
|
-
const r = Object.getOwnPropertyDescriptor(e, t);
|
|
393
|
-
if (["__proto__", "prototype", "constructor"].includes(t) || r.get || r.set) throw new g("input", "任务不能包含危险键或访问器");
|
|
394
|
-
return r.value;
|
|
395
|
-
}
|
|
396
|
-
function S(e, t = {}) {
|
|
397
|
-
const r = t.maxNodes ?? 2e4, s = t.maxCharacters ?? 1e6;
|
|
398
|
-
if (!Number.isSafeInteger(r) || r < 1 || r > 2e4 || !Number.isSafeInteger(s) || s < 1 || s > 1e6) throw new g("input", "任务JSON预算无效");
|
|
399
|
-
let n = 0, o = 0;
|
|
400
|
-
const c = /* @__PURE__ */ new Set();
|
|
401
|
-
function m(a, u) {
|
|
402
|
-
if (++n > r || u > 32) throw new g("input", "任务数据超过节点或深度预算");
|
|
403
|
-
if (typeof a == "string") {
|
|
404
|
-
if (o += a.length, o > s) throw new g("input", "任务文本超过预算");
|
|
405
|
-
return a;
|
|
406
|
-
}
|
|
407
|
-
if (a === null || typeof a == "boolean" || typeof a == "number" && Number.isFinite(a)) return a;
|
|
408
|
-
if (!a || typeof a != "object" || c.has(a)) throw new g("input", "任务只允许无循环的有限 JSON 值");
|
|
409
|
-
const i = Array.isArray(a), d = Ie(a);
|
|
410
|
-
c.add(a);
|
|
411
|
-
const w = /* @__PURE__ */ Object.create(null);
|
|
412
|
-
for (const y of d) {
|
|
413
|
-
if (o += y.length, o > s) throw new g("input", "任务文本超过预算");
|
|
414
|
-
w[y] = m(Be(a, y), u + 1);
|
|
415
|
-
}
|
|
416
|
-
return c.delete(a), i ? Array.from({ length: a.length }, (y, l) => w[String(l)]) : w;
|
|
417
|
-
}
|
|
418
|
-
const p = JSON.stringify(m(e, 0));
|
|
419
|
-
if (p.length > s) throw new g("input", "任务序列化数据超过字符预算");
|
|
420
|
-
return p;
|
|
421
|
-
}
|
|
422
|
-
function N(e) {
|
|
423
|
-
return JSON.parse(JSON.stringify(e));
|
|
424
|
-
}
|
|
425
|
-
function Ee(e, t, r, s) {
|
|
426
|
-
if ($(t, r), e.scope !== t || e.id !== r || e.revision !== (s ?? 0) + 1 || !Number.isSafeInteger(e.revision)) throw new g("input", "任务身份或修订不匹配");
|
|
427
|
-
if (![e.createdAt, e.updatedAt, e.attempt].every((n) => Number.isSafeInteger(n) && n >= 0) || !["queued", "running", "completed", "failed", "cancelled"].includes(e.status)) throw new g("input", "任务状态无效");
|
|
428
|
-
if (e.lease && (!e.lease.owner || !Number.isSafeInteger(e.lease.expiresAt))) throw new g("input", "任务租约无效");
|
|
429
|
-
if (!e.request || typeof e.request.kind != "string" || !e.request.kind.trim() || e.request.kind.length > 128) throw new g("input", "任务类型无效");
|
|
430
|
-
S(e.request.payload, { maxNodes: 19e3, maxCharacters: 75e4 }), S(e);
|
|
431
|
-
}
|
|
432
|
-
function ke(e, t) {
|
|
433
|
-
if (e && (e.createdAt !== t.createdAt || S(e.request) !== S(t.request))) throw new g("input", "任务创建时间与请求不可变更,请使用新任务ID");
|
|
434
|
-
}
|
|
435
|
-
function $e(e, t) {
|
|
436
|
-
return e.status === "queued" || e.status === "running" && (e.lease?.expiresAt ?? 0) <= t;
|
|
437
|
-
}
|
|
438
|
-
function Ze(e = {}) {
|
|
439
|
-
const t = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Map(), s = Ne(e);
|
|
440
|
-
let n = 0, o = 0, c = Promise.resolve();
|
|
441
|
-
const m = (a, u) => JSON.stringify([a, u]), p = (a) => {
|
|
442
|
-
const u = c.then(a);
|
|
443
|
-
return c = u.then(() => {
|
|
444
|
-
}, () => {
|
|
445
|
-
}), u;
|
|
446
|
-
};
|
|
447
|
-
return {
|
|
448
|
-
read: async (a, u) => {
|
|
449
|
-
await c;
|
|
450
|
-
const i = t.get(m(a, u));
|
|
451
|
-
return i ? N(i) : void 0;
|
|
452
|
-
},
|
|
453
|
-
readTombstone: async (a, u) => {
|
|
454
|
-
await c;
|
|
455
|
-
const i = r.get(m(a, u));
|
|
456
|
-
return i ? N(i) : void 0;
|
|
457
|
-
},
|
|
458
|
-
candidates: async (a, u) => (await c, Array.from(t.values()).filter((i) => $e(i, a)).sort((i, d) => i.createdAt - d.createdAt).slice(0, u).map(N)),
|
|
459
|
-
compareAndSwap: async (a, u, i, d) => {
|
|
460
|
-
Ee(d, a, u, i);
|
|
461
|
-
const w = N(d);
|
|
462
|
-
return p(async () => {
|
|
463
|
-
const y = m(a, u), l = t.get(y);
|
|
464
|
-
if ((l?.revision ?? null) !== i || r.has(y)) return !1;
|
|
465
|
-
ke(l, w);
|
|
466
|
-
const f = n - (l ? C(l, s) : 0) + C(w, s);
|
|
467
|
-
if (f > s.maxBytes || !l && t.size >= s.maxRecords) throw new g("capacity", "任务容量已满,请清理终态任务或扩大显式预算");
|
|
468
|
-
return t.set(y, w), n = f, !0;
|
|
469
|
-
});
|
|
470
|
-
},
|
|
471
|
-
prune: async (a) => {
|
|
472
|
-
const u = je(a);
|
|
473
|
-
return p(async () => {
|
|
474
|
-
const i = { archived: 0, expired: 0 };
|
|
475
|
-
for (const [d, w] of r)
|
|
476
|
-
w.expiresAt > u.now || i.expired >= u.limit || (r.delete(d), o -= q(w), i.expired++);
|
|
477
|
-
for (const [d, w] of t) {
|
|
478
|
-
if (!re(w) || w.updatedAt > u.terminalBefore || i.archived + i.expired >= u.limit) continue;
|
|
479
|
-
const y = await qe(w, u.now + u.tombstoneRetentionMs), l = q(y);
|
|
480
|
-
if (r.size >= s.maxTombstones || o + l > s.maxTombstoneBytes) break;
|
|
481
|
-
r.set(d, y), o += l, t.delete(d), n -= C(w, s), i.archived++;
|
|
482
|
-
}
|
|
483
|
-
return i;
|
|
484
|
-
});
|
|
195
|
+
i = !0;
|
|
196
|
+
for (const c of [...a]) c.cancel(new A("closed", "任务队列已关闭"));
|
|
197
|
+
if (u.cancelRunning) for (const c of r) c.cancel(new A("closed", "任务队列已关闭"));
|
|
485
198
|
}
|
|
486
199
|
};
|
|
487
200
|
}
|
|
488
|
-
function
|
|
489
|
-
let t,
|
|
490
|
-
const
|
|
491
|
-
t =
|
|
201
|
+
function Re(e) {
|
|
202
|
+
let t, s;
|
|
203
|
+
const a = new Promise((r, n) => {
|
|
204
|
+
t = r, s = n;
|
|
492
205
|
});
|
|
493
|
-
return
|
|
494
|
-
}), { progress: e, promise:
|
|
206
|
+
return a.catch(() => {
|
|
207
|
+
}), { progress: e, promise: a, resolve: t, reject: s };
|
|
495
208
|
}
|
|
496
|
-
function
|
|
209
|
+
function U(e) {
|
|
497
210
|
const t = Promise.reject(e);
|
|
498
211
|
return t.catch(() => {
|
|
499
212
|
}), t;
|
|
500
213
|
}
|
|
501
|
-
function
|
|
502
|
-
let
|
|
503
|
-
function
|
|
504
|
-
|
|
214
|
+
function Ie(e, t) {
|
|
215
|
+
let s, a, r = !0, n;
|
|
216
|
+
function i(o) {
|
|
217
|
+
n ??= o ?? new Error("任务心跳更新失败"), a?.reject(n), a = void 0, t(n);
|
|
505
218
|
}
|
|
506
|
-
function
|
|
507
|
-
const u = Promise.resolve().then(() => e(
|
|
508
|
-
() =>
|
|
509
|
-
(
|
|
510
|
-
|
|
219
|
+
function l(o) {
|
|
220
|
+
const u = Promise.resolve().then(() => e(o?.progress)).then(
|
|
221
|
+
() => o?.resolve(),
|
|
222
|
+
(c) => {
|
|
223
|
+
o?.reject(c), i(c);
|
|
511
224
|
}
|
|
512
225
|
).finally(() => {
|
|
513
|
-
|
|
514
|
-
const
|
|
515
|
-
|
|
226
|
+
s = void 0;
|
|
227
|
+
const c = a;
|
|
228
|
+
a = void 0, c && n === void 0 && l(c);
|
|
516
229
|
});
|
|
517
|
-
|
|
518
|
-
c
|
|
230
|
+
s = u, u.catch((c) => {
|
|
231
|
+
i(c);
|
|
519
232
|
});
|
|
520
233
|
}
|
|
521
|
-
function
|
|
522
|
-
if (!
|
|
523
|
-
return
|
|
524
|
-
new
|
|
234
|
+
function f(o) {
|
|
235
|
+
if (!r)
|
|
236
|
+
return U(
|
|
237
|
+
new v("closed", "任务进度上报已结束")
|
|
525
238
|
);
|
|
526
|
-
if (
|
|
527
|
-
|
|
528
|
-
const u =
|
|
529
|
-
return
|
|
239
|
+
if (n !== void 0) return U(n);
|
|
240
|
+
a ? a.progress = o : a = Re(o);
|
|
241
|
+
const u = a;
|
|
242
|
+
return s || (a = void 0, l(u)), u.promise;
|
|
530
243
|
}
|
|
531
244
|
return {
|
|
532
|
-
progress:
|
|
245
|
+
progress: f,
|
|
533
246
|
pulse() {
|
|
534
|
-
|
|
247
|
+
r && !s && n === void 0 && l();
|
|
535
248
|
},
|
|
536
249
|
async finish() {
|
|
537
|
-
for (
|
|
538
|
-
if (
|
|
250
|
+
for (r = !1; s; ) await s;
|
|
251
|
+
if (n !== void 0) throw n;
|
|
539
252
|
}
|
|
540
253
|
};
|
|
541
254
|
}
|
|
542
|
-
class
|
|
255
|
+
class W extends v {
|
|
543
256
|
constructor() {
|
|
544
257
|
super("capacity", "任务结果超过独立预算,请保存文件引用");
|
|
545
258
|
}
|
|
546
259
|
}
|
|
547
|
-
function
|
|
548
|
-
const t = e.concurrency ?? 1,
|
|
549
|
-
if (![t,
|
|
550
|
-
(
|
|
551
|
-
) ||
|
|
552
|
-
throw new
|
|
260
|
+
function Oe(e) {
|
|
261
|
+
const t = e.concurrency ?? 1, s = e.leaseMs ?? 3e4, a = e.heartbeatMs ?? 1e4, r = e.maxResultBytes ?? 256 * 1024;
|
|
262
|
+
if (![t, s, a, r].every(
|
|
263
|
+
(i) => Number.isSafeInteger(i) && i > 0
|
|
264
|
+
) || a * 2 > s)
|
|
265
|
+
throw new v(
|
|
553
266
|
"input",
|
|
554
267
|
"并发、租约、心跳应为正整数,租约至少为心跳的两倍"
|
|
555
268
|
);
|
|
556
|
-
if (
|
|
557
|
-
throw new
|
|
269
|
+
if (a > 2147483647)
|
|
270
|
+
throw new v(
|
|
558
271
|
"input",
|
|
559
272
|
"心跳间隔超过平台定时器上限(2147483647毫秒)"
|
|
560
273
|
);
|
|
561
|
-
return { concurrency: t, leaseMs:
|
|
562
|
-
const
|
|
563
|
-
if (!Number.isSafeInteger(
|
|
564
|
-
throw new
|
|
565
|
-
return
|
|
274
|
+
return { concurrency: t, leaseMs: s, heartbeatMs: a, maxResultBytes: r, now: () => {
|
|
275
|
+
const i = (e.now ?? Date.now)();
|
|
276
|
+
if (!Number.isSafeInteger(i) || i < 0)
|
|
277
|
+
throw new v("input", "任务时钟应返回非负整数毫秒");
|
|
278
|
+
return i;
|
|
566
279
|
} };
|
|
567
280
|
}
|
|
568
|
-
async function
|
|
569
|
-
$(t,
|
|
570
|
-
const
|
|
571
|
-
if (!
|
|
572
|
-
return
|
|
281
|
+
async function B(e, t, s) {
|
|
282
|
+
$(t, s);
|
|
283
|
+
const a = await e.read(t, s);
|
|
284
|
+
if (!a) throw new v("missing", "报表任务不存在");
|
|
285
|
+
return a;
|
|
573
286
|
}
|
|
574
|
-
async function
|
|
575
|
-
const
|
|
576
|
-
for (const
|
|
287
|
+
async function j(e, t, s, a = []) {
|
|
288
|
+
const r = { ...t, ...s, revision: t.revision + 1 };
|
|
289
|
+
for (const n of a) delete r[n];
|
|
577
290
|
if (!await e.compareAndSwap(
|
|
578
291
|
t.scope,
|
|
579
292
|
t.id,
|
|
580
293
|
t.revision,
|
|
581
|
-
|
|
294
|
+
r
|
|
582
295
|
))
|
|
583
|
-
throw new
|
|
584
|
-
return
|
|
296
|
+
throw new v("conflict", "报表任务已被其他请求更新");
|
|
297
|
+
return D(r);
|
|
585
298
|
}
|
|
586
|
-
async function
|
|
299
|
+
async function Ae(e, t, s, a) {
|
|
587
300
|
if (!t.trim() || t.length > 128)
|
|
588
|
-
throw new
|
|
589
|
-
for (const
|
|
590
|
-
const
|
|
591
|
-
...
|
|
592
|
-
revision:
|
|
301
|
+
throw new v("input", "workerId应为1–128位标识");
|
|
302
|
+
for (const r of await e.store.candidates(a, 100)) {
|
|
303
|
+
const n = r.cancelRequested ? {
|
|
304
|
+
...r,
|
|
305
|
+
revision: r.revision + 1,
|
|
593
306
|
status: "cancelled",
|
|
594
|
-
updatedAt:
|
|
307
|
+
updatedAt: a
|
|
595
308
|
} : {
|
|
596
|
-
...
|
|
597
|
-
revision:
|
|
309
|
+
...r,
|
|
310
|
+
revision: r.revision + 1,
|
|
598
311
|
status: "running",
|
|
599
|
-
attempt:
|
|
600
|
-
updatedAt:
|
|
601
|
-
lease: { owner: t, expiresAt:
|
|
312
|
+
attempt: r.attempt + 1,
|
|
313
|
+
updatedAt: a,
|
|
314
|
+
lease: { owner: t, expiresAt: a + s }
|
|
602
315
|
};
|
|
603
|
-
if (
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
316
|
+
if (n.status === "cancelled" && delete n.lease, await e.store.compareAndSwap(
|
|
317
|
+
r.scope,
|
|
318
|
+
r.id,
|
|
319
|
+
r.revision,
|
|
320
|
+
n
|
|
608
321
|
))
|
|
609
|
-
return
|
|
322
|
+
return n;
|
|
610
323
|
}
|
|
611
324
|
}
|
|
612
|
-
function
|
|
613
|
-
return e.status === "running" && e.attempt ===
|
|
614
|
-
}
|
|
615
|
-
async function
|
|
616
|
-
const { scope:
|
|
617
|
-
let
|
|
618
|
-
const
|
|
619
|
-
async (
|
|
620
|
-
const h = await
|
|
621
|
-
if (!
|
|
622
|
-
throw new
|
|
325
|
+
function Z(e, t, s, a) {
|
|
326
|
+
return e.status === "running" && e.attempt === a && e.lease?.owner === t && e.lease.expiresAt > s;
|
|
327
|
+
}
|
|
328
|
+
async function Pe(e, t, s, a) {
|
|
329
|
+
const { scope: r, id: n } = s, i = s.lease.owner;
|
|
330
|
+
let l;
|
|
331
|
+
const f = Ie(
|
|
332
|
+
async (p) => {
|
|
333
|
+
const h = await B(e.store, r, n), S = t.now();
|
|
334
|
+
if (!Z(h, i, S, s.attempt))
|
|
335
|
+
throw new v("lease", "报表任务租约已失效");
|
|
623
336
|
if (h.cancelRequested) {
|
|
624
|
-
|
|
337
|
+
a.abort(new v("closed", "任务已请求取消"));
|
|
625
338
|
return;
|
|
626
339
|
}
|
|
627
|
-
await
|
|
628
|
-
updatedAt:
|
|
629
|
-
lease: { owner:
|
|
630
|
-
...
|
|
340
|
+
await j(e.store, h, {
|
|
341
|
+
updatedAt: S,
|
|
342
|
+
lease: { owner: i, expiresAt: S + t.leaseMs },
|
|
343
|
+
...p ? { progress: p } : {}
|
|
631
344
|
});
|
|
632
345
|
},
|
|
633
|
-
(
|
|
634
|
-
|
|
346
|
+
(p) => {
|
|
347
|
+
l = p, a.abort(p);
|
|
635
348
|
}
|
|
636
|
-
),
|
|
637
|
-
completed:
|
|
349
|
+
), o = (p, h) => !Number.isFinite(p) || p < 0 || h !== void 0 && (!Number.isFinite(h) || h < p) ? Promise.reject(new v("input", "任务进度无效")) : f.progress({
|
|
350
|
+
completed: p,
|
|
638
351
|
...h === void 0 ? {} : { total: h }
|
|
639
352
|
}), u = setInterval(() => {
|
|
640
|
-
|
|
353
|
+
f.pulse();
|
|
641
354
|
}, t.heartbeatMs);
|
|
642
|
-
let
|
|
355
|
+
let c, d;
|
|
643
356
|
try {
|
|
644
|
-
const
|
|
357
|
+
const p = Object.prototype.hasOwnProperty.call(
|
|
645
358
|
e.handlers,
|
|
646
|
-
|
|
647
|
-
) ? e.handlers[
|
|
648
|
-
if (!
|
|
649
|
-
if (!
|
|
650
|
-
const h = await
|
|
651
|
-
scope:
|
|
652
|
-
taskId:
|
|
653
|
-
signal:
|
|
654
|
-
reportProgress:
|
|
359
|
+
s.request.kind
|
|
360
|
+
) ? e.handlers[s.request.kind] : void 0;
|
|
361
|
+
if (!p) throw new v("input", "报表任务处理器未注册");
|
|
362
|
+
if (!a.signal.aborted) {
|
|
363
|
+
const h = await p(D(s.request.payload), {
|
|
364
|
+
scope: r,
|
|
365
|
+
taskId: n,
|
|
366
|
+
signal: a.signal,
|
|
367
|
+
reportProgress: o
|
|
655
368
|
});
|
|
656
|
-
if (
|
|
369
|
+
if (c = JSON.parse(I(h)), we(c) > t.maxResultBytes) throw new W();
|
|
657
370
|
}
|
|
658
|
-
} catch (
|
|
659
|
-
d =
|
|
371
|
+
} catch (p) {
|
|
372
|
+
d = p ?? new Error("报表任务执行失败");
|
|
660
373
|
} finally {
|
|
661
|
-
clearInterval(u), await
|
|
374
|
+
clearInterval(u), await f.finish().catch(() => {
|
|
662
375
|
});
|
|
663
376
|
}
|
|
664
|
-
const
|
|
665
|
-
if (!
|
|
666
|
-
throw new
|
|
667
|
-
const
|
|
668
|
-
delete
|
|
669
|
-
code: d instanceof
|
|
377
|
+
const m = await B(e.store, r, n), y = t.now();
|
|
378
|
+
if (!Z(m, i, y, s.attempt))
|
|
379
|
+
throw new v("lease", "任务租约已失效,迟到结果不会写回");
|
|
380
|
+
const g = { ...m, updatedAt: y };
|
|
381
|
+
delete g.lease, d ??= l, m.cancelRequested || a.signal.aborted && l === void 0 ? g.status = "cancelled" : d !== void 0 ? (g.status = "failed", g.error = {
|
|
382
|
+
code: d instanceof W ? "result-budget" : d instanceof v ? d.code : "execution",
|
|
670
383
|
message: d instanceof Error ? d.message.slice(0, 500) : "报表任务执行失败"
|
|
671
|
-
}) : (
|
|
384
|
+
}) : (g.status = "completed", g.result = c);
|
|
672
385
|
try {
|
|
673
|
-
|
|
386
|
+
I(g);
|
|
674
387
|
} catch {
|
|
675
|
-
delete
|
|
388
|
+
delete g.result, g.status = "failed", g.error = {
|
|
676
389
|
code: "result-budget",
|
|
677
390
|
message: "任务结果与请求的组合超过存储预算,请保存文件引用而非文件内容"
|
|
678
391
|
};
|
|
679
392
|
}
|
|
680
|
-
return
|
|
393
|
+
return ke(e.store, m, g);
|
|
681
394
|
}
|
|
682
|
-
async function
|
|
395
|
+
async function ke(e, t, s) {
|
|
683
396
|
try {
|
|
684
|
-
return await
|
|
685
|
-
} catch (
|
|
686
|
-
if (!(
|
|
687
|
-
return delete
|
|
397
|
+
return await j(e, t, s, ["lease"]);
|
|
398
|
+
} catch (a) {
|
|
399
|
+
if (!(a instanceof v) || a.code !== "capacity" || s.status !== "completed") throw a;
|
|
400
|
+
return delete s.result, s.status = "failed", s.error = { code: "result-budget", message: "任务结果超过存储剩余预算,请保存文件引用而非文件内容" }, j(e, t, s, ["lease", "result"]);
|
|
688
401
|
}
|
|
689
402
|
}
|
|
690
|
-
async function
|
|
691
|
-
const
|
|
692
|
-
if (
|
|
693
|
-
if (
|
|
694
|
-
return { scope: t, id:
|
|
403
|
+
async function K(e, t, s, a) {
|
|
404
|
+
const r = await e.readTombstone?.(t, s);
|
|
405
|
+
if (r) {
|
|
406
|
+
if (r.requestHash !== await me(a)) throw new v("conflict", "相同任务ID不能提交不同内容(幂等保留期内)");
|
|
407
|
+
return { scope: t, id: s, revision: r.revision, request: D(a), status: r.status, createdAt: r.createdAt, updatedAt: r.updatedAt, attempt: r.attempt, archived: !0 };
|
|
695
408
|
}
|
|
696
409
|
}
|
|
697
|
-
function
|
|
410
|
+
function Xe(e) {
|
|
698
411
|
e = { ...e, handlers: { ...e.handlers } };
|
|
699
|
-
const t =
|
|
700
|
-
let
|
|
701
|
-
const
|
|
412
|
+
const t = Oe(e), s = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set();
|
|
413
|
+
let r = !1, n = 0;
|
|
414
|
+
const i = (o, u) => ($(o, u), e.store.read(o, u));
|
|
702
415
|
return {
|
|
703
|
-
submit: async (
|
|
704
|
-
if (
|
|
705
|
-
throw new
|
|
416
|
+
submit: async (o) => {
|
|
417
|
+
if (o = { ...o }, $(o.scope, o.id), !Object.prototype.hasOwnProperty.call(e.handlers, o.kind) || typeof e.handlers[o.kind] != "function")
|
|
418
|
+
throw new v("input", "报表任务处理器未注册");
|
|
706
419
|
const u = {
|
|
707
|
-
kind:
|
|
420
|
+
kind: o.kind,
|
|
708
421
|
payload: JSON.parse(
|
|
709
|
-
|
|
422
|
+
I(o.payload, {
|
|
710
423
|
maxNodes: 19e3,
|
|
711
424
|
maxCharacters: 75e4
|
|
712
425
|
})
|
|
713
426
|
)
|
|
714
|
-
},
|
|
715
|
-
if (
|
|
716
|
-
if (
|
|
717
|
-
throw new
|
|
718
|
-
return
|
|
427
|
+
}, c = await i(o.scope, o.id);
|
|
428
|
+
if (c) {
|
|
429
|
+
if (I(c.request) !== I(u))
|
|
430
|
+
throw new v("conflict", "相同任务ID不能提交不同内容");
|
|
431
|
+
return c;
|
|
719
432
|
}
|
|
720
|
-
const d = await
|
|
433
|
+
const d = await K(e.store, o.scope, o.id, u);
|
|
721
434
|
if (d) return d;
|
|
722
|
-
const
|
|
723
|
-
scope:
|
|
724
|
-
id:
|
|
435
|
+
const m = t.now(), y = {
|
|
436
|
+
scope: o.scope,
|
|
437
|
+
id: o.id,
|
|
725
438
|
revision: 1,
|
|
726
439
|
request: u,
|
|
727
440
|
status: "queued",
|
|
728
|
-
createdAt:
|
|
729
|
-
updatedAt:
|
|
441
|
+
createdAt: m,
|
|
442
|
+
updatedAt: m,
|
|
730
443
|
attempt: 0
|
|
731
444
|
};
|
|
732
|
-
if (!await e.store.compareAndSwap(
|
|
733
|
-
const
|
|
734
|
-
if (
|
|
735
|
-
return
|
|
736
|
-
const
|
|
737
|
-
if (
|
|
738
|
-
throw new
|
|
445
|
+
if (!await e.store.compareAndSwap(o.scope, o.id, null, y)) {
|
|
446
|
+
const g = await i(o.scope, o.id);
|
|
447
|
+
if (g && I(g.request) === I(u))
|
|
448
|
+
return g;
|
|
449
|
+
const p = await K(e.store, o.scope, o.id, u);
|
|
450
|
+
if (p) return p;
|
|
451
|
+
throw new v("conflict", "报表任务提交发生冲突");
|
|
739
452
|
}
|
|
740
|
-
return
|
|
453
|
+
return D(y);
|
|
741
454
|
},
|
|
742
|
-
get:
|
|
743
|
-
runNext: (
|
|
744
|
-
if (
|
|
745
|
-
return Promise.reject(new
|
|
746
|
-
if (
|
|
455
|
+
get: i,
|
|
456
|
+
runNext: (o) => {
|
|
457
|
+
if (r)
|
|
458
|
+
return Promise.reject(new v("closed", "报表任务服务已关闭"));
|
|
459
|
+
if (n >= t.concurrency)
|
|
747
460
|
return Promise.reject(
|
|
748
|
-
new
|
|
461
|
+
new v("capacity", "报表任务执行槽位已满")
|
|
749
462
|
);
|
|
750
|
-
|
|
463
|
+
n++;
|
|
751
464
|
const u = new AbortController();
|
|
752
|
-
|
|
753
|
-
const
|
|
465
|
+
s.add(u);
|
|
466
|
+
const c = (async () => {
|
|
754
467
|
try {
|
|
755
|
-
const d = await
|
|
468
|
+
const d = await Ae(
|
|
756
469
|
e,
|
|
757
|
-
|
|
470
|
+
o,
|
|
758
471
|
t.leaseMs,
|
|
759
472
|
t.now()
|
|
760
473
|
);
|
|
761
|
-
return d?.status === "running" ? await
|
|
474
|
+
return d?.status === "running" ? await Pe(e, t, d, u) : d;
|
|
762
475
|
} finally {
|
|
763
|
-
|
|
476
|
+
n--, s.delete(u);
|
|
764
477
|
}
|
|
765
478
|
})();
|
|
766
|
-
return
|
|
767
|
-
() =>
|
|
768
|
-
() =>
|
|
769
|
-
),
|
|
479
|
+
return a.add(c), c.then(
|
|
480
|
+
() => a.delete(c),
|
|
481
|
+
() => a.delete(c)
|
|
482
|
+
), c;
|
|
770
483
|
},
|
|
771
484
|
get active() {
|
|
772
|
-
return
|
|
485
|
+
return n;
|
|
773
486
|
},
|
|
774
|
-
cancel: async (
|
|
775
|
-
const
|
|
776
|
-
return
|
|
487
|
+
cancel: async (o, u) => {
|
|
488
|
+
const c = await B(e.store, o, u);
|
|
489
|
+
return c.status !== "queued" && c.status !== "running" ? c : j(e.store, c, {
|
|
777
490
|
updatedAt: t.now(),
|
|
778
|
-
...
|
|
491
|
+
...c.status === "queued" ? { status: "cancelled" } : { cancelRequested: !0 }
|
|
779
492
|
});
|
|
780
493
|
},
|
|
781
|
-
retry: async (
|
|
782
|
-
const d = await
|
|
783
|
-
if (d.revision !==
|
|
784
|
-
throw new
|
|
785
|
-
const
|
|
494
|
+
retry: async (o, u, c) => {
|
|
495
|
+
const d = await B(e.store, o, u);
|
|
496
|
+
if (d.revision !== c || d.status !== "failed")
|
|
497
|
+
throw new v("conflict", "仅可重试当前修订的失败任务");
|
|
498
|
+
const m = {
|
|
786
499
|
...d,
|
|
787
500
|
status: "queued",
|
|
788
501
|
updatedAt: t.now()
|
|
789
502
|
};
|
|
790
|
-
return delete
|
|
503
|
+
return delete m.error, delete m.progress, j(e.store, d, m, ["error", "progress"]);
|
|
791
504
|
},
|
|
792
|
-
prune: async (
|
|
793
|
-
if (!e.store.prune || !e.store.readTombstone) throw new
|
|
794
|
-
return e.store.prune({ ...
|
|
505
|
+
prune: async (o) => {
|
|
506
|
+
if (!e.store.prune || !e.store.readTombstone) throw new v("input", "当前任务适配器未实现可选终态保留能力");
|
|
507
|
+
return e.store.prune({ ...o, now: t.now() });
|
|
795
508
|
},
|
|
796
509
|
close: async () => {
|
|
797
|
-
|
|
798
|
-
for (const
|
|
799
|
-
|
|
800
|
-
await Promise.allSettled([...
|
|
510
|
+
r = !0;
|
|
511
|
+
for (const o of s)
|
|
512
|
+
o.abort(new v("closed", "任务服务正在关闭"));
|
|
513
|
+
await Promise.allSettled([...a]);
|
|
801
514
|
}
|
|
802
515
|
};
|
|
803
516
|
}
|
|
804
|
-
async function
|
|
805
|
-
const
|
|
806
|
-
maxRows:
|
|
807
|
-
maxPages:
|
|
808
|
-
maxCells:
|
|
809
|
-
maxOutputBytes:
|
|
810
|
-
maxDurationMs:
|
|
517
|
+
async function Ne(e, t, s, a, r) {
|
|
518
|
+
const n = Se({ reports: { sample: { template: s, datasets: e.datasets } }, budget: {
|
|
519
|
+
maxRows: a.maxSampleRows ?? 1e3,
|
|
520
|
+
maxPages: a.maxPages ?? 100,
|
|
521
|
+
maxCells: a.maxCells ?? 25e4,
|
|
522
|
+
maxOutputBytes: a.maxOutputBytes ?? 2e7,
|
|
523
|
+
maxDurationMs: a.maxDurationMs ?? 3e4
|
|
811
524
|
} });
|
|
812
525
|
try {
|
|
813
|
-
const { result:
|
|
814
|
-
const
|
|
815
|
-
return
|
|
526
|
+
const { result: i, digest: l } = await q(a.signal, a.maxDurationMs ?? 3e4, async (f) => {
|
|
527
|
+
const o = await n.export({ reportIds: ["sample"], params: e.params, format: t, signal: f, fidelity: a.strictOutputs ? "strict" : "warn", pdf: a.pdf, xlsx: a.xlsx }), u = await a.digest?.(o.bytes);
|
|
528
|
+
return b(f), await a.onArtifact?.(e.name, o), b(f), { result: o, digest: u };
|
|
816
529
|
});
|
|
817
|
-
|
|
818
|
-
} catch (
|
|
819
|
-
|
|
530
|
+
r.artifacts.push({ fixture: e.name, format: t, bytes: i.bytes.byteLength, pages: i.stats.pages, ...l ? { digest: l } : {} }), r.issues.push(...i.diagnostics.map((f) => ({ code: "output", severity: a.strictOutputs || f.severity === "error" ? "error" : "warning", path: "$.template", fixture: e.name, message: `${t}: ${f.message}` })));
|
|
531
|
+
} catch (i) {
|
|
532
|
+
b(a.signal), r.issues.push({ code: "output", severity: "error", path: "$.template", fixture: e.name, message: `${t}: ${i instanceof Error ? i.message : String(i)}` });
|
|
820
533
|
}
|
|
821
534
|
}
|
|
822
535
|
async function Ge(e, t = {}) {
|
|
823
|
-
|
|
824
|
-
const
|
|
825
|
-
if (!
|
|
826
|
-
const
|
|
827
|
-
if (!
|
|
828
|
-
return
|
|
829
|
-
for (const
|
|
830
|
-
for (const
|
|
831
|
-
|
|
832
|
-
return
|
|
536
|
+
b(t.signal);
|
|
537
|
+
const s = { ...fe(e, t), artifacts: [] };
|
|
538
|
+
if (!s.ok) return s;
|
|
539
|
+
const a = he(e).template, r = [...new Set(t.formats ?? ["pdf", "xlsx"])];
|
|
540
|
+
if (!r.length || r.some((n) => n !== "pdf" && n !== "xlsx"))
|
|
541
|
+
return s.issues.push({ code: "output", severity: "error", path: "$.formats", message: "真实文件验收应至少选择PDF/XLSX之一" }), s.ok = !1, s;
|
|
542
|
+
for (const n of t.fixtures ?? [])
|
|
543
|
+
for (const i of r)
|
|
544
|
+
b(t.signal), !(i !== "pdf" && i !== "xlsx") && await Ne(n, i, a, t, s);
|
|
545
|
+
return s.ok = s.issues.every((n) => n.severity !== "error"), s;
|
|
546
|
+
}
|
|
547
|
+
class w extends Error {
|
|
548
|
+
constructor(t, s) {
|
|
549
|
+
super(s), this.code = t, this.name = "ReportInstanceError";
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
function N(e, t) {
|
|
553
|
+
if (typeof e != "string" || !e.trim() || e.length > 256 || typeof t != "string" || t !== t.trim() || !/^[a-zA-Z0-9][a-zA-Z0-9_.:-]{0,127}$/.test(t)) throw new w("input", "实例范围应非空,ID 应为安全标识");
|
|
554
|
+
}
|
|
555
|
+
function je(e, t) {
|
|
556
|
+
const s = Object.getPrototypeOf(e);
|
|
557
|
+
if (s !== (t ? Array.prototype : Object.prototype) && !(s === null && !t) || Object.getOwnPropertySymbols(e).length) throw new w("input", "实例应为普通 JSON 对象");
|
|
558
|
+
if (t && Object.keys(e).some((r) => r !== String(Number(r)) || !Number.isSafeInteger(Number(r)) || Number(r) < 0 || Number(r) >= e.length)) throw new w("input", "实例数组不能包含额外属性");
|
|
559
|
+
if (Object.getOwnPropertyNames(e).filter((r) => !(t && r === "length")).length !== Object.keys(e).length) throw new w("input", "实例不能包含不可枚举属性");
|
|
560
|
+
}
|
|
561
|
+
function Ee(e) {
|
|
562
|
+
if (!Number.isSafeInteger(e.revision) || e.revision < 1 || typeof e.title != "string" || !e.title.trim() || e.title.length > 512) throw new w("input", "实例修订或标题无效");
|
|
563
|
+
if (typeof e.generatedAt != "string" || !Number.isFinite(Date.parse(e.generatedAt)) || new Date(e.generatedAt).toISOString() !== e.generatedAt) throw new w("input", "实例生成时间应为 ISO UTC 字符串");
|
|
564
|
+
if (!Array.isArray(e.reportIds) || !e.reportIds.length || e.reportIds.length > 100 || e.reportIds.some((t) => typeof t != "string" || !t.trim()) || new Set(e.reportIds).size !== e.reportIds.length) throw new w("input", "实例报表 ID 应非空且唯一");
|
|
565
|
+
}
|
|
566
|
+
function Je(e) {
|
|
567
|
+
return e === null || typeof e == "boolean" || typeof e == "string" || typeof e == "number" && Number.isFinite(e);
|
|
568
|
+
}
|
|
569
|
+
function se(e, t) {
|
|
570
|
+
if (!Number.isSafeInteger(t) || t < 1) throw new w("input", "实例快照字节预算应为正安全整数");
|
|
571
|
+
let s = 0, a = 0;
|
|
572
|
+
const r = /* @__PURE__ */ new Set();
|
|
573
|
+
function n(l, f) {
|
|
574
|
+
if (++s > 1e6 || f > 64) throw new w("capacity", "实例节点或嵌套深度超过预算");
|
|
575
|
+
if (typeof l == "string" && (a += l.length, a > t))
|
|
576
|
+
throw new w("capacity", "实例文本超过预算");
|
|
577
|
+
if (Je(l)) return l;
|
|
578
|
+
if (!l || typeof l != "object" || r.has(l)) throw new w("input", "实例只允许无循环的有限 JSON 值");
|
|
579
|
+
const o = Array.isArray(l);
|
|
580
|
+
je(l, o), r.add(l);
|
|
581
|
+
const u = /* @__PURE__ */ Object.create(null);
|
|
582
|
+
for (const c of Object.keys(l)) {
|
|
583
|
+
if (a += c.length, a > t) throw new w("capacity", "实例文本超过预算");
|
|
584
|
+
const d = Object.getOwnPropertyDescriptor(l, c);
|
|
585
|
+
if (d.get || d.set || ["__proto__", "constructor", "prototype"].includes(c)) throw new w("input", "实例不能包含访问器或危险键");
|
|
586
|
+
d.value !== void 0 && (u[c] = n(d.value, f + 1));
|
|
587
|
+
}
|
|
588
|
+
if (r.delete(l), o) {
|
|
589
|
+
if (Object.keys(u).length !== l.length) throw new w("input", "实例数组不能稀疏或包含额外属性");
|
|
590
|
+
return Array.from({ length: l.length }, (c, d) => u[String(d)]);
|
|
591
|
+
}
|
|
592
|
+
return u;
|
|
593
|
+
}
|
|
594
|
+
const i = JSON.stringify(n(e, 0));
|
|
595
|
+
if (new TextEncoder().encode(i).byteLength > t) throw new w("capacity", "实例快照超过单条字节预算");
|
|
596
|
+
return i;
|
|
597
|
+
}
|
|
598
|
+
function L(e, t = 8e6) {
|
|
599
|
+
const s = JSON.parse(se(e, t));
|
|
600
|
+
N(s.scope, s.id);
|
|
601
|
+
const a = /* @__PURE__ */ new Set(["scope", "id", "revision", "title", "generatedAt", "reportIds", "params", "templateRevisions", "sourceRevisions", "plan", "artifacts"]);
|
|
602
|
+
if (Object.keys(s).some((n) => !a.has(n))) throw new w("input", "实例包含未知字段");
|
|
603
|
+
Ee(s);
|
|
604
|
+
for (const n of [s.params, s.templateRevisions, s.sourceRevisions])
|
|
605
|
+
if (!n || typeof n != "object" || Array.isArray(n) || Object.values(n).some((i) => typeof i != "string")) throw new w("input", "实例参数和修订应为字符串字典");
|
|
606
|
+
if (s.reportIds.some((n) => !s.templateRevisions[n])) throw new w("input", "每张报表都应记录生成时的模板修订");
|
|
607
|
+
const r = ee(s.plan);
|
|
608
|
+
if (!r.ok) throw new w("input", `实例渲染计划无效:${r.errors[0]?.path}`);
|
|
609
|
+
return s.artifacts !== void 0 && Be(s.artifacts), s;
|
|
610
|
+
}
|
|
611
|
+
function Be(e) {
|
|
612
|
+
if (!Array.isArray(e) || e.length > 100) throw new w("input", "实例文件列表无效");
|
|
613
|
+
const t = /* @__PURE__ */ new Set();
|
|
614
|
+
for (const s of e) {
|
|
615
|
+
if (!s || typeof s.key != "string" || !s.key.trim() || s.key.length > 1024 || t.has(s.key) || !["pdf", "xlsx"].includes(s.format) || !Number.isSafeInteger(s.bytes) || s.bytes < 0 || s.sha256 !== void 0 && (typeof s.sha256 != "string" || s.sha256.length !== 64 || !/^[a-f0-9]{64}$/i.test(s.sha256))) throw new w("input", "实例文件应包含唯一存储键、格式、大小和可选 SHA256");
|
|
616
|
+
t.add(s.key);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
function De(e) {
|
|
620
|
+
const { scope: t, id: s, revision: a, title: r, generatedAt: n, reportIds: i, params: l, templateRevisions: f, sourceRevisions: o } = e;
|
|
621
|
+
return JSON.parse(JSON.stringify({ scope: t, id: s, revision: a, title: r, generatedAt: n, reportIds: i, params: l, templateRevisions: f, sourceRevisions: o }));
|
|
622
|
+
}
|
|
623
|
+
function Ce(e) {
|
|
624
|
+
const t = { maxInstances: 100, maxRevisions: 20, maxBytes: 64e6, maxSnapshotBytes: 8e6, ...e };
|
|
625
|
+
if (Object.values(t).some((s) => !Number.isSafeInteger(s) || s < 1)) throw new w("input", "实例存储预算应为正安全整数");
|
|
626
|
+
return t;
|
|
627
|
+
}
|
|
628
|
+
function Ue(e = {}) {
|
|
629
|
+
const t = Ce(e), s = /* @__PURE__ */ new Map();
|
|
630
|
+
let a = 0;
|
|
631
|
+
return {
|
|
632
|
+
read: async (r, n, i, l) => {
|
|
633
|
+
b(l), N(r, n);
|
|
634
|
+
const f = s.get(JSON.stringify([r, n])), o = f?.get(i ?? f.size);
|
|
635
|
+
return o ? L(o, t.maxSnapshotBytes) : void 0;
|
|
636
|
+
},
|
|
637
|
+
list: async (r, n = {}) => {
|
|
638
|
+
b(n.signal), N(r, "list");
|
|
639
|
+
const i = n.limit ?? 25;
|
|
640
|
+
if (!Number.isSafeInteger(i) || i < 1 || i > 100) throw new w("input", "实例每页数量应为 1–100");
|
|
641
|
+
const l = Array.from(s.values(), (f) => f.get(f.size)).filter((f) => f.scope === r && (!n.after || f.id > n.after) && (!n.reportId || f.reportIds.includes(n.reportId))).sort((f, o) => f.id < o.id ? -1 : 1).slice(0, i + 1);
|
|
642
|
+
return { items: l.slice(0, i).map(De), ...l.length > i ? { next: l[i - 1].id } : {} };
|
|
643
|
+
},
|
|
644
|
+
compareAndSwap: async (r, n, i, l, f) => {
|
|
645
|
+
b(f), N(r, n);
|
|
646
|
+
const o = L(l, t.maxSnapshotBytes);
|
|
647
|
+
if (o.scope !== r || o.id !== n || o.revision !== (i ?? 0) + 1) throw new w("input", "实例身份或修订不一致");
|
|
648
|
+
const u = JSON.stringify([r, n]), c = s.get(u) ?? /* @__PURE__ */ new Map();
|
|
649
|
+
if ((c.size || null) !== i) return !1;
|
|
650
|
+
const d = new TextEncoder().encode(JSON.stringify(o)).byteLength;
|
|
651
|
+
if (c.size >= t.maxRevisions || a + d > t.maxBytes || !c.size && s.size >= t.maxInstances) throw new w("capacity", "实例存储达到预算,请使用持久化归档策略或显式调整容量");
|
|
652
|
+
return c.set(o.revision, o), s.set(u, c), a += d, !0;
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
function Me(e, t = {}) {
|
|
657
|
+
const s = t.maxSnapshotBytes ?? 8e6;
|
|
658
|
+
if (!Number.isSafeInteger(s) || s < 1) throw new w("input", "实例快照字节预算应为正安全整数");
|
|
659
|
+
return {
|
|
660
|
+
read: e.read.bind(e),
|
|
661
|
+
list: e.list.bind(e),
|
|
662
|
+
save: async (a, r) => {
|
|
663
|
+
const n = r.expectedRevision;
|
|
664
|
+
if (n !== null && (!Number.isSafeInteger(n) || n < 1 || n >= Number.MAX_SAFE_INTEGER)) throw new w("input", "实例预期修订无效");
|
|
665
|
+
const i = JSON.parse(se(a, s)), l = L({ ...i, revision: (n ?? 0) + 1 }, s);
|
|
666
|
+
if (b(r.signal), !await e.compareAndSwap(l.scope, l.id, n, l, r.signal)) throw new w("conflict", "实例已存在或已变化,请显式确认修订后保存");
|
|
667
|
+
return l;
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
function We(e, t) {
|
|
672
|
+
return I({ reportIds: e, params: t });
|
|
673
|
+
}
|
|
674
|
+
function Te(e) {
|
|
675
|
+
if (!e || typeof e != "object" || Object.getOwnPropertySymbols(e).length) throw new w("input", "生成请求应为普通对象");
|
|
676
|
+
const t = /* @__PURE__ */ Object.create(null);
|
|
677
|
+
let s;
|
|
678
|
+
const a = /* @__PURE__ */ new Set(["scope", "id", "title", "reportIds", "params", "expectedRevision", "signal"]);
|
|
679
|
+
for (const r of Object.getOwnPropertyNames(e)) {
|
|
680
|
+
const n = Object.getOwnPropertyDescriptor(e, r);
|
|
681
|
+
if (!a.has(r) || !n.enumerable || n.get || n.set) throw new w("input", "生成请求不能包含未知字段或访问器");
|
|
682
|
+
r === "signal" ? s = n.value : n.value !== void 0 && (t[r] = n.value);
|
|
683
|
+
}
|
|
684
|
+
return { signal: s, request: JSON.parse(I(t)) };
|
|
685
|
+
}
|
|
686
|
+
function Ze(e) {
|
|
687
|
+
const t = JSON.parse(I(e.templateRevisions)), s = Me(e.instances, { maxSnapshotBytes: e.maxSnapshotBytes });
|
|
688
|
+
return {
|
|
689
|
+
async generate(a) {
|
|
690
|
+
const { signal: r, request: n } = Te(a);
|
|
691
|
+
if (N(n.scope, n.id), n.expectedRevision !== null && (!Number.isSafeInteger(n.expectedRevision) || n.expectedRevision < 1)) throw new w("input", "实例预期修订无效");
|
|
692
|
+
const i = e.runtime.validate(n);
|
|
693
|
+
if (!i.ok) throw new Y(i.issues);
|
|
694
|
+
const l = /* @__PURE__ */ Object.create(null);
|
|
695
|
+
for (const c of n.reportIds) {
|
|
696
|
+
if (typeof t[c] != "string" || !t[c]) throw new TypeError(`报表 ${c} 缺少生成时的模板修订`);
|
|
697
|
+
l[c] = t[c];
|
|
698
|
+
}
|
|
699
|
+
if (b(r), ((await e.instances.read(n.scope, n.id, void 0, r))?.revision ?? null) !== n.expectedRevision)
|
|
700
|
+
throw new w("conflict", "实例已存在或已变化,请显式确认修订后生成");
|
|
701
|
+
const o = await e.runtime.prepare({ reportIds: n.reportIds, params: i.values, signal: r });
|
|
702
|
+
b(r);
|
|
703
|
+
const u = /* @__PURE__ */ Object.create(null);
|
|
704
|
+
for (const [c, d] of Object.entries(o.revisions)) d.revision !== void 0 && (u[c] = d.revision);
|
|
705
|
+
return s.save({
|
|
706
|
+
scope: n.scope,
|
|
707
|
+
id: n.id,
|
|
708
|
+
title: n.title,
|
|
709
|
+
reportIds: n.reportIds,
|
|
710
|
+
params: i.values,
|
|
711
|
+
templateRevisions: l,
|
|
712
|
+
sourceRevisions: u,
|
|
713
|
+
generatedAt: (e.now?.() ?? /* @__PURE__ */ new Date()).toISOString(),
|
|
714
|
+
plan: o.plan
|
|
715
|
+
}, { expectedRevision: n.expectedRevision, signal: r });
|
|
716
|
+
},
|
|
717
|
+
read: s.read,
|
|
718
|
+
list: s.list,
|
|
719
|
+
/** Instance edits are explicit snapshots; source business persistence remains the Provider.save responsibility. */
|
|
720
|
+
save: s.save
|
|
721
|
+
};
|
|
833
722
|
}
|
|
834
723
|
export {
|
|
835
|
-
|
|
836
|
-
|
|
724
|
+
w as ReportInstanceError,
|
|
725
|
+
v as ReportJobError,
|
|
726
|
+
A as ReportRuntimeError,
|
|
727
|
+
N as checkInstanceIdentity,
|
|
837
728
|
$ as checkJobIdentity,
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
729
|
+
D as cloneJob,
|
|
730
|
+
Ue as createMemoryReportInstanceStore,
|
|
731
|
+
et as createMemoryReportJobStore,
|
|
732
|
+
Ze as createReportGenerationService,
|
|
733
|
+
Me as createReportInstanceManager,
|
|
734
|
+
Xe as createReportJobService,
|
|
735
|
+
Se as createReportRuntime,
|
|
736
|
+
Qe as createReportTaskQueue,
|
|
737
|
+
We as reportInstanceParameterKey,
|
|
738
|
+
De as reportInstanceSummary,
|
|
843
739
|
Ge as reviewReportPublication,
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
740
|
+
tt as runReportBatch,
|
|
741
|
+
rt as runnableJob,
|
|
742
|
+
I as serializeJobJson,
|
|
743
|
+
st as snapshotReportBatchCases,
|
|
744
|
+
L as snapshotReportInstance,
|
|
745
|
+
nt as validateJobRecord,
|
|
746
|
+
at as validateJobTransition
|
|
848
747
|
};
|