@dynamic-entity/server 2.4.1 → 3.0.0-rc.1

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/index.d.mts CHANGED
@@ -1,162 +1,77 @@
1
- import { I as ImportLimits } from './write-template-CzKVVjgT.mjs';
2
- export { B as BatchInfo, a as ByteSource, D as DEFAULT_LIMITS, b as ImportRunResult, O as OnBatch, P as PreviewSheetOptions, R as ReadSheetOptions, c as RunImportOptions, S as SheetFormat, d as SheetPreview, e as SheetSource, f as TEMPLATE_EXTENSION, g as TEMPLATE_MEDIA_TYPE, T as TemplateFormat, W as WriteTemplateOptions, h as destroySource, i as detectFormat, j as guardRows, l as limitBytes, p as peek, k as previewSheet, r as readSheet, m as resolveLimits, n as runImport, t as toByteStream, w as writeTemplate } from './write-template-CzKVVjgT.mjs';
1
+ import { I as ImportLimits } from './run-import-BUClq6BR.mjs';
2
+ export { B as BatchInfo, a as ByteSource, D as DEFAULT_LIMITS, b as ImportRunResult, O as OnBatch, P as PreviewSheetOptions, R as ReadSheetOptions, c as RunImportOptions, S as SheetFormat, d as SheetPreview, e as SheetSource, f as destroySource, g as detectFormat, h as guardRows, l as limitBytes, p as peek, i as previewSheet, r as readSheet, j as resolveLimits, k as runImport, t as toByteStream } from './run-import-BUClq6BR.mjs';
3
+ import { ImportErrorBody as ImportErrorBody$1, ImportErrorCode as ImportErrorCode$1, toErrorBody as toErrorBody$1, guardZip as guardZip$1, cellValue as cellValue$1, xlsxRows as xlsxRows$1, TemplateFormat as TemplateFormat$1 } from 'sheet-to-schema/node';
4
+ export { ImportError } from 'sheet-to-schema/node';
5
+ import { TemplateSpec } from '@dynamic-entity/core';
3
6
  export { cellText as sampleText } from '@dynamic-entity/core';
4
- import 'node:stream';
7
+ import { Writable } from 'node:stream';
5
8
 
6
9
  /**
7
- * errors.ts — one error type, a closed set of codes, and an envelope that says nothing else.
10
+ * errors.ts — the one failure an import raises, and the envelope it is answered with.
8
11
  *
9
- * **Information disclosure is a threat, so the envelope is the guard.** A stack trace tells an
10
- * attacker the library versions in use and the filesystem layout of the host; a parser's own
11
- * message tells them which parser. So a response carries a machine-readable `code` and a
12
- * message this package wrote, and nothing that came from below it. Whatever the real cause
13
- * was stays on the server, reachable through `cause` for the consumer's logger.
12
+ * Since 3.0 this is sheet-to-schema's, moved to `sheet-to-schema/node` unchanged, and this
13
+ * file re-exports it. The names stay importable from `@dynamic-entity/server` through 3.x and
14
+ * are removed in 4.0: import them from `sheet-to-schema/node`.
14
15
  */
