@nxgt/mongo 0.2.0 → 0.3.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 +89 -26
- package/dist/collection/context.d.ts +64 -0
- package/dist/collection/context.d.ts.map +1 -0
- package/dist/collection/documents.d.ts +21 -0
- package/dist/collection/documents.d.ts.map +1 -0
- package/dist/collection/filters.d.ts +15 -0
- package/dist/collection/filters.d.ts.map +1 -0
- package/dist/collection/get-collection.d.ts +26 -0
- package/dist/collection/get-collection.d.ts.map +1 -0
- package/dist/collection/paginate.d.ts +6 -0
- package/dist/collection/paginate.d.ts.map +1 -0
- package/dist/collection/reads.d.ts +19 -0
- package/dist/collection/reads.d.ts.map +1 -0
- package/dist/collection/types.d.ts +270 -0
- package/dist/collection/types.d.ts.map +1 -0
- package/dist/collection/writes.d.ts +12 -0
- package/dist/collection/writes.d.ts.map +1 -0
- package/dist/definition/define-collection.d.ts +2 -2
- package/dist/definition/fields.d.ts +5 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +664 -589
- package/dist/index.js.map +17 -11
- package/dist/transaction/with-transaction.d.ts +4 -4
- package/package.json +1 -1
- package/dist/repository/create-repository.d.ts +0 -21
- package/dist/repository/create-repository.d.ts.map +0 -1
- package/dist/repository/types.d.ts +0 -147
- package/dist/repository/types.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
A typed MongoDB collection, from one Zod schema: the schema types every read
|
|
4
4
|
and write, and the same schema becomes the collection's `$jsonSchema`
|
|
5
|
-
validator, applied idempotently. On top of it, a
|
|
5
|
+
validator, applied idempotently. On top of it, a collection with pagination,
|
|
6
6
|
transactions, optimistic locking, soft delete, audit stamps, and MongoDB's
|
|
7
7
|
errors turned into ones you can catch.
|
|
8
8
|
|
|
9
|
-
It wraps the official `mongodb` driver, which stays a peer dependency
|
|
10
|
-
driver's
|
|
9
|
+
It wraps the official `mongodb` driver, which stays a peer dependency — and it
|
|
10
|
+
does not hide it: the driver's own methods are on the very same object, so
|
|
11
|
+
`aggregate`, `watch` and `bulkWrite` are always at hand.
|
|
11
12
|
|
|
12
13
|
## Install
|
|
13
14
|
|
|
@@ -31,6 +32,7 @@ export const users = defineCollection({
|
|
|
31
32
|
_id: id(),
|
|
32
33
|
email: z.email(),
|
|
33
34
|
name: z.string().nullable().default(null),
|
|
35
|
+
loginCount: z.int().default(0),
|
|
34
36
|
...timestamps(),
|
|
35
37
|
...softDelete(),
|
|
36
38
|
...optimisticLock(),
|
|
@@ -109,29 +111,52 @@ already full.
|
|
|
109
111
|
## Documents
|
|
110
112
|
|
|
111
113
|
```ts
|
|
112
|
-
import {
|
|
114
|
+
import { getCollection } from '@nxgt/mongo';
|
|
113
115
|
|
|
114
|
-
const
|
|
116
|
+
const collection = getCollection(db, users); // a Db, or a MongoClient
|
|
115
117
|
|
|
116
|
-
const ada = await
|
|
118
|
+
const ada = await collection.create({ email: 'ada@example.com' });
|
|
117
119
|
// → { _id: ObjectId, id: '507f…', email, name: null, createdAt: Date, version: 0, … }
|
|
118
120
|
|
|
119
|
-
await
|
|
120
|
-
await
|
|
121
|
-
await
|
|
122
|
-
await
|
|
123
|
-
await
|
|
124
|
-
await
|
|
121
|
+
await collection.findById(ada._id); // the document, or undefined
|
|
122
|
+
await collection.getById(ada._id); // or NotFoundError
|
|
123
|
+
await collection.findFirst({ email: 'ada@example.com' });
|
|
124
|
+
await collection.findMany({ filter: { name: null }, sort: { createdAt: -1 }, limit: 10 });
|
|
125
|
+
await collection.count({ name: null });
|
|
126
|
+
await collection.exists({ email: 'ada@example.com' });
|
|
125
127
|
|
|
126
|
-
await
|
|
127
|
-
await
|
|
128
|
-
await
|
|
128
|
+
await collection.update(ada._id, { name: 'Ada' }); // checked field by field
|
|
129
|
+
await collection.update(ada._id, { $inc: { loginCount: 1 } }); // MongoDB's operators too
|
|
130
|
+
await collection.updateMany({ name: null }, { name: 'unknown' });
|
|
129
131
|
|
|
130
|
-
await
|
|
131
|
-
await
|
|
132
|
-
await
|
|
132
|
+
await collection.delete(ada._id); // soft, on a schema with deletedAt
|
|
133
|
+
await collection.restore(ada._id);
|
|
134
|
+
await collection.hardDelete(ada._id); // really gone
|
|
133
135
|
```
|
|
134
136
|
|
|
137
|
+
**The driver's collection is the same object.** Everything this package does
|
|
138
|
+
not wrap is on it directly — no `.collection` to go through:
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
await collection.aggregate([{ $group: { _id: '$teamId', n: { $sum: 1 } } }]).toArray();
|
|
142
|
+
collection.watch();
|
|
143
|
+
await collection.distinct('email');
|
|
144
|
+
await collection.bulkWrite([…]);
|
|
145
|
+
collection.collectionName; // 'users'
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Three names are defined by both, and this package's win, because a filter that
|
|
149
|
+
came out empty must not rewrite a collection: `count`, `updateMany` and
|
|
150
|
+
`deleteMany` return a number and require a filter. The driver's own are on
|
|
151
|
+
`raw`, which is its `Collection`, untouched:
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
await collection.updateMany({ name: null }, { name: 'x' }); // → number
|
|
155
|
+
await collection.raw.updateMany({}, { $set: { name: 'x' } }); // → UpdateResult
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`raw` is also the way out for an update operator this package does not name.
|
|
159
|
+
|
|
135
160
|
`create` checks the document against the schema before sending it, which is
|
|
136
161
|
also what fills its defaults. `update` checks each field of a patch — the
|
|
137
162
|
driver's own `UpdateFilter` is intersected with `Document` and accepts any key
|
|
@@ -192,15 +217,20 @@ document is repeated or skipped while the collection is written to, where
|
|
|
192
217
|
import { withTransaction } from '@nxgt/mongo';
|
|
193
218
|
|
|
194
219
|
await withTransaction(client, async (session) => {
|
|
195
|
-
const team = await teams.
|
|
196
|
-
await users.
|
|
220
|
+
const team = await teams.withSession(session).create({ name: 'Core' });
|
|
221
|
+
await users.withSession(session).update(userId, { teamId: team._id });
|
|
197
222
|
});
|
|
198
223
|
```
|
|
199
224
|
|
|
200
225
|
**Every operation has to be given the session.** MongoDB has no ambient
|
|
201
226
|
session: a write that was not given one runs outside the transaction and is not
|
|
202
|
-
rolled back with it. `
|
|
203
|
-
and it returns a new
|
|
227
|
+
rolled back with it. `collection.withSession(session)` is how a collection
|
|
228
|
+
takes it, and it returns a new collection rather than changing the one you
|
|
229
|
+
have.
|
|
230
|
+
|
|
231
|
+
`withSession` binds **this package's** methods. A driver method on the same
|
|
232
|
+
object — `aggregate`, `bulkWrite`, `countDocuments` — takes its session the
|
|
233
|
+
driver's way, in its options: `collection.aggregate(pipeline, { session })`.
|
|
204
234
|
|
|
205
235
|
Given a session that is already in a transaction, `withTransaction` joins it.
|
|
206
236
|
MongoDB has no savepoints, so an inner failure takes the whole transaction
|
|
@@ -259,7 +289,7 @@ server error reaches you untouched.
|
|
|
259
289
|
| `id`, `objectId`, `timestamps`, `softDelete`, `optimisticLock`, `actors` | the field helpers |
|
|
260
290
|
| `toObjectId`, `toObjectIds`, `tryObjectId`, `objectIdParam` | a string from outside as an `ObjectId` |
|
|
261
291
|
| `isValidObjectId`, `isObjectIdString`, `isObjectId` | the checks behind them |
|
|
262
|
-
| `
|
|
292
|
+
| `getCollection(dbOrClient, definition, options?)` | the typed collection, driver methods included |
|
|
263
293
|
| `syncCollection`, `syncCollections` | create and bring in line, with `dryRun` |
|
|
264
294
|
| `withTransaction(clientOrSession, fn, options?)` | a transaction, joined when nested |
|
|
265
295
|
| `toMongoJsonSchema(schema)` | a Zod schema as a MongoDB `$jsonSchema` |
|
|
@@ -267,14 +297,47 @@ server error reaches you untouched.
|
|
|
267
297
|
| `DataError` and its subclasses, `toDataError` | the errors |
|
|
268
298
|
| `diffIndexes`, `normalizeIndex`, `validationMatches` | what `sync` compares with |
|
|
269
299
|
|
|
270
|
-
`
|
|
271
|
-
`touchUpdatedAt`, `optimisticLock`, `validate: 'off'`, `maxPageSize
|
|
300
|
+
`CollectionOptions` turns the behaviours off one by one: `softDelete`,
|
|
301
|
+
`touchUpdatedAt`, `optimisticLock`, `validate: 'off'`, `maxPageSize`, and it
|
|
302
|
+
names the database with `db` when you pass a client.
|
|
303
|
+
|
|
304
|
+
## What does not compile
|
|
305
|
+
|
|
306
|
+
The schema types more than the documents. These are compile errors, each one
|
|
307
|
+
kept as a test in `test/types/strictness.ts`:
|
|
308
|
+
|
|
309
|
+
```ts
|
|
310
|
+
await collection.findMany({ sort: { nope: 1 } }); // no such field
|
|
311
|
+
await collection.findMany({ sort: { email: 'up' } }); // not a direction
|
|
312
|
+
await collection.findMany({ projection: { nope: 1 } }); // no such field
|
|
313
|
+
await collection.findMany({ projection: { email: 2 } }); // 0, 1 or an operator
|
|
314
|
+
await collection.update(id, { $set: { nope: 1 } }); // no such field
|
|
315
|
+
await collection.update(id, { $set: { email: 1 } }); // email is a string
|
|
316
|
+
await collection.update(id, { $inc: { email: 1 } }); // not a numeric field
|
|
317
|
+
await collection.update(id, { $push: { title: 'x' } }); // not an array field
|
|
318
|
+
await collection.update(id, { id: 'abc' }); // id is computed
|
|
319
|
+
collection.as('not-an-object-id'); // the schema types the actor
|
|
320
|
+
posts.as(someone); // posts stamp no actor
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
What is **not** checked: the tail of a dotted path, and a `filter`, which stays
|
|
324
|
+
the driver's `Filter` — rebuilding it would mean reimplementing every query
|
|
325
|
+
operator, and getting it subtly wrong is worse than being honest about it.
|
|
272
326
|
|
|
273
327
|
## Traps
|
|
274
328
|
|
|
275
329
|
- **There is no ambient session.** An operation inside `withTransaction` that
|
|
276
330
|
was not given the session is not part of the transaction. Use
|
|
277
|
-
`
|
|
331
|
+
`collection.withSession(session)` for every one of them.
|
|
332
|
+
- **A driver method does not take the collection's session.** `withSession`
|
|
333
|
+
binds this package's methods; `collection.aggregate(…)` is the driver's own,
|
|
334
|
+
so it wants `{ session }` in its options like anywhere else. The session is
|
|
335
|
+
on the collection as `collection.session` when you need to pass it along.
|
|
336
|
+
- **`estimatedDocumentCount` counts writes that have not committed.** It reads
|
|
337
|
+
the storage engine's metadata rather than the documents, so it is not
|
|
338
|
+
transactional and it is not exact — a document inserted by an open
|
|
339
|
+
transaction is already in its answer. `count` queries, and is the one to
|
|
340
|
+
assert on.
|
|
278
341
|
- **`$jsonSchema` is not JSON Schema.** MongoDB rejects `$ref`, `$schema`,
|
|
279
342
|
`default`, `format` and `id`, has no `integer` type, and treats a keyword it
|
|
280
343
|
does not know as an error rather than ignoring it. `toMongoJsonSchema`
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { ClientSession, Db, Collection as DriverCollection } from 'mongodb';
|
|
2
|
+
import type { z } from 'zod';
|
|
3
|
+
import { type AnyCollectionDefinition, stampsOf } from '../definition/define-collection';
|
|
4
|
+
import { NotFoundError } from '../errors/data-error';
|
|
5
|
+
import type { CollectionOptions } from './types';
|
|
6
|
+
/** Which of the fields the collection knows about a schema has. */
|
|
7
|
+
type Stamps = ReturnType<typeof stampsOf>;
|
|
8
|
+
/**
|
|
9
|
+
* What every method of a collection works from, resolved once: the
|
|
10
|
+
* definition, the driver's collection, and the options once they have been
|
|
11
|
+
* read against the schema.
|
|
12
|
+
*
|
|
13
|
+
* It holds **data only**. The operations are plain functions that take it as
|
|
14
|
+
* their first argument, in `filters.ts`, `documents.ts`, `reads.ts`,
|
|
15
|
+
* `writes.ts` and `paginate.ts` — a context of closures would only be the
|
|
16
|
+
* factory this package split up, one size down.
|
|
17
|
+
*
|
|
18
|
+
* `withSession` and `as` build another one, cheaply: they are the same
|
|
19
|
+
* collection with a single option changed.
|
|
20
|
+
*/
|
|
21
|
+
export interface CollectionContext {
|
|
22
|
+
readonly definition: AnyCollectionDefinition;
|
|
23
|
+
readonly db: Db;
|
|
24
|
+
/**
|
|
25
|
+
* The driver's collection, typed loosely on purpose: this layer works on
|
|
26
|
+
* any documents, and the public type is what callers see.
|
|
27
|
+
*/
|
|
28
|
+
readonly collection: DriverCollection<any>;
|
|
29
|
+
readonly name: string;
|
|
30
|
+
readonly shape: Record<string, z.ZodType>;
|
|
31
|
+
readonly stamps: Stamps;
|
|
32
|
+
/** Who is writing, stamped into the `*By` fields. */
|
|
33
|
+
readonly actor: unknown;
|
|
34
|
+
readonly session: ClientSession | undefined;
|
|
35
|
+
/** `{ session }` when there is one, to spread into the driver's options. */
|
|
36
|
+
readonly sessionOption: {
|
|
37
|
+
session?: ClientSession;
|
|
38
|
+
};
|
|
39
|
+
readonly maxPageSize: number;
|
|
40
|
+
/**
|
|
41
|
+
* Whether the schema declares an `id` field of its own. Then `id` is that
|
|
42
|
+
* field's, and this package neither computes it nor drops it.
|
|
43
|
+
*/
|
|
44
|
+
readonly hasOwnId: boolean;
|
|
45
|
+
/** Whether a write is checked against the schema, which fills its defaults. */
|
|
46
|
+
readonly parses: boolean;
|
|
47
|
+
/** Whether `delete` writes `deletedAt` rather than removing the document. */
|
|
48
|
+
readonly softDeletes: boolean;
|
|
49
|
+
/** Whether an update that does not set `updatedAt` gets it set. */
|
|
50
|
+
readonly touches: boolean;
|
|
51
|
+
/** Whether an update raises `version`. */
|
|
52
|
+
readonly locks: boolean;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Resolves a collection's options against its schema, and refuses the two
|
|
56
|
+
* that cannot be honoured: a soft delete without `deletedAt`, and an
|
|
57
|
+
* optimistic lock without `version`.
|
|
58
|
+
*/
|
|
59
|
+
export declare function createContext(db: Db, definition: AnyCollectionDefinition, options: CollectionOptions<never>): CollectionContext;
|
|
60
|
+
/** Runs an operation, turning a MongoDB error into a `DataError`. */
|
|
61
|
+
export declare function run<T>(ctx: CollectionContext, fn: () => Promise<T>): Promise<T>;
|
|
62
|
+
export declare function notFound(ctx: CollectionContext, id: unknown): NotFoundError;
|
|
63
|
+
export {};
|
|
64
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/collection/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,aAAa,EACb,EAAE,EACF,UAAU,IAAI,gBAAgB,EAC9B,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EACN,KAAK,uBAAuB,EAC5B,QAAQ,EACR,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,mEAAmE;AACnE,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAE1C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,UAAU,EAAE,uBAAuB,CAAC;IAC7C,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;IAChB;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;IAC1C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,SAAS,CAAC;IAC5C,4EAA4E;IAC5E,QAAQ,CAAC,aAAa,EAAE;QAAE,OAAO,CAAC,EAAE,aAAa,CAAA;KAAE,CAAC;IACpD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,+EAA+E;IAC/E,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,6EAA6E;IAC7E,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,mEAAmE;IACnE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC5B,EAAE,EAAE,EAAE,EACN,UAAU,EAAE,uBAAuB,EACnC,OAAO,EAAE,iBAAiB,CAAC,KAAK,CAAC,GAC/B,iBAAiB,CAkCnB;AAED,qEAAqE;AACrE,wBAAsB,GAAG,CAAC,CAAC,EAC1B,GAAG,EAAE,iBAAiB,EACtB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAClB,OAAO,CAAC,CAAC,CAAC,CAMZ;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,iBAAiB,EAAE,EAAE,EAAE,OAAO,GAAG,aAAa,CAK3E"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CollectionContext } from './context';
|
|
2
|
+
import { type Fields } from './filters';
|
|
3
|
+
/**
|
|
4
|
+
* `id` on a document a collection gives back: `_id` as a string, computed
|
|
5
|
+
* rather than stored — the collection holds `_id` alone.
|
|
6
|
+
*
|
|
7
|
+
* It is enumerable, so `JSON.stringify` and a spread carry it and a handler
|
|
8
|
+
* can return the document as it is. `toDocument` drops it again on a write,
|
|
9
|
+
* and it is no part of `DocumentOf`, so nothing can filter on it: the server
|
|
10
|
+
* would match nothing.
|
|
11
|
+
*/
|
|
12
|
+
export declare function withId<T>(ctx: CollectionContext, document: T): T;
|
|
13
|
+
/** The document to insert: checked against the schema, defaults filled. */
|
|
14
|
+
export declare function toDocument(ctx: CollectionContext, values: unknown): Fields;
|
|
15
|
+
/**
|
|
16
|
+
* The update to send: a patch of fields becomes `$set`, checked field by
|
|
17
|
+
* field against the schema, with the stamps this collection keeps. A patch
|
|
18
|
+
* that already speaks in operators is sent as it is, with the stamps added.
|
|
19
|
+
*/
|
|
20
|
+
export declare function toUpdate(ctx: CollectionContext, patch: unknown): Fields;
|
|
21
|
+
//# sourceMappingURL=documents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"documents.d.ts","sourceRoot":"","sources":["../../src/collection/documents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,KAAK,MAAM,EAA4B,MAAM,WAAW,CAAC;AAElE;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,iBAAiB,EAAE,QAAQ,EAAE,CAAC,GAAG,CAAC,CAehE;AAED,2EAA2E;AAC3E,wBAAgB,UAAU,CAAC,GAAG,EAAE,iBAAiB,EAAE,MAAM,EAAE,OAAO,GAAG,MAAM,CAkB1E;AAkBD;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,iBAAiB,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,CA6BvE"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { CollectionContext } from './context';
|
|
2
|
+
/** A document as this package handles one internally: keys it cannot know. */
|
|
3
|
+
export type Fields = Record<string, unknown>;
|
|
4
|
+
export declare function isRecord(value: unknown): value is Fields;
|
|
5
|
+
/** Does this patch speak in MongoDB's operators rather than in fields? */
|
|
6
|
+
export declare function isUpdateFilter(patch: Fields): boolean;
|
|
7
|
+
/** `a` and `b`, without letting one's `$or` swallow the other's. */
|
|
8
|
+
export declare function mergeFilters(a: Fields | undefined, b: Fields | undefined): Fields;
|
|
9
|
+
/** The filter that leaves soft-deleted documents out. */
|
|
10
|
+
export declare function live(ctx: CollectionContext, withDeleted?: boolean): Fields | undefined;
|
|
11
|
+
/** A caller's filter, narrowed to the documents this collection shows. */
|
|
12
|
+
export declare function scoped(ctx: CollectionContext, filter: unknown, withDeleted?: boolean): Fields;
|
|
13
|
+
/** Refuses a call that would otherwise run on the whole collection. */
|
|
14
|
+
export declare function requireFilter(ctx: CollectionContext, method: string, filter: unknown): void;
|
|
15
|
+
//# sourceMappingURL=filters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filters.d.ts","sourceRoot":"","sources":["../../src/collection/filters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD,8EAA8E;AAC9E,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE7C,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAExD;AAED,0EAA0E;AAC1E,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,oEAAoE;AACpE,wBAAgB,YAAY,CAC3B,CAAC,EAAE,MAAM,GAAG,SAAS,EACrB,CAAC,EAAE,MAAM,GAAG,SAAS,GACnB,MAAM,CAMR;AAED,yDAAyD;AACzD,wBAAgB,IAAI,CACnB,GAAG,EAAE,iBAAiB,EACtB,WAAW,CAAC,EAAE,OAAO,GACnB,MAAM,GAAG,SAAS,CAEpB;AAED,0EAA0E;AAC1E,wBAAgB,MAAM,CACrB,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,OAAO,EACf,WAAW,CAAC,EAAE,OAAO,GACnB,MAAM,CAKR;AAED,uEAAuE;AACvE,wBAAgB,aAAa,CAC5B,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,GACb,IAAI,CAMN"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Db, MongoClient } from 'mongodb';
|
|
2
|
+
import type { z } from 'zod';
|
|
3
|
+
import type { CollectionDefinition } from '../definition/define-collection';
|
|
4
|
+
import type { CollectionOptions, TypedCollection } from './types';
|
|
5
|
+
/** What a collection can be reached through: a database, or a client. */
|
|
6
|
+
export type CollectionSource = Db | MongoClient;
|
|
7
|
+
/**
|
|
8
|
+
* A collection: this package's methods and the driver's own, on one object.
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* const users = getCollection(db, usersDefinition);
|
|
12
|
+
*
|
|
13
|
+
* const ada = await users.create({ email: 'ada@example.com' });
|
|
14
|
+
* await users.update(ada._id, { name: 'Ada' }, { expectedVersion: ada.version });
|
|
15
|
+
* await users.aggregate([{ $group: { _id: '$teamId', n: { $sum: 1 } } }]);
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* It takes a `Db`, or a `MongoClient` — then the database is the URI's, or the
|
|
19
|
+
* one named in `{ db }`.
|
|
20
|
+
*
|
|
21
|
+
* Every operation runs in the collection's session, which `withSession` sets:
|
|
22
|
+
* MongoDB has no ambient session, so a write inside a transaction that was not
|
|
23
|
+
* given one is not part of it and is not rolled back.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getCollection<Schema extends z.ZodObject>(source: CollectionSource, definition: CollectionDefinition<Schema>, options?: CollectionOptions<CollectionDefinition<Schema>>): TypedCollection<CollectionDefinition<Schema>>;
|
|
26
|
+
//# sourceMappingURL=get-collection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-collection.d.ts","sourceRoot":"","sources":["../../src/collection/get-collection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,EAAE,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAEX,oBAAoB,EACpB,MAAM,iCAAiC,CAAC;AAazC,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAalE,yEAAyE;AACzE,MAAM,MAAM,gBAAgB,GAAG,EAAE,GAAG,WAAW,CAAC;AAmBhD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,MAAM,SAAS,CAAC,CAAC,SAAS,EACvD,MAAM,EAAE,gBAAgB,EACxB,UAAU,EAAE,oBAAoB,CAAC,MAAM,CAAC,EACxC,OAAO,GAAE,iBAAiB,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAM,GAC3D,eAAe,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAG/C"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type CursorPage, type Page } from '../pagination/page';
|
|
2
|
+
import type { CollectionContext } from './context';
|
|
3
|
+
import { type Fields } from './filters';
|
|
4
|
+
export declare function paginate(ctx: CollectionContext, opts?: Fields): Promise<Page<Fields>>;
|
|
5
|
+
export declare function paginateByCursor(ctx: CollectionContext, opts?: Fields): Promise<CursorPage<Fields>>;
|
|
6
|
+
//# sourceMappingURL=paginate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paginate.d.ts","sourceRoot":"","sources":["../../src/collection/paginate.ts"],"names":[],"mappings":"AAEA,OAAO,EACN,KAAK,UAAU,EAEf,KAAK,IAAI,EAGT,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,KAAK,MAAM,EAA0B,MAAM,WAAW,CAAC;AAIhE,wBAAsB,QAAQ,CAC7B,GAAG,EAAE,iBAAiB,EACtB,IAAI,GAAE,MAAW,GACf,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAevB;AAED,wBAAsB,gBAAgB,CACrC,GAAG,EAAE,iBAAiB,EACtB,IAAI,GAAE,MAAW,GACf,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CA+D7B"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type CollectionContext } from './context';
|
|
2
|
+
import { type Fields } from './filters';
|
|
3
|
+
/** One document, straight from the driver, carrying its computed `id`. */
|
|
4
|
+
export declare function findOne(ctx: CollectionContext, filter: Fields, projection?: unknown): Promise<Fields | null>;
|
|
5
|
+
export declare function findById(ctx: CollectionContext, id: unknown, opts?: {
|
|
6
|
+
withDeleted?: boolean;
|
|
7
|
+
}): Promise<Fields | undefined>;
|
|
8
|
+
export declare function getById(ctx: CollectionContext, id: unknown, opts?: {
|
|
9
|
+
withDeleted?: boolean;
|
|
10
|
+
}): Promise<Fields>;
|
|
11
|
+
export declare function findMany(ctx: CollectionContext, opts?: Fields): Promise<Fields[]>;
|
|
12
|
+
export declare function findFirst(ctx: CollectionContext, filter?: unknown, opts?: Fields): Promise<Fields | undefined>;
|
|
13
|
+
export declare function countDocuments(ctx: CollectionContext, filter?: unknown, opts?: {
|
|
14
|
+
withDeleted?: boolean;
|
|
15
|
+
}): Promise<number>;
|
|
16
|
+
export declare function exists(ctx: CollectionContext, filter: unknown, opts?: {
|
|
17
|
+
withDeleted?: boolean;
|
|
18
|
+
}): Promise<boolean>;
|
|
19
|
+
//# sourceMappingURL=reads.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reads.d.ts","sourceRoot":"","sources":["../../src/collection/reads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAAiB,MAAM,WAAW,CAAC;AAElE,OAAO,EAAE,KAAK,MAAM,EAAU,MAAM,WAAW,CAAC;AAEhD,0EAA0E;AAC1E,wBAAgB,OAAO,CACtB,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,OAAO,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQxB;AAED,wBAAsB,QAAQ,CAC7B,GAAG,EAAE,iBAAiB,EACtB,EAAE,EAAE,OAAO,EACX,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GAClC,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAG7B;AAED,wBAAsB,OAAO,CAC5B,GAAG,EAAE,iBAAiB,EACtB,EAAE,EAAE,OAAO,EACX,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GAClC,OAAO,CAAC,MAAM,CAAC,CAIjB;AAED,wBAAsB,QAAQ,CAC7B,GAAG,EAAE,iBAAiB,EACtB,IAAI,GAAE,MAAW,GACf,OAAO,CAAC,MAAM,EAAE,CAAC,CAenB;AAED,wBAAsB,SAAS,CAC9B,GAAG,EAAE,iBAAiB,EACtB,MAAM,CAAC,EAAE,OAAO,EAChB,IAAI,GAAE,MAAW,GACf,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAG7B;AAED,wBAAsB,cAAc,CACnC,GAAG,EAAE,iBAAiB,EACtB,MAAM,CAAC,EAAE,OAAO,EAChB,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GAClC,OAAO,CAAC,MAAM,CAAC,CAMjB;AAED,wBAAsB,MAAM,CAC3B,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,OAAO,EACf,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAA;CAAO,GAClC,OAAO,CAAC,OAAO,CAAC,CAKlB"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import type { ClientSession, Db, Collection as DriverCollection, Filter } from 'mongodb';
|
|
2
|
+
import type { DocumentOf, FieldOf, IdOf, NewDocumentOf, ReadDocumentOf } from '../definition/define-collection';
|
|
3
|
+
import type { CursorPage, Page, PageOptions } from '../pagination/page';
|
|
4
|
+
import type { SyncOptions, SyncReport } from '../sync/sync-collection';
|
|
5
|
+
export type OrderDirection = 'asc' | 'desc';
|
|
6
|
+
/**
|
|
7
|
+
* A field of the documents, or a path into one. The tail of a path cannot be
|
|
8
|
+
* checked — a schema says nothing about what is under an arbitrary key — but
|
|
9
|
+
* its head must be a field, which is what catches a misspelt name.
|
|
10
|
+
*/
|
|
11
|
+
export type FieldPath<Def> = FieldOf<Def> | `${FieldOf<Def>}.${string}`;
|
|
12
|
+
/** The fields whose type is a number, for `$inc` and `$mul`. */
|
|
13
|
+
type NumericFieldsOf<Doc> = {
|
|
14
|
+
[K in keyof Doc]: NonNullable<Doc[K]> extends number ? K : never;
|
|
15
|
+
}[keyof Doc] & string;
|
|
16
|
+
/** The fields whose type is an array, for `$push` and `$addToSet`. */
|
|
17
|
+
type ArrayFieldsOf<Doc> = {
|
|
18
|
+
[K in keyof Doc]: NonNullable<Doc[K]> extends readonly unknown[] ? K : never;
|
|
19
|
+
}[keyof Doc] & string;
|
|
20
|
+
type ElementOf<T> = NonNullable<T> extends readonly (infer Element)[] ? Element : never;
|
|
21
|
+
/** A sort, keyed on the schema's fields. */
|
|
22
|
+
export type SortOf<Def> = {
|
|
23
|
+
[Field in FieldPath<Def>]?: 1 | -1 | 'asc' | 'desc';
|
|
24
|
+
};
|
|
25
|
+
/** What a projection may hold beside `0` and `1`. */
|
|
26
|
+
export type ProjectionOperator = {
|
|
27
|
+
$slice: number | [number, number];
|
|
28
|
+
} | {
|
|
29
|
+
$elemMatch: Record<string, unknown>;
|
|
30
|
+
} | {
|
|
31
|
+
$meta: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* A projection, keyed on the schema's fields. It says what is sent over the
|
|
35
|
+
* wire; it does not narrow the type of the documents, because the driver
|
|
36
|
+
* cannot either — a projected read is typed as the whole document.
|
|
37
|
+
*/
|
|
38
|
+
export type ProjectionOf<Def> = {
|
|
39
|
+
[Field in FieldPath<Def>]?: 0 | 1 | boolean | ProjectionOperator;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Who is writing: the type the schema gives `createdBy`, or `updatedBy`, or
|
|
43
|
+
* `deletedBy`. A collection with none of them has no actor to stamp, so `as`
|
|
44
|
+
* cannot be called on it at all.
|
|
45
|
+
*/
|
|
46
|
+
export type ActorOf<Def> = 'createdBy' extends keyof DocumentOf<Def> ? NonNullable<DocumentOf<Def>['createdBy']> : 'updatedBy' extends keyof DocumentOf<Def> ? NonNullable<DocumentOf<Def>['updatedBy']> : 'deletedBy' extends keyof DocumentOf<Def> ? NonNullable<DocumentOf<Def>['deletedBy']> : never;
|
|
47
|
+
/** What `$set` takes: a field's own type, or anything under a path. */
|
|
48
|
+
export type SetOf<Def> = {
|
|
49
|
+
[Field in FieldPath<Def>]?: Field extends keyof DocumentOf<Def> ? DocumentOf<Def>[Field] : unknown;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* MongoDB's update operators, keyed on the schema.
|
|
53
|
+
*
|
|
54
|
+
* The driver's own `UpdateFilter` is intersected with `Document`, whose index
|
|
55
|
+
* signature accepts every key — `$set: { nope: 1 }` included — and `Omit`
|
|
56
|
+
* cannot take that back, since omitting a literal key from an index signature
|
|
57
|
+
* leaves the index signature. So the operators are declared here instead. One
|
|
58
|
+
* this does not name is a reason to reach for `raw`, which is the driver's own
|
|
59
|
+
* collection, untouched.
|
|
60
|
+
*/
|
|
61
|
+
export interface UpdateOperators<Def> {
|
|
62
|
+
$set?: SetOf<Def>;
|
|
63
|
+
$setOnInsert?: SetOf<Def>;
|
|
64
|
+
$unset?: {
|
|
65
|
+
[Field in FieldPath<Def>]?: '' | 1 | true;
|
|
66
|
+
};
|
|
67
|
+
$inc?: {
|
|
68
|
+
[Field in NumericFieldsOf<DocumentOf<Def>> | `${FieldOf<Def>}.${string}`]?: number;
|
|
69
|
+
};
|
|
70
|
+
$mul?: {
|
|
71
|
+
[Field in NumericFieldsOf<DocumentOf<Def>> | `${FieldOf<Def>}.${string}`]?: number;
|
|
72
|
+
};
|
|
73
|
+
$min?: SetOf<Def>;
|
|
74
|
+
$max?: SetOf<Def>;
|
|
75
|
+
$rename?: {
|
|
76
|
+
[Field in FieldPath<Def>]?: string;
|
|
77
|
+
};
|
|
78
|
+
$currentDate?: {
|
|
79
|
+
[Field in FieldPath<Def>]?: true | {
|
|
80
|
+
$type: 'date' | 'timestamp';
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
$push?: PushOf<Def>;
|
|
84
|
+
$addToSet?: PushOf<Def>;
|
|
85
|
+
$pull?: {
|
|
86
|
+
[Field in FieldPath<Def>]?: unknown;
|
|
87
|
+
};
|
|
88
|
+
$pullAll?: {
|
|
89
|
+
[Field in FieldPath<Def>]?: readonly unknown[];
|
|
90
|
+
};
|
|
91
|
+
$pop?: {
|
|
92
|
+
[Field in FieldPath<Def>]?: 1 | -1;
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/** What `$push` and `$addToSet` take: an element of the array, or `$each`. */
|
|
96
|
+
export type PushOf<Def> = {
|
|
97
|
+
[Field in ArrayFieldsOf<DocumentOf<Def>>]?: ElementOf<DocumentOf<Def>[Field]> | {
|
|
98
|
+
$each: readonly ElementOf<DocumentOf<Def>[Field]>[];
|
|
99
|
+
$position?: number;
|
|
100
|
+
$slice?: number;
|
|
101
|
+
$sort?: 1 | -1 | Record<string, 1 | -1>;
|
|
102
|
+
};
|
|
103
|
+
} & {
|
|
104
|
+
[Path in `${string}.${string}`]?: unknown;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* What an update writes: the document's own fields, checked against the
|
|
108
|
+
* schema, or MongoDB's operators for what they cannot say.
|
|
109
|
+
*/
|
|
110
|
+
export type Patch<Def> = Partial<DocumentOf<Def>> | (UpdateOperators<Def> & {
|
|
111
|
+
[K in keyof DocumentOf<Def>]?: never;
|
|
112
|
+
} & {
|
|
113
|
+
id?: never;
|
|
114
|
+
});
|
|
115
|
+
export interface ReadOptions {
|
|
116
|
+
/** Include soft-deleted documents. Ignored without a `deletedAt` field. */
|
|
117
|
+
withDeleted?: boolean;
|
|
118
|
+
}
|
|
119
|
+
export interface FindFirstOptions<Def> extends ReadOptions {
|
|
120
|
+
sort?: SortOf<Def>;
|
|
121
|
+
projection?: ProjectionOf<Def>;
|
|
122
|
+
}
|
|
123
|
+
export interface FindManyOptions<Def> extends FindFirstOptions<Def> {
|
|
124
|
+
filter?: Filter<DocumentOf<Def>>;
|
|
125
|
+
limit?: number;
|
|
126
|
+
skip?: number;
|
|
127
|
+
}
|
|
128
|
+
export interface PaginateOptions<Def> extends PageOptions, ReadOptions {
|
|
129
|
+
filter?: Filter<DocumentOf<Def>>;
|
|
130
|
+
/** Default `{ _id: 1 }`, so that pages are stable. */
|
|
131
|
+
sort?: SortOf<Def>;
|
|
132
|
+
}
|
|
133
|
+
export interface CursorPaginateOptions<Def> extends ReadOptions {
|
|
134
|
+
/** The `nextCursor` of the previous page. Omit it for the first page. */
|
|
135
|
+
after?: string | null | undefined;
|
|
136
|
+
/** Documents per page. Default `20`, at most `maxPageSize`. */
|
|
137
|
+
limit?: number;
|
|
138
|
+
filter?: Filter<DocumentOf<Def>>;
|
|
139
|
+
/**
|
|
140
|
+
* The field to page along. Default `_id`. Any other is followed by `_id`,
|
|
141
|
+
* which breaks its ties, and must be set on every document.
|
|
142
|
+
*/
|
|
143
|
+
orderBy?: FieldOf<Def>;
|
|
144
|
+
/** Default `'asc'`. */
|
|
145
|
+
direction?: OrderDirection;
|
|
146
|
+
}
|
|
147
|
+
export interface UpdateOptions {
|
|
148
|
+
/**
|
|
149
|
+
* Only update the document while its `version` is still this one. When it
|
|
150
|
+
* is not, nothing is written and `OptimisticLockError` is thrown with the
|
|
151
|
+
* version the document has now.
|
|
152
|
+
*/
|
|
153
|
+
expectedVersion?: number;
|
|
154
|
+
}
|
|
155
|
+
export interface CollectionOptions<Def> {
|
|
156
|
+
/**
|
|
157
|
+
* Soft delete through the `deletedAt` field. Default: on when the schema
|
|
158
|
+
* has one. `false` makes `delete` a real delete.
|
|
159
|
+
*/
|
|
160
|
+
softDelete?: boolean;
|
|
161
|
+
/**
|
|
162
|
+
* Set `updatedAt` on every update that does not set it. Default: on when
|
|
163
|
+
* the schema has the field.
|
|
164
|
+
*/
|
|
165
|
+
touchUpdatedAt?: boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Raise `version` by one on every update. Default: on when the schema has
|
|
168
|
+
* the field. `expectedVersion` needs it.
|
|
169
|
+
*/
|
|
170
|
+
optimisticLock?: boolean;
|
|
171
|
+
/**
|
|
172
|
+
* Check documents against the schema before writing them, which is also
|
|
173
|
+
* what fills their defaults. Default `'parse'`. `'off'` sends them as they
|
|
174
|
+
* are — and then nothing fills `_id`, `createdAt` or `version`.
|
|
175
|
+
*/
|
|
176
|
+
validate?: 'parse' | 'off';
|
|
177
|
+
/** The largest `pageSize` or `limit` a page may ask for. Default `100`. */
|
|
178
|
+
maxPageSize?: number;
|
|
179
|
+
/** The session every operation runs in. `withSession` is how it is set. */
|
|
180
|
+
session?: ClientSession;
|
|
181
|
+
/** Who is writing, stamped into `createdBy`, `updatedBy` and `deletedBy`. */
|
|
182
|
+
actor?: ActorOf<Def>;
|
|
183
|
+
/** Which database, when `getCollection` is given a client rather than a `Db`. */
|
|
184
|
+
db?: string;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* What this package adds to a collection. The collection you are handed is
|
|
188
|
+
* this **and** the driver's own `Collection`, so `aggregate`, `watch`,
|
|
189
|
+
* `bulkWrite` and the rest are on it directly.
|
|
190
|
+
*/
|
|
191
|
+
export interface CollectionApi<Def> {
|
|
192
|
+
readonly definition: Def;
|
|
193
|
+
readonly db: Db;
|
|
194
|
+
/**
|
|
195
|
+
* The driver's collection, untouched. It is where the three methods this
|
|
196
|
+
* one redefines still live — `raw.updateMany`, `raw.deleteMany` and
|
|
197
|
+
* `raw.count` — and where an update operator this package does not name
|
|
198
|
+
* can still be sent.
|
|
199
|
+
*/
|
|
200
|
+
readonly raw: DriverCollection<DocumentOf<Def>>;
|
|
201
|
+
/** The session every operation of this collection runs in, if any. */
|
|
202
|
+
readonly session: ClientSession | undefined;
|
|
203
|
+
/**
|
|
204
|
+
* The same collection, bound to a session. MongoDB has no ambient session:
|
|
205
|
+
* without this, an operation inside a transaction runs outside it.
|
|
206
|
+
*
|
|
207
|
+
* It binds **this package's** methods. A driver method reached through the
|
|
208
|
+
* collection takes its session the driver's way, in its options.
|
|
209
|
+
*/
|
|
210
|
+
withSession(session: ClientSession | undefined): TypedCollection<Def>;
|
|
211
|
+
/** The same collection, stamping this actor into the `*By` fields. */
|
|
212
|
+
as(actor: ActorOf<Def>): TypedCollection<Def>;
|
|
213
|
+
/** Creates the collection, its validator and its indexes. See `syncCollection`. */
|
|
214
|
+
sync(options?: SyncOptions): Promise<SyncReport>;
|
|
215
|
+
/** The document with this `_id`, or `undefined`. */
|
|
216
|
+
findById(id: IdOf<Def>, options?: ReadOptions): Promise<ReadDocumentOf<Def> | undefined>;
|
|
217
|
+
/** The document with this `_id`. Throws `NotFoundError`. */
|
|
218
|
+
getById(id: IdOf<Def>, options?: ReadOptions): Promise<ReadDocumentOf<Def>>;
|
|
219
|
+
/** The first document that matches, or `undefined`. */
|
|
220
|
+
findFirst(filter?: Filter<DocumentOf<Def>>, options?: FindFirstOptions<Def>): Promise<ReadDocumentOf<Def> | undefined>;
|
|
221
|
+
/** Every document that matches. */
|
|
222
|
+
findMany(options?: FindManyOptions<Def>): Promise<ReadDocumentOf<Def>[]>;
|
|
223
|
+
/** Checks the document against the schema, fills its defaults, inserts it. */
|
|
224
|
+
create(values: NewDocumentOf<Def>): Promise<ReadDocumentOf<Def>>;
|
|
225
|
+
/** The same, in one insert. `[]` sends nothing. */
|
|
226
|
+
createMany(values: readonly NewDocumentOf<Def>[]): Promise<ReadDocumentOf<Def>[]>;
|
|
227
|
+
/** Updates the document with this `_id` and returns it. Throws `NotFoundError`. */
|
|
228
|
+
update(id: IdOf<Def>, patch: Patch<Def>, options?: UpdateOptions): Promise<ReadDocumentOf<Def>>;
|
|
229
|
+
/**
|
|
230
|
+
* Updates every document that matches, and returns how many changed. The
|
|
231
|
+
* driver's own `updateMany`, which returns an `UpdateResult` and takes no
|
|
232
|
+
* filter for granted, is `raw.updateMany`.
|
|
233
|
+
*/
|
|
234
|
+
updateMany(filter: Filter<DocumentOf<Def>>, patch: Patch<Def>): Promise<number>;
|
|
235
|
+
/**
|
|
236
|
+
* Deletes the document with this `_id` and returns it: a soft delete on a
|
|
237
|
+
* collection with `deletedAt`. Throws `NotFoundError`.
|
|
238
|
+
*/
|
|
239
|
+
delete(id: IdOf<Def>): Promise<ReadDocumentOf<Def>>;
|
|
240
|
+
/** Deletes every document that matches, and returns how many. `raw.deleteMany` is the driver's. */
|
|
241
|
+
deleteMany(filter: Filter<DocumentOf<Def>>): Promise<number>;
|
|
242
|
+
/** A real delete, of a live or a soft-deleted document. */
|
|
243
|
+
hardDelete(id: IdOf<Def>): Promise<ReadDocumentOf<Def>>;
|
|
244
|
+
/** A real delete of every document that matches, soft-deleted ones included. */
|
|
245
|
+
hardDeleteMany(filter: Filter<DocumentOf<Def>>): Promise<number>;
|
|
246
|
+
/** Clears `deletedAt` and returns the document. Throws `NotFoundError`. */
|
|
247
|
+
restore(id: IdOf<Def>): Promise<ReadDocumentOf<Def>>;
|
|
248
|
+
/**
|
|
249
|
+
* How many documents match, soft-deleted ones left out. The driver's
|
|
250
|
+
* `count` is `raw.count`, and `estimatedDocumentCount` is on this
|
|
251
|
+
* collection directly.
|
|
252
|
+
*/
|
|
253
|
+
count(filter?: Filter<DocumentOf<Def>>, options?: ReadOptions): Promise<number>;
|
|
254
|
+
/** Whether any document matches. */
|
|
255
|
+
exists(filter: Filter<DocumentOf<Def>>, options?: ReadOptions): Promise<boolean>;
|
|
256
|
+
/** One page of the documents that match, and how many there are. */
|
|
257
|
+
paginate(options?: PaginateOptions<Def>): Promise<Page<ReadDocumentOf<Def>>>;
|
|
258
|
+
/** One page of the documents that match, after a cursor. */
|
|
259
|
+
paginateByCursor(options?: CursorPaginateOptions<Def>): Promise<CursorPage<ReadDocumentOf<Def>>>;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* A collection: this package's methods, plus every method of the driver's own
|
|
263
|
+
* `Collection` that they do not redefine.
|
|
264
|
+
*
|
|
265
|
+
* Three names are defined by both, and this package's win: `count`,
|
|
266
|
+
* `updateMany` and `deleteMany`. The driver's are on `raw`.
|
|
267
|
+
*/
|
|
268
|
+
export type TypedCollection<Def> = CollectionApi<Def> & Omit<DriverCollection<DocumentOf<Def>>, keyof CollectionApi<Def>>;
|
|
269
|
+
export {};
|
|
270
|
+
//# sourceMappingURL=types.d.ts.map
|