@thadeu/ndb 0.3.2 → 0.4.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/README.md +11 -1
- package/dist/index.cjs +44 -1
- package/dist/index.d.cts +26 -3
- package/dist/index.d.ts +26 -3
- package/dist/index.js +44 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -111,6 +111,16 @@ await calls.delete({ status: 'failed' }, { many: true })
|
|
|
111
111
|
|
|
112
112
|
An insert with a duplicate `_id` throws `DuplicateIdError`. A duplicate `unique` value throws `UniqueViolationError`. An empty or non-string `_id` fails with code `invalid_id`.
|
|
113
113
|
|
|
114
|
+
### Truncate and drop
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
await calls.truncate() // every document goes; the definition and indexes stay
|
|
118
|
+
await calls.drop() // the collection, its definition and its watch consumers go
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
- Both take the same time for 10 or 10 million documents. Watch consumers get one event with `op: 'truncate'` (`_id` is `''`), then the new changes.
|
|
122
|
+
- After `drop()`, the next call on the model declares the collection again. A collection declared in `ndb.yml` comes back, empty, when the daemon restarts.
|
|
123
|
+
|
|
114
124
|
### Expiry (TTL like Redis)
|
|
115
125
|
|
|
116
126
|
```ts
|
|
@@ -236,7 +246,7 @@ const controller = new AbortController()
|
|
|
236
246
|
|
|
237
247
|
try {
|
|
238
248
|
for await (const ev of calls.watch('relay', { where: { status: 'answered' }, signal: controller.signal })) {
|
|
239
|
-
// ev: { consumer, pos, op: 'put' | 'del', _id, v, doc }
|
|
249
|
+
// ev: { consumer, pos, op: 'put' | 'del' | 'truncate', _id, v, doc }
|
|
240
250
|
await handle(ev)
|
|
241
251
|
|
|
242
252
|
await calls.ack(ev)
|
package/dist/index.cjs
CHANGED
|
@@ -160,6 +160,12 @@ var Query = class _Query {
|
|
|
160
160
|
where(w) {
|
|
161
161
|
return this.with({ clauses: [...this.state.clauses, toWhere(w)] });
|
|
162
162
|
}
|
|
163
|
+
// A where object built elsewhere, such as from a search form. It is not
|
|
164
|
+
// type-checked and is sent as is; the daemon validates it. It is ANDed
|
|
165
|
+
// with the other clauses.
|
|
166
|
+
whereRaw(w) {
|
|
167
|
+
return this.with({ clauses: [...this.state.clauses, w] });
|
|
168
|
+
}
|
|
163
169
|
not(w) {
|
|
164
170
|
return this.with({ clauses: [...this.state.clauses, { $not: toWhere(w) }] });
|
|
165
171
|
}
|
|
@@ -256,7 +262,7 @@ async function* watchEvents(lines2, consumer) {
|
|
|
256
262
|
if (line.error) {
|
|
257
263
|
throw makeError(line.error.code, line.error.message);
|
|
258
264
|
}
|
|
259
|
-
yield { consumer, pos: line.pos, op: line.op, _id: line._id, v: line.v, doc: line.doc };
|
|
265
|
+
yield { consumer, pos: line.pos, op: line.op, _id: line._id ?? "", v: line.v, doc: line.doc };
|
|
260
266
|
}
|
|
261
267
|
}
|
|
262
268
|
|
|
@@ -275,7 +281,13 @@ var Model = class {
|
|
|
275
281
|
const base = `/v1/c/${encodeURIComponent(this.name)}`;
|
|
276
282
|
return op ? `${base}/${op}` : base;
|
|
277
283
|
}
|
|
284
|
+
// A collection pattern ("logs-2026-*") reads many collections and declares
|
|
285
|
+
// none: its writes fail with pattern_read_only.
|
|
286
|
+
get isPattern() {
|
|
287
|
+
return this.name.includes("*");
|
|
288
|
+
}
|
|
278
289
|
ready() {
|
|
290
|
+
if (this.isPattern) return Promise.resolve();
|
|
279
291
|
this.ensured ??= this.db.transport.request("PUT", this.path(), this.catalog()).catch((err) => {
|
|
280
292
|
this.ensured = void 0;
|
|
281
293
|
throw err;
|
|
@@ -323,6 +335,22 @@ var Model = class {
|
|
|
323
335
|
const filter = idOrFilter;
|
|
324
336
|
return this.db.transport.request("POST", this.path("delete") + writeQuery({ many: opts.many }), toWhere(filter));
|
|
325
337
|
}
|
|
338
|
+
// Removes every document of the collection and keeps its definition and
|
|
339
|
+
// indexes. The cost does not depend on the number of documents. Watch
|
|
340
|
+
// consumers get one event with op "truncate".
|
|
341
|
+
async truncate() {
|
|
342
|
+
await this.ready();
|
|
343
|
+
await this.db.transport.request("POST", this.path("truncate") + this.confirm());
|
|
344
|
+
}
|
|
345
|
+
// Removes the collection: its documents, its definition and the positions
|
|
346
|
+
// of its watch consumers. The next call on the model declares it again.
|
|
347
|
+
async drop() {
|
|
348
|
+
await this.db.transport.request("DELETE", this.path() + this.confirm());
|
|
349
|
+
this.ensured = void 0;
|
|
350
|
+
}
|
|
351
|
+
confirm() {
|
|
352
|
+
return `?confirm=${encodeURIComponent(this.name)}`;
|
|
353
|
+
}
|
|
326
354
|
// Makes a document expire, like EXPIRE in Redis: seconds or "30m". It throws
|
|
327
355
|
// NotFoundError for a missing or expired document, and TtlError when the
|
|
328
356
|
// schema has no expires field.
|
|
@@ -375,6 +403,9 @@ var Model = class {
|
|
|
375
403
|
where(w) {
|
|
376
404
|
return this.query().where(w);
|
|
377
405
|
}
|
|
406
|
+
whereRaw(w) {
|
|
407
|
+
return this.query().whereRaw(w);
|
|
408
|
+
}
|
|
378
409
|
not(w) {
|
|
379
410
|
return this.query().not(w);
|
|
380
411
|
}
|
|
@@ -411,6 +442,18 @@ var Model = class {
|
|
|
411
442
|
iterate() {
|
|
412
443
|
return this.query().iterate();
|
|
413
444
|
}
|
|
445
|
+
// Runs a find with a whole body built elsewhere, such as from a search
|
|
446
|
+
// form: { where, sort, limit, after, count }. The body is sent as is (the
|
|
447
|
+
// daemon validates it); rows are decoded like the rows of where().
|
|
448
|
+
async find(body) {
|
|
449
|
+
await this.ready();
|
|
450
|
+
const res = await this.db.transport.stream("POST", this.path("find"), { ...body, versions: true });
|
|
451
|
+
const rows = [];
|
|
452
|
+
for await (const raw of res.rows()) {
|
|
453
|
+
rows.push(this.decode(raw));
|
|
454
|
+
}
|
|
455
|
+
return { rows, next: res.header("x-ndb-next") ?? "", total: Number(res.header("x-ndb-total") ?? 0) };
|
|
456
|
+
}
|
|
414
457
|
async aggregate(pipeline, opts = {}) {
|
|
415
458
|
await this.ready();
|
|
416
459
|
const res = await this.db.transport.stream("POST", this.path("aggregate"), { pipeline, ...opts });
|
package/dist/index.d.cts
CHANGED
|
@@ -39,6 +39,7 @@ type Input<F extends Fields> = {
|
|
|
39
39
|
type Row<F extends Fields> = Doc<F> & {
|
|
40
40
|
_id: string;
|
|
41
41
|
_v: number;
|
|
42
|
+
_coll?: string;
|
|
42
43
|
};
|
|
43
44
|
interface Ops<V> {
|
|
44
45
|
$eq?: V;
|
|
@@ -52,6 +53,7 @@ interface Ops<V> {
|
|
|
52
53
|
$exists?: boolean;
|
|
53
54
|
$regex?: string | RegExp;
|
|
54
55
|
$options?: string;
|
|
56
|
+
$elemMatch?: Record<string, unknown>;
|
|
55
57
|
}
|
|
56
58
|
type Operand<V> = V extends Date ? Date | string : V;
|
|
57
59
|
type RegexOperand<V> = V extends string ? RegExp : never;
|
|
@@ -115,6 +117,20 @@ interface AggregateOptions {
|
|
|
115
117
|
after?: string;
|
|
116
118
|
count?: boolean;
|
|
117
119
|
}
|
|
120
|
+
interface FindBody {
|
|
121
|
+
where?: Record<string, unknown>;
|
|
122
|
+
fields?: string[];
|
|
123
|
+
sort?: Record<string, 1 | -1>;
|
|
124
|
+
limit?: number;
|
|
125
|
+
skip?: number;
|
|
126
|
+
after?: string;
|
|
127
|
+
count?: boolean;
|
|
128
|
+
}
|
|
129
|
+
interface FindResult<R> {
|
|
130
|
+
rows: R[];
|
|
131
|
+
next: string;
|
|
132
|
+
total: number;
|
|
133
|
+
}
|
|
118
134
|
interface AggregateResult<R = Record<string, unknown>> {
|
|
119
135
|
rows: R[];
|
|
120
136
|
next: string;
|
|
@@ -129,7 +145,7 @@ interface WatchOptions<F extends Fields = Fields> {
|
|
|
129
145
|
interface WatchEvent<R> {
|
|
130
146
|
consumer: string;
|
|
131
147
|
pos: string;
|
|
132
|
-
op: 'put' | 'del';
|
|
148
|
+
op: 'put' | 'del' | 'truncate';
|
|
133
149
|
_id: string;
|
|
134
150
|
v: number;
|
|
135
151
|
doc: R | undefined;
|
|
@@ -149,6 +165,7 @@ declare class Query<F extends Fields, R = Row<F>> implements PromiseLike<R[]> {
|
|
|
149
165
|
nextCursor: string;
|
|
150
166
|
constructor(model: Model<F>, state?: State);
|
|
151
167
|
where(w: Where<F>): Query<F, R>;
|
|
168
|
+
whereRaw(w: Record<string, unknown>): Query<F, R>;
|
|
152
169
|
not(w: Where<F>): Query<F, R>;
|
|
153
170
|
or(...ws: Where<F>[]): Query<F, R>;
|
|
154
171
|
sort(spec: SortSpec<F>): Query<F, R>;
|
|
@@ -175,11 +192,15 @@ declare class Model<F extends Fields> {
|
|
|
175
192
|
private ensured?;
|
|
176
193
|
constructor(db: Ndb, name: string, schema: Schema<F>);
|
|
177
194
|
path(op?: string): string;
|
|
195
|
+
get isPattern(): boolean;
|
|
178
196
|
ready(): Promise<void>;
|
|
179
197
|
insert(docs: Input<F> | Input<F>[], opts?: InsertOptions): Promise<WriteResult[]>;
|
|
180
198
|
create(docs: Input<F> | Input<F>[], opts?: InsertOptions): Promise<WriteResult[]>;
|
|
181
199
|
update(idOrFilter: string | Filter<F>, ops: UpdateOps<F>, opts?: UpdateOptions): Promise<UpdateResult<F>>;
|
|
182
200
|
delete(idOrFilter: string | Filter<F>, opts?: DeleteOptions): Promise<DeleteResult>;
|
|
201
|
+
truncate(): Promise<void>;
|
|
202
|
+
drop(): Promise<void>;
|
|
203
|
+
private confirm;
|
|
183
204
|
expire(id: string, duration: Duration): Promise<ExpireResult>;
|
|
184
205
|
expireAt(id: string, at: Date): Promise<ExpireResult>;
|
|
185
206
|
persist(id: string): Promise<WriteResult>;
|
|
@@ -188,6 +209,7 @@ declare class Model<F extends Fields> {
|
|
|
188
209
|
get(id: string): Promise<Row<F> | null>;
|
|
189
210
|
query(): Query<F>;
|
|
190
211
|
where(w: Where<F>): Query<F>;
|
|
212
|
+
whereRaw(w: Record<string, unknown>): Query<F>;
|
|
191
213
|
not(w: Where<F>): Query<F>;
|
|
192
214
|
or(...ws: Where<F>[]): Query<F>;
|
|
193
215
|
sort(spec: SortSpec<F>): Query<F>;
|
|
@@ -200,6 +222,7 @@ declare class Model<F extends Fields> {
|
|
|
200
222
|
count(): Promise<number>;
|
|
201
223
|
first(): Promise<Row<F> | null>;
|
|
202
224
|
iterate(): AsyncGenerator<Row<F>>;
|
|
225
|
+
find(body: FindBody): Promise<FindResult<Row<F>>>;
|
|
203
226
|
aggregate<R = Record<string, unknown>>(pipeline: Record<string, unknown>[], opts?: AggregateOptions): Promise<AggregateResult<R>>;
|
|
204
227
|
watch(consumer: string, opts?: WatchOptions<F>): AsyncGenerator<WatchEvent<Row<F>>>;
|
|
205
228
|
ack(event: Pick<WatchEvent<unknown>, 'consumer' | 'pos'>): Promise<void>;
|
|
@@ -245,7 +268,7 @@ declare function connect(addr?: string, opts?: ConnectOptions): Ndb;
|
|
|
245
268
|
|
|
246
269
|
declare function newId(): string;
|
|
247
270
|
|
|
248
|
-
type ErrorCode = 'unauthorized' | 'not_found' | 'duplicate_id' | 'unique_violation' | 'catalog_conflict' | 'catalog_invalid' | 'unknown_collection' | 'direct_collection' | 'invalid_request' | 'invalid_query' | 'invalid_pipeline' | 'group_limit_exceeded' | 'cursor_invalid' | 'cursor_mismatch' | 'cursor_expired' | 'request_too_large' | 'line_too_large' | 'not_ready' | 'closed' | 'watch_lagged' | 'invalid_position' | 'history_truncated' | 'ttl_not_enabled' | 'ttl_derived' | 'unknown_operator' | 'no_update' | 'conflicting_update' | 'invalid_field' | 'unindexed_many' | 'empty_filter' | 'invalid_update' | 'http_status' | (string & {});
|
|
271
|
+
type ErrorCode = 'unauthorized' | 'not_found' | 'duplicate_id' | 'unique_violation' | 'catalog_conflict' | 'catalog_invalid' | 'unknown_collection' | 'direct_collection' | 'invalid_request' | 'invalid_query' | 'invalid_pipeline' | 'group_limit_exceeded' | 'cursor_invalid' | 'cursor_mismatch' | 'cursor_expired' | 'request_too_large' | 'line_too_large' | 'not_ready' | 'closed' | 'watch_lagged' | 'invalid_position' | 'history_truncated' | 'ttl_not_enabled' | 'ttl_derived' | 'unknown_operator' | 'no_update' | 'conflicting_update' | 'invalid_field' | 'unindexed_many' | 'empty_filter' | 'confirm_required' | 'invalid_update' | 'http_status' | (string & {});
|
|
249
272
|
declare class NdbError extends Error {
|
|
250
273
|
readonly code: ErrorCode;
|
|
251
274
|
readonly status: number;
|
|
@@ -274,4 +297,4 @@ declare class TtlError extends NdbError {
|
|
|
274
297
|
declare function makeError(code: ErrorCode, message: string, status?: number): NdbError;
|
|
275
298
|
|
|
276
299
|
export { CursorError, DuplicateIdError, HistoryTruncatedError, InvalidQueryError, InvalidUpdateError, Model, Ndb, NdbError, NotFoundError, Query, TtlError, UnauthorizedError, UniqueViolationError, WatchLaggedError, connect, makeError, newId };
|
|
277
|
-
export type { AggregateOptions, AggregateResult, ConnectOptions, DeleteOptions, DeleteResult, Doc, Duration, ErrorCode, ExpireResult, FieldDef, FieldType, Fields, Filter, Input, InsertOptions, Ops, Row, Schema, SortSpec, TypeMap, UpdateOps, UpdateOptions, UpdateResult, WatchEvent, WatchOptions, Where, WriteResult };
|
|
300
|
+
export type { AggregateOptions, AggregateResult, ConnectOptions, DeleteOptions, DeleteResult, Doc, Duration, ErrorCode, ExpireResult, FieldDef, FieldType, Fields, Filter, FindBody, FindResult, Input, InsertOptions, Ops, Row, Schema, SortSpec, TypeMap, UpdateOps, UpdateOptions, UpdateResult, WatchEvent, WatchOptions, Where, WriteResult };
|
package/dist/index.d.ts
CHANGED
|
@@ -39,6 +39,7 @@ type Input<F extends Fields> = {
|
|
|
39
39
|
type Row<F extends Fields> = Doc<F> & {
|
|
40
40
|
_id: string;
|
|
41
41
|
_v: number;
|
|
42
|
+
_coll?: string;
|
|
42
43
|
};
|
|
43
44
|
interface Ops<V> {
|
|
44
45
|
$eq?: V;
|
|
@@ -52,6 +53,7 @@ interface Ops<V> {
|
|
|
52
53
|
$exists?: boolean;
|
|
53
54
|
$regex?: string | RegExp;
|
|
54
55
|
$options?: string;
|
|
56
|
+
$elemMatch?: Record<string, unknown>;
|
|
55
57
|
}
|
|
56
58
|
type Operand<V> = V extends Date ? Date | string : V;
|
|
57
59
|
type RegexOperand<V> = V extends string ? RegExp : never;
|
|
@@ -115,6 +117,20 @@ interface AggregateOptions {
|
|
|
115
117
|
after?: string;
|
|
116
118
|
count?: boolean;
|
|
117
119
|
}
|
|
120
|
+
interface FindBody {
|
|
121
|
+
where?: Record<string, unknown>;
|
|
122
|
+
fields?: string[];
|
|
123
|
+
sort?: Record<string, 1 | -1>;
|
|
124
|
+
limit?: number;
|
|
125
|
+
skip?: number;
|
|
126
|
+
after?: string;
|
|
127
|
+
count?: boolean;
|
|
128
|
+
}
|
|
129
|
+
interface FindResult<R> {
|
|
130
|
+
rows: R[];
|
|
131
|
+
next: string;
|
|
132
|
+
total: number;
|
|
133
|
+
}
|
|
118
134
|
interface AggregateResult<R = Record<string, unknown>> {
|
|
119
135
|
rows: R[];
|
|
120
136
|
next: string;
|
|
@@ -129,7 +145,7 @@ interface WatchOptions<F extends Fields = Fields> {
|
|
|
129
145
|
interface WatchEvent<R> {
|
|
130
146
|
consumer: string;
|
|
131
147
|
pos: string;
|
|
132
|
-
op: 'put' | 'del';
|
|
148
|
+
op: 'put' | 'del' | 'truncate';
|
|
133
149
|
_id: string;
|
|
134
150
|
v: number;
|
|
135
151
|
doc: R | undefined;
|
|
@@ -149,6 +165,7 @@ declare class Query<F extends Fields, R = Row<F>> implements PromiseLike<R[]> {
|
|
|
149
165
|
nextCursor: string;
|
|
150
166
|
constructor(model: Model<F>, state?: State);
|
|
151
167
|
where(w: Where<F>): Query<F, R>;
|
|
168
|
+
whereRaw(w: Record<string, unknown>): Query<F, R>;
|
|
152
169
|
not(w: Where<F>): Query<F, R>;
|
|
153
170
|
or(...ws: Where<F>[]): Query<F, R>;
|
|
154
171
|
sort(spec: SortSpec<F>): Query<F, R>;
|
|
@@ -175,11 +192,15 @@ declare class Model<F extends Fields> {
|
|
|
175
192
|
private ensured?;
|
|
176
193
|
constructor(db: Ndb, name: string, schema: Schema<F>);
|
|
177
194
|
path(op?: string): string;
|
|
195
|
+
get isPattern(): boolean;
|
|
178
196
|
ready(): Promise<void>;
|
|
179
197
|
insert(docs: Input<F> | Input<F>[], opts?: InsertOptions): Promise<WriteResult[]>;
|
|
180
198
|
create(docs: Input<F> | Input<F>[], opts?: InsertOptions): Promise<WriteResult[]>;
|
|
181
199
|
update(idOrFilter: string | Filter<F>, ops: UpdateOps<F>, opts?: UpdateOptions): Promise<UpdateResult<F>>;
|
|
182
200
|
delete(idOrFilter: string | Filter<F>, opts?: DeleteOptions): Promise<DeleteResult>;
|
|
201
|
+
truncate(): Promise<void>;
|
|
202
|
+
drop(): Promise<void>;
|
|
203
|
+
private confirm;
|
|
183
204
|
expire(id: string, duration: Duration): Promise<ExpireResult>;
|
|
184
205
|
expireAt(id: string, at: Date): Promise<ExpireResult>;
|
|
185
206
|
persist(id: string): Promise<WriteResult>;
|
|
@@ -188,6 +209,7 @@ declare class Model<F extends Fields> {
|
|
|
188
209
|
get(id: string): Promise<Row<F> | null>;
|
|
189
210
|
query(): Query<F>;
|
|
190
211
|
where(w: Where<F>): Query<F>;
|
|
212
|
+
whereRaw(w: Record<string, unknown>): Query<F>;
|
|
191
213
|
not(w: Where<F>): Query<F>;
|
|
192
214
|
or(...ws: Where<F>[]): Query<F>;
|
|
193
215
|
sort(spec: SortSpec<F>): Query<F>;
|
|
@@ -200,6 +222,7 @@ declare class Model<F extends Fields> {
|
|
|
200
222
|
count(): Promise<number>;
|
|
201
223
|
first(): Promise<Row<F> | null>;
|
|
202
224
|
iterate(): AsyncGenerator<Row<F>>;
|
|
225
|
+
find(body: FindBody): Promise<FindResult<Row<F>>>;
|
|
203
226
|
aggregate<R = Record<string, unknown>>(pipeline: Record<string, unknown>[], opts?: AggregateOptions): Promise<AggregateResult<R>>;
|
|
204
227
|
watch(consumer: string, opts?: WatchOptions<F>): AsyncGenerator<WatchEvent<Row<F>>>;
|
|
205
228
|
ack(event: Pick<WatchEvent<unknown>, 'consumer' | 'pos'>): Promise<void>;
|
|
@@ -245,7 +268,7 @@ declare function connect(addr?: string, opts?: ConnectOptions): Ndb;
|
|
|
245
268
|
|
|
246
269
|
declare function newId(): string;
|
|
247
270
|
|
|
248
|
-
type ErrorCode = 'unauthorized' | 'not_found' | 'duplicate_id' | 'unique_violation' | 'catalog_conflict' | 'catalog_invalid' | 'unknown_collection' | 'direct_collection' | 'invalid_request' | 'invalid_query' | 'invalid_pipeline' | 'group_limit_exceeded' | 'cursor_invalid' | 'cursor_mismatch' | 'cursor_expired' | 'request_too_large' | 'line_too_large' | 'not_ready' | 'closed' | 'watch_lagged' | 'invalid_position' | 'history_truncated' | 'ttl_not_enabled' | 'ttl_derived' | 'unknown_operator' | 'no_update' | 'conflicting_update' | 'invalid_field' | 'unindexed_many' | 'empty_filter' | 'invalid_update' | 'http_status' | (string & {});
|
|
271
|
+
type ErrorCode = 'unauthorized' | 'not_found' | 'duplicate_id' | 'unique_violation' | 'catalog_conflict' | 'catalog_invalid' | 'unknown_collection' | 'direct_collection' | 'invalid_request' | 'invalid_query' | 'invalid_pipeline' | 'group_limit_exceeded' | 'cursor_invalid' | 'cursor_mismatch' | 'cursor_expired' | 'request_too_large' | 'line_too_large' | 'not_ready' | 'closed' | 'watch_lagged' | 'invalid_position' | 'history_truncated' | 'ttl_not_enabled' | 'ttl_derived' | 'unknown_operator' | 'no_update' | 'conflicting_update' | 'invalid_field' | 'unindexed_many' | 'empty_filter' | 'confirm_required' | 'invalid_update' | 'http_status' | (string & {});
|
|
249
272
|
declare class NdbError extends Error {
|
|
250
273
|
readonly code: ErrorCode;
|
|
251
274
|
readonly status: number;
|
|
@@ -274,4 +297,4 @@ declare class TtlError extends NdbError {
|
|
|
274
297
|
declare function makeError(code: ErrorCode, message: string, status?: number): NdbError;
|
|
275
298
|
|
|
276
299
|
export { CursorError, DuplicateIdError, HistoryTruncatedError, InvalidQueryError, InvalidUpdateError, Model, Ndb, NdbError, NotFoundError, Query, TtlError, UnauthorizedError, UniqueViolationError, WatchLaggedError, connect, makeError, newId };
|
|
277
|
-
export type { AggregateOptions, AggregateResult, ConnectOptions, DeleteOptions, DeleteResult, Doc, Duration, ErrorCode, ExpireResult, FieldDef, FieldType, Fields, Filter, Input, InsertOptions, Ops, Row, Schema, SortSpec, TypeMap, UpdateOps, UpdateOptions, UpdateResult, WatchEvent, WatchOptions, Where, WriteResult };
|
|
300
|
+
export type { AggregateOptions, AggregateResult, ConnectOptions, DeleteOptions, DeleteResult, Doc, Duration, ErrorCode, ExpireResult, FieldDef, FieldType, Fields, Filter, FindBody, FindResult, Input, InsertOptions, Ops, Row, Schema, SortSpec, TypeMap, UpdateOps, UpdateOptions, UpdateResult, WatchEvent, WatchOptions, Where, WriteResult };
|
package/dist/index.js
CHANGED
|
@@ -118,6 +118,12 @@ var Query = class _Query {
|
|
|
118
118
|
where(w) {
|
|
119
119
|
return this.with({ clauses: [...this.state.clauses, toWhere(w)] });
|
|
120
120
|
}
|
|
121
|
+
// A where object built elsewhere, such as from a search form. It is not
|
|
122
|
+
// type-checked and is sent as is; the daemon validates it. It is ANDed
|
|
123
|
+
// with the other clauses.
|
|
124
|
+
whereRaw(w) {
|
|
125
|
+
return this.with({ clauses: [...this.state.clauses, w] });
|
|
126
|
+
}
|
|
121
127
|
not(w) {
|
|
122
128
|
return this.with({ clauses: [...this.state.clauses, { $not: toWhere(w) }] });
|
|
123
129
|
}
|
|
@@ -214,7 +220,7 @@ async function* watchEvents(lines2, consumer) {
|
|
|
214
220
|
if (line.error) {
|
|
215
221
|
throw makeError(line.error.code, line.error.message);
|
|
216
222
|
}
|
|
217
|
-
yield { consumer, pos: line.pos, op: line.op, _id: line._id, v: line.v, doc: line.doc };
|
|
223
|
+
yield { consumer, pos: line.pos, op: line.op, _id: line._id ?? "", v: line.v, doc: line.doc };
|
|
218
224
|
}
|
|
219
225
|
}
|
|
220
226
|
|
|
@@ -233,7 +239,13 @@ var Model = class {
|
|
|
233
239
|
const base = `/v1/c/${encodeURIComponent(this.name)}`;
|
|
234
240
|
return op ? `${base}/${op}` : base;
|
|
235
241
|
}
|
|
242
|
+
// A collection pattern ("logs-2026-*") reads many collections and declares
|
|
243
|
+
// none: its writes fail with pattern_read_only.
|
|
244
|
+
get isPattern() {
|
|
245
|
+
return this.name.includes("*");
|
|
246
|
+
}
|
|
236
247
|
ready() {
|
|
248
|
+
if (this.isPattern) return Promise.resolve();
|
|
237
249
|
this.ensured ??= this.db.transport.request("PUT", this.path(), this.catalog()).catch((err) => {
|
|
238
250
|
this.ensured = void 0;
|
|
239
251
|
throw err;
|
|
@@ -281,6 +293,22 @@ var Model = class {
|
|
|
281
293
|
const filter = idOrFilter;
|
|
282
294
|
return this.db.transport.request("POST", this.path("delete") + writeQuery({ many: opts.many }), toWhere(filter));
|
|
283
295
|
}
|
|
296
|
+
// Removes every document of the collection and keeps its definition and
|
|
297
|
+
// indexes. The cost does not depend on the number of documents. Watch
|
|
298
|
+
// consumers get one event with op "truncate".
|
|
299
|
+
async truncate() {
|
|
300
|
+
await this.ready();
|
|
301
|
+
await this.db.transport.request("POST", this.path("truncate") + this.confirm());
|
|
302
|
+
}
|
|
303
|
+
// Removes the collection: its documents, its definition and the positions
|
|
304
|
+
// of its watch consumers. The next call on the model declares it again.
|
|
305
|
+
async drop() {
|
|
306
|
+
await this.db.transport.request("DELETE", this.path() + this.confirm());
|
|
307
|
+
this.ensured = void 0;
|
|
308
|
+
}
|
|
309
|
+
confirm() {
|
|
310
|
+
return `?confirm=${encodeURIComponent(this.name)}`;
|
|
311
|
+
}
|
|
284
312
|
// Makes a document expire, like EXPIRE in Redis: seconds or "30m". It throws
|
|
285
313
|
// NotFoundError for a missing or expired document, and TtlError when the
|
|
286
314
|
// schema has no expires field.
|
|
@@ -333,6 +361,9 @@ var Model = class {
|
|
|
333
361
|
where(w) {
|
|
334
362
|
return this.query().where(w);
|
|
335
363
|
}
|
|
364
|
+
whereRaw(w) {
|
|
365
|
+
return this.query().whereRaw(w);
|
|
366
|
+
}
|
|
336
367
|
not(w) {
|
|
337
368
|
return this.query().not(w);
|
|
338
369
|
}
|
|
@@ -369,6 +400,18 @@ var Model = class {
|
|
|
369
400
|
iterate() {
|
|
370
401
|
return this.query().iterate();
|
|
371
402
|
}
|
|
403
|
+
// Runs a find with a whole body built elsewhere, such as from a search
|
|
404
|
+
// form: { where, sort, limit, after, count }. The body is sent as is (the
|
|
405
|
+
// daemon validates it); rows are decoded like the rows of where().
|
|
406
|
+
async find(body) {
|
|
407
|
+
await this.ready();
|
|
408
|
+
const res = await this.db.transport.stream("POST", this.path("find"), { ...body, versions: true });
|
|
409
|
+
const rows = [];
|
|
410
|
+
for await (const raw of res.rows()) {
|
|
411
|
+
rows.push(this.decode(raw));
|
|
412
|
+
}
|
|
413
|
+
return { rows, next: res.header("x-ndb-next") ?? "", total: Number(res.header("x-ndb-total") ?? 0) };
|
|
414
|
+
}
|
|
372
415
|
async aggregate(pipeline, opts = {}) {
|
|
373
416
|
await this.ready();
|
|
374
417
|
const res = await this.db.transport.stream("POST", this.path("aggregate"), { pipeline, ...opts });
|