15
- /**
16
- * Why a request failed, in a form a client can branch on.
17
- *
18
- * Closed on purpose: a client that has to match on message text is a client that breaks when
19
- * the text improves, and the wire shape is shared with `ngx-dynamic-entity`.
20
- */
21
- type ImportErrorCode =
22
- /** No file part in the multipart body. */
23
- 'NO_FILE'
24
- /** More file parts than `limits.maxFiles`. */
25
- | 'TOO_MANY_FILES'
26
- /** The body exceeded `limits.maxBytes`, or a field exceeded its own bound. */
27
- | 'TOO_LARGE'
28
- /** The bytes are not a format this package reads. Decided by content, not by filename. */
29
- | 'UNSUPPORTED_FORMAT'
30
- /** The bytes claim a format and are not valid in it. */
31
- | 'MALFORMED_FILE'
32
- /** A zip that inflates out of proportion to its size, or has too many entries. */
33
- | 'ARCHIVE_REFUSED'
34
- /** Rows, columns or one cell past the configured bound. */
35
- | 'SHEET_TOO_LARGE'
36
- /** No config is registered under the requested entity. */
37
- | 'UNKNOWN_ENTITY'
38
- /** The `plan` field is missing, is not JSON, or does not describe this config. */
39
- | 'INVALID_PLAN'
40
- /** The request took longer than `limits.totalTimeoutMs`, or stalled past the idle bound. */
41
- | 'TIMEOUT'
42
- /** The consumer's `onImport` threw. Nothing about *why* crosses the wire. */
43
- | 'IMPORT_FAILED'
44
- /** Anything else. Deliberately the least informative code there is. */
45
- | 'INTERNAL';
46
- /**
47
- * What a failing route sends.
48
- *
49
- * `details` is present only for `INVALID_PLAN`, and carries `validateMappingPlan`'s own
50
- * problems — those describe the client's own plan against a config the client already has,
51
- * so they disclose nothing the caller did not send.
52
- */
53
- interface ImportErrorBody {
54
- error: {
55
- code: ImportErrorCode;
56
- message: string;
57
- details?: unknown;
58
- };
59
- }
60
- declare class ImportError extends Error {
61
- readonly code: ImportErrorCode;
62
- readonly status: number;
63
- readonly details?: unknown;
64
- constructor(code: ImportErrorCode, message: string, options?: {
65
- cause?: unknown;
66
- details?: unknown;
67
- });
68
- }
69
- /**
70
- * Turn anything thrown into a response body.
71
- *
72
- * An `ImportError` says what it says. **Everything else becomes `INTERNAL` with a fixed
73
- * message** — that is the whole point, and the reason this is a function rather than a
74
- * `catch` block per route. A parser that throws `ENOENT: open '/srv/app/tmp/…'` must not be
75
- * the thing that answers the request.
76
- */
77
- declare function toErrorBody(error: unknown): {
78
- status: number;
79
- body: ImportErrorBody;
80
- };
81
16
 
82
- /**
83
- * guard-zip.ts — open the archive ourselves, and hand the parser only what it should see.
84
- *
85
- * An `.xlsx` is a zip, and a zip is the one upload format where the bytes on the wire say
86
- * nothing about the work they cause. Ten kilobytes can inflate to ten gigabytes. `maxBytes`
87
- * bounds what arrives and is therefore the wrong guard entirely for this.
88
- *
89
- * **Why the archive is rebuilt rather than passed through.** Two reasons, and the second was a
90
- * surprise:
91
- *
92
- * 1. exceljs inflates internally and reports nothing while it does, so a limit applied to its
93
- * output is applied after the memory it was protecting has been spent. The inflated size is
94
- * knowable early only here, so this inflates every entry to *measure* it and refuses at the
95
- * byte that crosses a bound.
96
- * 2. **exceljs's streaming reader loses entries when a worksheet precedes the shared strings.**
97
- * It defers such a worksheet to a temp file, and the archive's entry stream then ends at
98
- * that entry — `xl/workbook.xml`, which exceljs's own writer puts *last*, never arrives,
99
- * and the reader throws `Cannot read properties of undefined (reading 'sheets')`. Verified
100
- * by replicating its parse loop: sixteen entries became eight, on two runs out of three.
101
- * Reordering the archive so the strings, the relationships and the workbook all precede the
102
- * worksheet avoids the deferral entirely — thirty-two runs, no failures, chunked and whole.
103
- *
104
- * Rebuilding also means the parser sees **only the parts an import needs**. The theme, the
105
- * document properties, the drawings, the printer settings and every worksheet after the first
106
- * are dropped rather than parsed, and a part that is never parsed cannot be hostile.
107
- *
108
- * What this costs is the retained archive, held **compressed** and therefore bounded by
109
- * `maxBytes` — ten megabytes by default, against a fifty-thousand-row workbook's few. Entry
110
- * data is re-packed exactly as it arrived; nothing is inflated into memory to be kept.
111
- */
17
+ /** @deprecated Import `ImportErrorCode` from `sheet-to-schema/node`. Removed in 4.0. */
18
+ type ImportErrorCode = ImportErrorCode$1;
19
+ /** @deprecated Import `ImportErrorBody` from `sheet-to-schema/node`. Removed in 4.0. */
20
+ type ImportErrorBody = ImportErrorBody$1;
21
+ /** @deprecated Any failure as a status and an envelope. Import `toErrorBody` from `sheet-to-schema/node`. Removed in 4.0. */
22
+ declare const toErrorBody: typeof toErrorBody$1;
112
23
 
