@incoqnito.io/bajadab 1.1.0 → 1.2.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 +52 -0
- package/dist/base.d.ts +56 -0
- package/dist/base.js +18 -0
- package/dist/base.js.map +1 -1
- package/dist/basics.d.ts +27 -2
- package/dist/basics.js +286 -6
- package/dist/basics.js.map +1 -1
- package/dist/fileio.d.ts +3 -1
- package/dist/fileio.js +50 -1
- package/dist/fileio.js.map +1 -1
- package/package.json +1 -1
- package/src/main/base.ts +61 -0
- package/src/main/basics.ts +787 -481
- package/src/main/fileio.ts +207 -154
package/README.md
CHANGED
|
@@ -8,8 +8,10 @@ A lightweight JSON-file-backed database for small, single-machine setups. No ser
|
|
|
8
8
|
- `MAP` (keyed by id) or `ARRAY` (ordered list) in-memory storage per collection.
|
|
9
9
|
- Configurable behavior for duplicate ids, missing ids, array deletion, auto-flush, and unloading dirty data.
|
|
10
10
|
- Custom id extraction/assignment via a pluggable function registry.
|
|
11
|
+
- Optional secondary indexes for fast lookup by a derived key.
|
|
11
12
|
- Atomic writes (write-to-temp, then rename) and, on POSIX systems, owner-only file permissions (`0600` files, `0700` directories).
|
|
12
13
|
- In-process concurrency safety per collection and per database.
|
|
14
|
+
- `db.snapshot(targetDir, options?)` to copy the whole database into a new timestamped version folder, optionally pruning older ones.
|
|
13
15
|
|
|
14
16
|
## Install
|
|
15
17
|
|
|
@@ -54,6 +56,7 @@ Every collection has an `IBCollectionConfig`. `db.config.defaultCollectionConfig
|
|
|
54
56
|
| `autoFlushStrategy` | `ALWAYS_AUTO_FLUSH` (default) / `NO_AUTO_FLUSH` | Whether every mutation is written to disk immediately, or only on an explicit `flush()`. |
|
|
55
57
|
| `dirtyUnloadStrategy` | `FLUSH` (default) / `ERROR` / `IGNORE` | What `unload()` does with unsaved changes. |
|
|
56
58
|
| `getID` / `setID` | registry key (optional) | Custom id accessors — see below. Omit to use the default, which reads/writes a plain `.id` property. |
|
|
59
|
+
| `indexes` | `{ [indexKey: string]: registry key }` (optional) | Secondary indexes — see below. Omit for no indexes. |
|
|
57
60
|
|
|
58
61
|
## Custom ids
|
|
59
62
|
|
|
@@ -82,6 +85,34 @@ const users = await db.createCollection("users", {
|
|
|
82
85
|
|
|
83
86
|
A `getID`/`setID` key that isn't found in the registry causes `add()` to reject, rather than silently falling back to the default.
|
|
84
87
|
|
|
88
|
+
## Indexes
|
|
89
|
+
|
|
90
|
+
A collection can declare secondary indexes for fast lookup by a derived key. Like `getID`/`setID`, the extractor function lives in the registry — only its key is part of the (persisted) collection config:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
class Registry implements IBFunctionRegistry {
|
|
94
|
+
private fns = new Map<string, Function>([
|
|
95
|
+
["byEmail", async (v: any) => v.email],
|
|
96
|
+
]);
|
|
97
|
+
fetch(key?: string) {
|
|
98
|
+
return key ? this.fns.get(key) : undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const db = await getDatabase("./data", new Registry());
|
|
103
|
+
const users = await db.createCollection("users", {
|
|
104
|
+
...db.config.defaultCollectionConfig,
|
|
105
|
+
indexes: { email: "byEmail" },
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
await users.add({ email: "a@example.com", name: "A" });
|
|
109
|
+
const matches = await users.getByIndex("email", "a@example.com");
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
An extractor returns a `string`, a `string[]` for a multi-valued index, or `undefined` to leave a value out of the index. `getByIndex()` rejects if `indexKey` isn't configured. A configured index whose registry key isn't found rejects on the collection's first use after it's (re)loaded — `get()`, `add()`, whatever comes first — not just the mutations that actually need indexing; that's a wider blast radius than `getID`/`setID`, which only ever fail inside `add()`.
|
|
113
|
+
|
|
114
|
+
The index is maintained incrementally: `add()`/`update()`/`delete()` update only the affected buckets, not the whole index. A full rebuild only happens once, right after `reload()` loads fresh data from disk.
|
|
115
|
+
|
|
85
116
|
## Persistence and file layout
|
|
86
117
|
|
|
87
118
|
Each database directory contains:
|
|
@@ -96,6 +127,27 @@ Collections are addressed by a stable id, not by name, so a handle to a since-re
|
|
|
96
127
|
|
|
97
128
|
Operations on the same collection, and database-level operations (`create`/`get`/`has`/`dropCollection`), are serialized within one process. There is no cross-process locking — multiple processes pointed at the same directory can still race on the underlying files.
|
|
98
129
|
|
|
130
|
+
## Snapshots
|
|
131
|
+
|
|
132
|
+
`db.snapshot(targetDir, options?)` flushes every loaded collection, then copies the whole database directory into a new version folder under `targetDir` (created if it doesn't exist yet). The version folder is named after a sortable timestamp (e.g. `20260904T153012345Z`) and is itself a complete, independent database — open it directly with `getDatabase(versionPath)`.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const versionPath = await db.snapshot("./backups");
|
|
136
|
+
// later, e.g. after a bad deploy:
|
|
137
|
+
const restored = await getDatabase(versionPath);
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
`targetDir` is a pool that can hold several versions; each call adds one more. Options:
|
|
141
|
+
|
|
142
|
+
| Option | Values | Meaning |
|
|
143
|
+
| --- | --- | --- |
|
|
144
|
+
| `label` | string (optional) | Appended to the version folder's timestamp, e.g. `..._before-deploy`. Letters, digits, `-` and `_` only. |
|
|
145
|
+
| `keepLast` | number (optional) | Older version folders under `targetDir` to keep besides the one just created. `0` keeps only the new one. Omit to keep everything. Negative values reject. |
|
|
146
|
+
|
|
147
|
+
Pruning only ever deletes folders matching bajadab's own naming scheme — anything else you keep in `targetDir` is left alone.
|
|
148
|
+
|
|
149
|
+
`snapshot()` blocks every other operation on the database (same as `dropCollection()`, just across all collections at once) for as long as the copy takes, to guarantee a consistent point-in-time copy. There's no separate `restoreSnapshot()` — restoring means copying a version folder back over the original `basePath` (while nothing has it open), or just pointing `getDatabase()` at the version folder directly.
|
|
150
|
+
|
|
99
151
|
## License
|
|
100
152
|
|
|
101
153
|
See [LICENSE](./LICENSE).
|
package/dist/base.d.ts
CHANGED
|
@@ -48,6 +48,8 @@ export declare enum EBDirtyUnloadStrategy {
|
|
|
48
48
|
export type TGetIDFunction = (v: any) => Promise<string | undefined>;
|
|
49
49
|
/** Assigns an id onto a value. */
|
|
50
50
|
export type TSetIDFunction = (v: any, id: string) => Promise<void>;
|
|
51
|
+
/** Extracts an index key (or several, for a multi-valued index) from a value; `undefined` means "not indexed". */
|
|
52
|
+
export type TIndexKeyFunction<T = any> = (v: T) => Promise<string | string[] | undefined>;
|
|
51
53
|
/** Per-collection behavior. Passed to {@link IBDatabase.createCollection}/{@link IBDatabase.getCollection}. */
|
|
52
54
|
export interface IBCollectionConfig {
|
|
53
55
|
autoIDStrategy: EBAutoIDStrategy;
|
|
@@ -60,12 +62,23 @@ export interface IBCollectionConfig {
|
|
|
60
62
|
getID?: string;
|
|
61
63
|
/** Registry key for a custom {@link TSetIDFunction}. Omit to use the default (sets `.id`). */
|
|
62
64
|
setID?: string;
|
|
65
|
+
/** Index name → registry key of a {@link TIndexKeyFunction} for that index. Omit for no indexes. */
|
|
66
|
+
indexes?: {
|
|
67
|
+
[indexKey: string]: string;
|
|
68
|
+
};
|
|
63
69
|
}
|
|
64
70
|
/** Database-wide configuration. */
|
|
65
71
|
export interface IBDatabaseConfig {
|
|
66
72
|
/** Used for any collection created without an explicit config. */
|
|
67
73
|
readonly defaultCollectionConfig: IBCollectionConfig;
|
|
68
74
|
}
|
|
75
|
+
/** Options for {@link IBDatabase.snapshot}. */
|
|
76
|
+
export interface IBSnapshotOptions {
|
|
77
|
+
/** Appended to the version folder's timestamp. Letters, digits, `-` and `_` only. */
|
|
78
|
+
label?: string;
|
|
79
|
+
/** Older version folders under `targetDir` to keep besides the one just created. `0` keeps only the new one. Negative values reject. */
|
|
80
|
+
keepLast?: number;
|
|
81
|
+
}
|
|
69
82
|
/** A JSON-file-backed database. Obtain one via `getDatabase()`. */
|
|
70
83
|
export interface IBDatabase {
|
|
71
84
|
readonly config: IBDatabaseConfig;
|
|
@@ -77,6 +90,39 @@ export interface IBDatabase {
|
|
|
77
90
|
hasCollection(collectionName: string): Promise<boolean>;
|
|
78
91
|
/** Deletes a collection and invalidates any handle still held on it. Rejects if it doesn't exist. */
|
|
79
92
|
dropCollection(collectionName: string): Promise<void>;
|
|
93
|
+
/**
|
|
94
|
+
* Flushes every loaded collection, then copies the whole database directory into a new, timestamped
|
|
95
|
+
* version folder under `targetDir` (created if needed). Blocks all other database operations for the
|
|
96
|
+
* duration. See {@link IBSnapshotOptions} for pruning older versions. Returns the new version folder's path.
|
|
97
|
+
*/
|
|
98
|
+
snapshot(targetDir: string, options?: IBSnapshotOptions): Promise<string>;
|
|
99
|
+
}
|
|
100
|
+
/** What kind of collection mutation a handler subscribes to via {@link IBCollection.on}. */
|
|
101
|
+
export declare enum EBModificationType {
|
|
102
|
+
/** A value was stored by `add()` (including an id-based overwrite). */
|
|
103
|
+
ADD = "ADD",
|
|
104
|
+
/** A value was replaced by `update()`. */
|
|
105
|
+
UPDATE = "UPDATE",
|
|
106
|
+
/** A value was removed by `delete()`. */
|
|
107
|
+
DELETE = "DELETE"
|
|
108
|
+
}
|
|
109
|
+
/** Handler for {@link EBModificationType.ADD}: called with each value stored by `add()`. */
|
|
110
|
+
export type TAddHandler<T> = (added: T) => void | Promise<void>;
|
|
111
|
+
/** Handler for {@link EBModificationType.UPDATE}: called with the previous and the replacement value. */
|
|
112
|
+
export type TUpdateHandler<T> = (previous: T, updated: T) => void | Promise<void>;
|
|
113
|
+
/** Handler for {@link EBModificationType.DELETE}: called with each value removed by `delete()`. */
|
|
114
|
+
export type TDeleteHandler<T> = (deleted: T) => void | Promise<void>;
|
|
115
|
+
/** Handle returned by {@link IBCollection.on}. */
|
|
116
|
+
export interface IHandlerRegistration {
|
|
117
|
+
/** Unsubscribes the handler. Idempotent. */
|
|
118
|
+
cancel(): Promise<void>;
|
|
119
|
+
}
|
|
120
|
+
/** Whether a handler registered via {@link IBCollection.on} blocks the call that triggered it. */
|
|
121
|
+
export declare enum EBHandlerMode {
|
|
122
|
+
/** The triggering `add()`/`update()`/`delete()` call doesn't resolve until this handler has run. Default. */
|
|
123
|
+
SYNC = "SYNC",
|
|
124
|
+
/** The handler runs without the triggering call waiting for it. */
|
|
125
|
+
ASYNC = "ASYNC"
|
|
80
126
|
}
|
|
81
127
|
/** A single collection of values of type `T`. Obtain one via {@link IBDatabase}. */
|
|
82
128
|
export interface IBCollection<T = any> {
|
|
@@ -96,6 +142,16 @@ export interface IBCollection<T = any> {
|
|
|
96
142
|
add(...v: T[]): Promise<number>;
|
|
97
143
|
/** Replaces each item matching `predicate` with the (defined) result of `updater`. Returns the number updated. */
|
|
98
144
|
update(predicate: (v: T) => boolean, updater: (v: T) => Promise<T>): Promise<number>;
|
|
145
|
+
/** Number of items, or only those matching `predicate`. */
|
|
146
|
+
count(predicate?: (v: T) => boolean): Promise<number>;
|
|
147
|
+
/** Items whose {@link IBCollectionConfig.indexes}-configured `indexKey` extracts `key`. Always a defensive copy. Throws if `indexKey` isn't configured. */
|
|
148
|
+
getByIndex(indexKey: string, key: string): Promise<T[]>;
|
|
149
|
+
/** Subscribes to `add()` mutations. Fires after the value is stored, including any auto-flush to disk. `mode` defaults to {@link EBHandlerMode.SYNC}. A handler's own errors never fail the triggering call; they're logged only. */
|
|
150
|
+
on(modificationType: EBModificationType.ADD, handler: TAddHandler<T>, mode?: EBHandlerMode): Promise<IHandlerRegistration>;
|
|
151
|
+
/** Subscribes to `update()` mutations. Fires after the value is replaced, including any auto-flush to disk. `mode` defaults to {@link EBHandlerMode.SYNC}. A handler's own errors never fail the triggering call; they're logged only. */
|
|
152
|
+
on(modificationType: EBModificationType.UPDATE, handler: TUpdateHandler<T>, mode?: EBHandlerMode): Promise<IHandlerRegistration>;
|
|
153
|
+
/** Subscribes to `delete()` mutations. Fires after the value is removed, including any auto-flush to disk. `mode` defaults to {@link EBHandlerMode.SYNC}. A handler's own errors never fail the triggering call; they're logged only. */
|
|
154
|
+
on(modificationType: EBModificationType.DELETE, handler: TDeleteHandler<T>, mode?: EBHandlerMode): Promise<IHandlerRegistration>;
|
|
99
155
|
/** Writes the current in-memory state to disk. */
|
|
100
156
|
flush(): Promise<void>;
|
|
101
157
|
/** Discards in-memory state and re-reads it from disk. */
|
package/dist/base.js
CHANGED
|
@@ -51,4 +51,22 @@ export var EBDirtyUnloadStrategy;
|
|
|
51
51
|
/** Discard the unsaved changes silently. */
|
|
52
52
|
EBDirtyUnloadStrategy["IGNORE"] = "IGNORE";
|
|
53
53
|
})(EBDirtyUnloadStrategy || (EBDirtyUnloadStrategy = {}));
|
|
54
|
+
/** What kind of collection mutation a handler subscribes to via {@link IBCollection.on}. */
|
|
55
|
+
export var EBModificationType;
|
|
56
|
+
(function (EBModificationType) {
|
|
57
|
+
/** A value was stored by `add()` (including an id-based overwrite). */
|
|
58
|
+
EBModificationType["ADD"] = "ADD";
|
|
59
|
+
/** A value was replaced by `update()`. */
|
|
60
|
+
EBModificationType["UPDATE"] = "UPDATE";
|
|
61
|
+
/** A value was removed by `delete()`. */
|
|
62
|
+
EBModificationType["DELETE"] = "DELETE";
|
|
63
|
+
})(EBModificationType || (EBModificationType = {}));
|
|
64
|
+
/** Whether a handler registered via {@link IBCollection.on} blocks the call that triggered it. */
|
|
65
|
+
export var EBHandlerMode;
|
|
66
|
+
(function (EBHandlerMode) {
|
|
67
|
+
/** The triggering `add()`/`update()`/`delete()` call doesn't resolve until this handler has run. Default. */
|
|
68
|
+
EBHandlerMode["SYNC"] = "SYNC";
|
|
69
|
+
/** The handler runs without the triggering call waiting for it. */
|
|
70
|
+
EBHandlerMode["ASYNC"] = "ASYNC";
|
|
71
|
+
})(EBHandlerMode || (EBHandlerMode = {}));
|
|
54
72
|
//# sourceMappingURL=base.js.map
|
package/dist/base.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../src/main/base.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,MAAM,CAAN,IAAY,gBAKX;AALD,WAAY,gBAAgB;IACxB,mCAAmC;IACnC,6CAAyB,CAAA;IACzB,mEAAmE;IACnE,iDAA6B,CAAA;AACjC,CAAC,EALW,gBAAgB,KAAhB,gBAAgB,QAK3B;AAED,uDAAuD;AACvD,MAAM,CAAN,IAAY,oBAMX;AAND,WAAY,oBAAoB;IAC5B,oEAAoE;IACpE,mCAAW,CAAA;IACX,+BAA+B;IAC/B,gDAAgD;IAChD,uCAAe,CAAA;AACnB,CAAC,EANW,oBAAoB,KAApB,oBAAoB,QAM/B;AAED,iFAAiF;AACjF,MAAM,CAAN,IAAY,qBAOX;AAPD,WAAY,qBAAqB;IAC7B,kCAAkC;IAClC,gDAAuB,CAAA;IACvB,6BAA6B;IAC7B,wCAAe,CAAA;IACf,iDAAiD;IACjD,0CAAiB,CAAA;AACrB,CAAC,EAPW,qBAAqB,KAArB,qBAAqB,QAOhC;AAED,wFAAwF;AACxF,MAAM,CAAN,IAAY,uBAKX;AALD,WAAY,uBAAuB;IAC/B,wCAAwC;IACxC,kDAAuB,CAAA;IACvB,2CAA2C;IAC3C,gDAAqB,CAAA;AACzB,CAAC,EALW,uBAAuB,KAAvB,uBAAuB,QAKlC;AAED,6DAA6D;AAC7D,MAAM,CAAN,IAAY,mBAKX;AALD,WAAY,mBAAmB;IAC3B,2DAA2D;IAC3D,sDAA+B,CAAA;IAC/B,2DAA2D;IAC3D,8DAAuC,CAAA;AAC3C,CAAC,EALW,mBAAmB,KAAnB,mBAAmB,QAK9B;AAED,kEAAkE;AAClE,MAAM,CAAN,IAAY,qBAOX;AAPD,WAAY,qBAAqB;IAC7B,yBAAyB;IACzB,wCAAe,CAAA;IACf,gCAAgC;IAChC,wCAAe,CAAA;IACf,4CAA4C;IAC5C,0CAAiB,CAAA;AACrB,CAAC,EAPW,qBAAqB,KAArB,qBAAqB,QAOhC"}
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../src/main/base.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,MAAM,CAAN,IAAY,gBAKX;AALD,WAAY,gBAAgB;IACxB,mCAAmC;IACnC,6CAAyB,CAAA;IACzB,mEAAmE;IACnE,iDAA6B,CAAA;AACjC,CAAC,EALW,gBAAgB,KAAhB,gBAAgB,QAK3B;AAED,uDAAuD;AACvD,MAAM,CAAN,IAAY,oBAMX;AAND,WAAY,oBAAoB;IAC5B,oEAAoE;IACpE,mCAAW,CAAA;IACX,+BAA+B;IAC/B,gDAAgD;IAChD,uCAAe,CAAA;AACnB,CAAC,EANW,oBAAoB,KAApB,oBAAoB,QAM/B;AAED,iFAAiF;AACjF,MAAM,CAAN,IAAY,qBAOX;AAPD,WAAY,qBAAqB;IAC7B,kCAAkC;IAClC,gDAAuB,CAAA;IACvB,6BAA6B;IAC7B,wCAAe,CAAA;IACf,iDAAiD;IACjD,0CAAiB,CAAA;AACrB,CAAC,EAPW,qBAAqB,KAArB,qBAAqB,QAOhC;AAED,wFAAwF;AACxF,MAAM,CAAN,IAAY,uBAKX;AALD,WAAY,uBAAuB;IAC/B,wCAAwC;IACxC,kDAAuB,CAAA;IACvB,2CAA2C;IAC3C,gDAAqB,CAAA;AACzB,CAAC,EALW,uBAAuB,KAAvB,uBAAuB,QAKlC;AAED,6DAA6D;AAC7D,MAAM,CAAN,IAAY,mBAKX;AALD,WAAY,mBAAmB;IAC3B,2DAA2D;IAC3D,sDAA+B,CAAA;IAC/B,2DAA2D;IAC3D,8DAAuC,CAAA;AAC3C,CAAC,EALW,mBAAmB,KAAnB,mBAAmB,QAK9B;AAED,kEAAkE;AAClE,MAAM,CAAN,IAAY,qBAOX;AAPD,WAAY,qBAAqB;IAC7B,yBAAyB;IACzB,wCAAe,CAAA;IACf,gCAAgC;IAChC,wCAAe,CAAA;IACf,4CAA4C;IAC5C,0CAAiB,CAAA;AACrB,CAAC,EAPW,qBAAqB,KAArB,qBAAqB,QAOhC;AA4DD,4FAA4F;AAC5F,MAAM,CAAN,IAAY,kBAOX;AAPD,WAAY,kBAAkB;IAC1B,uEAAuE;IACvE,iCAAW,CAAA;IACX,0CAA0C;IAC1C,uCAAiB,CAAA;IACjB,yCAAyC;IACzC,uCAAiB,CAAA;AACrB,CAAC,EAPW,kBAAkB,KAAlB,kBAAkB,QAO7B;AAeD,kGAAkG;AAClG,MAAM,CAAN,IAAY,aAKX;AALD,WAAY,aAAa;IACrB,6GAA6G;IAC7G,8BAAa,CAAA;IACb,mEAAmE;IACnE,gCAAe,CAAA;AACnB,CAAC,EALW,aAAa,KAAb,aAAa,QAKxB"}
|
package/dist/basics.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IODatabase } from "./fileio.js";
|
|
2
|
-
import { IBCollection, IBCollectionConfig, IBDatabase, IBDatabaseConfig, IBFunctionRegistry, TGetIDFunction, TSetIDFunction } from "./base.js";
|
|
2
|
+
import { EBHandlerMode, EBModificationType, IBCollection, IBCollectionConfig, IBDatabase, IBDatabaseConfig, IBFunctionRegistry, IBSnapshotOptions, IHandlerRegistration, TAddHandler, TDeleteHandler, TGetIDFunction, TSetIDFunction, TUpdateHandler } from "./base.js";
|
|
3
3
|
/** Default {@link TGetIDFunction}: reads `v.id`, `undefined` if absent. */
|
|
4
4
|
export declare const DEFAULT_GET_ID: TGetIDFunction;
|
|
5
5
|
/** Default {@link TSetIDFunction}: assigns to `v.id`. */
|
|
@@ -19,6 +19,7 @@ export declare class BDatabase implements IBDatabase {
|
|
|
19
19
|
createCollection<T = any>(collectionName: string, collectionConfig?: IBCollectionConfig): Promise<BCollection<T>>;
|
|
20
20
|
hasCollection(collectionName: string): Promise<boolean>;
|
|
21
21
|
dropCollection(collectionName: string): Promise<void>;
|
|
22
|
+
snapshot(targetDir: string, options?: IBSnapshotOptions): Promise<string>;
|
|
22
23
|
}
|
|
23
24
|
export declare class BCollection<T = any> implements IBCollection<T> {
|
|
24
25
|
readonly database: BDatabase;
|
|
@@ -30,16 +31,40 @@ export declare class BCollection<T = any> implements IBCollection<T> {
|
|
|
30
31
|
private loaded;
|
|
31
32
|
private dirty;
|
|
32
33
|
private dropped;
|
|
34
|
+
private addHandlers;
|
|
35
|
+
private updateHandlers;
|
|
36
|
+
private deleteHandlers;
|
|
37
|
+
private indexDefinitions;
|
|
38
|
+
private indexRuntime;
|
|
33
39
|
constructor(database: BDatabase, collectionID: string, collectionName: string, collectionConfig: IBCollectionConfig);
|
|
34
40
|
private checkLoaded;
|
|
41
|
+
private runExclusive;
|
|
35
42
|
private runProtected;
|
|
36
43
|
/**
|
|
37
|
-
* call this only within the
|
|
44
|
+
* call this only within the protecting mutex
|
|
38
45
|
*/
|
|
39
46
|
markDropped(): void;
|
|
40
47
|
get(predicate?: (v: T) => boolean): Promise<T[]>;
|
|
48
|
+
count(predicate?: (v: T) => boolean): Promise<number>;
|
|
49
|
+
getByIndex(indexKey: string, key: string): Promise<T[]>;
|
|
50
|
+
private invokeHandler;
|
|
51
|
+
private fireAdd;
|
|
52
|
+
private fireUpdate;
|
|
53
|
+
private fireDelete;
|
|
54
|
+
on(modificationType: EBModificationType.ADD, handler: TAddHandler<T>, mode?: EBHandlerMode): Promise<IHandlerRegistration>;
|
|
55
|
+
on(modificationType: EBModificationType.UPDATE, handler: TUpdateHandler<T>, mode?: EBHandlerMode): Promise<IHandlerRegistration>;
|
|
56
|
+
on(modificationType: EBModificationType.DELETE, handler: TDeleteHandler<T>, mode?: EBHandlerMode): Promise<IHandlerRegistration>;
|
|
41
57
|
delete(predicate: (v: T) => boolean): Promise<number>;
|
|
42
58
|
has(predicate: (v: T) => boolean): Promise<boolean>;
|
|
59
|
+
private resolveIndexDefinitions;
|
|
60
|
+
private indexKeysFor;
|
|
61
|
+
private addToIndexes;
|
|
62
|
+
private removeFromIndexes;
|
|
63
|
+
/**
|
|
64
|
+
* full rebuild from currently loaded data; only needed right after (re)load, since every
|
|
65
|
+
* value then is a freshly deserialized object the incremental add/update/delete hooks never saw
|
|
66
|
+
*/
|
|
67
|
+
private rebuildIndexRuntime;
|
|
43
68
|
private getID;
|
|
44
69
|
add(...vs: T[]): Promise<number>;
|
|
45
70
|
update(predicate: (v: T) => boolean, updater: (v: T) => Promise<T>): Promise<number>;
|