inibase 3.6.0 → 3.7.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/README.md +21 -3
- package/dist/file.d.ts +26 -5
- package/dist/file.js +132 -32
- package/dist/format.d.ts +54 -0
- package/dist/format.js +108 -0
- package/dist/index.d.ts +114 -9
- package/dist/index.js +697 -108
- package/dist/overlay.d.ts +59 -0
- package/dist/overlay.js +106 -0
- package/dist/updatelog.d.ts +115 -0
- package/dist/updatelog.js +377 -0
- package/dist/utils.js +16 -0
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -44,6 +44,14 @@ export interface TableConfig {
|
|
|
44
44
|
cache?: boolean;
|
|
45
45
|
prepend?: boolean;
|
|
46
46
|
decodeID?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Opt a table into the incremental update log (format 2): `put` appends a
|
|
49
|
+
* small frame instead of rewriting whole columns, and reads merge the log
|
|
50
|
+
* over the base columns. Requires a schema of simple top-level fields and
|
|
51
|
+
* is incompatible with `prepend`, transactions and DDL on the table
|
|
52
|
+
* (those need compaction, shipped in 3.9).
|
|
53
|
+
*/
|
|
54
|
+
log?: boolean;
|
|
47
55
|
}
|
|
48
56
|
export interface TableObject {
|
|
49
57
|
schema?: Schema;
|
|
@@ -88,7 +96,7 @@ declare global {
|
|
|
88
96
|
entries<T extends object>(o: T): Entries<T>;
|
|
89
97
|
}
|
|
90
98
|
}
|
|
91
|
-
export declare const ERROR_CODES: readonly ["GROUP_UNIQUE", "FIELD_UNIQUE", "FIELD_REQUIRED", "NO_SCHEMA", "TABLE_EMPTY", "INVALID_ID", "INVALID_TYPE", "INVALID_PARAMETERS", "NO_ENV", "TABLE_EXISTS", "TABLE_NOT_EXISTS", "INVALID_REGEX_MATCH", "INVALID_NAME", "COMPUTED_FIELD_SYNTAX", "COMPUTED_FIELD_UNKNOWN_FIELD", "COMPUTED_FIELD_INVALID_LINK", "COMPUTED_FIELD_INVALID_TARGET", "COMPUTED_FIELD_CONFLICT", "COMPUTED_FIELD_CYCLE", "COMPUTED_FIELD_SETTABLE", "COMPUTED_FIELD_DANGLING_LINK", "COMPUTED_FIELD_ARITHMETIC"];
|
|
99
|
+
export declare const ERROR_CODES: readonly ["GROUP_UNIQUE", "FIELD_UNIQUE", "FIELD_REQUIRED", "NO_SCHEMA", "TABLE_EMPTY", "INVALID_ID", "INVALID_TYPE", "INVALID_PARAMETERS", "NO_ENV", "TABLE_EXISTS", "TABLE_NOT_EXISTS", "INVALID_REGEX_MATCH", "INVALID_NAME", "COMPUTED_FIELD_SYNTAX", "COMPUTED_FIELD_UNKNOWN_FIELD", "COMPUTED_FIELD_INVALID_LINK", "COMPUTED_FIELD_INVALID_TARGET", "COMPUTED_FIELD_CONFLICT", "COMPUTED_FIELD_CYCLE", "COMPUTED_FIELD_SETTABLE", "COMPUTED_FIELD_DANGLING_LINK", "COMPUTED_FIELD_ARITHMETIC", "UPDATE_LOG_CORRUPT", "UPDATE_LOG_FRAME_TOO_LARGE", "MAINTENANCE_REQUIRED", "UNSUPPORTED_FORMAT"];
|
|
92
100
|
export type ErrorCode = (typeof ERROR_CODES)[number];
|
|
93
101
|
export type ErrorLang = "en" | "ar" | "fr" | "es";
|
|
94
102
|
export declare const globalConfig: {
|
|
@@ -121,6 +129,15 @@ export default class Inibase {
|
|
|
121
129
|
* changes: see the invalidation in `getTable`'s reload branch,
|
|
122
130
|
* `createTable` and `updateTableLocked`. Bounded by the number of tables. */
|
|
123
131
|
private readonly computedPlanCache;
|
|
132
|
+
/** Per-table `.format` marker + live update-log overlays (format 2 tables).
|
|
133
|
+
* Keyed by `databasePath\0tableName` so two databases in one process never
|
|
134
|
+
* share state. Populated lazily by `getOverlay`. */
|
|
135
|
+
private readonly tableFormats;
|
|
136
|
+
private readonly overlays;
|
|
137
|
+
/** Last observed identity of each table's `.format` file (`mtime:size:ino`),
|
|
138
|
+
* used to detect a compaction by another process without re-reading the
|
|
139
|
+
* marker on every access. */
|
|
140
|
+
private readonly formatStamps;
|
|
124
141
|
private databasePath;
|
|
125
142
|
private uniqueMap;
|
|
126
143
|
private schemaFileExtension;
|
|
@@ -176,6 +193,74 @@ export default class Inibase {
|
|
|
176
193
|
* @return {*} {Promise<TableObject | undefined>}
|
|
177
194
|
*/
|
|
178
195
|
getTable(tableName: string): Promise<TableObject | undefined>;
|
|
196
|
+
private overlayKey;
|
|
197
|
+
/** True when the table opted into the incremental update log. */
|
|
198
|
+
private isLogTable;
|
|
199
|
+
/**
|
|
200
|
+
* Resolve a table's format marker, revalidating a cached *log* table when
|
|
201
|
+
* its `.format` file changed underneath us. A compaction by another process
|
|
202
|
+
* bumps `baseGen` and empties the log; without re-reading the marker this
|
|
203
|
+
* process would scan the new (empty) log with the old `baseGen`, and once a
|
|
204
|
+
* post-compaction frame appears the generation gap would look like
|
|
205
|
+
* corruption. Legacy tables never change format implicitly, so they skip
|
|
206
|
+
* the stat entirely and keep the pre-3.8 read path cost.
|
|
207
|
+
*/
|
|
208
|
+
/**
|
|
209
|
+
* Read a table's `.format` marker and refuse a table written by a newer
|
|
210
|
+
* engine (§4.1) *before* any column is read: a higher `format`, or a
|
|
211
|
+
* `minReader` above this build, throws UNSUPPORTED_FORMAT rather than being
|
|
212
|
+
* silently mis-read as format 2/legacy.
|
|
213
|
+
*/
|
|
214
|
+
private readValidatedFormat;
|
|
215
|
+
private currentFormat;
|
|
216
|
+
/**
|
|
217
|
+
* Load (or refresh) a table's live overlay. Returns null for legacy tables
|
|
218
|
+
* (no `.format` marker) so every existing code path stays untouched. With
|
|
219
|
+
* `forWrite`, repairs a torn tail and rebuilds to the committed boundary;
|
|
220
|
+
* the caller must already hold the table writer lock.
|
|
221
|
+
*/
|
|
222
|
+
private getOverlay;
|
|
223
|
+
private stampFormat;
|
|
224
|
+
/**
|
|
225
|
+
* The format-2 update log stores one encoded cell per changed *top-level
|
|
226
|
+
* simple* column; nested (object/array/table) and computed fields are not
|
|
227
|
+
* representable without a compaction step (3.9). A log table whose schema
|
|
228
|
+
* violates this is rejected at DDL time so the write path can always take
|
|
229
|
+
* the log and never needs to interleave a whole-column rewrite.
|
|
230
|
+
*/
|
|
231
|
+
private assertLogCompatibleSchema;
|
|
232
|
+
private idFieldOf;
|
|
233
|
+
/** Read the internal numeric id for each requested line (stable overlay key). */
|
|
234
|
+
private overlayLineIds;
|
|
235
|
+
/** Internal id -> current line number(s), built from the id column. */
|
|
236
|
+
private overlayIdToLines;
|
|
237
|
+
/**
|
|
238
|
+
* Per-line raw-cell overrides for one column, from the overlay. Used by
|
|
239
|
+
* `File.search` so criteria, uniqueness and aggregate scans see the merged
|
|
240
|
+
* (un-compacted) values. Returns undefined when the table has no overlay or
|
|
241
|
+
* the column is never overlaid.
|
|
242
|
+
*/
|
|
243
|
+
private overlayColumnOverrides;
|
|
244
|
+
/**
|
|
245
|
+
* Fold every logged update into the base columns and reset the log.
|
|
246
|
+
*
|
|
247
|
+
* Safe to call on any table: legacy tables (no `.format` marker) are a
|
|
248
|
+
* no-op. Semantically neutral — it only materializes already-acknowledged
|
|
249
|
+
* updates, so a failure never makes an acknowledged `put` disappear.
|
|
250
|
+
* Returns the new `baseGen` for a compacted table, or `null` when there was
|
|
251
|
+
* nothing to fold.
|
|
252
|
+
*/
|
|
253
|
+
compact(tableName: string): Promise<number | null>;
|
|
254
|
+
/**
|
|
255
|
+
* Compaction core. The caller must hold the table writer lock. Streams each
|
|
256
|
+
* overlaid base column through `File.replace` (which handles compression),
|
|
257
|
+
* then publishes the new columns, an empty `updates.log`, and a `.format`
|
|
258
|
+
* marker with the bumped generation in one journaled commit, so a crash
|
|
259
|
+
* either rolls every file back (old base + old log + old `baseGen`) or
|
|
260
|
+
* forward (new base + empty log + new `baseGen`). No acknowledged update is
|
|
261
|
+
* ever lost.
|
|
262
|
+
*/
|
|
263
|
+
private compactLogTable;
|
|
179
264
|
getTableSchema(tableName: string): Promise<Schema>;
|
|
180
265
|
private throwErrorIfTableEmpty;
|
|
181
266
|
validateData(data: Data | Data[], schema: Schema, skipRequiredField?: boolean): void;
|
|
@@ -190,6 +275,17 @@ export default class Inibase {
|
|
|
190
275
|
private joinPathesContents;
|
|
191
276
|
private _processSchemaDataHelper;
|
|
192
277
|
private processSchemaData;
|
|
278
|
+
/**
|
|
279
|
+
* Fold the table's un-compacted update-log overlay onto decoded rows.
|
|
280
|
+
*
|
|
281
|
+
* `RETURN` is keyed by line number and its `id` is the user-facing id, so
|
|
282
|
+
* the overlay (keyed by the internal numeric id) is matched through a fresh
|
|
283
|
+
* id-column read of just the requested lines. Only columns present in
|
|
284
|
+
* `schema` (which is already narrowed to the requested `columns`) are
|
|
285
|
+
* written, so a partial projection never grows extra keys. Legacy tables
|
|
286
|
+
* (no `.format` marker) return immediately.
|
|
287
|
+
*/
|
|
288
|
+
private mergeOverlayIntoRows;
|
|
193
289
|
/**
|
|
194
290
|
* Extract the raw expression from a field's `computed` property (string or
|
|
195
291
|
* persisted `{ expr, ast }` spec).
|
|
@@ -252,14 +348,6 @@ export default class Inibase {
|
|
|
252
348
|
private sameCellValue;
|
|
253
349
|
private isSimpleField;
|
|
254
350
|
private processSimpleField;
|
|
255
|
-
/**
|
|
256
|
-
* Batched read for top-level simple columns: a single `paste | sed` child
|
|
257
|
-
* process returns every requested line of every column at once instead of
|
|
258
|
-
* spawning one `sed`/`gunzip|sed` child process per column. Returning null
|
|
259
|
-
* (e.g. when any column file is missing, or the shell command fails) makes
|
|
260
|
-
* the caller fall back to the existing per-column reads.
|
|
261
|
-
*/
|
|
262
|
-
private processSimpleFieldsBatch;
|
|
263
351
|
private isArrayField;
|
|
264
352
|
private processArrayField;
|
|
265
353
|
private isObjectField;
|
|
@@ -390,6 +478,13 @@ export default class Inibase {
|
|
|
390
478
|
get<_TData extends Record<string, any> & Partial<Data>>(tableName: string, where: string | number | (string | number)[] | Criteria | undefined, options: Options | undefined, onlyOne: true, onlyLinesNumbers: true, _whereIsLinesNumbers?: boolean): Promise<number | null>;
|
|
391
479
|
private _get;
|
|
392
480
|
private getOnce;
|
|
481
|
+
/**
|
|
482
|
+
* In-process sort fallback for log tables with a non-empty overlay: the
|
|
483
|
+
* shell `paste | sort | awk` path reads base cells and would miss puts.
|
|
484
|
+
* Reads the merged rows for the (optionally filtered) lines, sorts them by
|
|
485
|
+
* the requested keys with type-aware comparison, then paginates.
|
|
486
|
+
*/
|
|
487
|
+
private getOnceSortedWithOverlay;
|
|
393
488
|
/**
|
|
394
489
|
* Create new item(s) in a table
|
|
395
490
|
*
|
|
@@ -422,6 +517,16 @@ export default class Inibase {
|
|
|
422
517
|
put<TData extends Record<string, any> & Partial<Data>>(tableName: string, data: Data & TData, where: number | string | (number | string)[] | Criteria | undefined, options: Options | undefined, returnUpdatedData: true | boolean, _whereIsLinesNumbers?: boolean): Promise<(Data & TData) | null>;
|
|
423
518
|
put<TData extends Record<string, any> & Partial<Data>>(tableName: string, data: (Data & TData)[], where: number | string | (number | string)[] | Criteria | undefined, options: Options | undefined, returnUpdatedData: true | boolean, _whereIsLinesNumbers?: boolean): Promise<(Data & TData)[] | null>;
|
|
424
519
|
put<TData extends Record<string, any> & Partial<Data>>(tableName: string, data: (Data & TData) | (Data & TData)[], where: number | string | (number | string)[] | Criteria | undefined, options: Options | undefined, returnUpdatedData: true | boolean, _whereIsLinesNumbers?: boolean): Promise<(Data & TData) | (Data & TData)[] | null>;
|
|
520
|
+
/**
|
|
521
|
+
* Incremental `put` for format-2 (log) tables.
|
|
522
|
+
*
|
|
523
|
+
* Resolves the target rows to their stable internal ids, validates the
|
|
524
|
+
* payload against the merged view (uniqueness included), and appends one
|
|
525
|
+
* bounded frame instead of rewriting whole columns. The base files are left
|
|
526
|
+
* untouched; readers merge the overlay. Returns `undefined` when nothing
|
|
527
|
+
* matches, matching the legacy `put` contract.
|
|
528
|
+
*/
|
|
529
|
+
private putViaLog;
|
|
425
530
|
private _put;
|
|
426
531
|
/**
|
|
427
532
|
* Delete item(s) in a table
|