113
24
  /**
114
- * Walk an archive under every archive-shaped bound, and return the parts an import needs.
25
+ * guard-zip.ts — a workbook is a zip, and a zip is checked before anything expands it.
115
26
  *
116
- * Parsing stops at the first thing that is not a local file header — the central directory —
117
- * because nothing after the last entry inflates and there is nothing there to guard.
27
+ * Since 3.0 the guard is sheet-to-schema's, moved to `sheet-to-schema/node` unchanged, and this
28
+ * file re-exports it. The names stay importable from `@dynamic-entity/server` through 3.x and
29
+ * are removed in 4.0: import them from `sheet-to-schema/node`.
118
30
  */
119
- declare function guardZip(source: AsyncIterable<Uint8Array>, limits: ImportLimits): Promise<Buffer>;
31
+
32
+ /** @deprecated Import `guardZip` from `sheet-to-schema/node`. Removed in 4.0. */
33
+ declare const guardZip: typeof guardZip$1;
120
34
 
121
35
  /**
122
- * xlsx-source.ts — a workbook, one row at a time.
123
- *
124
- * exceljs's streaming reader does the XML; this file does the three things around it that
125
- * decide whether a server-side xlsx import matches a browser one.
126
- *
127
- * 1. **Every byte goes through `guardZip` first.** exceljs inflates internally and reports
128
- * nothing while it does, so the only place an archive's real size is knowable early is
129
- * before it gets there.
130
- * 2. **Blank rows are put back.** exceljs skips them — a sheet with a gap emits row 3 then
131
- * row 5 — and a reader that passed that through would shift every later row number in
132
- * every error message, and disagree with the CSV path about `skipped`. The row numbers a
133
- * user is shown are the ones in their spreadsheet's gutter, so the gaps are synthesised.
134
- * 3. **Cells keep their types.** A date cell arrives as a `Date` at UTC midnight and is
135
- * handed on as one, because `coerceCell` reads a typed cell as its type. Stringifying here
136
- * to tidy the signature is the exact defect this feature already fixed once.
36
+ * xlsx-source.ts — a workbook's first sheet as rows of typed cells.
137
37
  *
138
- * **What this holds, stated rather than discovered:** the archive's wanted parts, kept
139
- * **compressed** and therefore bounded by `maxBytes` — ten megabytes by default, against a
140
- * fifty-thousand-row workbook's few. That is the cost of `guardZip` rebuilding the archive
141
- * rather than forwarding it, and the reasons it does are in that file. Row data is never
142
- * accumulated, which is the part that scales with the file.
38
+ * Since 3.0 the reader is sheet-to-schema's, moved to `sheet-to-schema/node` unchanged, and this
39
+ * file re-exports it. The names stay importable from `@dynamic-entity/server` through 3.x and
40
+ * are removed in 4.0: import them from `sheet-to-schema/node`.
143
41
  */
144
42
 
43
+ /** @deprecated What a workbook cell holds, as a plain value. Import `cellValue` from `sheet-to-schema/node`. Removed in 4.0. */
44
+ declare const cellValue: typeof cellValue$1;
45
+ /** @deprecated A workbook's rows, streamed. Import `xlsxRows` from `sheet-to-schema/node`. Removed in 4.0. */
46
+ declare const xlsxRows: typeof xlsxRows$1;
47
+
145
48
  /**
146
- * Turn one exceljs cell value into the value a record should be built from.
49
+ * write-template.ts — a template a user downloads, fills in, and uploads again.
147
50
  *
148
- * A formula cell yields its **result**, never its formula: a sheet someone uploaded may
149
- * contain anything, and importing the text `=SUM(A1:A9)` into a field is importing a string
150
- * the user never saw. An error cell yields its error text, which fails coercion loudly rather
151
- * than importing as blank.
51
+ * Since 3.0 the writer is sheet-to-schema's, which takes a sheet name, headers and notes. This
52
+ * is Dynamic Entity's signature over it: a `TemplateSpec`, as `buildTemplateSpec` makes one.
53
+ * The bytes are the same bytes.
152
54
  */
