@dipanshuhandoo/excelio 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # Changelog
2
+
3
+ ## 0.1.0 (Unreleased)
4
+
5
+ - Package as `@dipanshuhandoo/excelio`, supporting Node.js 22 and 24 LTS.
6
+ - Add readable/minified ESM and CommonJS builds, worker bundles, and declarations.
7
+ - Preserve Buffer results across worker threads and keep stream inputs inline.
8
+ - Add installed-tarball consumer verification and explicit public npm commands.
9
+ - Add runnable use-case examples, including XLSX-to-JSON conversion, selection/cleanup
10
+ tooling, and CI coverage.
11
+ - Document XLSX API behavior, memory limitations, and release/support policies.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DipanshuHandoo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,242 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
1
+ # ExcelIO
2
+
3
+ `@dipanshuhandoo/excelio` converts JavaScript row objects to XLSX workbooks and
4
+ reads XLSX files into structured data. It supports streaming writes, multiple
5
+ sheets/workbooks, row transforms and validation, and configurable worker-thread
6
+ offloading. It is a Node.js library, not a browser library.
7
+
8
+ ## Installation
9
+
10
+ ```sh
11
+ npm install @dipanshuhandoo/excelio
12
+ ```
13
+
14
+ Requires Node.js 22 or later. Node 22 and 24 LTS are the tested support matrix.
15
+ TypeScript consumers should install `typescript` and `@types/node` as development
16
+ dependencies; NodeNext resolution supports both import and require declarations.
17
+
18
+ ## Quick Start
19
+
20
+ ```js
21
+ import { excelio } from '@dipanshuhandoo/excelio';
22
+
23
+ const spec = [{
24
+ workbook: 'sales',
25
+ properties: { author: 'system', title: 'Sales Report' },
26
+ sheets: [{
27
+ sheet: 'Orders',
28
+ columns: [
29
+ { key: 'customer', header: 'Customer', width: 30 },
30
+ { key: 'amount', type: 'number', format: '#,##0.00' },
31
+ { key: 'date', type: 'date' }
32
+ ],
33
+ styling: { headerBold: true, freezeHeader: true, autoFilter: true },
34
+ data: [{ customer: 'Alice', amount: 100, date: new Date('2026-01-15') }]
35
+ }]
36
+ }];
37
+
38
+ const buffer = await excelio.write(spec);
39
+ await excelio.write(spec, { to: 'sales.xlsx' });
40
+ const result = await excelio.read(buffer);
41
+ console.log(result.data[0].sheets[0].data);
42
+ ```
43
+
44
+ CommonJS exposes the same named exports:
45
+
46
+ ```js
47
+ const { excelio, ExcelIoError } = require('@dipanshuhandoo/excelio');
48
+ ```
49
+
50
+ Opt-in minified builds have the same API and include their own worker files:
51
+
52
+ ```js
53
+ import { excelio } from '@dipanshuhandoo/excelio/min';
54
+ // CommonJS: const { excelio } = require('@dipanshuhandoo/excelio/min');
55
+ ```
56
+
57
+ Minification reduces library code size, not ExcelJS's installed dependencies or
58
+ workbook-processing time. Both builds include source maps and declarations.
59
+
60
+ ## Runnable Examples
61
+
62
+ See the [example guide](https://github.com/DipanshuHandoo/excelio/blob/main/examples/README.md)
63
+ for buffer round-trips, styled multi-sheet reports, validated imports, streaming,
64
+ workers/concurrent exports, progress/cancellation, CommonJS/minified usage, and
65
+ XLSX-to-JSON conversion.
66
+ Examples live in the repository and use public package exports.
67
+
68
+ From a checkout, run all cases or select one:
69
+
70
+ ```sh
71
+ npm run examples
72
+ npm run examples -- 03-import-validation
73
+ ```
74
+
75
+ The runner builds first, checks results, and cleans up temporary spreadsheets.
76
+ Run the file examples directly after building to keep their XLSX/JSON output:
77
+
78
+ ```sh
79
+ node examples/02-sales-report.mjs
80
+ node examples/04-streaming.mjs
81
+ node examples/08-excel-to-json.mjs
82
+ ```
83
+
84
+ These save to the ignored example-output/ directory by default.
85
+
86
+ ## API
87
+
88
+ ### Writing
89
+
90
+ - `await excelio.write(spec)` returns a Buffer for one workbook or Buffer[] for
91
+ multiple workbooks.
92
+ - `await excelio.write(spec, { to: filePath })` writes one workbook and returns
93
+ the path. A writable stream target is also supported and returned unchanged.
94
+ - `excelio.writeStream(spec)` returns a readable stream synchronously, writes
95
+ only the first workbook, and runs inline. Consume it or pipe it to a destination;
96
+ handle asynchronous errors via the stream's error event or pipeline.
97
+ - A single `to` target cannot receive multiple workbooks. Omit it to receive
98
+ separate buffers, or write each workbook individually. No ZIP wrapper is added.
99
+
100
+ `spec` is a non-empty array of workbooks, each containing a non-empty `sheets`
101
+ array. Sheets contain `sheet`, optional `columns` and `styling`, and a `data`
102
+ array. Workbook properties support author, company, title, created, and modified.
103
+ The `workbook` field is logical metadata, not an automatic filename.
104
+
105
+ Columns support key, header, width, type (`string`, `number`, `boolean`, `date`),
106
+ and Excel number-format string. Without explicit columns, keys are inferred from
107
+ the first row only. Width defaults to 15. Sheet names replace forbidden Excel
108
+ characters, truncate to 31 characters, and receive suffixes when duplicated.
109
+ `logger.warn` reports truncation.
110
+
111
+ ### Reading
112
+
113
+ ```js
114
+ const result = await excelio.read('sales.xlsx');
115
+ // Also accepts a Buffer or readable stream.
116
+ ```
117
+
118
+ The result contains:
119
+
120
+ ```js
121
+ {
122
+ ok: true,
123
+ data: [{ workbook: undefined, sheets: [{ sheet: 'Orders', columns: [], data: [] }] }],
124
+ errors: [],
125
+ stats: { totalRows: 0, totalSheets: 1, durationMs: 0 }
126
+ }
127
+ ```
128
+
129
+ Column entries contain `key` and `header`. Read data uses header text as object
130
+ keys, not the original write keys. A column written as `{ key: 'customer',
131
+ header: 'Customer' }` reads back as `{ Customer: 'Alice' }`. Keep header equal to
132
+ key for round-trippable field names. The original workbook label, properties,
133
+ column types, widths, and styling are not reconstructed in the read result.
134
+
135
+ Read options: `headerRow` (default 1), `nullForBlank` (true), `trimStrings` (true),
136
+ and `dateFormat` (`iso`, `date`, or `epoch`; default `iso`). Entirely blank rows
137
+ are skipped. Formula cells return cached results, not formula text; rich text
138
+ and hyperlinks return displayed text. Excel error values become null.
139
+ `totalRows` counts accepted rows after transformation and validation.
140
+
141
+ ### Transforms and Validation
142
+
143
+ ```js
144
+ const result = await excelio.read(buffer, {
145
+ afterRead: row => ({ ...row, email: row.email?.toLowerCase() }),
146
+ validateRow: row => row.amount < 0
147
+ ? { code: 'NEGATIVE_AMOUNT', message: 'Amount must be non-negative', column: 'amount' }
148
+ : null,
149
+ onRowError: 'collect'
150
+ });
151
+
152
+ await excelio.write(spec, {
153
+ beforeWrite: row => ({ ...row, amount: Number(row.amount) })
154
+ });
155
+ ```
156
+
157
+ Hooks are synchronous. They receive `(row, ctx)` where ctx contains workbookIndex,
158
+ workbookName, sheetIndex, sheetName, and the 1-based Excel rowNumber. Read applies
159
+ afterRead before validateRow. Invalid rows are excluded from data and collected
160
+ in errors by default; `onRowError: 'fail'` throws on the first issue. A hook
161
+ returning null/undefined keeps the original row. Write transforms do not add
162
+ columns beyond the explicit or inferred column set.
163
+
164
+ ### Workers, Progress, and Cancellation
165
+
166
+ ```js
167
+ await excelio.write(spec, { useWorker: true });
168
+ await excelio.read(buffer, { useWorker: false });
169
+ await excelio.write(spec, { workerThreshold: { rows: 100_000, bytes: 50 * 1024 * 1024 } });
170
+ ```
171
+
172
+ `useWorker` defaults to `auto`. Writes offload at 50,000 total rows; reads offload
173
+ at 10 MiB for buffers or file paths. Threshold comparisons are inclusive.
174
+ Each offloaded operation creates one worker, then terminates it. There is no
175
+ reusable worker pool, concurrency cap, or parallel splitting of a workbook.
176
+ Submit independent operations concurrently only when memory and CPU permit.
177
+
178
+ Functions (`beforeWrite`, `afterRead`, `validateRow`, `onProgress`), `logger`,
179
+ `signal`, stream inputs, and writable stream destinations force inline execution,
180
+ even when useWorker is true. Worker payloads must be structured-cloneable;
181
+ functions or unsupported values embedded in row data cannot be sent to workers.
182
+ Bundlers/serverless deployments must preserve the emitted entrypoint and its
183
+ sibling workers directory. Import the package normally rather than copying a
184
+ single bundled file.
185
+
186
+ `onProgress` receives phase and rowsProcessed plus available workbook/sheet
187
+ metadata. `batchSize` defaults to 5,000 and controls notifications, not memory
188
+ or yielding. Writes emit a final notification; reads notify at batch boundaries.
189
+ `signal` is checked between rows and sheets, but cannot interrupt initial XLSX
190
+ loading, commit, or synchronous row loops. Do not rely on timely cancellation of
191
+ an in-progress operation from an event-loop callback.
192
+
193
+ ### Values and Errors
194
+
195
+ Date columns accept Date, ISO date strings, and epoch milliseconds. Number
196
+ columns convert finite numeric strings; boolean columns recognize true/false,
197
+ the strings 'true'/'false', and 1/0. Unsupported coercions are left unchanged;
198
+ these hints are not schema validation. Multiline and multilingual text is supported.
199
+
200
+ `ExcelIoError` exposes code, optional cause, and optional details. Codes include
201
+ INVALID_SPEC, IO_ERROR, ABORTED, WORKER_ERROR, and ROW_VALIDATION. Collected read
202
+ errors contain workbook index, sheet, row, column, code, and message. `ok` is
203
+ false when collected errors exist; callers decide whether to accept partial data.
204
+ Some lower-level ExcelJS/write errors can propagate as ordinary Error instances.
205
+
206
+ ## Memory and Scope
207
+
208
+ Writes use ExcelJS's streaming XLSX writer and commit rows incrementally, but
209
+ input arrays and shared strings remain in memory; buffer output also collects
210
+ the complete file. Direct file/stream output avoids that final buffer.
211
+ Reading currently loads the entire workbook and collects accepted rows.
212
+ Workers keep processing off the main thread but do not guarantee lower total
213
+ memory or faster completion; cloning large inputs adds overhead.
214
+
215
+ Browsers, legacy XLS, charts, pivots, macros, encryption, and advanced formatting
216
+ are outside this library's API. Only features described above are supported.
217
+
218
+ ## Development and Releases
219
+
220
+ ```sh
221
+ npm ci
222
+ npm run verify
223
+ npm run build:min
224
+ npm run test:perf
225
+ npm run pack:check
226
+ npm run publish:dry-run
227
+ ```
228
+
229
+ `build` produces dist/esm, dist/cjs, dist/esm-min, and dist/cjs-min with bundled
230
+ worker entrypoints and matching declarations. `build:min` regenerates only the
231
+ minified outputs; run a full build for a release. The only direct runtime
232
+ dependency is ExcelJS; esbuild, TypeScript, and Node types are development tools.
233
+
234
+ See [Contributing](https://github.com/DipanshuHandoo/excelio/blob/main/CONTRIBUTING.md),
235
+ [Releasing](https://github.com/DipanshuHandoo/excelio/blob/main/RELEASING.md),
236
+ [Security](https://github.com/DipanshuHandoo/excelio/blob/main/SECURITY.md), and
237
+ [CHANGELOG.md](CHANGELOG.md). Public npm availability
238
+ starts with the first approved publication; repository setup does not publish it.
239
+
240
+ ## License
241
+
242
+ MIT. See [LICENSE](LICENSE).