laterite 0.5.1 → 0.6.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/index.d.ts CHANGED
@@ -1,7 +1,115 @@
1
- /* tslint:disable */
1
+ /* auto-generated by NAPI-RS */
2
2
  /* eslint-disable */
3
+ /**
4
+ * A parsed AGS4 file held native-side — the Node analog of laterite-py's
5
+ * `Reading` handle (and `laterite-ags4-wasm`'s `ParsedDataset`). Each group's typed
6
+ * `RecordBatch` is built lazily on `tableIpc(code)` and dropped after the
7
+ * bytes are returned, so peak residency is one batch.
8
+ */
9
+ export declare class Reading {
10
+ /** Group codes in file order (the order to load tables in). */
11
+ groupCodes(): Array<string>
12
+ /** The file's `TRAN_AGS` edition string, if present. */
13
+ get tranAgs(): string | null
14
+ /**
15
+ * `{headings, units, types, sqlTypes}` for one group, or `null` if the
16
+ * code isn't present. No Arrow built — cheap metadata only.
17
+ */
18
+ meta(code: string): GroupMeta | null
19
+ /**
20
+ * One group's rows as an Arrow **IPC stream** (`Buffer`), columns already
21
+ * correctly typed. The Node analog of the pyo3-arrow capsule: the typed
22
+ * columns come from the one shared emitter (`laterite_types::arrow_cols`), the
23
+ * SAME casting Python/wasm use — so a file types byte-identically across
24
+ * hosts. Returns `null` if the code isn't in the file.
25
+ */
26
+ tableIpc(code: string): Buffer | null
27
+ /**
28
+ * Re-emit byte-faithful AGS4 text from the retained parse (the raw DATA
29
+ * values, unchanged). = laterite-py's `Reading::emit`.
30
+ */
31
+ emit(): string
32
+ }
3
33
 
4
- /* auto-generated by NAPI-RS */
34
+ /**
35
+ * The `.ags.idx` validity certificate — the Node mirror of laterite-py's
36
+ * `Sidecar` pyclass, wrapping the ONE core `laterite_ags4_core::index::Sidecar`
37
+ * so a Node-minted cert is byte-identical + checker-compatible with Python,
38
+ * `lat-check --emit-index`, and the DuckDB extension. `Ags4File.certify()` mints
39
+ * one; `read(file, {index})` consumes it; a fresh + engine-matching cert lets a
40
+ * later `.validate()` skip the rule engine.
41
+ */
42
+ export declare class Sidecar {
43
+ /**
44
+ * Assemble a certificate for an ALREADY-clean file — the caller MUST have
45
+ * validated `data` clean (0 error findings); core trusts that, it cannot
46
+ * re-check. `edition` is the resolved AGS edition (e.g. `"4.1.1"`); `checkedAt`
47
+ * an RFC-3339 UTC timestamp (the TS side passes `new Date().toISOString()`);
48
+ * `warnings`/`fyi` the advisory counts present at validation. The validator
49
+ * name + engine version are stamped here. Throws if `data` isn't indexable
50
+ * AGS4 (e.g. non-UTF-8, which the byte index rejects).
51
+ */
52
+ static assemble(data: Uint8Array, edition: string, checkedAt: string, warnings?: number | undefined | null, fyi?: number | undefined | null, compat?: string | undefined | null, checkFiles?: boolean | undefined | null, editionForced?: boolean | undefined | null): Sidecar
53
+ /**
54
+ * Parse a certificate from its on-disk `.ags.idx` JSON bytes, rejecting an
55
+ * unknown format version. Throws on malformed / unsupported JSON.
56
+ */
57
+ static fromJson(data: Uint8Array): Sidecar
58
+ /** Serialise to the on-disk `.ags.idx` JSON (pretty). */
59
+ toJson(): Buffer
60
+ /**
61
+ * Is this certificate still current for `data`? Strong check: format version +
62
+ * byte length + SHA-256. A mismatch means the source changed under the cert.
63
+ */
64
+ isFreshFor(data: Uint8Array): boolean
65
+ /**
66
+ * Was this cert minted by the CURRENT native validator engine (same engine
67
+ * version, native — not a compat profile)? The `.validate()` skip trusts a
68
+ * carried cert only when this holds AND it's fresh.
69
+ */
70
+ matchesNativeValidator(): boolean
71
+ /**
72
+ * Does this cert's check profile cover a request's? (`checkFiles`: the cert ran
73
+ * at least what's asked; `forcedEdition`: a forced request needs the same
74
+ * forced edition, an auto request an auto cert.)
75
+ */
76
+ profileCovers(checkFiles: boolean, forcedEdition?: string | undefined | null): boolean
77
+ get version(): number
78
+ /**
79
+ * The certified source's byte length (a JS number; AGS files are well within
80
+ * the 2^53 safe-integer range).
81
+ */
82
+ get size(): number
83
+ get sha256(): string
84
+ get edition(): string
85
+ get validator(): string
86
+ get validatorVersion(): string
87
+ get compat(): string | null
88
+ get checkedAt(): string
89
+ get checkFiles(): boolean
90
+ get editionForced(): boolean
91
+ get warnings(): number
92
+ get fyi(): number
93
+ }
94
+
95
+ /**
96
+ * Write an AGS4 file's groups to an `.xlsx` — one worksheet per group.
97
+ * `orderedKeys` forces the worksheet order; otherwise AGS4 source order.
98
+ */
99
+ export declare function ags4ToExcel(agsPath: string, xlsxPath: string, orderedKeys?: Array<string> | undefined | null): ExcelStats
100
+
101
+ /**
102
+ * One applied fix — the Node mirror of laterite-py's `applied[]` entries.
103
+ * `kind`/`risk` are the serde snake_case strings (`strip_bom`, `safe`, …) so
104
+ * the shape is identical across Python / CLI / Node.
105
+ */
106
+ export interface AppliedFix {
107
+ kind: string
108
+ label: string
109
+ rule: string
110
+ line?: number
111
+ risk: string
112
+ }
5
113
 