153
- declare function cellValue(raw: unknown): unknown;
55
+
56
+ /** @deprecated Import `TemplateFormat` from `sheet-to-schema/node`. Removed in 4.0. */
57
+ type TemplateFormat = TemplateFormat$1;
58
+ /** @deprecated Import `TEMPLATE_EXTENSION` from `sheet-to-schema/node`. Removed in 4.0. */
59
+ declare const TEMPLATE_EXTENSION: Record<TemplateFormat$1, string>;
60
+ /** @deprecated Import `TEMPLATE_MEDIA_TYPE` from `sheet-to-schema/node`. Removed in 4.0. */
61
+ declare const TEMPLATE_MEDIA_TYPE: Record<TemplateFormat$1, string>;
62
+ interface WriteTemplateOptions {
63
+ spec: TemplateSpec;
64
+ format: TemplateFormat;
65
+ /** Where the bytes go. An HTTP response, a file stream, anything writable. */
66
+ out: Writable;
67
+ limits?: Partial<ImportLimits>;
68
+ }
154
69
  /**
155
- * Rows of the first worksheet, starting at spreadsheet row 1.
70
+ * Write a blank template: the header row, and for a workbook a note on each header cell.
156
71
  *
157
- * The first worksheet and no other: a mapping plan addresses one sheet's columns, and picking
158
- * a second one silently would import a different file from the one the user previewed.
72
+ * A CSV carries no notes, because it has nowhere to put them. Either way the file holds
73
+ * headers and no formulas, and a header that would run as one is neutralised.
159
74
  */
160
- declare function xlsxRows(source: AsyncIterable<Uint8Array>, limits: ImportLimits): AsyncGenerator<unknown[]>;
75
+ declare function writeTemplate(options: WriteTemplateOptions): Promise<void>;
161
76
 
162
- export { ImportError, type ImportErrorBody, type ImportErrorCode, ImportLimits, cellValue, guardZip, toErrorBody, xlsxRows };
77
+ export { type ImportErrorBody, type ImportErrorCode, ImportLimits, TEMPLATE_EXTENSION, TEMPLATE_MEDIA_TYPE, type TemplateFormat, type WriteTemplateOptions, cellValue, guardZip, toErrorBody, writeTemplate, xlsxRows };
package/index.d.ts CHANGED
@@ -1,162 +1,77 @@
1
- import { I as ImportLimits } from './write-template-CzKVVjgT.js';
2
- export { B as BatchInfo, a as ByteSource, D as DEFAULT_LIMITS, b as ImportRunResult, O as OnBatch, P as PreviewSheetOptions, R as ReadSheetOptions, c as RunImportOptions, S as SheetFormat, d as SheetPreview, e as SheetSource, f as TEMPLATE_EXTENSION, g as TEMPLATE_MEDIA_TYPE, T as TemplateFormat, W as WriteTemplateOptions, h as destroySource, i as detectFormat, j as guardRows, l as limitBytes, p as peek, k as previewSheet, r as readSheet, m as resolveLimits, n as runImport, t as toByteStream, w as writeTemplate } from './write-template-CzKVVjgT.js';
1
+ import { I as ImportLimits } from './run-import-BUClq6BR.js';
2
+ export { B as BatchInfo, a as ByteSource, D as DEFAULT_LIMITS, b as ImportRunResult, O as OnBatch, P as PreviewSheetOptions, R as ReadSheetOptions, c as RunImportOptions, S as SheetFormat, d as SheetPreview, e as SheetSource, f as destroySource, g as detectFormat, h as guardRows, l as limitBytes, p as peek, i as previewSheet, r as readSheet, j as resolveLimits, k as runImport, t as toByteStream } from './run-import-BUClq6BR.js';
3
+ import { ImportErrorBody as ImportErrorBody$1, ImportErrorCode as ImportErrorCode$1, toErrorBody as toErrorBody$1, guardZip as guardZip$1, cellValue as cellValue$1, xlsxRows as xlsxRows$1, TemplateFormat as TemplateFormat$1 } from 'sheet-to-schema/node';
4
+ export { ImportError } from 'sheet-to-schema/node';
5
+ import { TemplateSpec } from '@dynamic-entity/core';
3
6
  export { cellText as sampleText } from '@dynamic-entity/core';
4
- import 'node:stream';
7
+ import { Writable } from 'node:stream';
5
8
 
