@nhtio/adk 0.1.0-master-e6c58205 → 0.1.0-master-89b47bec
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +94 -0
- package/__vite-browser-external-CU7uua8b.mjs +9 -0
- package/__vite-browser-external-CU7uua8b.mjs.map +1 -0
- package/__vite-browser-external-DAHxjh-D.js +13 -0
- package/__vite-browser-external-DAHxjh-D.js.map +1 -0
- package/batteries/embeddings/openai/adapter.cjs +1 -1
- package/batteries/embeddings/openai/adapter.mjs +1 -1
- package/batteries/embeddings/webllm/adapter.cjs +1 -1
- package/batteries/embeddings/webllm/adapter.mjs +1 -1
- package/batteries/llm/ollama/adapter.cjs +5 -5
- package/batteries/llm/ollama/adapter.mjs +5 -5
- package/batteries/llm/ollama/helpers.cjs +2 -2
- package/batteries/llm/ollama/helpers.mjs +2 -2
- package/batteries/llm/ollama/validation.cjs +1 -1
- package/batteries/llm/ollama/validation.mjs +1 -1
- package/batteries/llm/openai_chat_completions/adapter.cjs +5 -5
- package/batteries/llm/openai_chat_completions/adapter.mjs +5 -5
- package/batteries/llm/openai_chat_completions/helpers.cjs +2 -2
- package/batteries/llm/openai_chat_completions/helpers.mjs +2 -2
- package/batteries/llm/openai_chat_completions/validation.cjs +1 -1
- package/batteries/llm/openai_chat_completions/validation.mjs +1 -1
- package/batteries/llm/webllm_chat_completions/adapter.cjs +5 -5
- package/batteries/llm/webllm_chat_completions/adapter.mjs +5 -5
- package/batteries/llm/webllm_chat_completions/validation.cjs +1 -1
- package/batteries/llm/webllm_chat_completions/validation.mjs +1 -1
- package/batteries/media/contracts.cjs +38 -8
- package/batteries/media/contracts.cjs.map +1 -1
- package/batteries/media/contracts.d.ts +86 -6
- package/batteries/media/contracts.mjs +37 -9
- package/batteries/media/contracts.mjs.map +1 -1
- package/batteries/media/engines/audio_decode.cjs +46 -6
- package/batteries/media/engines/audio_decode.cjs.map +1 -1
- package/batteries/media/engines/audio_decode.d.ts +9 -5
- package/batteries/media/engines/audio_decode.mjs +47 -7
- package/batteries/media/engines/audio_decode.mjs.map +1 -1
- package/batteries/media/engines/data.cjs +159 -0
- package/batteries/media/engines/data.cjs.map +1 -0
- package/batteries/media/engines/data.d.ts +36 -0
- package/batteries/media/engines/data.mjs +157 -0
- package/batteries/media/engines/data.mjs.map +1 -0
- package/batteries/media/engines/exceljs.cjs +290 -0
- package/batteries/media/engines/exceljs.cjs.map +1 -0
- package/batteries/media/engines/exceljs.d.ts +41 -0
- package/batteries/media/engines/exceljs.mjs +288 -0
- package/batteries/media/engines/exceljs.mjs.map +1 -0
- package/batteries/media/engines/execa_executor.cjs +1 -1
- package/batteries/media/engines/execa_executor.mjs +1 -1
- package/batteries/media/engines/fs_workspace.cjs +1 -1
- package/batteries/media/engines/fs_workspace.mjs +1 -1
- package/batteries/media/engines/jimp.cjs +24 -2
- package/batteries/media/engines/jimp.cjs.map +1 -1
- package/batteries/media/engines/jimp.d.ts +3 -1
- package/batteries/media/engines/jimp.mjs +24 -2
- package/batteries/media/engines/jimp.mjs.map +1 -1
- package/batteries/media/engines/sharp.cjs +37 -4
- package/batteries/media/engines/sharp.cjs.map +1 -1
- package/batteries/media/engines/sharp.d.ts +5 -3
- package/batteries/media/engines/sharp.mjs +37 -4
- package/batteries/media/engines/sharp.mjs.map +1 -1
- package/batteries/media/engines/sheetjs.cjs +438 -0
- package/batteries/media/engines/sheetjs.cjs.map +1 -0
- package/batteries/media/engines/sheetjs.d.ts +51 -0
- package/batteries/media/engines/sheetjs.mjs +436 -0
- package/batteries/media/engines/sheetjs.mjs.map +1 -0
- package/batteries/media/engines/soffice.cjs +37 -3
- package/batteries/media/engines/soffice.cjs.map +1 -1
- package/batteries/media/engines/soffice.mjs +38 -4
- package/batteries/media/engines/soffice.mjs.map +1 -1
- package/batteries/media/engines/tesseract_js.cjs +1 -1
- package/batteries/media/engines/tesseract_js.mjs +1 -1
- package/batteries/media/engines/transformers_asr.cjs +1 -1
- package/batteries/media/engines/transformers_asr.mjs +1 -1
- package/batteries/media/forge.cjs +89 -20
- package/batteries/media/forge.cjs.map +1 -1
- package/batteries/media/forge.mjs +89 -20
- package/batteries/media/forge.mjs.map +1 -1
- package/batteries/media/formats.d.ts +9 -0
- package/batteries/media/index.d.ts +8 -6
- package/batteries/media/lint.cjs +270 -58
- package/batteries/media/lint.cjs.map +1 -1
- package/batteries/media/lint.d.ts +45 -0
- package/batteries/media/lint.mjs +267 -58
- package/batteries/media/lint.mjs.map +1 -1
- package/batteries/media/registry.d.ts +11 -2
- package/batteries/media/steps/data.d.ts +26 -0
- package/batteries/media/steps/doc.d.ts +17 -7
- package/batteries/media/steps/patch.d.ts +90 -0
- package/batteries/media/steps/sheet.d.ts +10 -6
- package/batteries/media/steps/text.d.ts +4 -1
- package/batteries/media/validate.d.ts +5 -0
- package/batteries/media/verbs.d.ts +12 -1
- package/batteries/media.cjs +869 -448
- package/batteries/media.cjs.map +1 -1
- package/batteries/media.mjs +829 -409
- package/batteries/media.mjs.map +1 -1
- package/batteries/storage/flydrive.cjs +3 -6
- package/batteries/storage/flydrive.cjs.map +1 -1
- package/batteries/storage/flydrive.mjs +3 -6
- package/batteries/storage/flydrive.mjs.map +1 -1
- package/batteries/storage/in_memory.cjs +1 -1
- package/batteries/storage/in_memory.mjs +1 -1
- package/batteries/storage/opfs.cjs +1 -1
- package/batteries/storage/opfs.mjs +1 -1
- package/batteries/tools/_shared.cjs +2 -2
- package/batteries/tools/_shared.mjs +2 -2
- package/batteries/tools/color.cjs +2 -2
- package/batteries/tools/color.mjs +2 -2
- package/batteries/tools/comparison.cjs +3 -3
- package/batteries/tools/comparison.mjs +3 -3
- package/batteries/tools/data_structure.cjs +3 -3
- package/batteries/tools/data_structure.mjs +3 -3
- package/batteries/tools/datetime_extended.cjs +3 -3
- package/batteries/tools/datetime_extended.mjs +3 -3
- package/batteries/tools/datetime_math.cjs +3 -3
- package/batteries/tools/datetime_math.mjs +3 -3
- package/batteries/tools/encoding.cjs +3 -3
- package/batteries/tools/encoding.mjs +3 -3
- package/batteries/tools/formatting.cjs +3 -3
- package/batteries/tools/formatting.mjs +3 -3
- package/batteries/tools/geo_basics.cjs +2 -2
- package/batteries/tools/geo_basics.mjs +2 -2
- package/batteries/tools/math.cjs +3 -3
- package/batteries/tools/math.mjs +3 -3
- package/batteries/tools/memory.cjs +6 -6
- package/batteries/tools/memory.mjs +6 -6
- package/batteries/tools/parsing.cjs +4 -4
- package/batteries/tools/parsing.mjs +4 -4
- package/batteries/tools/retrievables.cjs +5 -5
- package/batteries/tools/retrievables.mjs +5 -5
- package/batteries/tools/scrapper.cjs +1 -1
- package/batteries/tools/scrapper.mjs +1 -1
- package/batteries/tools/searxng.cjs +1 -1
- package/batteries/tools/searxng.mjs +1 -1
- package/batteries/tools/standing_instructions.cjs +4 -4
- package/batteries/tools/standing_instructions.mjs +4 -4
- package/batteries/tools/statistics.cjs +4 -4
- package/batteries/tools/statistics.mjs +4 -4
- package/batteries/tools/string_processing.cjs +3 -3
- package/batteries/tools/string_processing.mjs +3 -3
- package/batteries/tools/structured_data.cjs +3 -3
- package/batteries/tools/structured_data.mjs +3 -3
- package/batteries/tools/text_analysis.cjs +3 -3
- package/batteries/tools/text_analysis.mjs +3 -3
- package/batteries/tools/text_comparison.cjs +2 -2
- package/batteries/tools/text_comparison.mjs +2 -2
- package/batteries/tools/time.cjs +3 -3
- package/batteries/tools/time.mjs +3 -3
- package/batteries/tools/unit_conversion.cjs +2 -2
- package/batteries/tools/unit_conversion.mjs +2 -2
- package/batteries/tools/web_retrieval.cjs +1 -1
- package/batteries/tools/web_retrieval.mjs +1 -1
- package/batteries/tools.cjs +2 -2
- package/batteries/tools.mjs +2 -2
- package/batteries/vector/arangodb.cjs +1 -1
- package/batteries/vector/arangodb.mjs +1 -1
- package/batteries/vector/clickhouse.cjs +1 -1
- package/batteries/vector/clickhouse.mjs +1 -1
- package/batteries/vector/cloudflare.cjs +1 -1
- package/batteries/vector/cloudflare.mjs +1 -1
- package/batteries/vector/couchbase.cjs +1 -1
- package/batteries/vector/couchbase.mjs +1 -1
- package/batteries/vector/duckdb.cjs +1 -1
- package/batteries/vector/duckdb.mjs +1 -1
- package/batteries/vector/elasticsearch.cjs +1 -1
- package/batteries/vector/elasticsearch.mjs +1 -1
- package/batteries/vector/filters.cjs +1 -1
- package/batteries/vector/filters.mjs +1 -1
- package/batteries/vector/hnswlib.cjs +1 -1
- package/batteries/vector/hnswlib.mjs +1 -1
- package/batteries/vector/lancedb.cjs +1 -1
- package/batteries/vector/lancedb.mjs +1 -1
- package/batteries/vector/mariadb.cjs +1 -1
- package/batteries/vector/mariadb.mjs +1 -1
- package/batteries/vector/meilisearch.cjs +1 -1
- package/batteries/vector/meilisearch.mjs +1 -1
- package/batteries/vector/migrate.cjs +1 -1
- package/batteries/vector/migrate.mjs +1 -1
- package/batteries/vector/mongodb.cjs +1 -1
- package/batteries/vector/mongodb.mjs +1 -1
- package/batteries/vector/neo4j.cjs +1 -1
- package/batteries/vector/neo4j.mjs +1 -1
- package/batteries/vector/opensearch.cjs +1 -1
- package/batteries/vector/opensearch.mjs +1 -1
- package/batteries/vector/oracle23ai.cjs +1 -1
- package/batteries/vector/oracle23ai.mjs +1 -1
- package/batteries/vector/pinecone.cjs +1 -1
- package/batteries/vector/pinecone.mjs +1 -1
- package/batteries/vector/redis.cjs +1 -1
- package/batteries/vector/redis.mjs +1 -1
- package/batteries/vector/retrievable.cjs +1 -1
- package/batteries/vector/retrievable.mjs +1 -1
- package/batteries/vector/s3vectors.cjs +1 -1
- package/batteries/vector/s3vectors.mjs +1 -1
- package/batteries/vector/solr.cjs +1 -1
- package/batteries/vector/solr.mjs +1 -1
- package/batteries/vector/surrealdb.cjs +1 -1
- package/batteries/vector/surrealdb.mjs +1 -1
- package/batteries/vector/typesense.cjs +1 -1
- package/batteries/vector/typesense.mjs +1 -1
- package/batteries/vector/vespa.cjs +1 -1
- package/batteries/vector/vespa.mjs +1 -1
- package/batteries/vector/weaviate.cjs +1 -1
- package/batteries/vector/weaviate.mjs +1 -1
- package/batteries.cjs +2 -2
- package/batteries.mjs +2 -2
- package/bundled_xlsx.d.ts +1075 -0
- package/{common-BxoznqbX.mjs → common-BQoFv108.mjs} +7 -7
- package/{common-BxoznqbX.mjs.map → common-BQoFv108.mjs.map} +1 -1
- package/{common-BBK2e5ro.js → common-DmDn4Gfl.js} +7 -7
- package/{common-BBK2e5ro.js.map → common-DmDn4Gfl.js.map} +1 -1
- package/common.cjs +7 -7
- package/common.mjs +7 -7
- package/{dispatch_runner-Hn5idJYx.js → dispatch_runner-BwplbCPr.js} +3 -3
- package/{dispatch_runner-Hn5idJYx.js.map → dispatch_runner-BwplbCPr.js.map} +1 -1
- package/{dispatch_runner-DUrpj0xR.mjs → dispatch_runner-C1ar_D7W.mjs} +3 -3
- package/{dispatch_runner-DUrpj0xR.mjs.map → dispatch_runner-C1ar_D7W.mjs.map} +1 -1
- package/dispatch_runner.cjs +1 -1
- package/dispatch_runner.mjs +1 -1
- package/eslint.cjs +1 -1
- package/eslint.mjs +1 -1
- package/forge.cjs +4 -4
- package/forge.mjs +4 -4
- package/formats-CCylUHZw.mjs +161 -0
- package/formats-CCylUHZw.mjs.map +1 -0
- package/formats-DZVuqZUN.js +196 -0
- package/formats-DZVuqZUN.js.map +1 -0
- package/guards.cjs +8 -8
- package/guards.mjs +8 -8
- package/index.cjs +11 -11
- package/index.mjs +11 -11
- package/mcp/adk-docs-corpus.json +1 -1
- package/package.json +198 -182
- package/{scrapper-DLj_KkxK.mjs → scrapper-Dn2wXu0Y.mjs} +5 -5
- package/{scrapper-DLj_KkxK.mjs.map → scrapper-Dn2wXu0Y.mjs.map} +1 -1
- package/{scrapper-Cmf1CSA-.js → scrapper-mBZ0Odq7.js} +5 -5
- package/{scrapper-Cmf1CSA-.js.map → scrapper-mBZ0Odq7.js.map} +1 -1
- package/{searxng-BKs5s8Su.js → searxng-Dj-iP_Vz.js} +5 -5
- package/{searxng-BKs5s8Su.js.map → searxng-Dj-iP_Vz.js.map} +1 -1
- package/{searxng-BJ-aZcMz.mjs → searxng-DjFxtFf6.mjs} +5 -5
- package/{searxng-BJ-aZcMz.mjs.map → searxng-DjFxtFf6.mjs.map} +1 -1
- package/server.json +21 -0
- package/skills/adk-assembly/SKILL.md +2 -2
- package/{spooled_artifact-BR0IhU9y.js → spooled_artifact-BCmPrxZS.js} +3 -3
- package/{spooled_artifact-BR0IhU9y.js.map → spooled_artifact-BCmPrxZS.js.map} +1 -1
- package/{spooled_artifact-nTE6ujM8.mjs → spooled_artifact-DL36jnqA.mjs} +3 -3
- package/{spooled_artifact-nTE6ujM8.mjs.map → spooled_artifact-DL36jnqA.mjs.map} +1 -1
- package/spooled_artifact.cjs +2 -2
- package/spooled_artifact.mjs +2 -2
- package/{spooled_markdown_artifact-Dj3fNowz.js → spooled_markdown_artifact-CD4PrrpV.js} +3 -3
- package/{spooled_markdown_artifact-Dj3fNowz.js.map → spooled_markdown_artifact-CD4PrrpV.js.map} +1 -1
- package/{spooled_markdown_artifact-DIYzbQv8.mjs → spooled_markdown_artifact-Da-Xnebh.mjs} +3 -3
- package/{spooled_markdown_artifact-DIYzbQv8.mjs.map → spooled_markdown_artifact-Da-Xnebh.mjs.map} +1 -1
- package/{thought-Cde2Y_GK.mjs → thought-CtOoZUSE.mjs} +3 -3
- package/{thought-Cde2Y_GK.mjs.map → thought-CtOoZUSE.mjs.map} +1 -1
- package/{thought-BFtsnUTU.js → thought-eka4iUHa.js} +3 -3
- package/{thought-BFtsnUTU.js.map → thought-eka4iUHa.js.map} +1 -1
- package/{tool-CcxYxA5X.mjs → tool-CITF20yJ.mjs} +3 -3
- package/{tool-CcxYxA5X.mjs.map → tool-CITF20yJ.mjs.map} +1 -1
- package/{tool-B2nnkwNU.js → tool-Dhjca7rC.js} +3 -3
- package/{tool-B2nnkwNU.js.map → tool-Dhjca7rC.js.map} +1 -1
- package/{tool_call-BxL3eU1k.js → tool_call-Cyi0hUUc.js} +4 -4
- package/{tool_call-BxL3eU1k.js.map → tool_call-Cyi0hUUc.js.map} +1 -1
- package/{tool_call-B3MOog2R.mjs → tool_call-D_k36aI4.mjs} +4 -4
- package/{tool_call-B3MOog2R.mjs.map → tool_call-D_k36aI4.mjs.map} +1 -1
- package/{tool_registry-BaLUIzWz.mjs → tool_registry-CZ55mIti.mjs} +152 -143
- package/tool_registry-CZ55mIti.mjs.map +1 -0
- package/{tool_registry-BdKlPuHS.js → tool_registry-DwZ6pzN4.js} +151 -142
- package/tool_registry-DwZ6pzN4.js.map +1 -0
- package/{turn_runner-M2I8G2ok.js → turn_runner-CCZcsoDU.js} +5 -5
- package/{turn_runner-M2I8G2ok.js.map → turn_runner-CCZcsoDU.js.map} +1 -1
- package/{turn_runner-BV4BaZK9.mjs → turn_runner-DRPpVvsd.mjs} +5 -5
- package/{turn_runner-BV4BaZK9.mjs.map → turn_runner-DRPpVvsd.mjs.map} +1 -1
- package/turn_runner.cjs +1 -1
- package/turn_runner.mjs +1 -1
- package/{validate-JOHfh-BB.mjs → validate-C_hTnDBE.mjs} +95 -8
- package/validate-C_hTnDBE.mjs.map +1 -0
- package/{validate-DgDZkUKs.js → validate-gaSa9bsk.js} +95 -8
- package/validate-gaSa9bsk.js.map +1 -0
- package/xlsx-B0sTpEC2.js +30615 -0
- package/xlsx-B0sTpEC2.js.map +1 -0
- package/xlsx-DiMpn_Xv.mjs +30596 -0
- package/xlsx-DiMpn_Xv.mjs.map +1 -0
- package/xlsx.zahl-D2_Q-Xs4.mjs +6 -0
- package/xlsx.zahl-D2_Q-Xs4.mjs.map +1 -0
- package/xlsx.zahl-ZIcUQVv8.js +7 -0
- package/xlsx.zahl-ZIcUQVv8.js.map +1 -0
- package/tool_registry-BaLUIzWz.mjs.map +0 -1
- package/tool_registry-BdKlPuHS.js.map +0 -1
- package/validate-DgDZkUKs.js.map +0 -1
- package/validate-JOHfh-BB.mjs.map +0 -1
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("../../../chunk-Cek0wNdY.js");
|
|
3
|
+
const require_tool_registry = require("../../../tool_registry-DwZ6pzN4.js");
|
|
4
|
+
require("../../../guards.cjs");
|
|
5
|
+
const require_batteries_media_contracts = require("../contracts.cjs");
|
|
6
|
+
const require_exceptions = require("../../../exceptions-D79HIKeX.js");
|
|
7
|
+
const require_formats = require("../../../formats-DZVuqZUN.js");
|
|
8
|
+
//#region src/batteries/media/engines/data.ts
|
|
9
|
+
/**
|
|
10
|
+
* The deterministic text/data {@link @nhtio/adk/batteries/media/contracts!MediaEngine}:
|
|
11
|
+
* seeds and conversions for the text-shaped family (txt/md/json/yaml/csv/html).
|
|
12
|
+
*
|
|
13
|
+
* @module @nhtio/adk/batteries/media/engines/data
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* The smallest engine in the fleet, and deliberately so: text-family media generation is a
|
|
17
|
+
* literal (`''`, `'{}'`, a minimal HTML shell) and text-family conversion is a parse and a
|
|
18
|
+
* re-serialize. Everything here is deterministic — same inputs, same bytes — and cross-env
|
|
19
|
+
* (no `node:*` anywhere).
|
|
20
|
+
*
|
|
21
|
+
* Capabilities:
|
|
22
|
+
*
|
|
23
|
+
* - **generate**: `EMPTY_MIME` → txt, md, json, yaml, csv, html.
|
|
24
|
+
* - **convert**: json ⇄ yaml (js-yaml), json ⇄ csv (papaparse), json → txt (pretty print).
|
|
25
|
+
*
|
|
26
|
+
* `papaparse` is an optional peer (lazily imported only for the csv edges); `js-yaml` is a
|
|
27
|
+
* regular dependency of the library.
|
|
28
|
+
*/
|
|
29
|
+
/** Literal seeds per generation target. */
|
|
30
|
+
var SEEDS = {
|
|
31
|
+
txt: {
|
|
32
|
+
content: "",
|
|
33
|
+
mimeType: require_formats.MIME.TXT
|
|
34
|
+
},
|
|
35
|
+
md: {
|
|
36
|
+
content: "",
|
|
37
|
+
mimeType: require_formats.MIME.MD
|
|
38
|
+
},
|
|
39
|
+
json: {
|
|
40
|
+
content: "{}",
|
|
41
|
+
mimeType: require_formats.MIME.JSON
|
|
42
|
+
},
|
|
43
|
+
yaml: {
|
|
44
|
+
content: "",
|
|
45
|
+
mimeType: require_formats.MIME.YAML
|
|
46
|
+
},
|
|
47
|
+
csv: {
|
|
48
|
+
content: "",
|
|
49
|
+
mimeType: require_formats.MIME.CSV
|
|
50
|
+
},
|
|
51
|
+
html: {
|
|
52
|
+
content: "<!doctype html>\n<html>\n<head><meta charset=\"utf-8\"></head>\n<body></body>\n</html>\n",
|
|
53
|
+
mimeType: require_formats.MIME.HTML
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
var encoder = new TextEncoder();
|
|
57
|
+
var decoder = new TextDecoder();
|
|
58
|
+
/**
|
|
59
|
+
* Construct the deterministic text/data engine.
|
|
60
|
+
*
|
|
61
|
+
* @param options - Optional module resolver override.
|
|
62
|
+
* @returns The engine.
|
|
63
|
+
*/
|
|
64
|
+
var dataEngine = (options = {}) => {
|
|
65
|
+
let papaPromise;
|
|
66
|
+
const getPapa = () => {
|
|
67
|
+
papaPromise ??= Promise.resolve(options.papaparse ? options.papaparse() : import("papaparse").then((m) => "default" in m ? m.default : m)).catch((err) => {
|
|
68
|
+
throw new require_exceptions.E_INVALID_MEDIA_PIPELINE_CONFIG([`the data engine could not load its peer dependency "papaparse" (needed for csv conversion): ${require_tool_registry.isError(err) ? err.message : String(err)} — install it (pnpm add papaparse)`]);
|
|
69
|
+
});
|
|
70
|
+
return papaPromise;
|
|
71
|
+
};
|
|
72
|
+
const generate = async (request) => {
|
|
73
|
+
const seed = SEEDS[request.to];
|
|
74
|
+
if (!seed) throw new Error(`the data engine generates ${Object.keys(SEEDS).join(", ")}; requested "${request.to}"`);
|
|
75
|
+
return { outputs: [{
|
|
76
|
+
bytes: encoder.encode(seed.content),
|
|
77
|
+
mimeType: seed.mimeType
|
|
78
|
+
}] };
|
|
79
|
+
};
|
|
80
|
+
const convert = async (request) => {
|
|
81
|
+
const mime = request.mimeType.toLowerCase().split(";")[0].trim();
|
|
82
|
+
const text = decoder.decode(request.bytes);
|
|
83
|
+
if (mime === require_formats.MIME.JSON && request.to === "yaml") {
|
|
84
|
+
const { dump } = await import("js-yaml");
|
|
85
|
+
const value = JSON.parse(text);
|
|
86
|
+
return { outputs: [{
|
|
87
|
+
bytes: encoder.encode(dump(value)),
|
|
88
|
+
mimeType: require_formats.MIME.YAML
|
|
89
|
+
}] };
|
|
90
|
+
}
|
|
91
|
+
if (mime === require_formats.MIME.JSON && request.to === "txt") {
|
|
92
|
+
const value = JSON.parse(text);
|
|
93
|
+
return { outputs: [{
|
|
94
|
+
bytes: encoder.encode(JSON.stringify(value, null, 2)),
|
|
95
|
+
mimeType: require_formats.MIME.TXT
|
|
96
|
+
}] };
|
|
97
|
+
}
|
|
98
|
+
if (mime === require_formats.MIME.JSON && request.to === "csv") {
|
|
99
|
+
const Papa = await getPapa();
|
|
100
|
+
const value = JSON.parse(text);
|
|
101
|
+
if (!Array.isArray(value)) throw new Error("json → csv expects a JSON array (of arrays, or of flat objects) at the top level");
|
|
102
|
+
const csv = Papa.unparse(value);
|
|
103
|
+
return { outputs: [{
|
|
104
|
+
bytes: encoder.encode(csv),
|
|
105
|
+
mimeType: require_formats.MIME.CSV
|
|
106
|
+
}] };
|
|
107
|
+
}
|
|
108
|
+
if (mime === require_formats.MIME.YAML && request.to === "json") {
|
|
109
|
+
const { load } = await import("js-yaml");
|
|
110
|
+
const value = load(text);
|
|
111
|
+
return { outputs: [{
|
|
112
|
+
bytes: encoder.encode(JSON.stringify(value ?? null)),
|
|
113
|
+
mimeType: require_formats.MIME.JSON
|
|
114
|
+
}] };
|
|
115
|
+
}
|
|
116
|
+
if (mime === require_formats.MIME.CSV && request.to === "json") {
|
|
117
|
+
const parsed = (await getPapa()).parse(text.replace(/\r\n/g, "\n").replace(/\n+$/, ""), { skipEmptyLines: true });
|
|
118
|
+
if (parsed.errors.length > 0) throw new Error(`csv parse failed: ${parsed.errors[0].message}`);
|
|
119
|
+
return { outputs: [{
|
|
120
|
+
bytes: encoder.encode(JSON.stringify(parsed.data)),
|
|
121
|
+
mimeType: require_formats.MIME.JSON
|
|
122
|
+
}] };
|
|
123
|
+
}
|
|
124
|
+
throw new Error(`the data engine cannot convert ${request.mimeType} to "${request.to}"`);
|
|
125
|
+
};
|
|
126
|
+
return {
|
|
127
|
+
id: "data",
|
|
128
|
+
converts: [
|
|
129
|
+
{
|
|
130
|
+
from: [require_batteries_media_contracts.EMPTY_MIME],
|
|
131
|
+
to: Object.keys(SEEDS),
|
|
132
|
+
convert: generate
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
from: [require_formats.MIME.JSON],
|
|
136
|
+
to: [
|
|
137
|
+
"yaml",
|
|
138
|
+
"txt",
|
|
139
|
+
"csv"
|
|
140
|
+
],
|
|
141
|
+
convert
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
from: [require_formats.MIME.YAML],
|
|
145
|
+
to: ["json"],
|
|
146
|
+
convert
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
from: [require_formats.MIME.CSV],
|
|
150
|
+
to: ["json"],
|
|
151
|
+
convert
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
//#endregion
|
|
157
|
+
exports.dataEngine = dataEngine;
|
|
158
|
+
|
|
159
|
+
//# sourceMappingURL=data.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.cjs","names":[],"sources":["../../../../src/batteries/media/engines/data.ts"],"sourcesContent":["/**\n * The deterministic text/data {@link @nhtio/adk/batteries/media/contracts!MediaEngine}:\n * seeds and conversions for the text-shaped family (txt/md/json/yaml/csv/html).\n *\n * @module @nhtio/adk/batteries/media/engines/data\n *\n * @remarks\n * The smallest engine in the fleet, and deliberately so: text-family media generation is a\n * literal (`''`, `'{}'`, a minimal HTML shell) and text-family conversion is a parse and a\n * re-serialize. Everything here is deterministic — same inputs, same bytes — and cross-env\n * (no `node:*` anywhere).\n *\n * Capabilities:\n *\n * - **generate**: `EMPTY_MIME` → txt, md, json, yaml, csv, html.\n * - **convert**: json ⇄ yaml (js-yaml), json ⇄ csv (papaparse), json → txt (pretty print).\n *\n * `papaparse` is an optional peer (lazily imported only for the csv edges); `js-yaml` is a\n * regular dependency of the library.\n */\n\nimport { MIME } from '../formats'\nimport { EMPTY_MIME } from '../contracts'\nimport { isError } from '@nhtio/adk/guards'\nimport { E_INVALID_MEDIA_PIPELINE_CONFIG } from '../exceptions'\nimport type * as PapaNS from 'papaparse'\nimport type { MediaEngine, ConvertRequest, ConvertResult } from '../contracts'\n\ntype PapaModule = typeof PapaNS\n\n/** Options for {@link dataEngine}. */\nexport interface DataEngineOptions {\n /** Override the papaparse resolution (tests / custom builds). Default: `import('papaparse')`. */\n papaparse?: () => PapaModule | Promise<PapaModule>\n}\n\n/** Literal seeds per generation target. */\nconst SEEDS: Record<string, { content: string; mimeType: string }> = {\n txt: { content: '', mimeType: MIME.TXT },\n md: { content: '', mimeType: MIME.MD },\n json: { content: '{}', mimeType: MIME.JSON },\n yaml: { content: '', mimeType: MIME.YAML },\n csv: { content: '', mimeType: MIME.CSV },\n html: {\n content:\n '<!doctype html>\\n<html>\\n<head><meta charset=\"utf-8\"></head>\\n<body></body>\\n</html>\\n',\n mimeType: MIME.HTML,\n },\n}\n\nconst encoder = new TextEncoder()\nconst decoder = new TextDecoder()\n\n/**\n * Construct the deterministic text/data engine.\n *\n * @param options - Optional module resolver override.\n * @returns The engine.\n */\nexport const dataEngine = (options: DataEngineOptions = {}): MediaEngine => {\n let papaPromise: Promise<PapaModule> | undefined\n const getPapa = (): Promise<PapaModule> => {\n papaPromise ??= Promise.resolve(\n options.papaparse\n ? options.papaparse()\n : import('papaparse').then((m) => ('default' in m ? m.default : m) as PapaModule)\n ).catch((err) => {\n const detail = isError(err) ? err.message : String(err)\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n `the data engine could not load its peer dependency \"papaparse\" (needed for csv conversion): ${detail} — install it (pnpm add papaparse)`,\n ])\n })\n return papaPromise\n }\n\n const generate = async (request: ConvertRequest): Promise<ConvertResult> => {\n const seed = SEEDS[request.to]\n if (!seed) {\n throw new Error(\n `the data engine generates ${Object.keys(SEEDS).join(', ')}; requested \"${request.to}\"`\n )\n }\n return {\n outputs: [{ bytes: encoder.encode(seed.content), mimeType: seed.mimeType }],\n }\n }\n\n const convert = async (request: ConvertRequest): Promise<ConvertResult> => {\n const mime = request.mimeType.toLowerCase().split(';')[0].trim()\n const text = decoder.decode(request.bytes)\n\n if (mime === MIME.JSON && request.to === 'yaml') {\n const { dump } = await import('js-yaml')\n const value: unknown = JSON.parse(text)\n return {\n outputs: [{ bytes: encoder.encode(dump(value)), mimeType: MIME.YAML }],\n }\n }\n if (mime === MIME.JSON && request.to === 'txt') {\n const value: unknown = JSON.parse(text)\n return {\n outputs: [{ bytes: encoder.encode(JSON.stringify(value, null, 2)), mimeType: MIME.TXT }],\n }\n }\n if (mime === MIME.JSON && request.to === 'csv') {\n const Papa = await getPapa()\n const value: unknown = JSON.parse(text)\n if (!Array.isArray(value)) {\n throw new Error(\n 'json → csv expects a JSON array (of arrays, or of flat objects) at the top level'\n )\n }\n const csv = Papa.unparse(value as unknown[])\n return { outputs: [{ bytes: encoder.encode(csv), mimeType: MIME.CSV }] }\n }\n if (mime === MIME.YAML && request.to === 'json') {\n const { load } = await import('js-yaml')\n const value = load(text)\n return {\n outputs: [{ bytes: encoder.encode(JSON.stringify(value ?? null)), mimeType: MIME.JSON }],\n }\n }\n if (mime === MIME.CSV && request.to === 'json') {\n const Papa = await getPapa()\n const parsed = Papa.parse<string[]>(text.replace(/\\r\\n/g, '\\n').replace(/\\n+$/, ''), {\n skipEmptyLines: true,\n })\n if (parsed.errors.length > 0) {\n throw new Error(`csv parse failed: ${parsed.errors[0].message}`)\n }\n // Array-of-arrays, matching the battery's json table shape (soffice/sheetjs emit it too).\n return {\n outputs: [{ bytes: encoder.encode(JSON.stringify(parsed.data)), mimeType: MIME.JSON }],\n }\n }\n throw new Error(`the data engine cannot convert ${request.mimeType} to \"${request.to}\"`)\n }\n\n return {\n id: 'data',\n converts: [\n { from: [EMPTY_MIME], to: Object.keys(SEEDS), convert: generate },\n { from: [MIME.JSON], to: ['yaml', 'txt', 'csv'], convert },\n { from: [MIME.YAML], to: ['json'], convert },\n { from: [MIME.CSV], to: ['json'], convert },\n ],\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The deterministic text/data {@link @nhtio/adk/batteries/media/contracts!MediaEngine}:
|
|
3
|
+
* seeds and conversions for the text-shaped family (txt/md/json/yaml/csv/html).
|
|
4
|
+
*
|
|
5
|
+
* @module @nhtio/adk/batteries/media/engines/data
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* The smallest engine in the fleet, and deliberately so: text-family media generation is a
|
|
9
|
+
* literal (`''`, `'{}'`, a minimal HTML shell) and text-family conversion is a parse and a
|
|
10
|
+
* re-serialize. Everything here is deterministic — same inputs, same bytes — and cross-env
|
|
11
|
+
* (no `node:*` anywhere).
|
|
12
|
+
*
|
|
13
|
+
* Capabilities:
|
|
14
|
+
*
|
|
15
|
+
* - **generate**: `EMPTY_MIME` → txt, md, json, yaml, csv, html.
|
|
16
|
+
* - **convert**: json ⇄ yaml (js-yaml), json ⇄ csv (papaparse), json → txt (pretty print).
|
|
17
|
+
*
|
|
18
|
+
* `papaparse` is an optional peer (lazily imported only for the csv edges); `js-yaml` is a
|
|
19
|
+
* regular dependency of the library.
|
|
20
|
+
*/
|
|
21
|
+
import type * as PapaNS from 'papaparse';
|
|
22
|
+
import type { MediaEngine } from "../contracts";
|
|
23
|
+
type PapaModule = typeof PapaNS;
|
|
24
|
+
/** Options for {@link dataEngine}. */
|
|
25
|
+
export interface DataEngineOptions {
|
|
26
|
+
/** Override the papaparse resolution (tests / custom builds). Default: `import('papaparse')`. */
|
|
27
|
+
papaparse?: () => PapaModule | Promise<PapaModule>;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Construct the deterministic text/data engine.
|
|
31
|
+
*
|
|
32
|
+
* @param options - Optional module resolver override.
|
|
33
|
+
* @returns The engine.
|
|
34
|
+
*/
|
|
35
|
+
export declare const dataEngine: (options?: DataEngineOptions) => MediaEngine;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { o as isError } from "../../../tool_registry-CZ55mIti.mjs";
|
|
2
|
+
import "../../../guards.mjs";
|
|
3
|
+
import { EMPTY_MIME } from "../contracts.mjs";
|
|
4
|
+
import { t as E_INVALID_MEDIA_PIPELINE_CONFIG } from "../../../exceptions-BLTn4Ofs.mjs";
|
|
5
|
+
import { n as MIME } from "../../../formats-CCylUHZw.mjs";
|
|
6
|
+
//#region src/batteries/media/engines/data.ts
|
|
7
|
+
/**
|
|
8
|
+
* The deterministic text/data {@link @nhtio/adk/batteries/media/contracts!MediaEngine}:
|
|
9
|
+
* seeds and conversions for the text-shaped family (txt/md/json/yaml/csv/html).
|
|
10
|
+
*
|
|
11
|
+
* @module @nhtio/adk/batteries/media/engines/data
|
|
12
|
+
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* The smallest engine in the fleet, and deliberately so: text-family media generation is a
|
|
15
|
+
* literal (`''`, `'{}'`, a minimal HTML shell) and text-family conversion is a parse and a
|
|
16
|
+
* re-serialize. Everything here is deterministic — same inputs, same bytes — and cross-env
|
|
17
|
+
* (no `node:*` anywhere).
|
|
18
|
+
*
|
|
19
|
+
* Capabilities:
|
|
20
|
+
*
|
|
21
|
+
* - **generate**: `EMPTY_MIME` → txt, md, json, yaml, csv, html.
|
|
22
|
+
* - **convert**: json ⇄ yaml (js-yaml), json ⇄ csv (papaparse), json → txt (pretty print).
|
|
23
|
+
*
|
|
24
|
+
* `papaparse` is an optional peer (lazily imported only for the csv edges); `js-yaml` is a
|
|
25
|
+
* regular dependency of the library.
|
|
26
|
+
*/
|
|
27
|
+
/** Literal seeds per generation target. */
|
|
28
|
+
var SEEDS = {
|
|
29
|
+
txt: {
|
|
30
|
+
content: "",
|
|
31
|
+
mimeType: MIME.TXT
|
|
32
|
+
},
|
|
33
|
+
md: {
|
|
34
|
+
content: "",
|
|
35
|
+
mimeType: MIME.MD
|
|
36
|
+
},
|
|
37
|
+
json: {
|
|
38
|
+
content: "{}",
|
|
39
|
+
mimeType: MIME.JSON
|
|
40
|
+
},
|
|
41
|
+
yaml: {
|
|
42
|
+
content: "",
|
|
43
|
+
mimeType: MIME.YAML
|
|
44
|
+
},
|
|
45
|
+
csv: {
|
|
46
|
+
content: "",
|
|
47
|
+
mimeType: MIME.CSV
|
|
48
|
+
},
|
|
49
|
+
html: {
|
|
50
|
+
content: "<!doctype html>\n<html>\n<head><meta charset=\"utf-8\"></head>\n<body></body>\n</html>\n",
|
|
51
|
+
mimeType: MIME.HTML
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var encoder = new TextEncoder();
|
|
55
|
+
var decoder = new TextDecoder();
|
|
56
|
+
/**
|
|
57
|
+
* Construct the deterministic text/data engine.
|
|
58
|
+
*
|
|
59
|
+
* @param options - Optional module resolver override.
|
|
60
|
+
* @returns The engine.
|
|
61
|
+
*/
|
|
62
|
+
var dataEngine = (options = {}) => {
|
|
63
|
+
let papaPromise;
|
|
64
|
+
const getPapa = () => {
|
|
65
|
+
papaPromise ??= Promise.resolve(options.papaparse ? options.papaparse() : import("papaparse").then((m) => "default" in m ? m.default : m)).catch((err) => {
|
|
66
|
+
throw new E_INVALID_MEDIA_PIPELINE_CONFIG([`the data engine could not load its peer dependency "papaparse" (needed for csv conversion): ${isError(err) ? err.message : String(err)} — install it (pnpm add papaparse)`]);
|
|
67
|
+
});
|
|
68
|
+
return papaPromise;
|
|
69
|
+
};
|
|
70
|
+
const generate = async (request) => {
|
|
71
|
+
const seed = SEEDS[request.to];
|
|
72
|
+
if (!seed) throw new Error(`the data engine generates ${Object.keys(SEEDS).join(", ")}; requested "${request.to}"`);
|
|
73
|
+
return { outputs: [{
|
|
74
|
+
bytes: encoder.encode(seed.content),
|
|
75
|
+
mimeType: seed.mimeType
|
|
76
|
+
}] };
|
|
77
|
+
};
|
|
78
|
+
const convert = async (request) => {
|
|
79
|
+
const mime = request.mimeType.toLowerCase().split(";")[0].trim();
|
|
80
|
+
const text = decoder.decode(request.bytes);
|
|
81
|
+
if (mime === MIME.JSON && request.to === "yaml") {
|
|
82
|
+
const { dump } = await import("js-yaml");
|
|
83
|
+
const value = JSON.parse(text);
|
|
84
|
+
return { outputs: [{
|
|
85
|
+
bytes: encoder.encode(dump(value)),
|
|
86
|
+
mimeType: MIME.YAML
|
|
87
|
+
}] };
|
|
88
|
+
}
|
|
89
|
+
if (mime === MIME.JSON && request.to === "txt") {
|
|
90
|
+
const value = JSON.parse(text);
|
|
91
|
+
return { outputs: [{
|
|
92
|
+
bytes: encoder.encode(JSON.stringify(value, null, 2)),
|
|
93
|
+
mimeType: MIME.TXT
|
|
94
|
+
}] };
|
|
95
|
+
}
|
|
96
|
+
if (mime === MIME.JSON && request.to === "csv") {
|
|
97
|
+
const Papa = await getPapa();
|
|
98
|
+
const value = JSON.parse(text);
|
|
99
|
+
if (!Array.isArray(value)) throw new Error("json → csv expects a JSON array (of arrays, or of flat objects) at the top level");
|
|
100
|
+
const csv = Papa.unparse(value);
|
|
101
|
+
return { outputs: [{
|
|
102
|
+
bytes: encoder.encode(csv),
|
|
103
|
+
mimeType: MIME.CSV
|
|
104
|
+
}] };
|
|
105
|
+
}
|
|
106
|
+
if (mime === MIME.YAML && request.to === "json") {
|
|
107
|
+
const { load } = await import("js-yaml");
|
|
108
|
+
const value = load(text);
|
|
109
|
+
return { outputs: [{
|
|
110
|
+
bytes: encoder.encode(JSON.stringify(value ?? null)),
|
|
111
|
+
mimeType: MIME.JSON
|
|
112
|
+
}] };
|
|
113
|
+
}
|
|
114
|
+
if (mime === MIME.CSV && request.to === "json") {
|
|
115
|
+
const parsed = (await getPapa()).parse(text.replace(/\r\n/g, "\n").replace(/\n+$/, ""), { skipEmptyLines: true });
|
|
116
|
+
if (parsed.errors.length > 0) throw new Error(`csv parse failed: ${parsed.errors[0].message}`);
|
|
117
|
+
return { outputs: [{
|
|
118
|
+
bytes: encoder.encode(JSON.stringify(parsed.data)),
|
|
119
|
+
mimeType: MIME.JSON
|
|
120
|
+
}] };
|
|
121
|
+
}
|
|
122
|
+
throw new Error(`the data engine cannot convert ${request.mimeType} to "${request.to}"`);
|
|
123
|
+
};
|
|
124
|
+
return {
|
|
125
|
+
id: "data",
|
|
126
|
+
converts: [
|
|
127
|
+
{
|
|
128
|
+
from: [EMPTY_MIME],
|
|
129
|
+
to: Object.keys(SEEDS),
|
|
130
|
+
convert: generate
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
from: [MIME.JSON],
|
|
134
|
+
to: [
|
|
135
|
+
"yaml",
|
|
136
|
+
"txt",
|
|
137
|
+
"csv"
|
|
138
|
+
],
|
|
139
|
+
convert
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
from: [MIME.YAML],
|
|
143
|
+
to: ["json"],
|
|
144
|
+
convert
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
from: [MIME.CSV],
|
|
148
|
+
to: ["json"],
|
|
149
|
+
convert
|
|
150
|
+
}
|
|
151
|
+
]
|
|
152
|
+
};
|
|
153
|
+
};
|
|
154
|
+
//#endregion
|
|
155
|
+
export { dataEngine };
|
|
156
|
+
|
|
157
|
+
//# sourceMappingURL=data.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.mjs","names":[],"sources":["../../../../src/batteries/media/engines/data.ts"],"sourcesContent":["/**\n * The deterministic text/data {@link @nhtio/adk/batteries/media/contracts!MediaEngine}:\n * seeds and conversions for the text-shaped family (txt/md/json/yaml/csv/html).\n *\n * @module @nhtio/adk/batteries/media/engines/data\n *\n * @remarks\n * The smallest engine in the fleet, and deliberately so: text-family media generation is a\n * literal (`''`, `'{}'`, a minimal HTML shell) and text-family conversion is a parse and a\n * re-serialize. Everything here is deterministic — same inputs, same bytes — and cross-env\n * (no `node:*` anywhere).\n *\n * Capabilities:\n *\n * - **generate**: `EMPTY_MIME` → txt, md, json, yaml, csv, html.\n * - **convert**: json ⇄ yaml (js-yaml), json ⇄ csv (papaparse), json → txt (pretty print).\n *\n * `papaparse` is an optional peer (lazily imported only for the csv edges); `js-yaml` is a\n * regular dependency of the library.\n */\n\nimport { MIME } from '../formats'\nimport { EMPTY_MIME } from '../contracts'\nimport { isError } from '@nhtio/adk/guards'\nimport { E_INVALID_MEDIA_PIPELINE_CONFIG } from '../exceptions'\nimport type * as PapaNS from 'papaparse'\nimport type { MediaEngine, ConvertRequest, ConvertResult } from '../contracts'\n\ntype PapaModule = typeof PapaNS\n\n/** Options for {@link dataEngine}. */\nexport interface DataEngineOptions {\n /** Override the papaparse resolution (tests / custom builds). Default: `import('papaparse')`. */\n papaparse?: () => PapaModule | Promise<PapaModule>\n}\n\n/** Literal seeds per generation target. */\nconst SEEDS: Record<string, { content: string; mimeType: string }> = {\n txt: { content: '', mimeType: MIME.TXT },\n md: { content: '', mimeType: MIME.MD },\n json: { content: '{}', mimeType: MIME.JSON },\n yaml: { content: '', mimeType: MIME.YAML },\n csv: { content: '', mimeType: MIME.CSV },\n html: {\n content:\n '<!doctype html>\\n<html>\\n<head><meta charset=\"utf-8\"></head>\\n<body></body>\\n</html>\\n',\n mimeType: MIME.HTML,\n },\n}\n\nconst encoder = new TextEncoder()\nconst decoder = new TextDecoder()\n\n/**\n * Construct the deterministic text/data engine.\n *\n * @param options - Optional module resolver override.\n * @returns The engine.\n */\nexport const dataEngine = (options: DataEngineOptions = {}): MediaEngine => {\n let papaPromise: Promise<PapaModule> | undefined\n const getPapa = (): Promise<PapaModule> => {\n papaPromise ??= Promise.resolve(\n options.papaparse\n ? options.papaparse()\n : import('papaparse').then((m) => ('default' in m ? m.default : m) as PapaModule)\n ).catch((err) => {\n const detail = isError(err) ? err.message : String(err)\n throw new E_INVALID_MEDIA_PIPELINE_CONFIG([\n `the data engine could not load its peer dependency \"papaparse\" (needed for csv conversion): ${detail} — install it (pnpm add papaparse)`,\n ])\n })\n return papaPromise\n }\n\n const generate = async (request: ConvertRequest): Promise<ConvertResult> => {\n const seed = SEEDS[request.to]\n if (!seed) {\n throw new Error(\n `the data engine generates ${Object.keys(SEEDS).join(', ')}; requested \"${request.to}\"`\n )\n }\n return {\n outputs: [{ bytes: encoder.encode(seed.content), mimeType: seed.mimeType }],\n }\n }\n\n const convert = async (request: ConvertRequest): Promise<ConvertResult> => {\n const mime = request.mimeType.toLowerCase().split(';')[0].trim()\n const text = decoder.decode(request.bytes)\n\n if (mime === MIME.JSON && request.to === 'yaml') {\n const { dump } = await import('js-yaml')\n const value: unknown = JSON.parse(text)\n return {\n outputs: [{ bytes: encoder.encode(dump(value)), mimeType: MIME.YAML }],\n }\n }\n if (mime === MIME.JSON && request.to === 'txt') {\n const value: unknown = JSON.parse(text)\n return {\n outputs: [{ bytes: encoder.encode(JSON.stringify(value, null, 2)), mimeType: MIME.TXT }],\n }\n }\n if (mime === MIME.JSON && request.to === 'csv') {\n const Papa = await getPapa()\n const value: unknown = JSON.parse(text)\n if (!Array.isArray(value)) {\n throw new Error(\n 'json → csv expects a JSON array (of arrays, or of flat objects) at the top level'\n )\n }\n const csv = Papa.unparse(value as unknown[])\n return { outputs: [{ bytes: encoder.encode(csv), mimeType: MIME.CSV }] }\n }\n if (mime === MIME.YAML && request.to === 'json') {\n const { load } = await import('js-yaml')\n const value = load(text)\n return {\n outputs: [{ bytes: encoder.encode(JSON.stringify(value ?? null)), mimeType: MIME.JSON }],\n }\n }\n if (mime === MIME.CSV && request.to === 'json') {\n const Papa = await getPapa()\n const parsed = Papa.parse<string[]>(text.replace(/\\r\\n/g, '\\n').replace(/\\n+$/, ''), {\n skipEmptyLines: true,\n })\n if (parsed.errors.length > 0) {\n throw new Error(`csv parse failed: ${parsed.errors[0].message}`)\n }\n // Array-of-arrays, matching the battery's json table shape (soffice/sheetjs emit it too).\n return {\n outputs: [{ bytes: encoder.encode(JSON.stringify(parsed.data)), mimeType: MIME.JSON }],\n }\n }\n throw new Error(`the data engine cannot convert ${request.mimeType} to \"${request.to}\"`)\n }\n\n return {\n id: 'data',\n converts: [\n { from: [EMPTY_MIME], to: Object.keys(SEEDS), convert: generate },\n { from: [MIME.JSON], to: ['yaml', 'txt', 'csv'], convert },\n { from: [MIME.YAML], to: ['json'], convert },\n { from: [MIME.CSV], to: ['json'], convert },\n ],\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,IAAM,QAA+D;CACnE,KAAK;EAAE,SAAS;EAAI,UAAU,KAAK;CAAI;CACvC,IAAI;EAAE,SAAS;EAAI,UAAU,KAAK;CAAG;CACrC,MAAM;EAAE,SAAS;EAAM,UAAU,KAAK;CAAK;CAC3C,MAAM;EAAE,SAAS;EAAI,UAAU,KAAK;CAAK;CACzC,KAAK;EAAE,SAAS;EAAI,UAAU,KAAK;CAAI;CACvC,MAAM;EACJ,SACE;EACF,UAAU,KAAK;CACjB;AACF;AAEA,IAAM,UAAU,IAAI,YAAY;AAChC,IAAM,UAAU,IAAI,YAAY;;;;;;;AAQhC,IAAa,cAAc,UAA6B,CAAC,MAAmB;CAC1E,IAAI;CACJ,MAAM,gBAAqC;EACzC,gBAAgB,QAAQ,QACtB,QAAQ,YACJ,QAAQ,UAAU,IAClB,OAAO,aAAa,MAAM,MAAO,aAAa,IAAI,EAAE,UAAU,CAAgB,CACpF,EAAE,OAAO,QAAQ;GAEf,MAAM,IAAI,gCAAgC,CACxC,+FAFa,QAAQ,GAAG,IAAI,IAAI,UAAU,OAAO,GAAG,EAEkD,mCACxG,CAAC;EACH,CAAC;EACD,OAAO;CACT;CAEA,MAAM,WAAW,OAAO,YAAoD;EAC1E,MAAM,OAAO,MAAM,QAAQ;EAC3B,IAAI,CAAC,MACH,MAAM,IAAI,MACR,6BAA6B,OAAO,KAAK,KAAK,EAAE,KAAK,IAAI,EAAE,eAAe,QAAQ,GAAG,EACvF;EAEF,OAAO,EACL,SAAS,CAAC;GAAE,OAAO,QAAQ,OAAO,KAAK,OAAO;GAAG,UAAU,KAAK;EAAS,CAAC,EAC5E;CACF;CAEA,MAAM,UAAU,OAAO,YAAoD;EACzE,MAAM,OAAO,QAAQ,SAAS,YAAY,EAAE,MAAM,GAAG,EAAE,GAAG,KAAK;EAC/D,MAAM,OAAO,QAAQ,OAAO,QAAQ,KAAK;EAEzC,IAAI,SAAS,KAAK,QAAQ,QAAQ,OAAO,QAAQ;GAC/C,MAAM,EAAE,SAAS,MAAM,OAAO;GAC9B,MAAM,QAAiB,KAAK,MAAM,IAAI;GACtC,OAAO,EACL,SAAS,CAAC;IAAE,OAAO,QAAQ,OAAO,KAAK,KAAK,CAAC;IAAG,UAAU,KAAK;GAAK,CAAC,EACvE;EACF;EACA,IAAI,SAAS,KAAK,QAAQ,QAAQ,OAAO,OAAO;GAC9C,MAAM,QAAiB,KAAK,MAAM,IAAI;GACtC,OAAO,EACL,SAAS,CAAC;IAAE,OAAO,QAAQ,OAAO,KAAK,UAAU,OAAO,MAAM,CAAC,CAAC;IAAG,UAAU,KAAK;GAAI,CAAC,EACzF;EACF;EACA,IAAI,SAAS,KAAK,QAAQ,QAAQ,OAAO,OAAO;GAC9C,MAAM,OAAO,MAAM,QAAQ;GAC3B,MAAM,QAAiB,KAAK,MAAM,IAAI;GACtC,IAAI,CAAC,MAAM,QAAQ,KAAK,GACtB,MAAM,IAAI,MACR,kFACF;GAEF,MAAM,MAAM,KAAK,QAAQ,KAAkB;GAC3C,OAAO,EAAE,SAAS,CAAC;IAAE,OAAO,QAAQ,OAAO,GAAG;IAAG,UAAU,KAAK;GAAI,CAAC,EAAE;EACzE;EACA,IAAI,SAAS,KAAK,QAAQ,QAAQ,OAAO,QAAQ;GAC/C,MAAM,EAAE,SAAS,MAAM,OAAO;GAC9B,MAAM,QAAQ,KAAK,IAAI;GACvB,OAAO,EACL,SAAS,CAAC;IAAE,OAAO,QAAQ,OAAO,KAAK,UAAU,SAAS,IAAI,CAAC;IAAG,UAAU,KAAK;GAAK,CAAC,EACzF;EACF;EACA,IAAI,SAAS,KAAK,OAAO,QAAQ,OAAO,QAAQ;GAE9C,MAAM,UAAS,MADI,QAAQ,GACP,MAAgB,KAAK,QAAQ,SAAS,IAAI,EAAE,QAAQ,QAAQ,EAAE,GAAG,EACnF,gBAAgB,KAClB,CAAC;GACD,IAAI,OAAO,OAAO,SAAS,GACzB,MAAM,IAAI,MAAM,qBAAqB,OAAO,OAAO,GAAG,SAAS;GAGjE,OAAO,EACL,SAAS,CAAC;IAAE,OAAO,QAAQ,OAAO,KAAK,UAAU,OAAO,IAAI,CAAC;IAAG,UAAU,KAAK;GAAK,CAAC,EACvF;EACF;EACA,MAAM,IAAI,MAAM,kCAAkC,QAAQ,SAAS,OAAO,QAAQ,GAAG,EAAE;CACzF;CAEA,OAAO;EACL,IAAI;EACJ,UAAU;GACR;IAAE,MAAM,CAAC,UAAU;IAAG,IAAI,OAAO,KAAK,KAAK;IAAG,SAAS;GAAS;GAChE;IAAE,MAAM,CAAC,KAAK,IAAI;IAAG,IAAI;KAAC;KAAQ;KAAO;IAAK;IAAG;GAAQ;GACzD;IAAE,MAAM,CAAC,KAAK,IAAI;IAAG,IAAI,CAAC,MAAM;IAAG;GAAQ;GAC3C;IAAE,MAAM,CAAC,KAAK,GAAG;IAAG,IAAI,CAAC,MAAM;IAAG;GAAQ;EAC5C;CACF;AACF"}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
require("../../../chunk-Cek0wNdY.js");
|
|
3
|
+
const require_tool_registry = require("../../../tool_registry-DwZ6pzN4.js");
|
|
4
|
+
require("../../../guards.cjs");
|
|
5
|
+
const require_batteries_media_contracts = require("../contracts.cjs");
|
|
6
|
+
const require_exceptions = require("../../../exceptions-D79HIKeX.js");
|
|
7
|
+
const require_formats = require("../../../formats-DZVuqZUN.js");
|
|
8
|
+
//#region src/batteries/media/engines/exceljs.ts
|
|
9
|
+
/**
|
|
10
|
+
* The ExcelJS-backed workbook {@link @nhtio/adk/batteries/media/contracts!MediaEngine}: the
|
|
11
|
+
* fidelity-preserving structural editor for xlsx, plus in-process blank-workbook generation.
|
|
12
|
+
*
|
|
13
|
+
* @module @nhtio/adk/batteries/media/engines/exceljs
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* ExcelJS models the parts of a workbook that matter to humans — fonts, fills, comments,
|
|
17
|
+
* merged ranges, data validations — and carries them through a read→edit→write cycle intact.
|
|
18
|
+
* That is this engine's whole reason to exist: the `sheet.*` verbs mutate workbooks users
|
|
19
|
+
* hand us, and an edit that strips the user's formatting as a side effect is corruption with
|
|
20
|
+
* good intentions. Compose this engine FIRST in the engines array when fidelity matters; the
|
|
21
|
+
* sheetjs engine edits a far wider read matrix (ODS, XLS, NUMBERS, …) but SheetJS Community
|
|
22
|
+
* Edition strips styling in the process.
|
|
23
|
+
*
|
|
24
|
+
* Capabilities:
|
|
25
|
+
*
|
|
26
|
+
* - **generate**: `EMPTY_MIME` → xlsx (a blank workbook with one `Sheet1` — every sheet step
|
|
27
|
+
* expects at least one worksheet).
|
|
28
|
+
* - **edit**: the ten `sheet.*` structural ops over xlsx, styling preserved.
|
|
29
|
+
*
|
|
30
|
+
* `exceljs` is an optional peer dependency, lazily imported on first actual use. Cross-env by
|
|
31
|
+
* construction: no `node:*` imports, `Uint8Array` in and out (ExcelJS ships a browser build
|
|
32
|
+
* via its `browser` field).
|
|
33
|
+
*/
|
|
34
|
+
/** The structural ops this engine edits (same names the verb table uses). */
|
|
35
|
+
var SHEET_OPS = [
|
|
36
|
+
"sheet.add_rows",
|
|
37
|
+
"sheet.add_columns",
|
|
38
|
+
"sheet.update_cells",
|
|
39
|
+
"sheet.delete_rows",
|
|
40
|
+
"sheet.delete_columns",
|
|
41
|
+
"sheet.rename_sheet",
|
|
42
|
+
"sheet.add_sheet",
|
|
43
|
+
"sheet.remove_sheet",
|
|
44
|
+
"sheet.reorder_sheets",
|
|
45
|
+
"sheet.transform_table"
|
|
46
|
+
];
|
|
47
|
+
/**
|
|
48
|
+
* Construct the ExcelJS-backed workbook engine.
|
|
49
|
+
*
|
|
50
|
+
* @param options - Optional module resolver override.
|
|
51
|
+
* @returns The engine.
|
|
52
|
+
*/
|
|
53
|
+
var exceljsEngine = (options = {}) => {
|
|
54
|
+
let modPromise;
|
|
55
|
+
const getExcel = () => {
|
|
56
|
+
modPromise ??= Promise.resolve(options.exceljs ? options.exceljs() : import("exceljs").then((m) => "default" in m ? m.default : m)).catch((err) => {
|
|
57
|
+
throw new require_exceptions.E_INVALID_MEDIA_PIPELINE_CONFIG([`the exceljs engine could not load its peer dependency "exceljs": ${require_tool_registry.isError(err) ? err.message : String(err)} — install it (pnpm add exceljs)`]);
|
|
58
|
+
});
|
|
59
|
+
return modPromise;
|
|
60
|
+
};
|
|
61
|
+
const convert = async (request) => {
|
|
62
|
+
if (request.to !== "xlsx") throw new Error(`exceljs generates "xlsx" only; requested "${request.to}"`);
|
|
63
|
+
const wb = new (await (getExcel())).Workbook();
|
|
64
|
+
wb.addWorksheet("Sheet1");
|
|
65
|
+
return { outputs: [{
|
|
66
|
+
bytes: new Uint8Array(await wb.xlsx.writeBuffer()),
|
|
67
|
+
mimeType: require_formats.MIME.XLSX
|
|
68
|
+
}] };
|
|
69
|
+
};
|
|
70
|
+
const edit = async (request) => {
|
|
71
|
+
const wb = new (await (getExcel())).Workbook();
|
|
72
|
+
try {
|
|
73
|
+
await wb.xlsx.load(request.bytes.buffer.slice(request.bytes.byteOffset, request.bytes.byteOffset + request.bytes.byteLength));
|
|
74
|
+
} catch (err) {
|
|
75
|
+
const detail = require_tool_registry.isError(err) ? err.message : String(err);
|
|
76
|
+
throw new Error(`could not open the spreadsheet: ${detail}`);
|
|
77
|
+
}
|
|
78
|
+
const summary = applyEdit(wb, request.op, request.args);
|
|
79
|
+
return {
|
|
80
|
+
bytes: new Uint8Array(await wb.xlsx.writeBuffer()),
|
|
81
|
+
mimeType: require_formats.MIME.XLSX,
|
|
82
|
+
summary
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
return {
|
|
86
|
+
id: "exceljs",
|
|
87
|
+
converts: [{
|
|
88
|
+
from: [require_batteries_media_contracts.EMPTY_MIME],
|
|
89
|
+
to: ["xlsx"],
|
|
90
|
+
convert
|
|
91
|
+
}],
|
|
92
|
+
edits: [{
|
|
93
|
+
over: [require_formats.MIME.XLSX],
|
|
94
|
+
ops: SHEET_OPS,
|
|
95
|
+
edit
|
|
96
|
+
}]
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
/** Resolve the target worksheet from the frozen `sheet=` rule (bare number=index, string=name). */
|
|
100
|
+
var resolveSheet = (wb, sheetArg) => {
|
|
101
|
+
if (sheetArg === void 0 || sheetArg === null) {
|
|
102
|
+
const first = wb.worksheets[0];
|
|
103
|
+
if (!first) throw new Error("the workbook has no worksheets");
|
|
104
|
+
return first;
|
|
105
|
+
}
|
|
106
|
+
if (typeof sheetArg === "number") {
|
|
107
|
+
const byIndex = wb.worksheets[sheetArg - 1];
|
|
108
|
+
if (byIndex) return byIndex;
|
|
109
|
+
if (wb.getWorksheet(String(sheetArg))) throw new Error(`no sheet at index ${sheetArg}, but a sheet NAMED "${sheetArg}" exists — quote it: sheet="${sheetArg}"`);
|
|
110
|
+
throw new Error(`sheet index ${sheetArg} is out of range (1-based; the workbook has ${wb.worksheets.length})`);
|
|
111
|
+
}
|
|
112
|
+
const ws = wb.getWorksheet(sheetArg);
|
|
113
|
+
if (!ws) {
|
|
114
|
+
const names = wb.worksheets.map((w) => `"${w.name}"`).join(", ");
|
|
115
|
+
throw new Error(`no sheet named "${String(sheetArg)}". Sheets: ${names}`);
|
|
116
|
+
}
|
|
117
|
+
return ws;
|
|
118
|
+
};
|
|
119
|
+
var columnLetterToNumber = (col) => {
|
|
120
|
+
let n = 0;
|
|
121
|
+
for (const ch of col.toUpperCase()) n = n * 26 + (ch.charCodeAt(0) - 64);
|
|
122
|
+
return n;
|
|
123
|
+
};
|
|
124
|
+
var asCellValue = (value) => {
|
|
125
|
+
if (value === null) return null;
|
|
126
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
|
|
127
|
+
throw new Error(`cell values must be string, number, boolean, or null; got ${typeof value}`);
|
|
128
|
+
};
|
|
129
|
+
/** Apply one structural op to the workbook in place; returns the change summary. */
|
|
130
|
+
var applyEdit = (wb, op, args) => {
|
|
131
|
+
switch (op) {
|
|
132
|
+
case "sheet.add_rows": {
|
|
133
|
+
const rows = args.rows;
|
|
134
|
+
if (!Array.isArray(rows) || rows.length === 0 || !rows.every(Array.isArray)) throw new Error(`rows must be a non-empty JSON array of arrays, e.g. rows='[["a",1]]'`);
|
|
135
|
+
const before = args.before;
|
|
136
|
+
const after = args.after;
|
|
137
|
+
const ws = resolveSheet(wb, args.sheet);
|
|
138
|
+
const insertAt = before !== void 0 ? before : after !== void 0 ? after + 1 : ws.rowCount + 1;
|
|
139
|
+
const cellRows = rows.map((r) => r.map(asCellValue));
|
|
140
|
+
ws.spliceRows(insertAt, 0, ...cellRows);
|
|
141
|
+
return { added: cellRows.length };
|
|
142
|
+
}
|
|
143
|
+
case "sheet.add_columns": {
|
|
144
|
+
const headers = args.headers;
|
|
145
|
+
const columns = args.columns ?? headers?.map((header) => ({ header }));
|
|
146
|
+
if (!Array.isArray(columns) || columns.length === 0) throw new Error(`provide headers=a,b or columns='[{"header":"X","values":[1]}]'`);
|
|
147
|
+
const before = args.before;
|
|
148
|
+
const after = args.after;
|
|
149
|
+
const ws = resolveSheet(wb, args.sheet);
|
|
150
|
+
const insertAt = before !== void 0 ? before : after !== void 0 ? after + 1 : ws.columnCount + 1;
|
|
151
|
+
for (const [i, col] of columns.entries()) {
|
|
152
|
+
if (typeof col?.header !== "string") throw new Error("every column needs a string header");
|
|
153
|
+
ws.spliceColumns(insertAt + i, 0, [col.header, ...(col.values ?? []).map(asCellValue)]);
|
|
154
|
+
}
|
|
155
|
+
return { added: columns.length };
|
|
156
|
+
}
|
|
157
|
+
case "sheet.update_cells": {
|
|
158
|
+
const updates = args.updates;
|
|
159
|
+
if (!Array.isArray(updates) || updates.length === 0) throw new Error(`updates must be a non-empty JSON array, e.g. updates='[{"address":"B2","value":3}]'`);
|
|
160
|
+
const ws = resolveSheet(wb, args.sheet);
|
|
161
|
+
let modified = 0;
|
|
162
|
+
for (const raw of updates) {
|
|
163
|
+
const address = raw.address;
|
|
164
|
+
const row = raw.row;
|
|
165
|
+
const col = raw.col;
|
|
166
|
+
let cell;
|
|
167
|
+
if (address) cell = ws.getCell(address);
|
|
168
|
+
else if (row !== void 0 && col !== void 0) cell = typeof col === "string" ? ws.getCell(row, columnLetterToNumber(col)) : ws.getCell(row, col);
|
|
169
|
+
else throw new Error("each update needs address, or both row and col");
|
|
170
|
+
const value = raw.value;
|
|
171
|
+
if (typeof value === "string" && value.startsWith("=")) cell.value = { formula: value.slice(1) };
|
|
172
|
+
else cell.value = asCellValue(value);
|
|
173
|
+
modified += 1;
|
|
174
|
+
}
|
|
175
|
+
return { modified };
|
|
176
|
+
}
|
|
177
|
+
case "sheet.delete_rows": {
|
|
178
|
+
const rows = args.rows;
|
|
179
|
+
const ws = resolveSheet(wb, args.sheet);
|
|
180
|
+
for (const r of [...rows].sort((a, b) => b - a)) ws.spliceRows(r, 1);
|
|
181
|
+
return { removed: rows.length };
|
|
182
|
+
}
|
|
183
|
+
case "sheet.delete_columns": {
|
|
184
|
+
const columns = args.columns;
|
|
185
|
+
const ws = resolveSheet(wb, args.sheet);
|
|
186
|
+
for (const c of [...columns].sort((a, b) => b - a)) ws.spliceColumns(c, 1);
|
|
187
|
+
return { removed: columns.length };
|
|
188
|
+
}
|
|
189
|
+
case "sheet.rename_sheet": {
|
|
190
|
+
const sheet = args.sheet;
|
|
191
|
+
const to = args.to;
|
|
192
|
+
const ws = wb.getWorksheet(sheet);
|
|
193
|
+
if (!ws) {
|
|
194
|
+
const names = wb.worksheets.map((w) => `"${w.name}"`).join(", ");
|
|
195
|
+
throw new Error(`rename targets a sheet NAME; no sheet named "${sheet}". Sheets: ${names}`);
|
|
196
|
+
}
|
|
197
|
+
ws.name = to;
|
|
198
|
+
return { modified: 1 };
|
|
199
|
+
}
|
|
200
|
+
case "sheet.add_sheet": {
|
|
201
|
+
const name = args.name;
|
|
202
|
+
const at = args.at;
|
|
203
|
+
if (wb.getWorksheet(name)) throw new Error(`a sheet named "${name}" already exists`);
|
|
204
|
+
const ws = wb.addWorksheet(name);
|
|
205
|
+
if (at !== void 0) {
|
|
206
|
+
const all = wb.worksheets;
|
|
207
|
+
const wsIdx = all.indexOf(ws);
|
|
208
|
+
if (wsIdx !== at - 1) all.forEach((w, i) => {
|
|
209
|
+
w.orderNo = w === ws ? at : i + 1 >= at && i < wsIdx ? i + 2 : i + 1;
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
return { added: 1 };
|
|
213
|
+
}
|
|
214
|
+
case "sheet.remove_sheet": {
|
|
215
|
+
const sheet = args.sheet;
|
|
216
|
+
const ws = wb.getWorksheet(sheet);
|
|
217
|
+
if (!ws) {
|
|
218
|
+
const names = wb.worksheets.map((w) => `"${w.name}"`).join(", ");
|
|
219
|
+
throw new Error(`remove targets a sheet NAME; no sheet named "${sheet}". Sheets: ${names}`);
|
|
220
|
+
}
|
|
221
|
+
wb.removeWorksheet(ws.id);
|
|
222
|
+
return { removed: 1 };
|
|
223
|
+
}
|
|
224
|
+
case "sheet.reorder_sheets": {
|
|
225
|
+
const order = args.order;
|
|
226
|
+
if (!Array.isArray(order) || order.length === 0) throw new Error(`order must be a JSON array of names/indices, e.g. order='["Summary",2]'`);
|
|
227
|
+
const refs = order;
|
|
228
|
+
if (refs.length !== wb.worksheets.length) throw new Error(`order must include every worksheet exactly once (the workbook has ${wb.worksheets.length})`);
|
|
229
|
+
const reordered = [];
|
|
230
|
+
const seen = /* @__PURE__ */ new Set();
|
|
231
|
+
for (const ref of refs) {
|
|
232
|
+
const ws = typeof ref === "number" ? wb.worksheets[ref - 1] : wb.getWorksheet(ref);
|
|
233
|
+
if (!ws) throw new Error(`sheet not found: ${String(ref)}`);
|
|
234
|
+
if (seen.has(ws.id)) throw new Error(`duplicate sheet reference: ${String(ref)}`);
|
|
235
|
+
seen.add(ws.id);
|
|
236
|
+
reordered.push(ws);
|
|
237
|
+
}
|
|
238
|
+
reordered.forEach((ws, i) => {
|
|
239
|
+
ws.orderNo = i + 1;
|
|
240
|
+
});
|
|
241
|
+
return { modified: reordered.length };
|
|
242
|
+
}
|
|
243
|
+
case "sheet.transform_table": {
|
|
244
|
+
const headerRow = args.header_row ?? 1;
|
|
245
|
+
const rename = args.rename;
|
|
246
|
+
const select = args.select;
|
|
247
|
+
const drop = args.drop;
|
|
248
|
+
const ws = resolveSheet(wb, args.sheet);
|
|
249
|
+
let modified = 0;
|
|
250
|
+
const headerMap = /* @__PURE__ */ new Map();
|
|
251
|
+
ws.getRow(headerRow).eachCell({ includeEmpty: false }, (cell, colNumber) => {
|
|
252
|
+
if (typeof cell.value === "string") headerMap.set(cell.value, colNumber);
|
|
253
|
+
});
|
|
254
|
+
if (rename) for (const { from, to } of rename) {
|
|
255
|
+
const colNum = headerMap.get(from);
|
|
256
|
+
if (colNum !== void 0) {
|
|
257
|
+
ws.getRow(headerRow).getCell(colNum).value = to;
|
|
258
|
+
headerMap.delete(from);
|
|
259
|
+
headerMap.set(to, colNum);
|
|
260
|
+
modified += 1;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (drop) {
|
|
264
|
+
const cols = drop.map((name) => headerMap.get(name)).filter((n) => n !== void 0).sort((a, b) => b - a);
|
|
265
|
+
for (const col of cols) {
|
|
266
|
+
ws.spliceColumns(col, 1);
|
|
267
|
+
modified += 1;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (select) {
|
|
271
|
+
const keep = new Set(select);
|
|
272
|
+
const cols = [];
|
|
273
|
+
ws.getRow(headerRow).eachCell({ includeEmpty: false }, (cell, colNumber) => {
|
|
274
|
+
if (typeof cell.value === "string" && !keep.has(cell.value)) cols.push(colNumber);
|
|
275
|
+
});
|
|
276
|
+
cols.sort((a, b) => b - a);
|
|
277
|
+
for (const col of cols) {
|
|
278
|
+
ws.spliceColumns(col, 1);
|
|
279
|
+
modified += 1;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return { modified };
|
|
283
|
+
}
|
|
284
|
+
default: throw new Error(`exceljs does not implement edit op "${op}"`);
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
//#endregion
|
|
288
|
+
exports.exceljsEngine = exceljsEngine;
|
|
289
|
+
|
|
290
|
+
//# sourceMappingURL=exceljs.cjs.map
|