6
114
  /**
7
115
  * AGS spec type code → canonical category label (`"string"`, `"integer"`,
@@ -9,49 +117,106 @@
9
117
  * for unknown codes (the TS wrapper re-raises as an error).
10
118
  */
11
119
  export declare function canonicalType(agsType: string): string | null
120
+
121
+ /**
122
+ * Compare two AGS4 documents (raw `a` baseline / `b` revision bytes) — the
123
+ * revision diff, mirroring laterite-py's `diff()` and the wasm `diff()`.
124
+ * `dict_version` `None`/`"auto"` resolves the KEY-heading edition from the
125
+ * revision (`b`)'s `TRAN_AGS`, else forces it; `encoding` decodes both sides
126
+ * (default UTF-8). Returns the serialised `RevisionDelta` JSON — the shared
127
+ * `laterite-ags4-diff` leaf's `{groups, groups_added, groups_removed,
128
+ * total_added, total_removed, total_changed}` shape — that the TS `diff()`
129
+ * parses. Parse failure throws the mapped error (`NotAgs4Error`, …).
130
+ */
131
+ export declare function diff(a: Uint8Array, b: Uint8Array, dictVersion?: string | undefined | null, encoding?: string | undefined | null): string
132
+
12
133
  /**
13
134
  * Presentation hint for a numeric AGS type: `"2DP"` → `"%.2f"`, `"3SF"` →
14
135
  * `"%.3g"`, `"1SCI"` → `"%.1e"`; `null` for non-numeric / unknown codes.
15
136
  */
16
137
  export declare function displayHint(agsType: string): string | null
138
+
17
139
  /**
18
- * Parse an AGS4-shaped raw string into its canonical value — the same engine
19
- * the read path uses. Permissive: empty / unparseable → `null`. Returns native
20
- * JS: integer/decimal → number, bool → boolean, string/enum → string,
21
- * **datetime/date/time → the canonical string** (`"YYYY-MM-DD HH:MM:SS"` /
22
- * `"YYYY-MM-DD"` / `"HH:MM:SS"`), unknown code → the trimmed input.
140
+ * Build valid AGS4 from per-group **Arrow IPC** streams (the columnar
141
+ * producer; the read boundary reversed). = `laterite-ags4-wasm`'s `to_ags4_ipc`.
23
142
  */