6
9
  /**
7
- * errors.ts — one error type, a closed set of codes, and an envelope that says nothing else.
10
+ * errors.ts — the one failure an import raises, and the envelope it is answered with.
8
11
  *
9
- * **Information disclosure is a threat, so the envelope is the guard.** A stack trace tells an
10
- * attacker the library versions in use and the filesystem layout of the host; a parser's own
11
- * message tells them which parser. So a response carries a machine-readable `code` and a
12
- * message this package wrote, and nothing that came from below it. Whatever the real cause
13
- * was stays on the server, reachable through `cause` for the consumer's logger.
12
+ * Since 3.0 this is sheet-to-schema's, moved to `sheet-to-schema/node` unchanged, and this
13
+ * file re-exports it. The names stay importable from `@dynamic-entity/server` through 3.x and
14
+ * are removed in 4.0: import them from `sheet-to-schema/node`.
14
15
  */
15
- /**
16
- * Why a request failed, in a form a client can branch on.
17
- *
18
- * Closed on purpose: a client that has to match on message text is a client that breaks when
19
- * the text improves, and the wire shape is shared with `ngx-dynamic-entity`.
20
- */
21
- type ImportErrorCode =
22
- /** No file part in the multipart body. */
23
- 'NO_FILE'
24
- /** More file parts than `limits.maxFiles`. */
25
- | 'TOO_MANY_FILES'
26
- /** The body exceeded `limits.maxBytes`, or a field exceeded its own bound. */
27
- | 'TOO_LARGE'
28
- /** The bytes are not a format this package reads. Decided by content, not by filename. */
29
- | 'UNSUPPORTED_FORMAT'
30
- /** The bytes claim a format and are not valid in it. */
31
- | 'MALFORMED_FILE'
32
- /** A zip that inflates out of proportion to its size, or has too many entries. */
33
- | 'ARCHIVE_REFUSED'
34
- /** Rows, columns or one cell past the configured bound. */
35
- | 'SHEET_TOO_LARGE'
36
- /** No config is registered under the requested entity. */
37
- | 'UNKNOWN_ENTITY'
38
- /** The `plan` field is missing, is not JSON, or does not describe this config. */
39
- | 'INVALID_PLAN'
40
- /** The request took longer than `limits.totalTimeoutMs`, or stalled past the idle bound. */
41
- | 'TIMEOUT'
42
- /** The consumer's `onImport` threw. Nothing about *why* crosses the wire. */
43
- | 'IMPORT_FAILED'
44
- /** Anything else. Deliberately the least informative code there is. */
45
- | 'INTERNAL';
46
- /**
47
- * What a failing route sends.
48
- *
49
- * `details` is present only for `INVALID_PLAN`, and carries `validateMappingPlan`'s own
50
- * problems — those describe the client's own plan against a config the client already has,
51
- * so they disclose nothing the caller did not send.
52
- */
53
- interface ImportErrorBody {
54
- error: {
55
- code: ImportErrorCode;
56
- message: string;
57
- details?: unknown;
58
- };
59
- }
60
- declare class ImportError extends Error {
61
- readonly code: ImportErrorCode;
62
- readonly status: number;
63
- readonly details?: unknown;
64
- constructor(code: ImportErrorCode, message: string, options?: {
65
- cause?: unknown;
66
- details?: unknown;
67
- });
68
- }
69
- /**
70
- * Turn anything thrown into a response body.
71
- *
72
- * An `ImportError` says what it says. **Everything else becomes `INTERNAL` with a fixed
73
- * message** — that is the whole point, and the reason this is a function rather than a
74
- * `catch` block per route. A parser that throws `ENOENT: open '/srv/app/tmp/…'` must not be
75
- * the thing that answers the request.
76
- */
77
- declare function toErrorBody(error: unknown): {
78
- status: number;
79
- body: ImportErrorBody;
80
- };
81
16
 
