@wavehouse/chtypes 0.1.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 +24 -0
- package/LICENSE +202 -0
- package/README.md +442 -0
- package/dist/cli.d.ts +43 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +303 -0
- package/dist/cli.js.map +1 -0
- package/dist/discover.d.ts +134 -0
- package/dist/discover.d.ts.map +1 -0
- package/dist/discover.js +291 -0
- package/dist/discover.js.map +1 -0
- package/dist/errors.d.ts +204 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +228 -0
- package/dist/errors.js.map +1 -0
- package/dist/fetch.d.ts +235 -0
- package/dist/fetch.d.ts.map +1 -0
- package/dist/fetch.js +842 -0
- package/dist/fetch.js.map +1 -0
- package/dist/ffi.d.ts +346 -0
- package/dist/ffi.d.ts.map +1 -0
- package/dist/ffi.js +913 -0
- package/dist/ffi.js.map +1 -0
- package/dist/format.d.ts +104 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +108 -0
- package/dist/format.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/json.d.ts +127 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/json.js +577 -0
- package/dist/json.js.map +1 -0
- package/dist/library.d.ts +225 -0
- package/dist/library.d.ts.map +1 -0
- package/dist/library.js +234 -0
- package/dist/library.js.map +1 -0
- package/dist/numeric.d.ts +20 -0
- package/dist/numeric.d.ts.map +1 -0
- package/dist/numeric.js +107 -0
- package/dist/numeric.js.map +1 -0
- package/dist/paths.d.ts +47 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +78 -0
- package/dist/paths.js.map +1 -0
- package/dist/registry.d.ts +204 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +409 -0
- package/dist/registry.js.map +1 -0
- package/dist/results.d.ts +326 -0
- package/dist/results.d.ts.map +1 -0
- package/dist/results.js +235 -0
- package/dist/results.js.map +1 -0
- package/dist/schema.d.ts +444 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +448 -0
- package/dist/schema.js.map +1 -0
- package/dist/settings.d.ts +43 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +33 -0
- package/dist/settings.js.map +1 -0
- package/dist/tar.d.ts +32 -0
- package/dist/tar.d.ts.map +1 -0
- package/dist/tar.js +310 -0
- package/dist/tar.js.map +1 -0
- package/dist/transform.d.ts +73 -0
- package/dist/transform.d.ts.map +1 -0
- package/dist/transform.js +527 -0
- package/dist/transform.js.map +1 -0
- package/package.json +62 -0
package/dist/tar.js
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A streaming reader for the artifact tarballs — ustar, pax extended
|
|
3
|
+
* headers, GNU long names — written here rather than taken from a
|
|
4
|
+
* dependency: this package's one runtime dependency is ffi-rs, and a reader
|
|
5
|
+
* that extracts regular files under one directory is a page of code.
|
|
6
|
+
*
|
|
7
|
+
* Files only. Directories are created; everything else — symlinks, hard
|
|
8
|
+
* links, devices, FIFOs — is skipped without being followed: an artifact is
|
|
9
|
+
* `manifest.json`, one library and two text files, and a link inside one is
|
|
10
|
+
* an attack, not a feature. Every entry name is confined to the destination
|
|
11
|
+
* (no absolute names, no `..` components, no escape once resolved), and a
|
|
12
|
+
* name that escapes is refused as corrupt rather than clamped.
|
|
13
|
+
*
|
|
14
|
+
* The archive is consumed as a stream: a 300 MB library is written to disk
|
|
15
|
+
* as it inflates and never sits in memory whole.
|
|
16
|
+
*/
|
|
17
|
+
import { createReadStream } from 'node:fs';
|
|
18
|
+
import { mkdir, open as openFile } from 'node:fs/promises';
|
|
19
|
+
import path from 'node:path';
|
|
20
|
+
import { Writable } from 'node:stream';
|
|
21
|
+
import { pipeline } from 'node:stream/promises';
|
|
22
|
+
import { createGunzip } from 'node:zlib';
|
|
23
|
+
import { ArtifactCorruptError, FetchError } from './errors.js';
|
|
24
|
+
const BLOCK = 512;
|
|
25
|
+
/** pax records and long names are tiny; a megabyte of them is not a tarball. */
|
|
26
|
+
const MAX_META = 1 << 20;
|
|
27
|
+
/**
|
|
28
|
+
* Inflate and unpack `archive` (a `.tar.gz`) into `dest`, which must already
|
|
29
|
+
* exist. Returns the regular files written, in archive order.
|
|
30
|
+
*
|
|
31
|
+
* @throws {ArtifactCorruptError} when the bytes are not a gzip stream, a
|
|
32
|
+
* header fails its checksum, the archive is truncated, or an entry name
|
|
33
|
+
* would land outside `dest`.
|
|
34
|
+
*/
|
|
35
|
+
export async function extractTarGz(archive, dest) {
|
|
36
|
+
const extractor = new TarExtractor(path.resolve(dest));
|
|
37
|
+
try {
|
|
38
|
+
await pipeline(createReadStream(archive), createGunzip(), extractor);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
if (err instanceof FetchError)
|
|
42
|
+
throw err;
|
|
43
|
+
throw new ArtifactCorruptError(`chtypes: ${archive} is not a readable tar.gz: ${errorText(err)}`, {
|
|
44
|
+
cause: err,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return extractor.entries;
|
|
48
|
+
}
|
|
49
|
+
class TarExtractor extends Writable {
|
|
50
|
+
dest;
|
|
51
|
+
entries = [];
|
|
52
|
+
head = Buffer.alloc(BLOCK);
|
|
53
|
+
headFill = 0;
|
|
54
|
+
/** Data bytes still to consume for the current entry, then the block padding after them. */
|
|
55
|
+
remaining = 0;
|
|
56
|
+
padding = 0;
|
|
57
|
+
pending = null;
|
|
58
|
+
/** Overrides a pax `x` or GNU `L` entry set for the entry that follows. */
|
|
59
|
+
nextName = null;
|
|
60
|
+
nextSize = null;
|
|
61
|
+
zeroBlocks = 0;
|
|
62
|
+
ended = false;
|
|
63
|
+
constructor(dest) {
|
|
64
|
+
super();
|
|
65
|
+
this.dest = dest;
|
|
66
|
+
}
|
|
67
|
+
_write(chunk, _encoding, callback) {
|
|
68
|
+
this.consume(chunk).then(() => callback(), (err) => callback(err instanceof Error ? err : new Error(String(err))));
|
|
69
|
+
}
|
|
70
|
+
_final(callback) {
|
|
71
|
+
const truncated = !this.ended && (this.headFill !== 0 || this.remaining !== 0 || this.pending !== null);
|
|
72
|
+
this.closePending().then(() => callback(truncated ? new ArtifactCorruptError('chtypes: tarball is truncated') : null), (err) => callback(err instanceof Error ? err : new Error(String(err))));
|
|
73
|
+
}
|
|
74
|
+
_destroy(error, callback) {
|
|
75
|
+
this.closePending().then(() => callback(error), () => callback(error));
|
|
76
|
+
}
|
|
77
|
+
async closePending() {
|
|
78
|
+
const p = this.pending;
|
|
79
|
+
this.pending = null;
|
|
80
|
+
if (p !== null && p.kind === 'file')
|
|
81
|
+
await p.handle.close();
|
|
82
|
+
}
|
|
83
|
+
async consume(chunk) {
|
|
84
|
+
let off = 0;
|
|
85
|
+
while (off < chunk.length) {
|
|
86
|
+
// Bytes after the end-of-archive marker are padding; nothing lives there.
|
|
87
|
+
if (this.ended)
|
|
88
|
+
return;
|
|
89
|
+
if (this.remaining > 0) {
|
|
90
|
+
const n = Math.min(this.remaining, chunk.length - off);
|
|
91
|
+
await this.data(chunk.subarray(off, off + n));
|
|
92
|
+
this.remaining -= n;
|
|
93
|
+
off += n;
|
|
94
|
+
if (this.remaining === 0)
|
|
95
|
+
await this.finishEntry();
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (this.padding > 0) {
|
|
99
|
+
const n = Math.min(this.padding, chunk.length - off);
|
|
100
|
+
this.padding -= n;
|
|
101
|
+
off += n;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const n = Math.min(BLOCK - this.headFill, chunk.length - off);
|
|
105
|
+
chunk.copy(this.head, this.headFill, off, off + n);
|
|
106
|
+
this.headFill += n;
|
|
107
|
+
off += n;
|
|
108
|
+
if (this.headFill === BLOCK) {
|
|
109
|
+
this.headFill = 0;
|
|
110
|
+
await this.header(this.head);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
async header(block) {
|
|
115
|
+
if (isZero(block)) {
|
|
116
|
+
// Two zero blocks end the archive; one followed by EOF is tolerated in _final.
|
|
117
|
+
this.zeroBlocks += 1;
|
|
118
|
+
if (this.zeroBlocks >= 2)
|
|
119
|
+
this.ended = true;
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
this.zeroBlocks = 0;
|
|
123
|
+
if (!checksumOk(block))
|
|
124
|
+
throw new ArtifactCorruptError('chtypes: tarball header fails its checksum');
|
|
125
|
+
const flag = block[156];
|
|
126
|
+
const ownSize = parseSize(block, 124, 12);
|
|
127
|
+
if (Number.isNaN(ownSize))
|
|
128
|
+
throw new ArtifactCorruptError('chtypes: tarball header carries an unreadable size');
|
|
129
|
+
const isMeta = flag === 0x78 /* x */ || flag === 0x67 /* g */ || flag === 0x4c /* L */;
|
|
130
|
+
let name;
|
|
131
|
+
let size;
|
|
132
|
+
if (isMeta) {
|
|
133
|
+
name = '';
|
|
134
|
+
size = ownSize;
|
|
135
|
+
if (size > MAX_META)
|
|
136
|
+
throw new ArtifactCorruptError('chtypes: tarball extended header is implausibly large');
|
|
137
|
+
this.pending = { kind: 'meta', flag, chunks: [] };
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const magic = block.toString('latin1', 257, 262);
|
|
141
|
+
const prefix = magic === 'ustar' ? cstr(block, 345, 155) : '';
|
|
142
|
+
const base = cstr(block, 0, 100);
|
|
143
|
+
name = this.nextName ?? (prefix !== '' ? `${prefix}/${base}` : base);
|
|
144
|
+
size = this.nextSize ?? ownSize;
|
|
145
|
+
this.nextName = null;
|
|
146
|
+
this.nextSize = null;
|
|
147
|
+
if (flag === 0x30 /* 0 */ || flag === 0x00 || flag === 0x37 /* 7 */) {
|
|
148
|
+
const target = this.confine(name, false);
|
|
149
|
+
await mkdir(path.dirname(target), { recursive: true });
|
|
150
|
+
const handle = await openFile(target, 'w');
|
|
151
|
+
this.pending = { kind: 'file', handle };
|
|
152
|
+
this.entries.push({ name: path.relative(this.dest, target).split(path.sep).join('/'), size });
|
|
153
|
+
}
|
|
154
|
+
else if (flag === 0x35 /* 5 */) {
|
|
155
|
+
const target = this.confine(name, true);
|
|
156
|
+
if (target !== this.dest)
|
|
157
|
+
await mkdir(target, { recursive: true });
|
|
158
|
+
this.pending = { kind: 'skip' };
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
// Links, devices, FIFOs: files only. Skipped, never followed.
|
|
162
|
+
this.pending = { kind: 'skip' };
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
this.remaining = size;
|
|
166
|
+
this.padding = (BLOCK - (size % BLOCK)) % BLOCK;
|
|
167
|
+
if (size === 0)
|
|
168
|
+
await this.finishEntry();
|
|
169
|
+
}
|
|
170
|
+
async data(slice) {
|
|
171
|
+
const p = this.pending;
|
|
172
|
+
if (p === null)
|
|
173
|
+
return;
|
|
174
|
+
if (p.kind === 'file') {
|
|
175
|
+
let written = 0;
|
|
176
|
+
while (written < slice.length) {
|
|
177
|
+
const r = await p.handle.write(slice, written, slice.length - written);
|
|
178
|
+
if (r.bytesWritten <= 0)
|
|
179
|
+
throw new Error('short write');
|
|
180
|
+
written += r.bytesWritten;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else if (p.kind === 'meta') {
|
|
184
|
+
p.chunks.push(Buffer.from(slice));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
async finishEntry() {
|
|
188
|
+
const p = this.pending;
|
|
189
|
+
this.pending = null;
|
|
190
|
+
if (p === null)
|
|
191
|
+
return;
|
|
192
|
+
if (p.kind === 'file') {
|
|
193
|
+
await p.handle.close();
|
|
194
|
+
}
|
|
195
|
+
else if (p.kind === 'meta') {
|
|
196
|
+
const payload = Buffer.concat(p.chunks);
|
|
197
|
+
if (p.flag === 0x4c /* L: GNU long name */) {
|
|
198
|
+
this.nextName = cstr(payload, 0, payload.length);
|
|
199
|
+
}
|
|
200
|
+
else if (p.flag === 0x78 /* x: pax, for the next entry */) {
|
|
201
|
+
for (const [key, value] of paxRecords(payload)) {
|
|
202
|
+
if (key === 'path')
|
|
203
|
+
this.nextName = value;
|
|
204
|
+
else if (key === 'size') {
|
|
205
|
+
const n = Number(value);
|
|
206
|
+
if (!/^\d+$/.test(value) || !Number.isSafeInteger(n)) {
|
|
207
|
+
throw new ArtifactCorruptError('chtypes: tarball pax header carries an unreadable size');
|
|
208
|
+
}
|
|
209
|
+
this.nextSize = n;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
// 'g' (global pax) carries nothing an artifact needs; consumed, ignored.
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/** Resolve an entry name under the destination, refusing anything that would leave it. */
|
|
217
|
+
confine(name, isDir) {
|
|
218
|
+
const bad = (why) => {
|
|
219
|
+
throw new ArtifactCorruptError(`chtypes: tarball entry ${JSON.stringify(name)} refused: ${why}`);
|
|
220
|
+
};
|
|
221
|
+
if (name === '')
|
|
222
|
+
bad('empty name');
|
|
223
|
+
if (name.includes('\\'))
|
|
224
|
+
bad('backslash in name');
|
|
225
|
+
if (name.startsWith('/'))
|
|
226
|
+
bad('absolute path');
|
|
227
|
+
const parts = name.split('/').filter((p) => p !== '' && p !== '.');
|
|
228
|
+
if (parts.some((p) => p === '..'))
|
|
229
|
+
bad('path traversal');
|
|
230
|
+
if (parts.length === 0) {
|
|
231
|
+
if (isDir)
|
|
232
|
+
return this.dest;
|
|
233
|
+
bad('no file name');
|
|
234
|
+
}
|
|
235
|
+
const target = path.join(this.dest, ...parts);
|
|
236
|
+
if (target !== this.dest && !target.startsWith(this.dest + path.sep))
|
|
237
|
+
bad('escapes the destination');
|
|
238
|
+
return target;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function isZero(block) {
|
|
242
|
+
for (let i = 0; i < block.length; i++)
|
|
243
|
+
if (block[i] !== 0)
|
|
244
|
+
return false;
|
|
245
|
+
return true;
|
|
246
|
+
}
|
|
247
|
+
/** The header checksum, with the checksum field itself read as spaces; unsigned and signed sums both accepted. */
|
|
248
|
+
function checksumOk(block) {
|
|
249
|
+
const recorded = parseOctal(block, 148, 8);
|
|
250
|
+
if (Number.isNaN(recorded))
|
|
251
|
+
return false;
|
|
252
|
+
let unsigned = 0;
|
|
253
|
+
let signed = 0;
|
|
254
|
+
for (let i = 0; i < BLOCK; i++) {
|
|
255
|
+
const b = i >= 148 && i < 156 ? 0x20 : block[i];
|
|
256
|
+
unsigned += b;
|
|
257
|
+
signed += b >= 0x80 ? b - 0x100 : b;
|
|
258
|
+
}
|
|
259
|
+
return recorded === unsigned || recorded === signed;
|
|
260
|
+
}
|
|
261
|
+
function cstr(buf, off, len) {
|
|
262
|
+
const end = Math.min(buf.length, off + len);
|
|
263
|
+
let nul = off;
|
|
264
|
+
while (nul < end && buf[nul] !== 0)
|
|
265
|
+
nul++;
|
|
266
|
+
return buf.toString('utf8', off, nul);
|
|
267
|
+
}
|
|
268
|
+
function parseOctal(buf, off, len) {
|
|
269
|
+
const text = cstr(buf, off, len).trim();
|
|
270
|
+
if (text === '')
|
|
271
|
+
return 0;
|
|
272
|
+
if (!/^[0-7]+$/.test(text))
|
|
273
|
+
return Number.NaN;
|
|
274
|
+
return Number.parseInt(text, 8);
|
|
275
|
+
}
|
|
276
|
+
/** Sizes are octal, or base-256 with the high bit of the first byte set (GNU, for > 8 GiB). */
|
|
277
|
+
function parseSize(buf, off, len) {
|
|
278
|
+
const first = buf[off];
|
|
279
|
+
if ((first & 0x80) !== 0) {
|
|
280
|
+
let value = first & 0x7f;
|
|
281
|
+
for (let i = 1; i < len; i++)
|
|
282
|
+
value = value * 256 + buf[off + i];
|
|
283
|
+
return Number.isSafeInteger(value) ? value : Number.NaN;
|
|
284
|
+
}
|
|
285
|
+
return parseOctal(buf, off, len);
|
|
286
|
+
}
|
|
287
|
+
/** pax records: `<decimal length> <key>=<value>\n`, the length counting the whole record. */
|
|
288
|
+
function paxRecords(payload) {
|
|
289
|
+
const out = [];
|
|
290
|
+
let pos = 0;
|
|
291
|
+
while (pos < payload.length) {
|
|
292
|
+
const space = payload.indexOf(0x20, pos);
|
|
293
|
+
if (space < 0)
|
|
294
|
+
break;
|
|
295
|
+
const len = Number.parseInt(payload.toString('latin1', pos, space), 10);
|
|
296
|
+
if (!Number.isInteger(len) || len <= 0 || pos + len > payload.length) {
|
|
297
|
+
throw new ArtifactCorruptError('chtypes: tarball pax header is malformed');
|
|
298
|
+
}
|
|
299
|
+
const record = payload.toString('utf8', space + 1, pos + len - 1);
|
|
300
|
+
const eq = record.indexOf('=');
|
|
301
|
+
if (eq > 0)
|
|
302
|
+
out.push([record.slice(0, eq), record.slice(eq + 1)]);
|
|
303
|
+
pos += len;
|
|
304
|
+
}
|
|
305
|
+
return out;
|
|
306
|
+
}
|
|
307
|
+
function errorText(err) {
|
|
308
|
+
return err instanceof Error ? err.message : String(err);
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=tar.js.map
|
package/dist/tar.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tar.js","sourceRoot":"","sources":["../src/tar.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Silent-transformation detection — a port of `go/chtypes/transform.go`.
|
|
3
|
+
*
|
|
4
|
+
* ClickHouse has no notion of "I changed your value": `readIntText` wraps mod
|
|
5
|
+
* 2^N, `SerializationDateTime` truncates, `parseUUID` maps every non-hex byte to
|
|
6
|
+
* 0xff, and all of it returns success. So the fact of a change has to be
|
|
7
|
+
* established from outside, and this is the one part of chtypes that is derived
|
|
8
|
+
* rather than executed by ClickHouse — which makes it the one part a binding can
|
|
9
|
+
* get wrong without the C library noticing. Omitting it scores 0 % recall on the
|
|
10
|
+
* arbiter's transformation axis regardless of everything else.
|
|
11
|
+
*
|
|
12
|
+
* Two independent detectors run and their union is reported:
|
|
13
|
+
*
|
|
14
|
+
* 1. **Supplied vs stored** — the raw input text against ClickHouse's rendering
|
|
15
|
+
* of what it kept. Models nothing; catches changes a widened type makes
|
|
16
|
+
* identically (2024-02-30 -> 2024-03-01) and types with no wider type to
|
|
17
|
+
* compare against (Float64, Int256, String).
|
|
18
|
+
* 2. **Reference type** — the C layer already parsed each field a second time
|
|
19
|
+
* through a structurally identical type with widened leaves and reported it
|
|
20
|
+
* as `ref` / `ref_type`. This names the reason precisely (an overflow wrap
|
|
21
|
+
* versus a decimal truncation) and still fires where the supplied text is
|
|
22
|
+
* not comparable (a CSV field, a base64 blob).
|
|
23
|
+
*
|
|
24
|
+
* Neither reimplements a coercion rule: the first compares two values already in
|
|
25
|
+
* hand, the second compares two ClickHouse answers.
|
|
26
|
+
*
|
|
27
|
+
* Both compare **bytes**. A supplied field and a stored `String` can each be any
|
|
28
|
+
* byte sequence, and two different byte sequences that both decode to U+FFFD are
|
|
29
|
+
* not the same value — deciding on decoded text would silently merge them, and
|
|
30
|
+
* `equivalent`'s fast path would then call a real change identical.
|
|
31
|
+
*/
|
|
32
|
+
import type { ColumnDoc, Transform } from './results.js';
|
|
33
|
+
/** The stable reason vocabulary. The harness groups on these strings. */
|
|
34
|
+
export declare const Reason: {
|
|
35
|
+
readonly OverflowWrap: 'overflow_wrap';
|
|
36
|
+
readonly NullToDefault: 'null_to_default';
|
|
37
|
+
readonly NullLoss: 'null_loss';
|
|
38
|
+
readonly DecimalTruncate: 'decimal_truncate';
|
|
39
|
+
readonly DateClamp: 'date_clamp';
|
|
40
|
+
readonly DateTimeWrap: 'datetime_wrap';
|
|
41
|
+
readonly DateShift: 'date_shift';
|
|
42
|
+
readonly UuidMangle: 'uuid_mangle';
|
|
43
|
+
readonly IpMangle: 'ip_mangle';
|
|
44
|
+
readonly FloatPrecision: 'float_precision';
|
|
45
|
+
readonly LossyNumeric: 'lossy_numeric';
|
|
46
|
+
readonly FixedStringPad: 'fixedstring_pad';
|
|
47
|
+
readonly Emptied: 'emptied';
|
|
48
|
+
readonly ElementChanged: 'element_changed';
|
|
49
|
+
readonly EnumCoerce: 'enum_coerce';
|
|
50
|
+
readonly ValueChanged: 'value_changed';
|
|
51
|
+
readonly Poisoned: 'poisoned';
|
|
52
|
+
readonly DuplicateKeyDropped: 'duplicate_key_dropped';
|
|
53
|
+
readonly Reformat: 'reformat';
|
|
54
|
+
readonly DefaultFilled: 'default_filled';
|
|
55
|
+
readonly ZeroFilled: 'zero_filled';
|
|
56
|
+
readonly DefaultMaterialised: 'default_materialised';
|
|
57
|
+
readonly TtlExpired: 'ttl_expired';
|
|
58
|
+
readonly TtlColumnExpired: 'ttl_column_expired';
|
|
59
|
+
};
|
|
60
|
+
/** One of the stable reason strings — see the `Reason` constant object. */
|
|
61
|
+
export type Reason = (typeof Reason)[keyof typeof Reason];
|
|
62
|
+
/**
|
|
63
|
+
* Whether a transform reason means information was LOST (a warning to raise to
|
|
64
|
+
* the tenant) rather than merely re-spelled or filled in. False for exactly
|
|
65
|
+
* four reasons — `reformat`, `default_filled`, `zero_filled`,
|
|
66
|
+
* `default_materialised` — true for everything else, unknown strings included:
|
|
67
|
+
* a reason nobody has audited must degrade to a warning, never to silence.
|
|
68
|
+
* Mirrors `Transform#lossy`. Never throws.
|
|
69
|
+
*/
|
|
70
|
+
export declare function isLossyReason(reason: string): boolean;
|
|
71
|
+
/** Classify one column of a row document. */
|
|
72
|
+
export declare function classify(c: ColumnDoc): Transform[];
|
|
73
|
+
//# sourceMappingURL=transform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../src/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD,yEAAyE;AACzE,eAAO,MAAM,MAAM;aACjB,YAAY,EAAE,eAAe;aAC7B,aAAa,EAAE,iBAAiB;aAChC,QAAQ,EAAE,WAAW;aACrB,eAAe,EAAE,kBAAkB;aACnC,SAAS,EAAE,YAAY;aACvB,YAAY,EAAE,eAAe;aAC7B,SAAS,EAAE,YAAY;aACvB,UAAU,EAAE,aAAa;aACzB,QAAQ,EAAE,WAAW;aACrB,cAAc,EAAE,iBAAiB;aACjC,YAAY,EAAE,eAAe;aAC7B,cAAc,EAAE,iBAAiB;aACjC,OAAO,EAAE,SAAS;aAClB,cAAc,EAAE,iBAAiB;aACjC,UAAU,EAAE,aAAa;aACzB,YAAY,EAAE,eAAe;aAC7B,QAAQ,EAAE,UAAU;aACpB,mBAAmB,EAAE,uBAAuB;aAC5C,QAAQ,EAAE,UAAU;aACpB,aAAa,EAAE,gBAAgB;aAC/B,UAAU,EAAE,aAAa;aACzB,mBAAmB,EAAE,sBAAsB;aAC3C,UAAU,EAAE,aAAa;aACzB,gBAAgB,EAAE,oBAAoB;CAC9B,CAAC;AAEX,2EAA2E;AAC3E,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,MAAM,CAAC,CAAC,MAAM,OAAO,MAAM,CAAC,CAAC;AAe1D;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAErD;AAsBD,6CAA6C;AAC7C,wBAAgB,QAAQ,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,EAAE,CAkFlD"}
|