24
- export declare function parseValue(raw: string | undefined | null, agsType: string): any
143
+ export declare function emitAgs4FromIpc(groups: Array<GroupIpc>, edition?: string | undefined | null, mode?: string | undefined | null, units?: Record<string, Record<string, string>> | undefined | null, types?: Record<string, Record<string, string>> | undefined | null): EmitResult
144
+
25
145
  /**
26
- * Result of `transportPack` / `transportLock`: output size, ratio vs source,
27
- * elapsed seconds.
146
+ * The emit result. `bytes` is the AGS4 document; `findingsJson` is the
147
+ * validator's `{rule:[…]}` map on the output; `applied` is the safe-fix ledger
148
+ * AutoFix made (same shape as `fix()`'s `FixReport.applied`); `fixesApplied`
149
+ * is its length.
28
150
  */
29
- export interface PackStats {
30
- bytes: bigint
31
- ratio: number
32
- elapsedS: number
151
+ export interface EmitResult {
152
+ bytes: Buffer
153
+ findingsJson: string
154
+ applied: Array<AppliedFix>
155
+ fixesApplied: number
33
156
  }
34
- /** Result of `transportUnpack` / `transportUnlock`: output size, elapsed seconds. */
35
- export interface UnpackStats {
36
- bytes: bigint
37
- elapsedS: number
157
+
158
+ /** The outcome of an Excel conversion (mirrors `laterite_excel::ExcelStats`). */
159
+ export interface ExcelStats {
160
+ /** Worksheets written (AGS4→XLSX) or read (XLSX→AGS4). */
161
+ sheetsWritten: number
162
+ /** DATA rows written across all sheets. */
163
+ rowsWritten: number
164
+ /** Non-fatal conversion warnings. */
165
+ warnings: Array<string>
38
166
  }
39
- /** zstd-compress `src` → `dest`. `level` is 1–22 (default 9, the AGS sweet spot). */
40
- export declare function transportPack(src: string, dest: string, level?: number | undefined | null): PackStats
41
- /** zstd-decompress `src` → `dest`. */
42
- export declare function transportUnpack(src: string, dest: string): UnpackStats
167
+
43
168
  /**
44
- * zstd-compress, then age-encrypt with `password` `dest`. Compress-then-
45
- * encrypt is load-bearing: zstd needs low-entropy input; ciphertext is random.
169
+ * Read an `.xlsx` back into an AGS4 file. `formatNumericColumns` (default
170
+ * true) re-applies AGS4 numeric formatting to numeric-looking columns.
46
171
  */
47
- export declare function transportLock(src: string, dest: string, password: string, level?: number | undefined | null): PackStats
172
+ export declare function excelToAgs4(xlsxPath: string, agsPath: string, formatNumericColumns?: boolean | undefined | null): ExcelStats
173
+
174
+ /** One rule violation (omitting `severity` ⇒ error, matching the engine). */
175
+ export interface Finding {
176
+ rule: string
177
+ line?: number
178
+ group: string
179
+ desc: string
180
+ severity?: string
181
+ }
182
+
48
183
  /**
49
- * age-decrypt with `password`, then zstd-decompress `dest`. Wrong passphrase
50
- * / non-passphrase envelopes surface as an error.
184
+ * Mechanically repair an AGS4 file (`path`) / `text` / `data`: apply the SAFE
185
+ * fixes (plus the risky set when `includeRisky`), re-validate, and return the
186
+ * fixed bytes + residual findings. Mirrors laterite-py's `fix()` /
187
+ * `lat-check --fix`; the single `fix_document` orchestration is shared. The TS
188
+ * layer wraps this into a `FixResult` (`.bytes` / `.text` / `.save(path)`).
51
189
  */
52
- export declare function transportUnlock(src: string, dest: string, password: string): UnpackStats
53
- /** The crate version. */
54
- export declare function version(): string
190
+ export declare function fixFile(path?: string | undefined | null, text?: string | undefined | null, data?: Uint8Array | undefined | null, dictVersion?: string | undefined | null, encoding?: string | undefined | null, includeRisky?: boolean | undefined | null): FixReport
191
+
192
+ /**
193
+ * The repair report — the Node mirror of laterite-py's `fix_file` dict. `ok` is
194
+ * false only for un-fixable input (the TS layer raises then). `fixed` is the
195
+ * repaired bytes (the original verbatim when nothing applied); `residual` is
196
+ * what could *not* be mechanically fixed.
197
+ */
198
+ export interface FixReport {
199
+ ok: boolean
200
+ errorKind?: string
201
+ error?: string
202
+ exitCode: number
203
+ fixed: Buffer
204
+ dictVersion: string
205
+ resolution: string
206
+ fixesApplied: number
207
+ applied: Array<AppliedFix>
208
+ residual: Array<Finding>
209
+ }
210
+
211
+ /**
212
+ * One group of columnar input — its code + an Arrow IPC stream (`Buffer`)
213
+ * whose column names are the AGS headings.
214
+ */
215
+ export interface GroupIpc {
216
+ code: string
217
+ ipc: Buffer
218
+ }
219
+
55
220
  /** Per-group schema — parallel arrays, one entry per heading. */
56
221
  export interface GroupMeta {
57
222
  headings: Array<string>
@@ -66,6 +231,24 @@ export interface GroupMeta {
66
231
  /** 1-indexed source line of each DATA row (parallel to the group's rows). */
67
232
  lineNumbers: Array<number>
68
233
  }
234
+
235
+ /**
236
+ * The AGS4 rule catalogue as the gated `rules_meta.json` — byte-identical to
237
+ * laterite-py's `list_rules()` and `lat-check --list-rules --json`. The TS
238
+ * layer parses it into typed `RuleMeta[]`. No input file.
239
+ */
240
+ export declare function listRules(): string
241
+
242
+ /**
243
+ * Result of `transportPack` / `transportLock`: output size, ratio vs source,
244
+ * elapsed seconds.
245
+ */
246
+ export interface PackStats {
247
+ bytes: bigint
248
+ ratio: number
249
+ elapsedS: number
250
+ }
251
+
69
252
  /**
70
253
  * Parse an AGS4 file (`path`), in-memory `text`, or raw `data` bytes into a
71
254
  * `Reading` handle. `encoding`: `"utf-8"` (default) / `"windows-1252"` / a label
@@ -73,14 +256,61 @@ export interface GroupMeta {
73
256
  * `kind␟code␟message` (see the error-protocol note) on bad input.
74
257
  */
75
258
  export declare function parseArrow(path?: string | undefined | null, text?: string | undefined | null, data?: Uint8Array | undefined | null, encoding?: string | undefined | null): Reading
76
- /** One rule violation (omitting `severity` ⇒ error, matching the engine). */
77
- export interface Finding {
78
- rule: string
79
- line?: number
80
- group: string
81
- desc: string
82
- severity?: string
259
+
260
+ /**
261
+ * Parse an AGS4-shaped raw string into its canonical value — the same engine
262
+ * the read path uses. Permissive: empty / unparseable → `null`. Returns native
263
+ * JS: integer/decimal → number, bool → boolean, string/enum → string,
264
+ * **datetime/date/time → the canonical string** (`"YYYY-MM-DD HH:MM:SS"` /
265
+ * `"YYYY-MM-DD"` / `"HH:MM:SS"`), unknown code → the trimmed input.
266
+ */
267
+ export declare function parseValue(raw: string | undefined | null, agsType: string): any
268
+
269
+ /**
270
+ * The bundled standard dictionary for `edition` as JSON — the
271
+ * `{ags_edition, groups:[{code, contents, parent, headings:[…]}]}` shape the
272
+ * browser and `laterite.registry.dictionary()` also render, from the ONE shared
273
+ * `dict::dictionary_dto` builder (#294 F#6). `None`/`"auto"` → the fallback
274
+ * edition; else 4.0.3|4.0.4|4.1|4.1.1|4.2. The TS `registry.dictionary()` parses
275
+ * it. (The generated `GROUPS` stays the default union registry.)
276
+ */
277
+ export declare function registryDictionaryJson(edition?: string | undefined | null): string
278
+
279
+ /**
280
+ * Validate an AGS4 file (`path`) or `text` against the AGS4 rules. `dict_version`
281
+ * `None`/`"auto"` auto-detects from `TRAN_AGS`, else forces an edition. Returns
282
+ * the `{ok:false}` failure report (not a throw) for un-validatable input.
283
+ *
284
+ * Severity tiers track importance (like a compiler): errors **and WARNINGs** are
285
+ * returned by default (`includeWarnings` defaults to `true`); pass `false` for
286
+ * errors-only. `includeFyi` (default `false`) adds the low-signal FYI tier.
287
+ */
288
+ export declare function runCheck(path?: string | undefined | null, text?: string | undefined | null, data?: Uint8Array | undefined | null, dictVersion?: string | undefined | null, includeWarnings?: boolean | undefined | null, includeFyi?: boolean | undefined | null, checkFiles?: boolean | undefined | null, encoding?: string | undefined | null): ValidationReport
289
+
290
+ /**
291
+ * zstd-compress, then age-encrypt with `password` → `dest`. Compress-then-
292
+ * encrypt is load-bearing: zstd needs low-entropy input; ciphertext is random.
293
+ */
294
+ export declare function transportLock(src: string, dest: string, password: string, level?: number | undefined | null): PackStats
295
+
296
+ /** zstd-compress `src` → `dest`. `level` is 1–22 (default 9, the AGS sweet spot). */
297
+ export declare function transportPack(src: string, dest: string, level?: number | undefined | null): PackStats
298
+
299
+ /**
300
+ * age-decrypt with `password`, then zstd-decompress → `dest`. Wrong passphrase
301
+ * / non-passphrase envelopes surface as an error.
302
+ */
303
+ export declare function transportUnlock(src: string, dest: string, password: string): UnpackStats
304
+
305
+ /** zstd-decompress `src` → `dest`. */
306
+ export declare function transportUnpack(src: string, dest: string): UnpackStats
307
+
308
+ /** Result of `transportUnpack` / `transportUnlock`: output size, elapsed seconds. */
309
+ export interface UnpackStats {
310
+ bytes: bigint
311
+ elapsedS: number
83
312
  }
313
+
84
314
  /**
85
315
  * The validation report — the Node mirror of laterite-py's `run_check` dict.
86
316
  * `ok` is **false only for un-validatable input** (the TS `raiseFor` raises
@@ -109,109 +339,6 @@ export interface ValidationReport {
109
339
  json: string
110
340
  ndjson: string
111
341
  }
112
- /**
113
- * Validate an AGS4 file (`path`) or `text` against the AGS4 rules. `dict_version`
114
- * `None`/`"auto"` auto-detects from `TRAN_AGS`, else forces an edition. Returns
115
- * the `{ok:false}` failure report (not a throw) for un-validatable input.
116
- *
117
- * Severity tiers track importance (like a compiler): errors **and WARNINGs** are
118
- * returned by default (`includeWarnings` defaults to `true`); pass `false` for
119
- * errors-only. `includeFyi` (default `false`) adds the low-signal FYI tier.
120
- */
121
- export declare function runCheck(path?: string | undefined | null, text?: string | undefined | null, data?: Uint8Array | undefined | null, dictVersion?: string | undefined | null, includeWarnings?: boolean | undefined | null, includeFyi?: boolean | undefined | null, checkFiles?: boolean | undefined | null, encoding?: string | undefined | null): ValidationReport
122
- /**
123
- * The AGS4 rule catalogue as the gated `rules_meta.json` — byte-identical to
124
- * laterite-py's `list_rules()` and `lat-check --list-rules --json`. The TS
125
- * layer parses it into typed `RuleMeta[]`. No input file.
126
- */
127
- export declare function listRules(): string
128
- /**
129
- * One applied fix — the Node mirror of laterite-py's `applied[]` entries.
130
- * `kind`/`risk` are the serde snake_case strings (`strip_bom`, `safe`, …) so
131
- * the shape is identical across Python / CLI / Node.
132
- */
133
- export interface AppliedFix {
134
- kind: string
135
- label: string
136
- rule: string
137
- line?: number
138
- risk: string
139
- }
140
- /**
141
- * The repair report — the Node mirror of laterite-py's `fix_file` dict. `ok` is
142
- * false only for un-fixable input (the TS layer raises then). `fixed` is the
143
- * repaired bytes (the original verbatim when nothing applied); `residual` is
144
- * what could *not* be mechanically fixed.
145
- */
146
- export interface FixReport {
147
- ok: boolean
148
- errorKind?: string
149
- error?: string
150
- exitCode: number
151
- fixed: Buffer
152
- dictVersion: string
153
- resolution: string
154
- fixesApplied: number
155
- applied: Array<AppliedFix>
156
- residual: Array<Finding>
157
- }
158
- /**
159
- * Mechanically repair an AGS4 file (`path`) / `text` / `data`: apply the SAFE
160
- * fixes (plus the risky set when `includeRisky`), re-validate, and return the
161
- * fixed bytes + residual findings. Mirrors laterite-py's `fix()` /
162
- * `lat-check --fix`; the single `fix_document` orchestration is shared. The TS
163
- * layer wraps this into a `FixResult` (`.bytes` / `.text` / `.save(path)`).
164
- */
165
- export declare function fixFile(path?: string | undefined | null, text?: string | undefined | null, data?: Uint8Array | undefined | null, dictVersion?: string | undefined | null, encoding?: string | undefined | null, includeRisky?: boolean | undefined | null): FixReport
166
- /**
167
- * One group of columnar input — its code + an Arrow IPC stream (`Buffer`)
168
- * whose column names are the AGS headings.
169
- */
170
- export interface GroupIpc {
171
- code: string
172
- ipc: Buffer
173
- }
174
- /**
175
- * The emit result. `bytes` is the AGS4 document; `findingsJson` is the
176
- * validator's `{rule:[…]}` map on the output; `fixesApplied` counts safe fixes.
177
- */
178
- export interface EmitResult {
179
- bytes: Buffer
180
- findingsJson: string
181
- fixesApplied: number
182
- }
183
- /**
184
- * Build valid AGS4 from per-group **Arrow IPC** streams (the columnar
185
- * producer; the read boundary reversed). = `laterite-ags4-wasm`'s `to_ags4_ipc`.
186
- */
187
- export declare function emitAgs4FromIpc(groups: Array<GroupIpc>, edition?: string | undefined | null, mode?: string | undefined | null): EmitResult
188
- /**
189
- * A parsed AGS4 file held native-side — the Node analog of laterite-py's
190
- * `Reading` handle (and `laterite-ags4-wasm`'s `ParsedDataset`). Each group's typed
191
- * `RecordBatch` is built lazily on `tableIpc(code)` and dropped after the
192
- * bytes are returned, so peak residency is one batch.
193
- */
194
- export declare class Reading {
195
- /** Group codes in file order (the order to load tables in). */
196
- groupCodes(): Array<string>
197
- /** The file's `TRAN_AGS` edition string, if present. */
198
- get tranAgs(): string | null
199
- /**
200
- * `{headings, units, types, sqlTypes}` for one group, or `null` if the
201
- * code isn't present. No Arrow built — cheap metadata only.
202
- */
203
- meta(code: string): GroupMeta | null
204
- /**
205
- * One group's rows as an Arrow **IPC stream** (`Buffer`), columns already
206
- * correctly typed. The Node analog of the pyo3-arrow capsule: the typed
207
- * columns come from the one shared emitter (`laterite_types::arrow_cols`), the
208
- * SAME casting Python/wasm use — so a file types byte-identically across
209
- * hosts. Returns `null` if the code isn't in the file.
210
- */
211
- tableIpc(code: string): Buffer | null
212
- /**
213
- * Re-emit byte-faithful AGS4 text from the retained parse (the raw DATA
214
- * values, unchanged). = laterite-py's `Reading::emit`.
215
- */
216
- emit(): string
217
- }
342
+
343
+ /** The crate version. */
344
+ export declare function version(): string