82
- /**
83
- * guard-zip.ts — open the archive ourselves, and hand the parser only what it should see.
84
- *
85
- * An `.xlsx` is a zip, and a zip is the one upload format where the bytes on the wire say
86
- * nothing about the work they cause. Ten kilobytes can inflate to ten gigabytes. `maxBytes`
87
- * bounds what arrives and is therefore the wrong guard entirely for this.
88
- *
89
- * **Why the archive is rebuilt rather than passed through.** Two reasons, and the second was a
90
- * surprise:
91
- *
92
- * 1. exceljs inflates internally and reports nothing while it does, so a limit applied to its
93
- * output is applied after the memory it was protecting has been spent. The inflated size is
94
- * knowable early only here, so this inflates every entry to *measure* it and refuses at the
95
- * byte that crosses a bound.
96
- * 2. **exceljs's streaming reader loses entries when a worksheet precedes the shared strings.**
97
- * It defers such a worksheet to a temp file, and the archive's entry stream then ends at
98
- * that entry — `xl/workbook.xml`, which exceljs's own writer puts *last*, never arrives,
99
- * and the reader throws `Cannot read properties of undefined (reading 'sheets')`. Verified
100
- * by replicating its parse loop: sixteen entries became eight, on two runs out of three.
101
- * Reordering the archive so the strings, the relationships and the workbook all precede the
102
- * worksheet avoids the deferral entirely — thirty-two runs, no failures, chunked and whole.
103
- *
104
- * Rebuilding also means the parser sees **only the parts an import needs**. The theme, the
105
- * document properties, the drawings, the printer settings and every worksheet after the first
106
- * are dropped rather than parsed, and a part that is never parsed cannot be hostile.
107
- *
108
- * What this costs is the retained archive, held **compressed** and therefore bounded by
109
- * `maxBytes` — ten megabytes by default, against a fifty-thousand-row workbook's few. Entry
110
- * data is re-packed exactly as it arrived; nothing is inflated into memory to be kept.
111
- */
17
+ /** @deprecated Import `ImportErrorCode` from `sheet-to-schema/node`. Removed in 4.0. */
18
+ type ImportErrorCode = ImportErrorCode$1;
19
+ /** @deprecated Import `ImportErrorBody` from `sheet-to-schema/node`. Removed in 4.0. */
20
+ type ImportErrorBody = ImportErrorBody$1;
21
+ /** @deprecated Any failure as a status and an envelope. Import `toErrorBody` from `sheet-to-schema/node`. Removed in 4.0. */
22
+ declare const toErrorBody: typeof toErrorBody$1;
112
23
 
113
24
  /**
114
- * Walk an archive under every archive-shaped bound, and return the parts an import needs.
25
+ * guard-zip.ts — a workbook is a zip, and a zip is checked before anything expands it.
115
26
  *
116
- * Parsing stops at the first thing that is not a local file header — the central directory —
117
- * because nothing after the last entry inflates and there is nothing there to guard.
27
+ * Since 3.0 the guard is sheet-to-schema's, moved to `sheet-to-schema/node` unchanged, and this
28
+ * file re-exports it. The names stay importable from `@dynamic-entity/server` through 3.x and
29
+ * are removed in 4.0: import them from `sheet-to-schema/node`.
118
30
  */
119
- declare function guardZip(source: AsyncIterable<Uint8Array>, limits: ImportLimits): Promise<Buffer>;
31
+
32
+ /** @deprecated Import `guardZip` from `sheet-to-schema/node`. Removed in 4.0. */
33
+ declare const guardZip: typeof guardZip$1;
120
34
 
121
35
  /**
122
- * xlsx-source.ts — a workbook, one row at a time.
123
- *
124
- * exceljs's streaming reader does the XML; this file does the three things around it that
125
- * decide whether a server-side xlsx import matches a browser one.
126
- *
127
- * 1. **Every byte goes through `guardZip` first.** exceljs inflates internally and reports
128
- * nothing while it does, so the only place an archive's real size is knowable early is
129
- * before it gets there.
130
- * 2. **Blank rows are put back.** exceljs skips them — a sheet with a gap emits row 3 then
131
- * row 5 — and a reader that passed that through would shift every later row number in
132
- * every error message, and disagree with the CSV path about `skipped`. The row numbers a
133
- * user is shown are the ones in their spreadsheet's gutter, so the gaps are synthesised.
134
- * 3. **Cells keep their types.** A date cell arrives as a `Date` at UTC midnight and is
135
- * handed on as one, because `coerceCell` reads a typed cell as its type. Stringifying here
136
- * to tidy the signature is the exact defect this feature already fixed once.
36
+ * xlsx-source.ts — a workbook's first sheet as rows of typed cells.
137
37
  *
138
- * **What this holds, stated rather than discovered:** the archive's wanted parts, kept
139
- * **compressed** and therefore bounded by `maxBytes` — ten megabytes by default, against a
140
- * fifty-thousand-row workbook's few. That is the cost of `guardZip` rebuilding the archive
141
- * rather than forwarding it, and the reasons it does are in that file. Row data is never
142
- * accumulated, which is the part that scales with the file.
38
+ * Since 3.0 the reader is sheet-to-schema's, moved to `sheet-to-schema/node` unchanged, and this
39
+ * file re-exports it. The names stay importable from `@dynamic-entity/server` through 3.x and
40
+ * are removed in 4.0: import them from `sheet-to-schema/node`.
143
41
  */
