@univerjs-pro/exchange-node 1.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # @univerjs-pro/exchange-node
2
+
3
+ Node.js SDK for converting between Office formats, Univer unit data, and complete Univer snapshots.
4
+
5
+ The package exposes two API families:
6
+
7
+ - `importFile` / `importBuffer` and `exportToFile` / `exportToBuffer` convert Univer in-memory unit data.
8
+ - `importFileToSnapshot` / `importBufferToSnapshot` and `exportSnapshotToFile` / `exportSnapshotToBuffer` convert complete snapshot aggregates without creating a Univer runtime.
9
+
10
+ ## Install
11
+
12
+ Keep this package and its Univer SDK dependencies on the same SDK version:
13
+
14
+ ```sh
15
+ pnpm add @univerjs-pro/exchange-node
16
+ ```
17
+
18
+ ## Import
19
+
20
+ ```ts
21
+ import { UniverInstanceType } from '@univerjs/core';
22
+ import { ExchangeFormat, importBuffer } from '@univerjs-pro/exchange-node';
23
+
24
+ const workbook = await importBuffer(xlsxBuffer, {
25
+ type: UniverInstanceType.UNIVER_SHEET,
26
+ format: ExchangeFormat.XLSX,
27
+ fileName: 'example.xlsx',
28
+ });
29
+ ```
30
+
31
+ `importBuffer` requires `fileName`. File imports use the path basename by default and allow `fileName` to override format inference. An explicit `format` always takes precedence.
32
+
33
+ ## Export
34
+
35
+ ```ts
36
+ import { UniverInstanceType } from '@univerjs/core';
37
+ import {
38
+ ExchangeFormat,
39
+ FormulaCalculationMode,
40
+ exportToBuffer,
41
+ } from '@univerjs-pro/exchange-node';
42
+
43
+ const xlsxBuffer = await exportToBuffer(workbook, {
44
+ type: UniverInstanceType.UNIVER_SHEET,
45
+ format: ExchangeFormat.XLSX,
46
+ formulaCalculation: FormulaCalculationMode.WHEN_EMPTY,
47
+ });
48
+ ```
49
+
50
+ Sheet export defaults to `FormulaCalculationMode.WHEN_EMPTY`: missing cached formula values are calculated, while existing cached values are preserved. Pass `FormulaCalculationMode.NO` to disable calculation.
51
+
52
+ ## Complete snapshots
53
+
54
+ Snapshot APIs use `ISnapshotWithBlocks`:
55
+
56
+ ```ts
57
+ interface ISnapshotWithBlocks {
58
+ snapshot: ISnapshot;
59
+ sheetBlocks: ISheetBlock[];
60
+ }
61
+ ```
62
+
63
+ Sheet and Base snapshots must include every referenced sheet block. Doc and Slide snapshots normally use an empty `sheetBlocks` array.
64
+
65
+ Snapshot APIs materialize the complete aggregate in memory. They do not call a Snapshot Server or stream blocks to storage.
66
+
67
+ ## Formats and platforms
68
+
69
+ The initial release supports Sheet and Base import from XLS, XLSX, CSV, and TSV; Doc import from DOC and DOCX; and Slide import from PPT and PPTX. Export supports XLSX, CSV, TSV, DOCX, and PPTX for their corresponding unit types.
70
+
71
+ Native packages are published for Linux x64 GNU, Linux arm64 GNU, Windows x64 MSVC, and macOS arm64.
@@ -0,0 +1,432 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf, __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: !0 });
10
+ }, __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from == "object" || typeof from == "function")
12
+ for (let key of __getOwnPropNames(from))
13
+ !__hasOwnProp.call(to, key) && key !== except && __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ return to;
15
+ };
16
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
17
+ // If the importer is in node compatibility mode or this is not an ESM
18
+ // file that has been converted to a CommonJS file using a Babel-
19
+ // compatible transform (i.e. "__esModule" has not been set), then set
20
+ // "default" to the CommonJS "module.exports" for node compatibility.
21
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: !0 }) : target,
22
+ mod
23
+ )), __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: !0 }), mod);
24
+
25
+ // src/index.ts
26
+ var index_exports = {};
27
+ __export(index_exports, {
28
+ BaseAttachmentPolicy: () => BaseAttachmentPolicy,
29
+ BaseExportMode: () => BaseExportMode,
30
+ BaseFormulaPolicy: () => BaseFormulaPolicy,
31
+ BaseHeaderPolicy: () => BaseHeaderPolicy,
32
+ BaseImagePolicy: () => BaseImagePolicy,
33
+ BaseImportMode: () => BaseImportMode,
34
+ BaseTypeInference: () => BaseTypeInference,
35
+ CsvFormulaMode: () => CsvFormulaMode,
36
+ CsvLineEnding: () => CsvLineEnding,
37
+ CsvQuoteStyle: () => CsvQuoteStyle,
38
+ CsvTypeInferenceMode: () => CsvTypeInferenceMode,
39
+ CsvValueMode: () => CsvValueMode,
40
+ DocxCompatibilityMode: () => DocxCompatibilityMode,
41
+ ExchangeError: () => ExchangeError,
42
+ ExchangeErrorCode: () => ExchangeErrorCode,
43
+ ExchangeFormat: () => ExchangeFormat,
44
+ FormulaCalculationMode: () => FormulaCalculationMode,
45
+ exportSnapshotToBuffer: () => exportSnapshotToBuffer,
46
+ exportSnapshotToFile: () => exportSnapshotToFile,
47
+ exportToBuffer: () => exportToBuffer,
48
+ exportToFile: () => exportToFile,
49
+ importBuffer: () => importBuffer,
50
+ importBufferToSnapshot: () => importBufferToSnapshot,
51
+ importFile: () => importFile,
52
+ importFileToSnapshot: () => importFileToSnapshot
53
+ });
54
+ module.exports = __toCommonJS(index_exports);
55
+ var import_collaboration = require("@univerjs-pro/collaboration"), import_core = require("@univerjs/core"), import_node_path = require("node:path"), import_promises = require("node:fs/promises");
56
+
57
+ // src/binding.ts
58
+ var import_node_module = require("node:module"), import_node_process = __toESM(require("node:process"), 1);
59
+
60
+ // src/types.ts
61
+ var ExchangeFormat = /* @__PURE__ */ ((ExchangeFormat2) => (ExchangeFormat2.XLS = "xls", ExchangeFormat2.XLSX = "xlsx", ExchangeFormat2.CSV = "csv", ExchangeFormat2.TSV = "tsv", ExchangeFormat2.DOC = "doc", ExchangeFormat2.DOCX = "docx", ExchangeFormat2.PPT = "ppt", ExchangeFormat2.PPTX = "pptx", ExchangeFormat2))(ExchangeFormat || {}), FormulaCalculationMode = /* @__PURE__ */ ((FormulaCalculationMode2) => (FormulaCalculationMode2.FORCED = "forced", FormulaCalculationMode2.WHEN_EMPTY = "when_empty", FormulaCalculationMode2.NO = "no", FormulaCalculationMode2))(FormulaCalculationMode || {}), CsvTypeInferenceMode = /* @__PURE__ */ ((CsvTypeInferenceMode2) => (CsvTypeInferenceMode2.OFF = "off", CsvTypeInferenceMode2.SAFE = "safe", CsvTypeInferenceMode2.AGGRESSIVE = "aggressive", CsvTypeInferenceMode2))(CsvTypeInferenceMode || {}), CsvQuoteStyle = /* @__PURE__ */ ((CsvQuoteStyle2) => (CsvQuoteStyle2.MINIMAL = "minimal", CsvQuoteStyle2.ALWAYS = "always", CsvQuoteStyle2))(CsvQuoteStyle || {}), CsvLineEnding = /* @__PURE__ */ ((CsvLineEnding2) => (CsvLineEnding2.LF = "lf", CsvLineEnding2.CRLF = "cr_lf", CsvLineEnding2))(CsvLineEnding || {}), CsvValueMode = /* @__PURE__ */ ((CsvValueMode2) => (CsvValueMode2.DISPLAY = "display", CsvValueMode2.RAW = "raw", CsvValueMode2))(CsvValueMode || {}), CsvFormulaMode = /* @__PURE__ */ ((CsvFormulaMode2) => (CsvFormulaMode2.CACHED = "cached", CsvFormulaMode2.EXPRESSION = "expression", CsvFormulaMode2))(CsvFormulaMode || {}), BaseImportMode = /* @__PURE__ */ ((BaseImportMode2) => (BaseImportMode2.TABLES = "tables", BaseImportMode2.SHEETS = "sheets", BaseImportMode2.HYBRID = "hybrid", BaseImportMode2.AUTO = "auto", BaseImportMode2))(BaseImportMode || {}), BaseTypeInference = /* @__PURE__ */ ((BaseTypeInference2) => (BaseTypeInference2.NONE = "none", BaseTypeInference2.SAFE = "safe", BaseTypeInference2.AGGRESSIVE = "aggressive", BaseTypeInference2))(BaseTypeInference || {}), BaseFormulaPolicy = /* @__PURE__ */ ((BaseFormulaPolicy2) => (BaseFormulaPolicy2.VALUES = "values", BaseFormulaPolicy2.TEXT = "text", BaseFormulaPolicy2.FAIL = "fail", BaseFormulaPolicy2.CONVERT_THEN_VALUES = "convertThenValues", BaseFormulaPolicy2))(BaseFormulaPolicy || {}), BaseImagePolicy = /* @__PURE__ */ ((BaseImagePolicy2) => (BaseImagePolicy2.SAFE = "safe", BaseImagePolicy2.CELL_ONLY = "cell-only", BaseImagePolicy2.MEDIA_TABLE = "media-table", BaseImagePolicy2.NONE = "none", BaseImagePolicy2))(BaseImagePolicy || {}), BaseHeaderPolicy = /* @__PURE__ */ ((BaseHeaderPolicy2) => (BaseHeaderPolicy2.FIRST_ROW = "firstRow", BaseHeaderPolicy2.NONE = "none", BaseHeaderPolicy2))(BaseHeaderPolicy || {}), BaseExportMode = /* @__PURE__ */ ((BaseExportMode2) => (BaseExportMode2.TABLES = "tables", BaseExportMode2.RANGES = "ranges", BaseExportMode2))(BaseExportMode || {}), BaseAttachmentPolicy = /* @__PURE__ */ ((BaseAttachmentPolicy2) => (BaseAttachmentPolicy2.HYBRID = "hybrid", BaseAttachmentPolicy2.MANIFEST = "manifest", BaseAttachmentPolicy2.LINKS = "links", BaseAttachmentPolicy2.NONE = "none", BaseAttachmentPolicy2))(BaseAttachmentPolicy || {}), DocxCompatibilityMode = /* @__PURE__ */ ((DocxCompatibilityMode2) => (DocxCompatibilityMode2.TRADITIONAL = "traditional", DocxCompatibilityMode2.MODERN = "modern", DocxCompatibilityMode2))(DocxCompatibilityMode || {}), ExchangeErrorCode = /* @__PURE__ */ ((ExchangeErrorCode2) => (ExchangeErrorCode2.INVALID_ARGUMENT = "INVALID_ARGUMENT", ExchangeErrorCode2.UNSUPPORTED_FORMAT = "UNSUPPORTED_FORMAT", ExchangeErrorCode2.INVALID_FILE = "INVALID_FILE", ExchangeErrorCode2.INCOMPLETE_SNAPSHOT = "INCOMPLETE_SNAPSHOT", ExchangeErrorCode2.IO_ERROR = "IO_ERROR", ExchangeErrorCode2.NATIVE_LOAD_FAILED = "NATIVE_LOAD_FAILED", ExchangeErrorCode2.CONVERSION_FAILED = "CONVERSION_FAILED", ExchangeErrorCode2))(ExchangeErrorCode || {}), ExchangeError = class extends Error {
62
+ constructor(code, message, options) {
63
+ super(message, options);
64
+ this.code = code;
65
+ }
66
+ code;
67
+ name = "ExchangeError";
68
+ };
69
+
70
+ // src/binding.ts
71
+ var nativeBinding = null, nativeBindingSource = null, nodeRequire = (0, import_node_module.createRequire)(__filename);
72
+ function errorMessage(error) {
73
+ return error instanceof Error ? error.message : String(error);
74
+ }
75
+ async function loadNativeBinding() {
76
+ if (nativeBinding)
77
+ return nativeBinding;
78
+ let errors = [];
79
+ try {
80
+ return nativeBinding = nodeRequire("@univerjs-pro/exchange-node-binding"), nativeBindingSource = "@univerjs-pro/exchange-node-binding", nativeBinding;
81
+ } catch (error) {
82
+ errors.push(`@univerjs-pro/exchange-node-binding: ${errorMessage(error)}`);
83
+ }
84
+ throw new ExchangeError(
85
+ "NATIVE_LOAD_FAILED" /* NATIVE_LOAD_FAILED */,
86
+ [
87
+ "Failed to load native exchange binding.",
88
+ `platform=${import_node_process.default.platform}`,
89
+ `arch=${import_node_process.default.arch}`,
90
+ "expected npm package=@univerjs-pro/exchange-node-binding",
91
+ "attempted paths:",
92
+ ...errors.map((item) => `- ${item}`)
93
+ ].join(`
94
+ `)
95
+ );
96
+ }
97
+
98
+ // src/snapshot-collector.ts
99
+ var import_protocol = require("@univerjs/protocol");
100
+ function createSnapshotCollector() {
101
+ let sheetBlocks = /* @__PURE__ */ new Map();
102
+ return {
103
+ // The public Pro conversion functions accept the host-wide service
104
+ // contract even though these conversion paths use its two write methods.
105
+ service: {
106
+ async saveSheetBlock(_context, { block }) {
107
+ return block ? (sheetBlocks.set(block.id, block), {
108
+ blockID: block.id,
109
+ error: { code: import_protocol.ErrorCode.OK, message: "" }
110
+ }) : {
111
+ blockID: "",
112
+ error: { code: import_protocol.ErrorCode.UNDEFINED, message: "block is required" }
113
+ };
114
+ },
115
+ async saveSnapshot() {
116
+ return { error: { code: import_protocol.ErrorCode.OK, message: "" } };
117
+ }
118
+ },
119
+ get sheetBlocks() {
120
+ return [...sheetBlocks.values()];
121
+ }
122
+ };
123
+ }
124
+
125
+ // src/snapshot.ts
126
+ var import_node_buffer = require("node:buffer");
127
+ function bufferView(bytes) {
128
+ return import_node_buffer.Buffer.isBuffer(bytes) ? bytes : import_node_buffer.Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
129
+ }
130
+ function takeMetadata(owner, kind, metadata, ownerId) {
131
+ if (!owner)
132
+ return owner;
133
+ let { originalMeta, ...rest } = owner;
134
+ if (originalMeta instanceof Uint8Array)
135
+ metadata.push({ kind, ownerId, data: bufferView(originalMeta) });
136
+ else if (originalMeta != null)
137
+ throw new TypeError(`${kind} originalMeta must be a Uint8Array`);
138
+ return rest;
139
+ }
140
+ function toNativeSnapshot(value) {
141
+ let metadata = [], source = value.snapshot, snapshot = { ...source }, sourceWorkbook = source.workbook;
142
+ if (sourceWorkbook) {
143
+ let workbook = takeMetadata(sourceWorkbook, "workbook", metadata), sourceSheets = sourceWorkbook.sheets;
144
+ sourceSheets && (workbook.sheets = Object.fromEntries(
145
+ Object.entries(sourceSheets).map(([sheetId, sheet]) => [
146
+ sheetId,
147
+ takeMetadata(sheet, "worksheet", metadata, sheetId)
148
+ ])
149
+ )), snapshot.workbook = workbook;
150
+ }
151
+ for (let kind of ["doc", "slide"]) {
152
+ let owner = source[kind];
153
+ owner && (snapshot[kind] = takeMetadata(owner, kind, metadata));
154
+ }
155
+ return {
156
+ snapshotJson: import_node_buffer.Buffer.from(JSON.stringify(snapshot)),
157
+ metadata,
158
+ sheetBlocks: value.sheetBlocks.map((block) => ({
159
+ id: block.id,
160
+ startRow: block.startRow,
161
+ endRow: block.endRow,
162
+ data: bufferView(block.data)
163
+ }))
164
+ };
165
+ }
166
+ function restoreMetadata(snapshot, metadata) {
167
+ for (let entry of metadata) {
168
+ let owner;
169
+ if (entry.kind === "worksheet") {
170
+ let sheets = snapshot.workbook?.sheets;
171
+ owner = entry.ownerId ? sheets?.[entry.ownerId] : void 0;
172
+ } else {
173
+ if (entry.kind !== "workbook" && entry.kind !== "doc" && entry.kind !== "slide")
174
+ throw new TypeError(`unsupported native snapshot metadata kind ${entry.kind}`);
175
+ owner = snapshot[entry.kind];
176
+ }
177
+ if (!owner)
178
+ throw new TypeError(`native snapshot metadata owner ${entry.kind}/${entry.ownerId ?? ""} is missing`);
179
+ owner.originalMeta = entry.data;
180
+ }
181
+ }
182
+ function fromNativeSnapshot(value) {
183
+ let snapshot = JSON.parse(value.snapshotJson.toString("utf8"));
184
+ return restoreMetadata(snapshot, value.metadata), {
185
+ snapshot,
186
+ sheetBlocks: value.sheetBlocks.map((block) => ({
187
+ id: block.id,
188
+ startRow: block.startRow,
189
+ endRow: block.endRow,
190
+ data: block.data
191
+ }))
192
+ };
193
+ }
194
+
195
+ // src/index.ts
196
+ var FORMAT_BY_EXTENSION = {
197
+ ".xls": "xls" /* XLS */,
198
+ ".xlsx": "xlsx" /* XLSX */,
199
+ ".csv": "csv" /* CSV */,
200
+ ".tsv": "tsv" /* TSV */,
201
+ ".doc": "doc" /* DOC */,
202
+ ".docx": "docx" /* DOCX */,
203
+ ".ppt": "ppt" /* PPT */,
204
+ ".pptx": "pptx" /* PPTX */
205
+ };
206
+ function normalizeWorkbookSheetOrder(data) {
207
+ let existingOrder = Array.isArray(data.sheetOrder) ? data.sheetOrder.filter((sheetId) => typeof sheetId == "string") : [], ordered = new Set(existingOrder), missingSheetIds = Object.keys(data.sheets).filter((sheetId) => !ordered.has(sheetId));
208
+ return missingSheetIds.length === 0 ? data : { ...data, sheetOrder: [...existingOrder, ...missingSheetIds] };
209
+ }
210
+ function exchangeError(error, fallback) {
211
+ if (error instanceof ExchangeError)
212
+ return error;
213
+ let message = error instanceof Error ? error.message : String(error), nativeCode = /^\[([A-Z_]+)]\s*/.exec(message)?.[1];
214
+ return nativeCode && Object.values(ExchangeErrorCode).includes(nativeCode) ? new ExchangeError(nativeCode, message.replace(/^\[[A-Z_]+]\s*/, ""), {
215
+ cause: error
216
+ }) : error instanceof TypeError ? new ExchangeError("INVALID_ARGUMENT" /* INVALID_ARGUMENT */, message, { cause: error }) : new ExchangeError(fallback, message, { cause: error });
217
+ }
218
+ function resolveFormat(fileName, format) {
219
+ if (format)
220
+ return format;
221
+ let inferred = FORMAT_BY_EXTENSION[(0, import_node_path.extname)(fileName).toLowerCase()];
222
+ if (!inferred)
223
+ throw new ExchangeError(
224
+ "UNSUPPORTED_FORMAT" /* UNSUPPORTED_FORMAT */,
225
+ `Cannot infer an exchange format from fileName: ${fileName}`
226
+ );
227
+ return inferred;
228
+ }
229
+ function nativeUnitType(type) {
230
+ switch (type) {
231
+ case import_core.UniverInstanceType.UNIVER_SHEET:
232
+ return "sheet";
233
+ case import_core.UniverInstanceType.UNIVER_BASE:
234
+ return "base";
235
+ case import_core.UniverInstanceType.UNIVER_DOC:
236
+ return "doc";
237
+ case import_core.UniverInstanceType.UNIVER_SLIDE:
238
+ return "slide";
239
+ default:
240
+ throw new ExchangeError("INVALID_ARGUMENT" /* INVALID_ARGUMENT */, `Unsupported Univer unit type: ${type}`);
241
+ }
242
+ }
243
+ function nativeImportOptions(options, fileName) {
244
+ return {
245
+ format: resolveFormat(fileName, options.format),
246
+ unitType: nativeUnitType(options.type),
247
+ fileName,
248
+ unitId: options.unitId,
249
+ minSheetRowCount: "minSheetRowCount" in options ? options.minSheetRowCount : void 0,
250
+ minSheetColumnCount: "minSheetColumnCount" in options ? options.minSheetColumnCount : void 0,
251
+ compatibilityMode: "compatibilityMode" in options ? options.compatibilityMode : void 0,
252
+ csv: "csv" in options ? options.csv : void 0,
253
+ base: options.type === import_core.UniverInstanceType.UNIVER_BASE ? {
254
+ mode: options.mode,
255
+ typeInference: options.typeInference,
256
+ formulaPolicy: options.formulaPolicy,
257
+ imagePolicy: options.imagePolicy,
258
+ maxCells: options.maxCells,
259
+ mapping: options.mapping
260
+ } : void 0,
261
+ formulaCalculation: "formulaCalculation" in options ? options.formulaCalculation : void 0
262
+ };
263
+ }
264
+ function nativeExportOptions(options) {
265
+ return {
266
+ format: options.format,
267
+ unitType: nativeUnitType(options.type),
268
+ csv: "csv" in options ? options.csv : void 0,
269
+ base: options.type === import_core.UniverInstanceType.UNIVER_BASE && options.format === "xlsx" /* XLSX */ ? {
270
+ mode: options.mode,
271
+ formulaPolicy: options.formulaPolicy,
272
+ attachmentPolicy: options.attachmentPolicy,
273
+ mapping: options.mapping
274
+ } : void 0,
275
+ formulaCalculation: "formulaCalculation" in options ? options.formulaCalculation : void 0
276
+ };
277
+ }
278
+ async function importSnapshot(input, options, fileName) {
279
+ try {
280
+ let result = await (await loadNativeBinding()).exchangeImportToSnapshot(
281
+ input,
282
+ JSON.stringify(nativeImportOptions(options, fileName))
283
+ );
284
+ return fromNativeSnapshot(result);
285
+ } catch (error) {
286
+ throw exchangeError(error, "CONVERSION_FAILED" /* CONVERSION_FAILED */);
287
+ }
288
+ }
289
+ async function snapshotToMemory(snapshot, type) {
290
+ try {
291
+ switch (type) {
292
+ case import_core.UniverInstanceType.UNIVER_SHEET:
293
+ return await (0, import_collaboration.transformSnapshotToWorkbookData)(snapshot.snapshot, snapshot.sheetBlocks);
294
+ case import_core.UniverInstanceType.UNIVER_BASE:
295
+ return await (0, import_collaboration.transformSnapshotToBaseData)(snapshot.snapshot, snapshot.sheetBlocks);
296
+ case import_core.UniverInstanceType.UNIVER_DOC:
297
+ return (0, import_collaboration.transformSnapshotToDocumentData)(snapshot.snapshot);
298
+ case import_core.UniverInstanceType.UNIVER_SLIDE:
299
+ return (0, import_collaboration.transformSnapshotToSlideData)(snapshot.snapshot);
300
+ default:
301
+ throw new TypeError(`Unsupported Univer unit type: ${type}`);
302
+ }
303
+ } catch (error) {
304
+ throw exchangeError(error, "CONVERSION_FAILED" /* CONVERSION_FAILED */);
305
+ }
306
+ }
307
+ async function memoryToSnapshot(data, options) {
308
+ try {
309
+ let unitId = data.id;
310
+ if (!unitId)
311
+ throw new ExchangeError("INVALID_ARGUMENT" /* INVALID_ARGUMENT */, "Export data must have a non-empty id");
312
+ let rev = data.rev ?? 0, collector = createSnapshotCollector();
313
+ switch (options.type) {
314
+ case import_core.UniverInstanceType.UNIVER_SHEET: {
315
+ let workbook = normalizeWorkbookSheetOrder(data), { snapshot } = await (0, import_collaboration.transformWorkbookDataToSnapshot)(
316
+ { metadata: void 0 },
317
+ workbook,
318
+ unitId,
319
+ rev,
320
+ collector.service
321
+ );
322
+ return { snapshot, sheetBlocks: collector.sheetBlocks };
323
+ }
324
+ case import_core.UniverInstanceType.UNIVER_BASE: {
325
+ let { snapshot } = await (0, import_collaboration.transformBaseDataToSnapshot)(
326
+ { metadata: void 0 },
327
+ data,
328
+ unitId,
329
+ rev,
330
+ collector.service
331
+ );
332
+ return { snapshot, sheetBlocks: collector.sheetBlocks };
333
+ }
334
+ case import_core.UniverInstanceType.UNIVER_DOC: {
335
+ let { snapshot } = await (0, import_collaboration.transformDocumentDataToSnapshot)(
336
+ { metadata: void 0 },
337
+ data,
338
+ unitId,
339
+ rev,
340
+ collector.service
341
+ );
342
+ return { snapshot, sheetBlocks: [] };
343
+ }
344
+ case import_core.UniverInstanceType.UNIVER_SLIDE: {
345
+ let slide = data, { snapshot } = await (0, import_collaboration.transformSlideDataToSnapshot)(
346
+ slide.resources,
347
+ slide,
348
+ unitId,
349
+ rev,
350
+ collector.service
351
+ );
352
+ return { snapshot, sheetBlocks: [] };
353
+ }
354
+ default:
355
+ throw new TypeError("Unsupported Univer unit type");
356
+ }
357
+ } catch (error) {
358
+ throw exchangeError(error, "CONVERSION_FAILED" /* CONVERSION_FAILED */);
359
+ }
360
+ }
361
+ async function importFile(path, options) {
362
+ let snapshot = await importFileToSnapshot(path, options);
363
+ return snapshotToMemory(snapshot, options.type);
364
+ }
365
+ async function importBuffer(input, options) {
366
+ let snapshot = await importSnapshot(input, options, options.fileName);
367
+ return snapshotToMemory(snapshot, options.type);
368
+ }
369
+ async function importFileToSnapshot(path, options) {
370
+ let fileName = options.fileName ?? (0, import_node_path.basename)(path), input;
371
+ try {
372
+ input = await (0, import_promises.readFile)(path);
373
+ } catch (error) {
374
+ throw exchangeError(error, "IO_ERROR" /* IO_ERROR */);
375
+ }
376
+ return importSnapshot(input, options, fileName);
377
+ }
378
+ async function importBufferToSnapshot(input, options) {
379
+ return importSnapshot(input, options, options.fileName);
380
+ }
381
+ async function exportToBuffer(data, options) {
382
+ return exportSnapshotToBuffer(await memoryToSnapshot(data, options), options);
383
+ }
384
+ async function exportToFile(data, path, options) {
385
+ await exportSnapshotToFile(await memoryToSnapshot(data, options), path, options);
386
+ }
387
+ async function exportSnapshotToBuffer(snapshot, options) {
388
+ try {
389
+ return await (await loadNativeBinding()).exchangeExportSnapshot(
390
+ toNativeSnapshot(snapshot),
391
+ JSON.stringify(nativeExportOptions(options))
392
+ );
393
+ } catch (error) {
394
+ throw exchangeError(error, "CONVERSION_FAILED" /* CONVERSION_FAILED */);
395
+ }
396
+ }
397
+ async function exportSnapshotToFile(snapshot, path, options) {
398
+ let output = await exportSnapshotToBuffer(snapshot, options);
399
+ try {
400
+ await (0, import_promises.writeFile)(path, output);
401
+ } catch (error) {
402
+ throw exchangeError(error, "IO_ERROR" /* IO_ERROR */);
403
+ }
404
+ }
405
+ // Annotate the CommonJS export names for ESM import in node:
406
+ 0 && (module.exports = {
407
+ BaseAttachmentPolicy,
408
+ BaseExportMode,
409
+ BaseFormulaPolicy,
410
+ BaseHeaderPolicy,
411
+ BaseImagePolicy,
412
+ BaseImportMode,
413
+ BaseTypeInference,
414
+ CsvFormulaMode,
415
+ CsvLineEnding,
416
+ CsvQuoteStyle,
417
+ CsvTypeInferenceMode,
418
+ CsvValueMode,
419
+ DocxCompatibilityMode,
420
+ ExchangeError,
421
+ ExchangeErrorCode,
422
+ ExchangeFormat,
423
+ FormulaCalculationMode,
424
+ exportSnapshotToBuffer,
425
+ exportSnapshotToFile,
426
+ exportToBuffer,
427
+ exportToFile,
428
+ importBuffer,
429
+ importBufferToSnapshot,
430
+ importFile,
431
+ importFileToSnapshot
432
+ });
@@ -0,0 +1,391 @@
1
+ // src/index.ts
2
+ import {
3
+ transformBaseDataToSnapshot,
4
+ transformDocumentDataToSnapshot,
5
+ transformSlideDataToSnapshot,
6
+ transformSnapshotToBaseData,
7
+ transformSnapshotToDocumentData,
8
+ transformSnapshotToSlideData,
9
+ transformSnapshotToWorkbookData,
10
+ transformWorkbookDataToSnapshot
11
+ } from "@univerjs-pro/collaboration";
12
+ import { UniverInstanceType } from "@univerjs/core";
13
+ import { basename, extname } from "node:path";
14
+ import { readFile, writeFile } from "node:fs/promises";
15
+
16
+ // src/binding.ts
17
+ import { createRequire } from "node:module";
18
+ import process from "node:process";
19
+
20
+ // src/types.ts
21
+ var ExchangeFormat = /* @__PURE__ */ ((ExchangeFormat2) => (ExchangeFormat2.XLS = "xls", ExchangeFormat2.XLSX = "xlsx", ExchangeFormat2.CSV = "csv", ExchangeFormat2.TSV = "tsv", ExchangeFormat2.DOC = "doc", ExchangeFormat2.DOCX = "docx", ExchangeFormat2.PPT = "ppt", ExchangeFormat2.PPTX = "pptx", ExchangeFormat2))(ExchangeFormat || {}), FormulaCalculationMode = /* @__PURE__ */ ((FormulaCalculationMode2) => (FormulaCalculationMode2.FORCED = "forced", FormulaCalculationMode2.WHEN_EMPTY = "when_empty", FormulaCalculationMode2.NO = "no", FormulaCalculationMode2))(FormulaCalculationMode || {}), CsvTypeInferenceMode = /* @__PURE__ */ ((CsvTypeInferenceMode2) => (CsvTypeInferenceMode2.OFF = "off", CsvTypeInferenceMode2.SAFE = "safe", CsvTypeInferenceMode2.AGGRESSIVE = "aggressive", CsvTypeInferenceMode2))(CsvTypeInferenceMode || {}), CsvQuoteStyle = /* @__PURE__ */ ((CsvQuoteStyle2) => (CsvQuoteStyle2.MINIMAL = "minimal", CsvQuoteStyle2.ALWAYS = "always", CsvQuoteStyle2))(CsvQuoteStyle || {}), CsvLineEnding = /* @__PURE__ */ ((CsvLineEnding2) => (CsvLineEnding2.LF = "lf", CsvLineEnding2.CRLF = "cr_lf", CsvLineEnding2))(CsvLineEnding || {}), CsvValueMode = /* @__PURE__ */ ((CsvValueMode2) => (CsvValueMode2.DISPLAY = "display", CsvValueMode2.RAW = "raw", CsvValueMode2))(CsvValueMode || {}), CsvFormulaMode = /* @__PURE__ */ ((CsvFormulaMode2) => (CsvFormulaMode2.CACHED = "cached", CsvFormulaMode2.EXPRESSION = "expression", CsvFormulaMode2))(CsvFormulaMode || {}), BaseImportMode = /* @__PURE__ */ ((BaseImportMode2) => (BaseImportMode2.TABLES = "tables", BaseImportMode2.SHEETS = "sheets", BaseImportMode2.HYBRID = "hybrid", BaseImportMode2.AUTO = "auto", BaseImportMode2))(BaseImportMode || {}), BaseTypeInference = /* @__PURE__ */ ((BaseTypeInference2) => (BaseTypeInference2.NONE = "none", BaseTypeInference2.SAFE = "safe", BaseTypeInference2.AGGRESSIVE = "aggressive", BaseTypeInference2))(BaseTypeInference || {}), BaseFormulaPolicy = /* @__PURE__ */ ((BaseFormulaPolicy2) => (BaseFormulaPolicy2.VALUES = "values", BaseFormulaPolicy2.TEXT = "text", BaseFormulaPolicy2.FAIL = "fail", BaseFormulaPolicy2.CONVERT_THEN_VALUES = "convertThenValues", BaseFormulaPolicy2))(BaseFormulaPolicy || {}), BaseImagePolicy = /* @__PURE__ */ ((BaseImagePolicy2) => (BaseImagePolicy2.SAFE = "safe", BaseImagePolicy2.CELL_ONLY = "cell-only", BaseImagePolicy2.MEDIA_TABLE = "media-table", BaseImagePolicy2.NONE = "none", BaseImagePolicy2))(BaseImagePolicy || {}), BaseHeaderPolicy = /* @__PURE__ */ ((BaseHeaderPolicy2) => (BaseHeaderPolicy2.FIRST_ROW = "firstRow", BaseHeaderPolicy2.NONE = "none", BaseHeaderPolicy2))(BaseHeaderPolicy || {}), BaseExportMode = /* @__PURE__ */ ((BaseExportMode2) => (BaseExportMode2.TABLES = "tables", BaseExportMode2.RANGES = "ranges", BaseExportMode2))(BaseExportMode || {}), BaseAttachmentPolicy = /* @__PURE__ */ ((BaseAttachmentPolicy2) => (BaseAttachmentPolicy2.HYBRID = "hybrid", BaseAttachmentPolicy2.MANIFEST = "manifest", BaseAttachmentPolicy2.LINKS = "links", BaseAttachmentPolicy2.NONE = "none", BaseAttachmentPolicy2))(BaseAttachmentPolicy || {}), DocxCompatibilityMode = /* @__PURE__ */ ((DocxCompatibilityMode2) => (DocxCompatibilityMode2.TRADITIONAL = "traditional", DocxCompatibilityMode2.MODERN = "modern", DocxCompatibilityMode2))(DocxCompatibilityMode || {}), ExchangeErrorCode = /* @__PURE__ */ ((ExchangeErrorCode2) => (ExchangeErrorCode2.INVALID_ARGUMENT = "INVALID_ARGUMENT", ExchangeErrorCode2.UNSUPPORTED_FORMAT = "UNSUPPORTED_FORMAT", ExchangeErrorCode2.INVALID_FILE = "INVALID_FILE", ExchangeErrorCode2.INCOMPLETE_SNAPSHOT = "INCOMPLETE_SNAPSHOT", ExchangeErrorCode2.IO_ERROR = "IO_ERROR", ExchangeErrorCode2.NATIVE_LOAD_FAILED = "NATIVE_LOAD_FAILED", ExchangeErrorCode2.CONVERSION_FAILED = "CONVERSION_FAILED", ExchangeErrorCode2))(ExchangeErrorCode || {}), ExchangeError = class extends Error {
22
+ constructor(code, message, options) {
23
+ super(message, options);
24
+ this.code = code;
25
+ }
26
+ code;
27
+ name = "ExchangeError";
28
+ };
29
+
30
+ // src/binding.ts
31
+ var nativeBinding = null, nativeBindingSource = null, nodeRequire = createRequire(import.meta.url);
32
+ function errorMessage(error) {
33
+ return error instanceof Error ? error.message : String(error);
34
+ }
35
+ async function loadNativeBinding() {
36
+ if (nativeBinding)
37
+ return nativeBinding;
38
+ let errors = [];
39
+ try {
40
+ return nativeBinding = nodeRequire("@univerjs-pro/exchange-node-binding"), nativeBindingSource = "@univerjs-pro/exchange-node-binding", nativeBinding;
41
+ } catch (error) {
42
+ errors.push(`@univerjs-pro/exchange-node-binding: ${errorMessage(error)}`);
43
+ }
44
+ throw new ExchangeError(
45
+ "NATIVE_LOAD_FAILED" /* NATIVE_LOAD_FAILED */,
46
+ [
47
+ "Failed to load native exchange binding.",
48
+ `platform=${process.platform}`,
49
+ `arch=${process.arch}`,
50
+ "expected npm package=@univerjs-pro/exchange-node-binding",
51
+ "attempted paths:",
52
+ ...errors.map((item) => `- ${item}`)
53
+ ].join(`
54
+ `)
55
+ );
56
+ }
57
+
58
+ // src/snapshot-collector.ts
59
+ import { ErrorCode } from "@univerjs/protocol";
60
+ function createSnapshotCollector() {
61
+ let sheetBlocks = /* @__PURE__ */ new Map();
62
+ return {
63
+ // The public Pro conversion functions accept the host-wide service
64
+ // contract even though these conversion paths use its two write methods.
65
+ service: {
66
+ async saveSheetBlock(_context, { block }) {
67
+ return block ? (sheetBlocks.set(block.id, block), {
68
+ blockID: block.id,
69
+ error: { code: ErrorCode.OK, message: "" }
70
+ }) : {
71
+ blockID: "",
72
+ error: { code: ErrorCode.UNDEFINED, message: "block is required" }
73
+ };
74
+ },
75
+ async saveSnapshot() {
76
+ return { error: { code: ErrorCode.OK, message: "" } };
77
+ }
78
+ },
79
+ get sheetBlocks() {
80
+ return [...sheetBlocks.values()];
81
+ }
82
+ };
83
+ }
84
+
85
+ // src/snapshot.ts
86
+ import { Buffer as NodeBuffer } from "node:buffer";
87
+ function bufferView(bytes) {
88
+ return NodeBuffer.isBuffer(bytes) ? bytes : NodeBuffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
89
+ }
90
+ function takeMetadata(owner, kind, metadata, ownerId) {
91
+ if (!owner)
92
+ return owner;
93
+ let { originalMeta, ...rest } = owner;
94
+ if (originalMeta instanceof Uint8Array)
95
+ metadata.push({ kind, ownerId, data: bufferView(originalMeta) });
96
+ else if (originalMeta != null)
97
+ throw new TypeError(`${kind} originalMeta must be a Uint8Array`);
98
+ return rest;
99
+ }
100
+ function toNativeSnapshot(value) {
101
+ let metadata = [], source = value.snapshot, snapshot = { ...source }, sourceWorkbook = source.workbook;
102
+ if (sourceWorkbook) {
103
+ let workbook = takeMetadata(sourceWorkbook, "workbook", metadata), sourceSheets = sourceWorkbook.sheets;
104
+ sourceSheets && (workbook.sheets = Object.fromEntries(
105
+ Object.entries(sourceSheets).map(([sheetId, sheet]) => [
106
+ sheetId,
107
+ takeMetadata(sheet, "worksheet", metadata, sheetId)
108
+ ])
109
+ )), snapshot.workbook = workbook;
110
+ }
111
+ for (let kind of ["doc", "slide"]) {
112
+ let owner = source[kind];
113
+ owner && (snapshot[kind] = takeMetadata(owner, kind, metadata));
114
+ }
115
+ return {
116
+ snapshotJson: NodeBuffer.from(JSON.stringify(snapshot)),
117
+ metadata,
118
+ sheetBlocks: value.sheetBlocks.map((block) => ({
119
+ id: block.id,
120
+ startRow: block.startRow,
121
+ endRow: block.endRow,
122
+ data: bufferView(block.data)
123
+ }))
124
+ };
125
+ }
126
+ function restoreMetadata(snapshot, metadata) {
127
+ for (let entry of metadata) {
128
+ let owner;
129
+ if (entry.kind === "worksheet") {
130
+ let sheets = snapshot.workbook?.sheets;
131
+ owner = entry.ownerId ? sheets?.[entry.ownerId] : void 0;
132
+ } else {
133
+ if (entry.kind !== "workbook" && entry.kind !== "doc" && entry.kind !== "slide")
134
+ throw new TypeError(`unsupported native snapshot metadata kind ${entry.kind}`);
135
+ owner = snapshot[entry.kind];
136
+ }
137
+ if (!owner)
138
+ throw new TypeError(`native snapshot metadata owner ${entry.kind}/${entry.ownerId ?? ""} is missing`);
139
+ owner.originalMeta = entry.data;
140
+ }
141
+ }
142
+ function fromNativeSnapshot(value) {
143
+ let snapshot = JSON.parse(value.snapshotJson.toString("utf8"));
144
+ return restoreMetadata(snapshot, value.metadata), {
145
+ snapshot,
146
+ sheetBlocks: value.sheetBlocks.map((block) => ({
147
+ id: block.id,
148
+ startRow: block.startRow,
149
+ endRow: block.endRow,
150
+ data: block.data
151
+ }))
152
+ };
153
+ }
154
+
155
+ // src/index.ts
156
+ var FORMAT_BY_EXTENSION = {
157
+ ".xls": "xls" /* XLS */,
158
+ ".xlsx": "xlsx" /* XLSX */,
159
+ ".csv": "csv" /* CSV */,
160
+ ".tsv": "tsv" /* TSV */,
161
+ ".doc": "doc" /* DOC */,
162
+ ".docx": "docx" /* DOCX */,
163
+ ".ppt": "ppt" /* PPT */,
164
+ ".pptx": "pptx" /* PPTX */
165
+ };
166
+ function normalizeWorkbookSheetOrder(data) {
167
+ let existingOrder = Array.isArray(data.sheetOrder) ? data.sheetOrder.filter((sheetId) => typeof sheetId == "string") : [], ordered = new Set(existingOrder), missingSheetIds = Object.keys(data.sheets).filter((sheetId) => !ordered.has(sheetId));
168
+ return missingSheetIds.length === 0 ? data : { ...data, sheetOrder: [...existingOrder, ...missingSheetIds] };
169
+ }
170
+ function exchangeError(error, fallback) {
171
+ if (error instanceof ExchangeError)
172
+ return error;
173
+ let message = error instanceof Error ? error.message : String(error), nativeCode = /^\[([A-Z_]+)]\s*/.exec(message)?.[1];
174
+ return nativeCode && Object.values(ExchangeErrorCode).includes(nativeCode) ? new ExchangeError(nativeCode, message.replace(/^\[[A-Z_]+]\s*/, ""), {
175
+ cause: error
176
+ }) : error instanceof TypeError ? new ExchangeError("INVALID_ARGUMENT" /* INVALID_ARGUMENT */, message, { cause: error }) : new ExchangeError(fallback, message, { cause: error });
177
+ }
178
+ function resolveFormat(fileName, format) {
179
+ if (format)
180
+ return format;
181
+ let inferred = FORMAT_BY_EXTENSION[extname(fileName).toLowerCase()];
182
+ if (!inferred)
183
+ throw new ExchangeError(
184
+ "UNSUPPORTED_FORMAT" /* UNSUPPORTED_FORMAT */,
185
+ `Cannot infer an exchange format from fileName: ${fileName}`
186
+ );
187
+ return inferred;
188
+ }
189
+ function nativeUnitType(type) {
190
+ switch (type) {
191
+ case UniverInstanceType.UNIVER_SHEET:
192
+ return "sheet";
193
+ case UniverInstanceType.UNIVER_BASE:
194
+ return "base";
195
+ case UniverInstanceType.UNIVER_DOC:
196
+ return "doc";
197
+ case UniverInstanceType.UNIVER_SLIDE:
198
+ return "slide";
199
+ default:
200
+ throw new ExchangeError("INVALID_ARGUMENT" /* INVALID_ARGUMENT */, `Unsupported Univer unit type: ${type}`);
201
+ }
202
+ }
203
+ function nativeImportOptions(options, fileName) {
204
+ return {
205
+ format: resolveFormat(fileName, options.format),
206
+ unitType: nativeUnitType(options.type),
207
+ fileName,
208
+ unitId: options.unitId,
209
+ minSheetRowCount: "minSheetRowCount" in options ? options.minSheetRowCount : void 0,
210
+ minSheetColumnCount: "minSheetColumnCount" in options ? options.minSheetColumnCount : void 0,
211
+ compatibilityMode: "compatibilityMode" in options ? options.compatibilityMode : void 0,
212
+ csv: "csv" in options ? options.csv : void 0,
213
+ base: options.type === UniverInstanceType.UNIVER_BASE ? {
214
+ mode: options.mode,
215
+ typeInference: options.typeInference,
216
+ formulaPolicy: options.formulaPolicy,
217
+ imagePolicy: options.imagePolicy,
218
+ maxCells: options.maxCells,
219
+ mapping: options.mapping
220
+ } : void 0,
221
+ formulaCalculation: "formulaCalculation" in options ? options.formulaCalculation : void 0
222
+ };
223
+ }
224
+ function nativeExportOptions(options) {
225
+ return {
226
+ format: options.format,
227
+ unitType: nativeUnitType(options.type),
228
+ csv: "csv" in options ? options.csv : void 0,
229
+ base: options.type === UniverInstanceType.UNIVER_BASE && options.format === "xlsx" /* XLSX */ ? {
230
+ mode: options.mode,
231
+ formulaPolicy: options.formulaPolicy,
232
+ attachmentPolicy: options.attachmentPolicy,
233
+ mapping: options.mapping
234
+ } : void 0,
235
+ formulaCalculation: "formulaCalculation" in options ? options.formulaCalculation : void 0
236
+ };
237
+ }
238
+ async function importSnapshot(input, options, fileName) {
239
+ try {
240
+ let result = await (await loadNativeBinding()).exchangeImportToSnapshot(
241
+ input,
242
+ JSON.stringify(nativeImportOptions(options, fileName))
243
+ );
244
+ return fromNativeSnapshot(result);
245
+ } catch (error) {
246
+ throw exchangeError(error, "CONVERSION_FAILED" /* CONVERSION_FAILED */);
247
+ }
248
+ }
249
+ async function snapshotToMemory(snapshot, type) {
250
+ try {
251
+ switch (type) {
252
+ case UniverInstanceType.UNIVER_SHEET:
253
+ return await transformSnapshotToWorkbookData(snapshot.snapshot, snapshot.sheetBlocks);
254
+ case UniverInstanceType.UNIVER_BASE:
255
+ return await transformSnapshotToBaseData(snapshot.snapshot, snapshot.sheetBlocks);
256
+ case UniverInstanceType.UNIVER_DOC:
257
+ return transformSnapshotToDocumentData(snapshot.snapshot);
258
+ case UniverInstanceType.UNIVER_SLIDE:
259
+ return transformSnapshotToSlideData(snapshot.snapshot);
260
+ default:
261
+ throw new TypeError(`Unsupported Univer unit type: ${type}`);
262
+ }
263
+ } catch (error) {
264
+ throw exchangeError(error, "CONVERSION_FAILED" /* CONVERSION_FAILED */);
265
+ }
266
+ }
267
+ async function memoryToSnapshot(data, options) {
268
+ try {
269
+ let unitId = data.id;
270
+ if (!unitId)
271
+ throw new ExchangeError("INVALID_ARGUMENT" /* INVALID_ARGUMENT */, "Export data must have a non-empty id");
272
+ let rev = data.rev ?? 0, collector = createSnapshotCollector();
273
+ switch (options.type) {
274
+ case UniverInstanceType.UNIVER_SHEET: {
275
+ let workbook = normalizeWorkbookSheetOrder(data), { snapshot } = await transformWorkbookDataToSnapshot(
276
+ { metadata: void 0 },
277
+ workbook,
278
+ unitId,
279
+ rev,
280
+ collector.service
281
+ );
282
+ return { snapshot, sheetBlocks: collector.sheetBlocks };
283
+ }
284
+ case UniverInstanceType.UNIVER_BASE: {
285
+ let { snapshot } = await transformBaseDataToSnapshot(
286
+ { metadata: void 0 },
287
+ data,
288
+ unitId,
289
+ rev,
290
+ collector.service
291
+ );
292
+ return { snapshot, sheetBlocks: collector.sheetBlocks };
293
+ }
294
+ case UniverInstanceType.UNIVER_DOC: {
295
+ let { snapshot } = await transformDocumentDataToSnapshot(
296
+ { metadata: void 0 },
297
+ data,
298
+ unitId,
299
+ rev,
300
+ collector.service
301
+ );
302
+ return { snapshot, sheetBlocks: [] };
303
+ }
304
+ case UniverInstanceType.UNIVER_SLIDE: {
305
+ let slide = data, { snapshot } = await transformSlideDataToSnapshot(
306
+ slide.resources,
307
+ slide,
308
+ unitId,
309
+ rev,
310
+ collector.service
311
+ );
312
+ return { snapshot, sheetBlocks: [] };
313
+ }
314
+ default:
315
+ throw new TypeError("Unsupported Univer unit type");
316
+ }
317
+ } catch (error) {
318
+ throw exchangeError(error, "CONVERSION_FAILED" /* CONVERSION_FAILED */);
319
+ }
320
+ }
321
+ async function importFile(path, options) {
322
+ let snapshot = await importFileToSnapshot(path, options);
323
+ return snapshotToMemory(snapshot, options.type);
324
+ }
325
+ async function importBuffer(input, options) {
326
+ let snapshot = await importSnapshot(input, options, options.fileName);
327
+ return snapshotToMemory(snapshot, options.type);
328
+ }
329
+ async function importFileToSnapshot(path, options) {
330
+ let fileName = options.fileName ?? basename(path), input;
331
+ try {
332
+ input = await readFile(path);
333
+ } catch (error) {
334
+ throw exchangeError(error, "IO_ERROR" /* IO_ERROR */);
335
+ }
336
+ return importSnapshot(input, options, fileName);
337
+ }
338
+ async function importBufferToSnapshot(input, options) {
339
+ return importSnapshot(input, options, options.fileName);
340
+ }
341
+ async function exportToBuffer(data, options) {
342
+ return exportSnapshotToBuffer(await memoryToSnapshot(data, options), options);
343
+ }
344
+ async function exportToFile(data, path, options) {
345
+ await exportSnapshotToFile(await memoryToSnapshot(data, options), path, options);
346
+ }
347
+ async function exportSnapshotToBuffer(snapshot, options) {
348
+ try {
349
+ return await (await loadNativeBinding()).exchangeExportSnapshot(
350
+ toNativeSnapshot(snapshot),
351
+ JSON.stringify(nativeExportOptions(options))
352
+ );
353
+ } catch (error) {
354
+ throw exchangeError(error, "CONVERSION_FAILED" /* CONVERSION_FAILED */);
355
+ }
356
+ }
357
+ async function exportSnapshotToFile(snapshot, path, options) {
358
+ let output = await exportSnapshotToBuffer(snapshot, options);
359
+ try {
360
+ await writeFile(path, output);
361
+ } catch (error) {
362
+ throw exchangeError(error, "IO_ERROR" /* IO_ERROR */);
363
+ }
364
+ }
365
+ export {
366
+ BaseAttachmentPolicy,
367
+ BaseExportMode,
368
+ BaseFormulaPolicy,
369
+ BaseHeaderPolicy,
370
+ BaseImagePolicy,
371
+ BaseImportMode,
372
+ BaseTypeInference,
373
+ CsvFormulaMode,
374
+ CsvLineEnding,
375
+ CsvQuoteStyle,
376
+ CsvTypeInferenceMode,
377
+ CsvValueMode,
378
+ DocxCompatibilityMode,
379
+ ExchangeError,
380
+ ExchangeErrorCode,
381
+ ExchangeFormat,
382
+ FormulaCalculationMode,
383
+ exportSnapshotToBuffer,
384
+ exportSnapshotToFile,
385
+ exportToBuffer,
386
+ exportToFile,
387
+ importBuffer,
388
+ importBufferToSnapshot,
389
+ importFile,
390
+ importFileToSnapshot
391
+ };
@@ -0,0 +1,256 @@
1
+ import { ISlideData } from "@univerjs-pro/slides";
2
+ import { IBaseSnapshot, IDocumentData, IWorkbookData, UniverInstanceType } from "@univerjs/core";
3
+ import { Buffer } from "node:buffer";
4
+ import { ISheetBlock, ISnapshot } from "@univerjs/protocol";
5
+ //#region src/types.d.ts
6
+ declare enum ExchangeFormat {
7
+ XLS = "xls",
8
+ XLSX = "xlsx",
9
+ CSV = "csv",
10
+ TSV = "tsv",
11
+ DOC = "doc",
12
+ DOCX = "docx",
13
+ PPT = "ppt",
14
+ PPTX = "pptx"
15
+ }
16
+ declare enum FormulaCalculationMode {
17
+ FORCED = "forced",
18
+ WHEN_EMPTY = "when_empty",
19
+ NO = "no"
20
+ }
21
+ declare enum CsvTypeInferenceMode {
22
+ OFF = "off",
23
+ SAFE = "safe",
24
+ AGGRESSIVE = "aggressive"
25
+ }
26
+ declare enum CsvQuoteStyle {
27
+ MINIMAL = "minimal",
28
+ ALWAYS = "always"
29
+ }
30
+ declare enum CsvLineEnding {
31
+ LF = "lf",
32
+ CRLF = "cr_lf"
33
+ }
34
+ declare enum CsvValueMode {
35
+ DISPLAY = "display",
36
+ RAW = "raw"
37
+ }
38
+ declare enum CsvFormulaMode {
39
+ CACHED = "cached",
40
+ EXPRESSION = "expression"
41
+ }
42
+ declare enum BaseImportMode {
43
+ TABLES = "tables",
44
+ SHEETS = "sheets",
45
+ HYBRID = "hybrid",
46
+ AUTO = "auto"
47
+ }
48
+ declare enum BaseTypeInference {
49
+ NONE = "none",
50
+ SAFE = "safe",
51
+ AGGRESSIVE = "aggressive"
52
+ }
53
+ declare enum BaseFormulaPolicy {
54
+ VALUES = "values",
55
+ TEXT = "text",
56
+ FAIL = "fail",
57
+ CONVERT_THEN_VALUES = "convertThenValues"
58
+ }
59
+ declare enum BaseImagePolicy {
60
+ SAFE = "safe",
61
+ CELL_ONLY = "cell-only",
62
+ MEDIA_TABLE = "media-table",
63
+ NONE = "none"
64
+ }
65
+ declare enum BaseHeaderPolicy {
66
+ FIRST_ROW = "firstRow",
67
+ NONE = "none"
68
+ }
69
+ declare enum BaseExportMode {
70
+ TABLES = "tables",
71
+ RANGES = "ranges"
72
+ }
73
+ declare enum BaseAttachmentPolicy {
74
+ HYBRID = "hybrid",
75
+ MANIFEST = "manifest",
76
+ LINKS = "links",
77
+ NONE = "none"
78
+ }
79
+ declare enum DocxCompatibilityMode {
80
+ TRADITIONAL = "traditional",
81
+ MODERN = "modern"
82
+ }
83
+ interface IBaseFieldMapping {
84
+ name?: string;
85
+ type?: string;
86
+ config?: unknown;
87
+ formulaPolicy?: BaseFormulaPolicy;
88
+ }
89
+ interface IBaseTableMapping {
90
+ include?: boolean;
91
+ name?: string;
92
+ primaryField?: string;
93
+ header?: BaseHeaderPolicy;
94
+ formulaPolicy?: BaseFormulaPolicy;
95
+ fields?: Record<string, IBaseFieldMapping>;
96
+ }
97
+ interface IBaseImportMapping {
98
+ selectedOnly?: boolean;
99
+ tables?: Record<string, IBaseTableMapping>;
100
+ sheets?: Record<string, IBaseTableMapping>;
101
+ }
102
+ interface IBaseExportMapping {
103
+ tables?: Record<string, {
104
+ name?: string;
105
+ fields?: Record<string, {
106
+ name?: string;
107
+ }>;
108
+ }>;
109
+ }
110
+ interface ICsvImportOptions {
111
+ delimiter?: 'auto' | 'comma' | 'tab' | 'semicolon' | 'pipe' | 'space' | string;
112
+ quote?: 'auto' | 'none' | 'double' | 'single' | string;
113
+ encoding?: string;
114
+ inferTypes?: CsvTypeInferenceMode;
115
+ }
116
+ type ICsvExportSelector = {
117
+ worksheetId: string;
118
+ worksheetName?: never;
119
+ tableId?: never;
120
+ tableName?: never;
121
+ } | {
122
+ worksheetId?: never;
123
+ worksheetName: string;
124
+ tableId?: never;
125
+ tableName?: never;
126
+ } | {
127
+ worksheetId?: never;
128
+ worksheetName?: never;
129
+ tableId: string;
130
+ tableName?: never;
131
+ } | {
132
+ worksheetId?: never;
133
+ worksheetName?: never;
134
+ tableId?: never;
135
+ tableName: string;
136
+ };
137
+ type ICsvExportOptions = ICsvExportSelector & {
138
+ delimiter?: 'comma' | 'tab' | 'semicolon' | 'pipe' | 'space' | string;
139
+ quoteStyle?: CsvQuoteStyle;
140
+ lineEnding?: CsvLineEnding;
141
+ encoding?: string;
142
+ valueMode?: CsvValueMode;
143
+ formulaMode?: CsvFormulaMode;
144
+ };
145
+ interface IImportOptionsBase<TType extends UniverInstanceType, TFormat extends ExchangeFormat> {
146
+ type: TType;
147
+ format?: TFormat;
148
+ fileName?: string;
149
+ unitId?: string;
150
+ }
151
+ interface IGridImportOptions {
152
+ minSheetRowCount?: number;
153
+ minSheetColumnCount?: number;
154
+ }
155
+ type ISheetImportOptions = IGridImportOptions & ((IImportOptionsBase<UniverInstanceType.UNIVER_SHEET, ExchangeFormat.XLS> & {
156
+ csv?: never;
157
+ formulaCalculation?: never;
158
+ }) | (IImportOptionsBase<UniverInstanceType.UNIVER_SHEET, ExchangeFormat.XLSX> & {
159
+ csv?: never;
160
+ formulaCalculation?: FormulaCalculationMode;
161
+ }) | (IImportOptionsBase<UniverInstanceType.UNIVER_SHEET, ExchangeFormat.CSV | ExchangeFormat.TSV> & {
162
+ csv?: ICsvImportOptions;
163
+ formulaCalculation?: never;
164
+ }));
165
+ interface IBaseImportConfig extends IGridImportOptions {
166
+ mode?: BaseImportMode;
167
+ typeInference?: BaseTypeInference;
168
+ formulaPolicy?: BaseFormulaPolicy;
169
+ imagePolicy?: BaseImagePolicy;
170
+ maxCells?: number | null;
171
+ mapping?: IBaseImportMapping;
172
+ }
173
+ type IBaseImportOptions = IBaseImportConfig & ((IImportOptionsBase<UniverInstanceType.UNIVER_BASE, ExchangeFormat.XLS | ExchangeFormat.XLSX> & {
174
+ csv?: never;
175
+ }) | (IImportOptionsBase<UniverInstanceType.UNIVER_BASE, ExchangeFormat.CSV | ExchangeFormat.TSV> & {
176
+ csv?: ICsvImportOptions;
177
+ }));
178
+ interface IDocImportOptions extends IImportOptionsBase<UniverInstanceType.UNIVER_DOC, ExchangeFormat.DOC | ExchangeFormat.DOCX> {
179
+ compatibilityMode?: DocxCompatibilityMode;
180
+ }
181
+ interface ISlideImportOptions extends IImportOptionsBase<UniverInstanceType.UNIVER_SLIDE, ExchangeFormat.PPT | ExchangeFormat.PPTX> {}
182
+ type ImportOptions = ISheetImportOptions | IBaseImportOptions | IDocImportOptions | ISlideImportOptions;
183
+ type BufferImportOptions<T extends ImportOptions = ImportOptions> = T & {
184
+ fileName: string;
185
+ };
186
+ interface IExportOptionsBase<TType extends UniverInstanceType, TFormat extends ExchangeFormat> {
187
+ type: TType;
188
+ format: TFormat;
189
+ }
190
+ interface ISheetExportConfig {
191
+ /** @default FormulaCalculationMode.WHEN_EMPTY */
192
+ formulaCalculation?: FormulaCalculationMode;
193
+ }
194
+ type ISheetExportOptions = ISheetExportConfig & ((IExportOptionsBase<UniverInstanceType.UNIVER_SHEET, ExchangeFormat.XLSX> & {
195
+ csv?: never;
196
+ }) | (IExportOptionsBase<UniverInstanceType.UNIVER_SHEET, ExchangeFormat.CSV | ExchangeFormat.TSV> & {
197
+ csv: ICsvExportOptions;
198
+ }));
199
+ interface IBaseXlsxExportConfig {
200
+ mode?: BaseExportMode;
201
+ formulaPolicy?: BaseFormulaPolicy;
202
+ attachmentPolicy?: BaseAttachmentPolicy;
203
+ mapping?: IBaseExportMapping;
204
+ }
205
+ type IBaseExportOptions = (IExportOptionsBase<UniverInstanceType.UNIVER_BASE, ExchangeFormat.XLSX> & IBaseXlsxExportConfig & {
206
+ csv?: never;
207
+ }) | (IExportOptionsBase<UniverInstanceType.UNIVER_BASE, ExchangeFormat.CSV | ExchangeFormat.TSV> & {
208
+ csv: ICsvExportOptions;
209
+ });
210
+ interface IDocExportOptions extends IExportOptionsBase<UniverInstanceType.UNIVER_DOC, ExchangeFormat.DOCX> {}
211
+ interface ISlideExportOptions extends IExportOptionsBase<UniverInstanceType.UNIVER_SLIDE, ExchangeFormat.PPTX> {}
212
+ type ExportOptions = ISheetExportOptions | IBaseExportOptions | IDocExportOptions | ISlideExportOptions;
213
+ interface ISnapshotWithBlocks {
214
+ snapshot: ISnapshot;
215
+ sheetBlocks: ISheetBlock[];
216
+ }
217
+ declare enum ExchangeErrorCode {
218
+ INVALID_ARGUMENT = "INVALID_ARGUMENT",
219
+ UNSUPPORTED_FORMAT = "UNSUPPORTED_FORMAT",
220
+ INVALID_FILE = "INVALID_FILE",
221
+ INCOMPLETE_SNAPSHOT = "INCOMPLETE_SNAPSHOT",
222
+ IO_ERROR = "IO_ERROR",
223
+ NATIVE_LOAD_FAILED = "NATIVE_LOAD_FAILED",
224
+ CONVERSION_FAILED = "CONVERSION_FAILED"
225
+ }
226
+ declare class ExchangeError extends Error {
227
+ readonly code: ExchangeErrorCode;
228
+ readonly name = "ExchangeError";
229
+ constructor(code: ExchangeErrorCode, message: string, options?: {
230
+ cause?: unknown;
231
+ });
232
+ }
233
+ //#endregion
234
+ //#region src/index.d.ts
235
+ declare function importFile(path: string, options: ISheetImportOptions): Promise<IWorkbookData>;
236
+ declare function importFile(path: string, options: IBaseImportOptions): Promise<IBaseSnapshot>;
237
+ declare function importFile(path: string, options: IDocImportOptions): Promise<IDocumentData>;
238
+ declare function importFile(path: string, options: ISlideImportOptions): Promise<ISlideData>;
239
+ declare function importBuffer(input: Buffer, options: BufferImportOptions<ISheetImportOptions>): Promise<IWorkbookData>;
240
+ declare function importBuffer(input: Buffer, options: BufferImportOptions<IBaseImportOptions>): Promise<IBaseSnapshot>;
241
+ declare function importBuffer(input: Buffer, options: BufferImportOptions<IDocImportOptions>): Promise<IDocumentData>;
242
+ declare function importBuffer(input: Buffer, options: BufferImportOptions<ISlideImportOptions>): Promise<ISlideData>;
243
+ declare function importFileToSnapshot(path: string, options: ImportOptions): Promise<ISnapshotWithBlocks>;
244
+ declare function importBufferToSnapshot<T extends ImportOptions>(input: Buffer, options: BufferImportOptions<T>): Promise<ISnapshotWithBlocks>;
245
+ declare function exportToBuffer(data: IWorkbookData, options: ISheetExportOptions): Promise<Buffer>;
246
+ declare function exportToBuffer(data: IBaseSnapshot, options: IBaseExportOptions): Promise<Buffer>;
247
+ declare function exportToBuffer(data: IDocumentData, options: IDocExportOptions): Promise<Buffer>;
248
+ declare function exportToBuffer(data: ISlideData, options: ISlideExportOptions): Promise<Buffer>;
249
+ declare function exportToFile(data: IWorkbookData, path: string, options: ISheetExportOptions): Promise<void>;
250
+ declare function exportToFile(data: IBaseSnapshot, path: string, options: IBaseExportOptions): Promise<void>;
251
+ declare function exportToFile(data: IDocumentData, path: string, options: IDocExportOptions): Promise<void>;
252
+ declare function exportToFile(data: ISlideData, path: string, options: ISlideExportOptions): Promise<void>;
253
+ declare function exportSnapshotToBuffer(snapshot: ISnapshotWithBlocks, options: ExportOptions): Promise<Buffer>;
254
+ declare function exportSnapshotToFile(snapshot: ISnapshotWithBlocks, path: string, options: ExportOptions): Promise<void>;
255
+ //#endregion
256
+ export { BaseAttachmentPolicy, BaseExportMode, BaseFormulaPolicy, BaseHeaderPolicy, BaseImagePolicy, BaseImportMode, BaseTypeInference, BufferImportOptions, CsvFormulaMode, CsvLineEnding, CsvQuoteStyle, CsvTypeInferenceMode, CsvValueMode, DocxCompatibilityMode, ExchangeError, ExchangeErrorCode, ExchangeFormat, ExportOptions, FormulaCalculationMode, IBaseExportMapping, IBaseExportOptions, IBaseFieldMapping, IBaseImportMapping, IBaseImportOptions, IBaseTableMapping, ICsvExportOptions, ICsvExportSelector, ICsvImportOptions, IDocExportOptions, IDocImportOptions, IExportOptionsBase, IGridImportOptions, IImportOptionsBase, ISheetExportOptions, ISheetImportOptions, ISlideExportOptions, ISlideImportOptions, ISnapshotWithBlocks, ImportOptions, exportSnapshotToBuffer, exportSnapshotToFile, exportToBuffer, exportToFile, importBuffer, importBufferToSnapshot, importFile, importFileToSnapshot };
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "author": "DreamNum Co., Ltd. <developer@univer.ai>",
3
+ "dependencies": {
4
+ "@univerjs-pro/collaboration": "1.0.0-beta.2",
5
+ "@univerjs-pro/exchange-node-binding": "0.1.0",
6
+ "@univerjs-pro/slides": "1.0.0-beta.2",
7
+ "@univerjs/core": "1.0.0-beta.2",
8
+ "@univerjs/protocol": "1.0.0-beta.2"
9
+ },
10
+ "description": "Node.js SDK for converting between Office formats, Univer unit data, and snapshots",
11
+ "files": [
12
+ "lib",
13
+ "README.md"
14
+ ],
15
+ "name": "@univerjs-pro/exchange-node",
16
+ "type": "module",
17
+ "version": "1.0.0-beta.2",
18
+ "main": "./lib/cjs/index.cjs",
19
+ "module": "./lib/es/index.js",
20
+ "types": "./lib/types/index.d.ts",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./lib/types/index.d.ts",
24
+ "import": "./lib/es/index.js",
25
+ "require": "./lib/cjs/index.cjs",
26
+ "default": "./lib/es/index.js"
27
+ }
28
+ },
29
+ "publishConfig": {
30
+ "main": "./lib/cjs/index.cjs",
31
+ "module": "./lib/es/index.js",
32
+ "types": "./lib/types/index.d.ts",
33
+ "exports": {
34
+ ".": {
35
+ "types": "./lib/types/index.d.ts",
36
+ "import": "./lib/es/index.js",
37
+ "require": "./lib/cjs/index.cjs",
38
+ "default": "./lib/es/index.js"
39
+ }
40
+ },
41
+ "access": "public"
42
+ }
43
+ }