144
42
 
43
+ /** @deprecated What a workbook cell holds, as a plain value. Import `cellValue` from `sheet-to-schema/node`. Removed in 4.0. */
44
+ declare const cellValue: typeof cellValue$1;
45
+ /** @deprecated A workbook's rows, streamed. Import `xlsxRows` from `sheet-to-schema/node`. Removed in 4.0. */
46
+ declare const xlsxRows: typeof xlsxRows$1;
47
+
145
48
  /**
146
- * Turn one exceljs cell value into the value a record should be built from.
49
+ * write-template.ts — a template a user downloads, fills in, and uploads again.
147
50
  *
148
- * A formula cell yields its **result**, never its formula: a sheet someone uploaded may
149
- * contain anything, and importing the text `=SUM(A1:A9)` into a field is importing a string
150
- * the user never saw. An error cell yields its error text, which fails coercion loudly rather
151
- * than importing as blank.
51
+ * Since 3.0 the writer is sheet-to-schema's, which takes a sheet name, headers and notes. This
52
+ * is Dynamic Entity's signature over it: a `TemplateSpec`, as `buildTemplateSpec` makes one.
53
+ * The bytes are the same bytes.
152
54
  */
153
- declare function cellValue(raw: unknown): unknown;
55
+
56
+ /** @deprecated Import `TemplateFormat` from `sheet-to-schema/node`. Removed in 4.0. */
57
+ type TemplateFormat = TemplateFormat$1;
58
+ /** @deprecated Import `TEMPLATE_EXTENSION` from `sheet-to-schema/node`. Removed in 4.0. */
59
+ declare const TEMPLATE_EXTENSION: Record<TemplateFormat$1, string>;
60
+ /** @deprecated Import `TEMPLATE_MEDIA_TYPE` from `sheet-to-schema/node`. Removed in 4.0. */
61
+ declare const TEMPLATE_MEDIA_TYPE: Record<TemplateFormat$1, string>;
62
+ interface WriteTemplateOptions {
63
+ spec: TemplateSpec;
64
+ format: TemplateFormat;
65
+ /** Where the bytes go. An HTTP response, a file stream, anything writable. */
66
+ out: Writable;
67
+ limits?: Partial<ImportLimits>;
68
+ }
154
69
  /**
155
- * Rows of the first worksheet, starting at spreadsheet row 1.
70
+ * Write a blank template: the header row, and for a workbook a note on each header cell.
156
71
  *
157
- * The first worksheet and no other: a mapping plan addresses one sheet's columns, and picking
158
- * a second one silently would import a different file from the one the user previewed.
72
+ * A CSV carries no notes, because it has nowhere to put them. Either way the file holds
73
+ * headers and no formulas, and a header that would run as one is neutralised.
159
74
  */
160
- declare function xlsxRows(source: AsyncIterable<Uint8Array>, limits: ImportLimits): AsyncGenerator<unknown[]>;
75
+ declare function writeTemplate(options: WriteTemplateOptions): Promise<void>;
161
76
 
162
- export { ImportError, type ImportErrorBody, type ImportErrorCode, ImportLimits, cellValue, guardZip, toErrorBody, xlsxRows };
77
+ export { type ImportErrorBody, type ImportErrorCode, ImportLimits, TEMPLATE_EXTENSION, TEMPLATE_MEDIA_TYPE, type TemplateFormat, type WriteTemplateOptions, cellValue, guardZip, toErrorBody, writeTemplate, xlsxRows };