@nxgt/mongo 0.1.0 → 0.2.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 +60 -3
- package/dist/definition/define-collection.d.ts +36 -4
- package/dist/definition/define-collection.d.ts.map +1 -1
- package/dist/definition/fields.d.ts.map +1 -1
- package/dist/definition/object-id.d.ts +51 -0
- package/dist/definition/object-id.d.ts.map +1 -0
- package/dist/errors/data-error.d.ts +13 -1
- package/dist/errors/data-error.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +158 -78
- package/dist/index.js.map +8 -7
- package/dist/repository/types.d.ts +15 -13
- package/dist/repository/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -46,8 +46,23 @@ const db = client.db('app');
|
|
|
46
46
|
## Definition
|
|
47
47
|
|
|
48
48
|
`defineCollection` takes the collection's name, the Zod schema of its
|
|
49
|
-
documents, its indexes
|
|
50
|
-
|
|
49
|
+
documents, its indexes, and how its validator is applied.
|
|
50
|
+
|
|
51
|
+
An index is keyed on the schema's own fields, so an editor completes them and a
|
|
52
|
+
typo does not compile. A path into a field is allowed too, since that is how
|
|
53
|
+
MongoDB indexes a nested key. Everything else is the driver's own
|
|
54
|
+
`IndexDescription` — `unique`, `name`, `collation`, `expireAfterSeconds`,
|
|
55
|
+
`partialFilterExpression`:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
indexes: [
|
|
59
|
+
{ key: { email: 1 }, unique: true, name: 'users_email_unique' },
|
|
60
|
+
{ key: { createdAt: -1 } },
|
|
61
|
+
{ key: { 'address.city': 1 } },
|
|
62
|
+
// @ts-expect-error there is no such field
|
|
63
|
+
{ key: { emial: 1 } },
|
|
64
|
+
]
|
|
65
|
+
```
|
|
51
66
|
|
|
52
67
|
The schema is the one source of truth. `z.output` is what a read gives back,
|
|
53
68
|
`z.input` what a write takes: a field with a default — `_id`, `createdAt`,
|
|
@@ -99,7 +114,7 @@ import { createRepository } from '@nxgt/mongo';
|
|
|
99
114
|
const repo = createRepository(db, users);
|
|
100
115
|
|
|
101
116
|
const ada = await repo.create({ email: 'ada@example.com' });
|
|
102
|
-
// → { _id: ObjectId, email, name: null, createdAt: Date, version: 0, … }
|
|
117
|
+
// → { _id: ObjectId, id: '507f…', email, name: null, createdAt: Date, version: 0, … }
|
|
103
118
|
|
|
104
119
|
await repo.findById(ada._id); // the document, or undefined
|
|
105
120
|
await repo.getById(ada._id); // or NotFoundError
|
|
@@ -122,6 +137,36 @@ also what fills its defaults. `update` checks each field of a patch — the
|
|
|
122
137
|
driver's own `UpdateFilter` is intersected with `Document` and accepts any key
|
|
123
138
|
whatsoever, including a typo.
|
|
124
139
|
|
|
140
|
+
## Ids
|
|
141
|
+
|
|
142
|
+
Every document a repository gives back carries `id`: its `_id` as a string. It
|
|
143
|
+
is computed, never stored — the collection holds `_id` alone — and it is an
|
|
144
|
+
ordinary enumerable property, so `JSON.stringify` and a spread carry it and a
|
|
145
|
+
handler can return the document as it is.
|
|
146
|
+
|
|
147
|
+
Because it is not a stored field, nothing can be filtered or patched on it: the
|
|
148
|
+
server would match nothing, and TypeScript refuses it. To go the other way,
|
|
149
|
+
from a string that arrived over HTTP:
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
import { toObjectId, tryObjectId, isValidObjectId, objectIdParam } from '@nxgt/mongo';
|
|
153
|
+
|
|
154
|
+
await repo.getById(toObjectId(params.id)); // an ObjectId, or InvalidIdError
|
|
155
|
+
tryObjectId(params.id); // an ObjectId, or undefined
|
|
156
|
+
isValidObjectId(params.id); // a boolean
|
|
157
|
+
toObjectIds(query.ids); // for a `$in` filter
|
|
158
|
+
|
|
159
|
+
// Or as part of a schema, where the parameters are parsed:
|
|
160
|
+
const route = z.object({ id: objectIdParam() });
|
|
161
|
+
const { id } = route.parse(params); // ObjectId
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Do not call `new ObjectId(value)` on input you did not produce.** Given
|
|
165
|
+
`null` or `undefined` the driver does not throw: it invents a fresh id, so a
|
|
166
|
+
parameter that never arrived becomes a perfectly valid id that matches nothing.
|
|
167
|
+
`toObjectId` throws `InvalidIdError`, which a handler can turn into a 400 or a
|
|
168
|
+
404.
|
|
169
|
+
|
|
125
170
|
## Pagination
|
|
126
171
|
|
|
127
172
|
```ts
|
|
@@ -190,6 +235,7 @@ application never reads a numeric code:
|
|
|
190
235
|
| `ValidationError` | `VALIDATION` | the collection's validator refused it (121) |
|
|
191
236
|
| `OptimisticLockError` | `OPTIMISTIC_LOCK` | `expectedVersion` no longer matches |
|
|
192
237
|
| `InvalidCursorError` | `INVALID_CURSOR` | a cursor this package did not write |
|
|
238
|
+
| `InvalidIdError` | `INVALID_ID` | a value that is no `ObjectId`, nor the string of one |
|
|
193
239
|
| `DataError` | `DATABASE` | any other server error, with its `serverCode` |
|
|
194
240
|
|
|
195
241
|
`ConflictError` carries `index`, `keys` and, when the server gives them,
|
|
@@ -211,6 +257,8 @@ server error reaches you untouched.
|
|
|
211
257
|
| --- | --- |
|
|
212
258
|
| `defineCollection(config)` | a collection: name, schema, indexes, validation |
|
|
213
259
|
| `id`, `objectId`, `timestamps`, `softDelete`, `optimisticLock`, `actors` | the field helpers |
|
|
260
|
+
| `toObjectId`, `toObjectIds`, `tryObjectId`, `objectIdParam` | a string from outside as an `ObjectId` |
|
|
261
|
+
| `isValidObjectId`, `isObjectIdString`, `isObjectId` | the checks behind them |
|
|
214
262
|
| `createRepository(db, definition, options?)` | the typed repository |
|
|
215
263
|
| `syncCollection`, `syncCollections` | create and bring in line, with `dryRun` |
|
|
216
264
|
| `withTransaction(clientOrSession, fn, options?)` | a transaction, joined when nested |
|
|
@@ -255,6 +303,15 @@ server error reaches you untouched.
|
|
|
255
303
|
- **Rebuilding an index drops it first.** MongoDB cannot alter an index in
|
|
256
304
|
place, so `sync` drops and recreates one whose options changed: there is a
|
|
257
305
|
window with no index, and on a large collection the rebuild is not free.
|
|
306
|
+
- **`new ObjectId(undefined)` is a fresh id, not an error.** So is
|
|
307
|
+
`new ObjectId(null)`. A missing route parameter turns into a valid id that
|
|
308
|
+
matches nothing, and the bug surfaces as an empty result rather than as a
|
|
309
|
+
failure. Use `toObjectId`, which throws, or `tryObjectId`, which answers
|
|
310
|
+
`undefined`.
|
|
311
|
+
- **`id` is computed, not stored.** It is on every document a repository
|
|
312
|
+
returns, and on none in the collection: a filter or a patch keyed on it would
|
|
313
|
+
match nothing, so both are compile errors. Query on `_id`. A schema that
|
|
314
|
+
declares an `id` field of its own keeps it, untouched.
|
|
258
315
|
- **`validate: 'off'` also turns the defaults off.** Nothing fills `_id`,
|
|
259
316
|
`createdAt` or `version` any more, because filling them is what parsing does.
|
|
260
317
|
- **The driver retries a transaction's callback** on a transient error, for up
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IndexDescription, ObjectId } from 'mongodb';
|
|
1
|
+
import type { IndexDescription, IndexDirection, ObjectId } from 'mongodb';
|
|
2
2
|
import type { z } from 'zod';
|
|
3
3
|
/** What MongoDB does with a document that fails the validator. */
|
|
4
4
|
export type ValidationAction = 'error' | 'warn';
|
|
@@ -13,6 +13,23 @@ export interface ValidationConfig {
|
|
|
13
13
|
/** Default `'error'`. `'warn'` logs and lets the write through. */
|
|
14
14
|
action?: ValidationAction;
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* What an index may be keyed on: a field of the documents, which an editor
|
|
18
|
+
* completes, or a path into one — `{ 'address.city': 1 }` is how MongoDB
|
|
19
|
+
* indexes a nested field, and there is no way to check the tail of a path
|
|
20
|
+
* against a schema without rejecting the paths Mongo allows.
|
|
21
|
+
*/
|
|
22
|
+
export type IndexKey<Doc> = {
|
|
23
|
+
[Field in (keyof Doc & string) | `${keyof Doc & string}.${string}`]?: IndexDirection;
|
|
24
|
+
} | Map<string, IndexDirection>;
|
|
25
|
+
/**
|
|
26
|
+
* An index, keyed on the schema's own fields. Everything else — `unique`,
|
|
27
|
+
* `name`, `collation`, `partialFilterExpression`, the TTL — is the driver's
|
|
28
|
+
* `IndexDescription`, unchanged.
|
|
29
|
+
*/
|
|
30
|
+
export interface CollectionIndex<Doc> extends Omit<IndexDescription, 'key'> {
|
|
31
|
+
key: IndexKey<Doc>;
|
|
32
|
+
}
|
|
16
33
|
/** What `defineCollection` takes. */
|
|
17
34
|
export interface CollectionConfig<Schema extends z.ZodObject> {
|
|
18
35
|
/** The collection's name on the server. */
|
|
@@ -22,13 +39,16 @@ export interface CollectionConfig<Schema extends z.ZodObject> {
|
|
|
22
39
|
* `z.input` what a write takes. It must have an `_id`.
|
|
23
40
|
*/
|
|
24
41
|
schema: Schema;
|
|
25
|
-
/** The indexes `sync` creates,
|
|
26
|
-
indexes?: readonly
|
|
42
|
+
/** The indexes `sync` creates, keyed on the schema's fields. */
|
|
43
|
+
indexes?: readonly CollectionIndex<z.output<Schema>>[];
|
|
27
44
|
/** The `$jsonSchema` validator `sync` writes from the schema. */
|
|
28
45
|
validation?: ValidationConfig;
|
|
29
46
|
}
|
|
30
47
|
/** A collection, as `defineCollection` returns it: frozen, with its defaults. */
|
|
31
|
-
export interface CollectionDefinition<Schema extends z.ZodObject = z.ZodObject>
|
|
48
|
+
export interface CollectionDefinition<Schema extends z.ZodObject = z.ZodObject> {
|
|
49
|
+
readonly name: string;
|
|
50
|
+
readonly schema: Schema;
|
|
51
|
+
/** As the driver takes them: `sync` hands these straight to MongoDB. */
|
|
32
52
|
readonly indexes: readonly IndexDescription[];
|
|
33
53
|
readonly validation: Required<ValidationConfig>;
|
|
34
54
|
}
|
|
@@ -38,6 +58,18 @@ export type AnyCollectionDefinition = CollectionDefinition<any>;
|
|
|
38
58
|
export type DocumentOf<Def> = Def extends {
|
|
39
59
|
schema: infer Schema;
|
|
40
60
|
} ? Schema extends z.ZodType ? z.output<Schema> : never : never;
|
|
61
|
+
/**
|
|
62
|
+
* A document as a repository gives it back: the stored document, plus `id`.
|
|
63
|
+
*
|
|
64
|
+
* `id` is `_id` as a string, computed rather than stored — the collection
|
|
65
|
+
* holds `_id` alone. It is enumerable, so `JSON.stringify` and a spread carry
|
|
66
|
+
* it, which is what makes a document ready to return from an API; it is not
|
|
67
|
+
* part of `DocumentOf`, so a filter or a patch cannot be keyed on it, because
|
|
68
|
+
* the server would match nothing.
|
|
69
|
+
*/
|
|
70
|
+
export type ReadDocumentOf<Def> = DocumentOf<Def> & {
|
|
71
|
+
readonly id: string;
|
|
72
|
+
};
|
|
41
73
|
/** What a write takes: the documents before their defaults are filled. */
|
|
42
74
|
export type NewDocumentOf<Def> = Def extends {
|
|
43
75
|
schema: infer Schema;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"define-collection.d.ts","sourceRoot":"","sources":["../../src/definition/define-collection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"define-collection.d.ts","sourceRoot":"","sources":["../../src/definition/define-collection.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/definition/fields.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../src/definition/fields.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;GAGG;AACH,wBAAgB,QAAQ,oCAIvB;AAED;;;GAGG;AACH,wBAAgB,EAAE,kDAEjB;AAED;;;GAGG;AACH,wBAAgB,UAAU;;;EAKzB;AAED;;;GAGG;AACH,wBAAgB,UAAU;;EAEzB;AAED;;;;GAIG;AACH,wBAAgB,cAAc;;EAE7B;AAED;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,KAAK,SAAS,CAAC,CAAC,OAAO,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,EAC3E,KAAK,GAAE,KAAsC;;;;EAO7C;AAED,6DAA6D;AAC7D,eAAO,MAAM,YAAY;;;;;;;;;CASf,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { ObjectId } from 'mongodb';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
/**
|
|
4
|
+
* An `ObjectId`, read by its BSON tag rather than with `instanceof`, which
|
|
5
|
+
* answers `false` across two copies of the driver in one tree.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isObjectId(value: unknown): value is ObjectId;
|
|
8
|
+
/** Is this the 24-character hex string an `ObjectId` is written as? */
|
|
9
|
+
export declare function isObjectIdString(value: unknown): value is string;
|
|
10
|
+
/** An `ObjectId`, or a string that stands for one. */
|
|
11
|
+
export declare function isValidObjectId(value: unknown): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* The `ObjectId` this value stands for, or `undefined`. Never throws.
|
|
14
|
+
*
|
|
15
|
+
* Prefer it to `new ObjectId(value)`, which **invents a fresh id** when it is
|
|
16
|
+
* given `null` or `undefined` — a missing route parameter then reads as a
|
|
17
|
+
* perfectly valid id that matches nothing.
|
|
18
|
+
*/
|
|
19
|
+
export declare function tryObjectId(value: unknown): ObjectId | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* The `ObjectId` this value stands for. Throws `InvalidIdError` for anything
|
|
22
|
+
* else, `null` and `undefined` included.
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
25
|
+
* const user = await users.getById(toObjectId(request.params.id));
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function toObjectId(value: unknown, field?: string): ObjectId;
|
|
29
|
+
/**
|
|
30
|
+
* The same, for a list — a `$in` filter built from query parameters.
|
|
31
|
+
*
|
|
32
|
+
* ```ts
|
|
33
|
+
* await users.findMany({ filter: { _id: { $in: toObjectIds(ids) } } });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function toObjectIds(values: Iterable<unknown>, field?: string): ObjectId[];
|
|
37
|
+
/**
|
|
38
|
+
* A Zod schema for an id that arrives from outside: it takes an `ObjectId` or
|
|
39
|
+
* its hex string and gives back an `ObjectId`.
|
|
40
|
+
*
|
|
41
|
+
* It belongs in the schema of a route's parameters, **not** in a collection's:
|
|
42
|
+
* a field that parses one type into another has no honest `$jsonSchema`, and
|
|
43
|
+
* what a collection stores is `objectId()`.
|
|
44
|
+
*
|
|
45
|
+
* ```ts
|
|
46
|
+
* const params = z.object({ id: objectIdParam() });
|
|
47
|
+
* const { id } = params.parse(request.params); // ObjectId
|
|
48
|
+
* ```
|
|
49
|
+
*/
|
|
50
|
+
export declare function objectIdParam(): z.ZodPipe<z.ZodCustom<string | ObjectId, string | ObjectId>, z.ZodTransform<ObjectId, string | ObjectId>>;
|
|
51
|
+
//# sourceMappingURL=object-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"object-id.d.ts","sourceRoot":"","sources":["../../src/definition/object-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAM5D;AAED,uEAAuE;AACvE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAEhE;AAED,sDAAsD;AACtD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEvD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CAIhE;AASD;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAQ,GAAG,QAAQ,CAOlE;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAC1B,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,EACzB,KAAK,SAAQ,GACX,QAAQ,EAAE,CAEZ;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,8GAM5B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** What went wrong, as a string a caller can switch on. */
|
|
2
|
-
export type DataErrorCode = 'DATABASE' | 'NOT_FOUND' | 'CONFLICT' | 'VALIDATION' | 'OPTIMISTIC_LOCK' | 'INVALID_CURSOR';
|
|
2
|
+
export type DataErrorCode = 'DATABASE' | 'NOT_FOUND' | 'CONFLICT' | 'VALIDATION' | 'OPTIMISTIC_LOCK' | 'INVALID_CURSOR' | 'INVALID_ID';
|
|
3
3
|
/** One reason a document failed the collection's `$jsonSchema` validator. */
|
|
4
4
|
export interface ValidationIssue {
|
|
5
5
|
/** The dotted path of the field, empty for the document itself. */
|
|
@@ -83,6 +83,18 @@ export declare class OptimisticLockError extends DataError {
|
|
|
83
83
|
readonly code: "OPTIMISTIC_LOCK";
|
|
84
84
|
constructor(message?: string, options?: DataErrorOptions);
|
|
85
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* A value that is not an `ObjectId` and not the string of one.
|
|
88
|
+
*
|
|
89
|
+
* It is a `DataError` rather than a `TypeError` because it is usually data,
|
|
90
|
+
* not a mistake in the code: an id off a URL or a form reaches `toObjectId`,
|
|
91
|
+
* and a handler wants to answer 400 or 404 rather than crash.
|
|
92
|
+
*/
|
|
93
|
+
export declare class InvalidIdError extends DataError {
|
|
94
|
+
name: string;
|
|
95
|
+
readonly code: "INVALID_ID";
|
|
96
|
+
constructor(message?: string, options?: DataErrorOptions);
|
|
97
|
+
}
|
|
86
98
|
/** A cursor this package did not write, or one for another ordering. */
|
|
87
99
|
export declare class InvalidCursorError extends DataError {
|
|
88
100
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-error.d.ts","sourceRoot":"","sources":["../../src/errors/data-error.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,MAAM,MAAM,aAAa,GACtB,UAAU,GACV,WAAW,GACX,UAAU,GACV,YAAY,GACZ,iBAAiB,GACjB,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"data-error.d.ts","sourceRoot":"","sources":["../../src/errors/data-error.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
export { type AnyCollectionDefinition, type CollectionConfig, type CollectionDefinition, type DocumentOf, defineCollection, type FieldOf, type IdOf, type NewDocumentOf, stampsOf, type ValidationAction, type ValidationConfig, type ValidationLevel, } from './definition/define-collection';
|
|
1
|
+
export { type AnyCollectionDefinition, type CollectionConfig, type CollectionDefinition, type CollectionIndex, type DocumentOf, defineCollection, type FieldOf, type IdOf, type IndexKey, type NewDocumentOf, type ReadDocumentOf, stampsOf, type ValidationAction, type ValidationConfig, type ValidationLevel, } from './definition/define-collection';
|
|
2
2
|
export { actors, id, objectId, optimisticLock, STAMP_FIELDS, softDelete, timestamps, } from './definition/fields';
|
|
3
3
|
export { MONGO_JSON_SCHEMA_KEYWORDS, toMongoJsonSchema, } from './definition/json-schema';
|
|
4
|
-
export {
|
|
4
|
+
export { isObjectId, isObjectIdString, isValidObjectId, objectIdParam, toObjectId, toObjectIds, tryObjectId, } from './definition/object-id';
|
|
5
|
+
export { ConflictError, DataError, type DataErrorCode, type DataErrorOptions, InvalidCursorError, InvalidIdError, NotFoundError, OptimisticLockError, ValidationError, type ValidationIssue, } from './errors/data-error';
|
|
5
6
|
export { toDataError } from './errors/to-data-error';
|
|
6
7
|
export { type CursorPayload, decodeCursor, encodeCursor, } from './pagination/cursor';
|
|
7
8
|
export { type CursorPage, cursorLimit, DEFAULT_MAX_PAGE_SIZE, DEFAULT_PAGE_SIZE, type Page, type PageOptions, type PageWindow, pageWindow, toPage, } from './pagination/page';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,UAAU,EACf,gBAAgB,EAChB,KAAK,OAAO,EACZ,KAAK,IAAI,EACT,KAAK,aAAa,EAClB,QAAQ,EACR,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACpB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACN,MAAM,EACN,EAAE,EACF,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,UAAU,EACV,UAAU,GACV,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,0BAA0B,EAC1B,iBAAiB,GACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,aAAa,EACb,SAAS,EACT,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,kBAAkB,EAClB,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,KAAK,eAAe,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EACN,KAAK,aAAa,EAClB,YAAY,EACZ,YAAY,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,KAAK,UAAU,EACf,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,IAAI,EACT,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,UAAU,EACV,MAAM,GACN,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,YAAY,EACX,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,eAAe,EACf,KAAK,EACL,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,aAAa,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACN,WAAW,EACX,KAAK,SAAS,EACd,YAAY,EACZ,WAAW,EACX,KAAK,eAAe,EACpB,cAAc,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,cAAc,EACd,eAAe,GACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACN,YAAY,EACZ,KAAK,cAAc,EACnB,iBAAiB,EACjB,KAAK,gBAAgB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,KAAK,eAAe,EACpB,eAAe,GACf,MAAM,gCAAgC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,UAAU,EACf,gBAAgB,EAChB,KAAK,OAAO,EACZ,KAAK,IAAI,EACT,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,QAAQ,EACR,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACpB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACN,MAAM,EACN,EAAE,EACF,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,UAAU,EACV,UAAU,GACV,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,0BAA0B,EAC1B,iBAAiB,GACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACN,UAAU,EACV,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,UAAU,EACV,WAAW,EACX,WAAW,GACX,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACN,aAAa,EACb,SAAS,EACT,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,kBAAkB,EAClB,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,KAAK,eAAe,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EACN,KAAK,aAAa,EAClB,YAAY,EACZ,YAAY,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,KAAK,UAAU,EACf,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,KAAK,IAAI,EACT,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,UAAU,EACV,MAAM,GACN,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,YAAY,EACX,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,eAAe,EACf,KAAK,EACL,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,aAAa,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACN,WAAW,EACX,KAAK,SAAS,EACd,YAAY,EACZ,WAAW,EACX,KAAK,eAAe,EACpB,cAAc,GACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,cAAc,EACd,eAAe,GACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACN,YAAY,EACZ,KAAK,cAAc,EACnB,iBAAiB,EACjB,KAAK,gBAAgB,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACN,KAAK,eAAe,EACpB,eAAe,GACf,MAAM,gCAAgC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -26,28 +26,140 @@ function stampsOf(definition) {
|
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
// src/definition/fields.ts
|
|
29
|
+
import { ObjectId as ObjectId2 } from "mongodb";
|
|
30
|
+
import { z as z2 } from "zod";
|
|
31
|
+
|
|
32
|
+
// src/definition/object-id.ts
|
|
29
33
|
import { ObjectId } from "mongodb";
|
|
30
34
|
import { z } from "zod";
|
|
35
|
+
|
|
36
|
+
// src/errors/data-error.ts
|
|
37
|
+
class DataError extends Error {
|
|
38
|
+
constructor(message = "Database error", options = {}) {
|
|
39
|
+
super(message, options.cause === undefined ? undefined : { cause: options.cause });
|
|
40
|
+
this.name = "DataError";
|
|
41
|
+
this.code = "DATABASE";
|
|
42
|
+
this.collection = options.collection;
|
|
43
|
+
this.id = options.id;
|
|
44
|
+
this.serverCode = options.serverCode;
|
|
45
|
+
this.serverCodeName = options.serverCodeName;
|
|
46
|
+
this.index = options.index;
|
|
47
|
+
this.keys = options.keys ?? [];
|
|
48
|
+
this.values = options.values;
|
|
49
|
+
this.issues = options.issues ?? [];
|
|
50
|
+
this.expectedVersion = options.expectedVersion;
|
|
51
|
+
this.actualVersion = options.actualVersion;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
class NotFoundError extends DataError {
|
|
56
|
+
constructor(message = "Not found", options = {}) {
|
|
57
|
+
super(message, options);
|
|
58
|
+
this.name = "NotFoundError";
|
|
59
|
+
this.code = "NOT_FOUND";
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
class ConflictError extends DataError {
|
|
64
|
+
constructor(message = "Duplicate key", options = {}) {
|
|
65
|
+
super(message, { serverCode: 11000, ...options });
|
|
66
|
+
this.name = "ConflictError";
|
|
67
|
+
this.code = "CONFLICT";
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
class ValidationError extends DataError {
|
|
72
|
+
constructor(message = "Document failed validation", options = {}) {
|
|
73
|
+
super(message, { serverCode: 121, ...options });
|
|
74
|
+
this.name = "ValidationError";
|
|
75
|
+
this.code = "VALIDATION";
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
class OptimisticLockError extends DataError {
|
|
80
|
+
constructor(message = "Version conflict", options = {}) {
|
|
81
|
+
super(message, options);
|
|
82
|
+
this.name = "OptimisticLockError";
|
|
83
|
+
this.code = "OPTIMISTIC_LOCK";
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
class InvalidIdError extends DataError {
|
|
88
|
+
constructor(message = "Invalid id", options = {}) {
|
|
89
|
+
super(message, options);
|
|
90
|
+
this.name = "InvalidIdError";
|
|
91
|
+
this.code = "INVALID_ID";
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
class InvalidCursorError extends DataError {
|
|
96
|
+
constructor(message = "Invalid cursor", options = {}) {
|
|
97
|
+
super(message, options);
|
|
98
|
+
this.name = "InvalidCursorError";
|
|
99
|
+
this.code = "INVALID_CURSOR";
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// src/definition/object-id.ts
|
|
104
|
+
var HEX_24 = /^[0-9a-fA-F]{24}$/;
|
|
31
105
|
function isObjectId(value) {
|
|
32
106
|
return typeof value === "object" && value !== null && value._bsontype === "ObjectId";
|
|
33
107
|
}
|
|
108
|
+
function isObjectIdString(value) {
|
|
109
|
+
return typeof value === "string" && HEX_24.test(value);
|
|
110
|
+
}
|
|
111
|
+
function isValidObjectId(value) {
|
|
112
|
+
return isObjectId(value) || isObjectIdString(value);
|
|
113
|
+
}
|
|
114
|
+
function tryObjectId(value) {
|
|
115
|
+
if (isObjectId(value))
|
|
116
|
+
return value;
|
|
117
|
+
if (isObjectIdString(value))
|
|
118
|
+
return ObjectId.createFromHexString(value);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
function describe(value) {
|
|
122
|
+
if (value === null)
|
|
123
|
+
return "null";
|
|
124
|
+
if (value === undefined)
|
|
125
|
+
return "undefined";
|
|
126
|
+
if (typeof value === "string")
|
|
127
|
+
return `the string ${JSON.stringify(value)}`;
|
|
128
|
+
return `a ${typeof value}`;
|
|
129
|
+
}
|
|
130
|
+
function toObjectId(value, field = "_id") {
|
|
131
|
+
const made = tryObjectId(value);
|
|
132
|
+
if (made)
|
|
133
|
+
return made;
|
|
134
|
+
throw new InvalidIdError(`${field}: expected an ObjectId or its 24-character hex string, got ${describe(value)}`, { id: value, keys: [field] });
|
|
135
|
+
}
|
|
136
|
+
function toObjectIds(values, field = "_id") {
|
|
137
|
+
return [...values].map((value) => toObjectId(value, field));
|
|
138
|
+
}
|
|
139
|
+
function objectIdParam() {
|
|
140
|
+
return z.custom(isValidObjectId, {
|
|
141
|
+
error: "must be an ObjectId or its 24-character hex string"
|
|
142
|
+
}).transform((value) => toObjectId(value));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/definition/fields.ts
|
|
34
146
|
function objectId() {
|
|
35
|
-
return
|
|
147
|
+
return z2.custom(isObjectId, { error: "must be an ObjectId" }).meta({ bsonType: "objectId" });
|
|
36
148
|
}
|
|
37
149
|
function id() {
|
|
38
|
-
return objectId().default(() => new
|
|
150
|
+
return objectId().default(() => new ObjectId2);
|
|
39
151
|
}
|
|
40
152
|
function timestamps() {
|
|
41
153
|
return {
|
|
42
|
-
createdAt:
|
|
43
|
-
updatedAt:
|
|
154
|
+
createdAt: z2.date().default(() => new Date),
|
|
155
|
+
updatedAt: z2.date().default(() => new Date)
|
|
44
156
|
};
|
|
45
157
|
}
|
|
46
158
|
function softDelete() {
|
|
47
|
-
return { deletedAt:
|
|
159
|
+
return { deletedAt: z2.date().nullable().default(null) };
|
|
48
160
|
}
|
|
49
161
|
function optimisticLock() {
|
|
50
|
-
return { version:
|
|
162
|
+
return { version: z2.int().nonnegative().default(0) };
|
|
51
163
|
}
|
|
52
164
|
function actors(actor = objectId()) {
|
|
53
165
|
return {
|
|
@@ -67,7 +179,7 @@ var STAMP_FIELDS = {
|
|
|
67
179
|
deletedBy: "deletedBy"
|
|
68
180
|
};
|
|
69
181
|
// src/definition/json-schema.ts
|
|
70
|
-
import { z as
|
|
182
|
+
import { z as z3 } from "zod";
|
|
71
183
|
var MONGO_JSON_SCHEMA_KEYWORDS = new Set([
|
|
72
184
|
"additionalItems",
|
|
73
185
|
"additionalProperties",
|
|
@@ -167,7 +279,7 @@ function inline(value, defs, stack) {
|
|
|
167
279
|
return out;
|
|
168
280
|
}
|
|
169
281
|
function toMongoJsonSchema(schema) {
|
|
170
|
-
const json =
|
|
282
|
+
const json = z3.toJSONSchema(schema, {
|
|
171
283
|
target: "draft-4",
|
|
172
284
|
io: "output",
|
|
173
285
|
unrepresentable: "any",
|
|
@@ -181,64 +293,6 @@ function toMongoJsonSchema(schema) {
|
|
|
181
293
|
const definitions = isRecord(json.definitions) ? json.definitions : isRecord(json.$defs) ? json.$defs : {};
|
|
182
294
|
return inline(json, definitions, []);
|
|
183
295
|
}
|
|
184
|
-
// src/errors/data-error.ts
|
|
185
|
-
class DataError extends Error {
|
|
186
|
-
constructor(message = "Database error", options = {}) {
|
|
187
|
-
super(message, options.cause === undefined ? undefined : { cause: options.cause });
|
|
188
|
-
this.name = "DataError";
|
|
189
|
-
this.code = "DATABASE";
|
|
190
|
-
this.collection = options.collection;
|
|
191
|
-
this.id = options.id;
|
|
192
|
-
this.serverCode = options.serverCode;
|
|
193
|
-
this.serverCodeName = options.serverCodeName;
|
|
194
|
-
this.index = options.index;
|
|
195
|
-
this.keys = options.keys ?? [];
|
|
196
|
-
this.values = options.values;
|
|
197
|
-
this.issues = options.issues ?? [];
|
|
198
|
-
this.expectedVersion = options.expectedVersion;
|
|
199
|
-
this.actualVersion = options.actualVersion;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
class NotFoundError extends DataError {
|
|
204
|
-
constructor(message = "Not found", options = {}) {
|
|
205
|
-
super(message, options);
|
|
206
|
-
this.name = "NotFoundError";
|
|
207
|
-
this.code = "NOT_FOUND";
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
class ConflictError extends DataError {
|
|
212
|
-
constructor(message = "Duplicate key", options = {}) {
|
|
213
|
-
super(message, { serverCode: 11000, ...options });
|
|
214
|
-
this.name = "ConflictError";
|
|
215
|
-
this.code = "CONFLICT";
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
class ValidationError extends DataError {
|
|
220
|
-
constructor(message = "Document failed validation", options = {}) {
|
|
221
|
-
super(message, { serverCode: 121, ...options });
|
|
222
|
-
this.name = "ValidationError";
|
|
223
|
-
this.code = "VALIDATION";
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
class OptimisticLockError extends DataError {
|
|
228
|
-
constructor(message = "Version conflict", options = {}) {
|
|
229
|
-
super(message, options);
|
|
230
|
-
this.name = "OptimisticLockError";
|
|
231
|
-
this.code = "OPTIMISTIC_LOCK";
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
class InvalidCursorError extends DataError {
|
|
236
|
-
constructor(message = "Invalid cursor", options = {}) {
|
|
237
|
-
super(message, options);
|
|
238
|
-
this.name = "InvalidCursorError";
|
|
239
|
-
this.code = "INVALID_CURSOR";
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
296
|
// src/errors/to-data-error.ts
|
|
243
297
|
function isRecord2(value) {
|
|
244
298
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -344,7 +398,7 @@ function toDataError(error, context = {}) {
|
|
|
344
398
|
return new DataError(message || `MongoDB error ${code}`, common);
|
|
345
399
|
}
|
|
346
400
|
// src/pagination/cursor.ts
|
|
347
|
-
import { ObjectId as
|
|
401
|
+
import { ObjectId as ObjectId3 } from "mongodb";
|
|
348
402
|
function isObjectId2(value) {
|
|
349
403
|
return typeof value === "object" && value !== null && value._bsontype === "ObjectId";
|
|
350
404
|
}
|
|
@@ -368,7 +422,7 @@ function reviver(_key, value) {
|
|
|
368
422
|
if (typeof tagged.$bigint === "string")
|
|
369
423
|
return BigInt(tagged.$bigint);
|
|
370
424
|
if (typeof tagged.$oid === "string")
|
|
371
|
-
return new
|
|
425
|
+
return new ObjectId3(tagged.$oid);
|
|
372
426
|
}
|
|
373
427
|
}
|
|
374
428
|
return value;
|
|
@@ -678,6 +732,7 @@ function build(db, definition, options) {
|
|
|
678
732
|
const name = definition.name;
|
|
679
733
|
const collection = db.collection(name);
|
|
680
734
|
const shape = definition.schema.shape;
|
|
735
|
+
const hasOwnId = "id" in shape;
|
|
681
736
|
const stamps = stampsOf(definition);
|
|
682
737
|
const session = options.session;
|
|
683
738
|
const actor = options.actor;
|
|
@@ -702,6 +757,17 @@ function build(db, definition, options) {
|
|
|
702
757
|
const sessionOption = session ? { session } : {};
|
|
703
758
|
const live = (withDeleted) => softDeletes && !withDeleted ? { deletedAt: null } : undefined;
|
|
704
759
|
const scoped = (filter, withDeleted) => mergeFilters(isRecord3(filter) ? filter : undefined, live(withDeleted));
|
|
760
|
+
const withId = (document) => {
|
|
761
|
+
if (hasOwnId || !isRecord3(document) || document._id === undefined || Object.hasOwn(document, "id")) {
|
|
762
|
+
return document;
|
|
763
|
+
}
|
|
764
|
+
Object.defineProperty(document, "id", {
|
|
765
|
+
get: () => String(document._id),
|
|
766
|
+
enumerable: true,
|
|
767
|
+
configurable: true
|
|
768
|
+
});
|
|
769
|
+
return document;
|
|
770
|
+
};
|
|
705
771
|
const notFound = (id) => new NotFoundError(`No document in "${name}" with _id ${String(id)}`, {
|
|
706
772
|
collection: name,
|
|
707
773
|
id
|
|
@@ -713,6 +779,8 @@ function build(db, definition, options) {
|
|
|
713
779
|
};
|
|
714
780
|
const toDocument = (values) => {
|
|
715
781
|
const stamped = { ...values };
|
|
782
|
+
if (!hasOwnId)
|
|
783
|
+
delete stamped.id;
|
|
716
784
|
if (actor !== undefined) {
|
|
717
785
|
if (stamps.createdBy && stamped.createdBy === undefined) {
|
|
718
786
|
stamped.createdBy = actor;
|
|
@@ -754,10 +822,13 @@ function build(db, definition, options) {
|
|
|
754
822
|
}
|
|
755
823
|
return update;
|
|
756
824
|
};
|
|
757
|
-
const findOne = async (filter, projection) => run(async () =>
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
825
|
+
const findOne = async (filter, projection) => run(async () => {
|
|
826
|
+
const found = await collection.findOne(filter, {
|
|
827
|
+
...sessionOption,
|
|
828
|
+
...projection ? { projection } : {}
|
|
829
|
+
});
|
|
830
|
+
return found === null ? null : withId(found);
|
|
831
|
+
});
|
|
761
832
|
async function findById(id, opts = {}) {
|
|
762
833
|
const found = await findOne(scoped({ _id: id }, opts.withDeleted));
|
|
763
834
|
return found ?? undefined;
|
|
@@ -780,7 +851,8 @@ function build(db, definition, options) {
|
|
|
780
851
|
cursor = cursor.skip(opts.skip);
|
|
781
852
|
if (opts.limit !== undefined)
|
|
782
853
|
cursor = cursor.limit(opts.limit);
|
|
783
|
-
|
|
854
|
+
const found = await cursor.toArray();
|
|
855
|
+
return found.map((document) => withId(document));
|
|
784
856
|
});
|
|
785
857
|
}
|
|
786
858
|
async function countDocuments(filter, opts = {}) {
|
|
@@ -794,7 +866,7 @@ function build(db, definition, options) {
|
|
|
794
866
|
returnDocument: "after"
|
|
795
867
|
}));
|
|
796
868
|
if (updated)
|
|
797
|
-
return updated;
|
|
869
|
+
return withId(updated);
|
|
798
870
|
if (expectedVersion !== undefined) {
|
|
799
871
|
const current = await findOne({ _id: id });
|
|
800
872
|
if (current) {
|
|
@@ -812,7 +884,7 @@ function build(db, definition, options) {
|
|
|
812
884
|
const deleted = await run(async () => collection.findOneAndDelete({ _id: id }, { ...sessionOption }));
|
|
813
885
|
if (!deleted)
|
|
814
886
|
throw notFound(id);
|
|
815
|
-
return deleted;
|
|
887
|
+
return withId(deleted);
|
|
816
888
|
}
|
|
817
889
|
async function hardDeleteMany(filter) {
|
|
818
890
|
requireFilter("hardDeleteMany", filter);
|
|
@@ -842,7 +914,7 @@ function build(db, definition, options) {
|
|
|
842
914
|
const document = toDocument(values);
|
|
843
915
|
return run(async () => {
|
|
844
916
|
await collection.insertOne(document, { ...sessionOption });
|
|
845
|
-
return document;
|
|
917
|
+
return withId(document);
|
|
846
918
|
});
|
|
847
919
|
},
|
|
848
920
|
async createMany(values) {
|
|
@@ -853,7 +925,7 @@ function build(db, definition, options) {
|
|
|
853
925
|
await collection.insertMany(documents, {
|
|
854
926
|
...sessionOption
|
|
855
927
|
});
|
|
856
|
-
return documents;
|
|
928
|
+
return documents.map((document) => withId(document));
|
|
857
929
|
});
|
|
858
930
|
},
|
|
859
931
|
async update(id, patch, opts = {}) {
|
|
@@ -1021,6 +1093,7 @@ export {
|
|
|
1021
1093
|
DEFAULT_PAGE_SIZE,
|
|
1022
1094
|
DataError,
|
|
1023
1095
|
InvalidCursorError,
|
|
1096
|
+
InvalidIdError,
|
|
1024
1097
|
MONGO_JSON_SCHEMA_KEYWORDS,
|
|
1025
1098
|
NotFoundError,
|
|
1026
1099
|
OptimisticLockError,
|
|
@@ -1037,8 +1110,12 @@ export {
|
|
|
1037
1110
|
id,
|
|
1038
1111
|
indexMatches,
|
|
1039
1112
|
indexNameOf,
|
|
1113
|
+
isObjectId,
|
|
1114
|
+
isObjectIdString,
|
|
1115
|
+
isValidObjectId,
|
|
1040
1116
|
normalizeIndex,
|
|
1041
1117
|
objectId,
|
|
1118
|
+
objectIdParam,
|
|
1042
1119
|
optimisticLock,
|
|
1043
1120
|
pageWindow,
|
|
1044
1121
|
softDelete,
|
|
@@ -1048,10 +1125,13 @@ export {
|
|
|
1048
1125
|
timestamps,
|
|
1049
1126
|
toDataError,
|
|
1050
1127
|
toMongoJsonSchema,
|
|
1128
|
+
toObjectId,
|
|
1129
|
+
toObjectIds,
|
|
1051
1130
|
toPage,
|
|
1131
|
+
tryObjectId,
|
|
1052
1132
|
validationMatches,
|
|
1053
1133
|
withTransaction
|
|
1054
1134
|
};
|
|
1055
1135
|
|
|
1056
|
-
//# debugId=
|
|
1136
|
+
//# debugId=5C569B791BADEA5664756E2164756E21
|
|
1057
1137
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/definition/define-collection.ts", "../src/definition/fields.ts", "../src/definition/
|
|
3
|
+
"sources": ["../src/definition/define-collection.ts", "../src/definition/fields.ts", "../src/definition/object-id.ts", "../src/errors/data-error.ts", "../src/definition/json-schema.ts", "../src/errors/to-data-error.ts", "../src/pagination/cursor.ts", "../src/pagination/page.ts", "../src/sync/index-diff.ts", "../src/sync/validator-diff.ts", "../src/sync/sync-collection.ts", "../src/repository/create-repository.ts", "../src/transaction/with-transaction.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"import type { IndexDescription, ObjectId } from 'mongodb';\nimport type { z } from 'zod';\n\n/** What MongoDB does with a document that fails the validator. */\nexport type ValidationAction = 'error' | 'warn';\n\n/**\n * Which documents the validator applies to. `off` writes no validator at all;\n * `moderate` exempts documents that were already invalid from updates.\n */\nexport type ValidationLevel = 'off' | 'moderate' | 'strict';\n\nexport interface ValidationConfig {\n\t/** Default `'strict'`. */\n\tlevel?: ValidationLevel;\n\t/** Default `'error'`. `'warn'` logs and lets the write through. */\n\taction?: ValidationAction;\n}\n\n/** What `defineCollection` takes. */\nexport interface CollectionConfig<Schema extends z.ZodObject> {\n\t/** The collection's name on the server. */\n\tname: string;\n\t/**\n\t * The documents, as they are stored: `z.output` is what a read gives back,\n\t * `z.input` what a write takes. It must have an `_id`.\n\t */\n\tschema: Schema;\n\t/** The indexes `sync` creates,
|
|
6
|
-
"import { ObjectId } from 'mongodb';\nimport { z } from 'zod';\
|
|
5
|
+
"import type { IndexDescription, IndexDirection, ObjectId } from 'mongodb';\nimport type { z } from 'zod';\n\n/** What MongoDB does with a document that fails the validator. */\nexport type ValidationAction = 'error' | 'warn';\n\n/**\n * Which documents the validator applies to. `off` writes no validator at all;\n * `moderate` exempts documents that were already invalid from updates.\n */\nexport type ValidationLevel = 'off' | 'moderate' | 'strict';\n\nexport interface ValidationConfig {\n\t/** Default `'strict'`. */\n\tlevel?: ValidationLevel;\n\t/** Default `'error'`. `'warn'` logs and lets the write through. */\n\taction?: ValidationAction;\n}\n\n/**\n * What an index may be keyed on: a field of the documents, which an editor\n * completes, or a path into one — `{ 'address.city': 1 }` is how MongoDB\n * indexes a nested field, and there is no way to check the tail of a path\n * against a schema without rejecting the paths Mongo allows.\n */\nexport type IndexKey<Doc> =\n\t| {\n\t\t\t[Field in\n\t\t\t\t| (keyof Doc & string)\n\t\t\t\t| `${keyof Doc & string}.${string}`]?: IndexDirection;\n\t }\n\t// The driver takes a `Map` too, and an index read back off the server comes\n\t// as one: refusing it here would refuse a definition built from a live one.\n\t| Map<string, IndexDirection>;\n\n/**\n * An index, keyed on the schema's own fields. Everything else — `unique`,\n * `name`, `collation`, `partialFilterExpression`, the TTL — is the driver's\n * `IndexDescription`, unchanged.\n */\nexport interface CollectionIndex<Doc> extends Omit<IndexDescription, 'key'> {\n\tkey: IndexKey<Doc>;\n}\n\n/** What `defineCollection` takes. */\nexport interface CollectionConfig<Schema extends z.ZodObject> {\n\t/** The collection's name on the server. */\n\tname: string;\n\t/**\n\t * The documents, as they are stored: `z.output` is what a read gives back,\n\t * `z.input` what a write takes. It must have an `_id`.\n\t */\n\tschema: Schema;\n\t/** The indexes `sync` creates, keyed on the schema's fields. */\n\tindexes?: readonly CollectionIndex<z.output<Schema>>[];\n\t/** The `$jsonSchema` validator `sync` writes from the schema. */\n\tvalidation?: ValidationConfig;\n}\n\n/** A collection, as `defineCollection` returns it: frozen, with its defaults. */\nexport interface CollectionDefinition<\n\tSchema extends z.ZodObject = z.ZodObject,\n> {\n\treadonly name: string;\n\treadonly schema: Schema;\n\t/** As the driver takes them: `sync` hands these straight to MongoDB. */\n\treadonly indexes: readonly IndexDescription[];\n\treadonly validation: Required<ValidationConfig>;\n}\n\n/** Any definition, whatever its documents. */\nexport type AnyCollectionDefinition = CollectionDefinition<any>;\n\n/** The documents of a definition, as they are read back. */\nexport type DocumentOf<Def> = Def extends { schema: infer Schema }\n\t? Schema extends z.ZodType\n\t\t? z.output<Schema>\n\t\t: never\n\t: never;\n\n/**\n * A document as a repository gives it back: the stored document, plus `id`.\n *\n * `id` is `_id` as a string, computed rather than stored — the collection\n * holds `_id` alone. It is enumerable, so `JSON.stringify` and a spread carry\n * it, which is what makes a document ready to return from an API; it is not\n * part of `DocumentOf`, so a filter or a patch cannot be keyed on it, because\n * the server would match nothing.\n */\nexport type ReadDocumentOf<Def> = DocumentOf<Def> & { readonly id: string };\n\n/** What a write takes: the documents before their defaults are filled. */\nexport type NewDocumentOf<Def> = Def extends { schema: infer Schema }\n\t? Schema extends z.ZodType\n\t\t? z.input<Schema>\n\t\t: never\n\t: never;\n\n/** The type of `_id`. */\nexport type IdOf<Def> =\n\tDocumentOf<Def> extends { _id: infer Id } ? Id : ObjectId;\n\n/** A field of the documents, as a top-level key. */\nexport type FieldOf<Def> = keyof DocumentOf<Def> & string;\n\n/**\n * Defines a collection: its name, the Zod schema of its documents, its\n * indexes, and how its validator is applied.\n *\n * The schema is the one source: it types every read and write, and `sync`\n * derives the collection's `$jsonSchema` validator from it.\n *\n * ```ts\n * export const users = defineCollection({\n * \tname: 'users',\n * \tschema: z.object({\n * \t\t_id: id(),\n * \t\temail: z.email(),\n * \t\t...timestamps(),\n * \t\t...softDelete(),\n * \t}),\n * \tindexes: [{ key: { email: 1 }, unique: true, name: 'users_email_unique' }],\n * });\n * ```\n */\nexport function defineCollection<Schema extends z.ZodObject>(\n\tconfig: CollectionConfig<Schema>,\n): CollectionDefinition<Schema> {\n\tif (!('_id' in config.schema.shape)) {\n\t\tthrow new TypeError(\n\t\t\t`defineCollection: \"${config.name}\"'s schema has no _id. Add ` +\n\t\t\t\t'`_id: id()`, which fills a new ObjectId on create, or declare the ' +\n\t\t\t\t'key your documents use.',\n\t\t);\n\t}\n\treturn Object.freeze({\n\t\t...config,\n\t\tindexes: Object.freeze([...(config.indexes ?? [])]),\n\t\tvalidation: Object.freeze({\n\t\t\tlevel: config.validation?.level ?? 'strict',\n\t\t\taction: config.validation?.action ?? 'error',\n\t\t}),\n\t}) as CollectionDefinition<Schema>;\n}\n\n/** Which of the fields the repository knows about a definition's schema has. */\nexport function stampsOf(definition: AnyCollectionDefinition): {\n\tcreatedAt: boolean;\n\tupdatedAt: boolean;\n\tdeletedAt: boolean;\n\tversion: boolean;\n\tcreatedBy: boolean;\n\tupdatedBy: boolean;\n\tdeletedBy: boolean;\n} {\n\tconst shape = definition.schema.shape as Record<string, unknown>;\n\tconst has = (name: string) => name in shape;\n\treturn {\n\t\tcreatedAt: has('createdAt'),\n\t\tupdatedAt: has('updatedAt'),\n\t\tdeletedAt: has('deletedAt'),\n\t\tversion: has('version'),\n\t\tcreatedBy: has('createdBy'),\n\t\tupdatedBy: has('updatedBy'),\n\t\tdeletedBy: has('deletedBy'),\n\t};\n}\n",
|
|
6
|
+
"import { ObjectId } from 'mongodb';\nimport { z } from 'zod';\nimport { isObjectId } from './object-id';\n\n/**\n * An `ObjectId`, declared to MongoDB as `bsonType: 'objectId'`. JSON Schema\n * has no type for one, so the metadata is how the validator learns of it.\n */\nexport function objectId() {\n\treturn z\n\t\t.custom<ObjectId>(isObjectId, { error: 'must be an ObjectId' })\n\t\t.meta({ bsonType: 'objectId' });\n}\n\n/**\n * `_id`, filled with a new `ObjectId` when a document is created: optional to\n * write, always there once read.\n */\nexport function id() {\n\treturn objectId().default(() => new ObjectId());\n}\n\n/**\n * `createdAt` and `updatedAt`, filled on create. A repository sets `updatedAt`\n * on every update.\n */\nexport function timestamps() {\n\treturn {\n\t\tcreatedAt: z.date().default(() => new Date()),\n\t\tupdatedAt: z.date().default(() => new Date()),\n\t};\n}\n\n/**\n * `deletedAt`, `null` while the document is live. A repository on a collection\n * with it soft-deletes, and leaves deleted documents out of every read.\n */\nexport function softDelete() {\n\treturn { deletedAt: z.date().nullable().default(null) };\n}\n\n/**\n * `version`, raised by one on every update. A repository with it takes\n * `expectedVersion` and throws `OptimisticLockError` when it no longer\n * matches.\n */\nexport function optimisticLock() {\n\treturn { version: z.int().nonnegative().default(0) };\n}\n\n/**\n * `createdBy`, `updatedBy` and `deletedBy`, stamped from the actor a\n * repository was given with `as(actor)`. The actor's own type is the schema\n * passed in, an `ObjectId` by default.\n */\nexport function actors<Actor extends z.ZodType = ReturnType<typeof objectId>>(\n\tactor: Actor = objectId() as unknown as Actor,\n) {\n\treturn {\n\t\tcreatedBy: actor.nullable().default(null),\n\t\tupdatedBy: actor.nullable().default(null),\n\t\tdeletedBy: actor.nullable().default(null),\n\t};\n}\n\n/** The fields the repository gives a meaning to, by name. */\nexport const STAMP_FIELDS = {\n\tid: '_id',\n\tcreatedAt: 'createdAt',\n\tupdatedAt: 'updatedAt',\n\tdeletedAt: 'deletedAt',\n\tversion: 'version',\n\tcreatedBy: 'createdBy',\n\tupdatedBy: 'updatedBy',\n\tdeletedBy: 'deletedBy',\n} as const;\n",
|
|
7
|
+
"import { ObjectId } from 'mongodb';\nimport { z } from 'zod';\nimport { InvalidIdError } from '../errors/data-error';\n\n/** The 24 hex characters an `ObjectId` is written as. */\nconst HEX_24 = /^[0-9a-fA-F]{24}$/;\n\n/**\n * An `ObjectId`, read by its BSON tag rather than with `instanceof`, which\n * answers `false` across two copies of the driver in one tree.\n */\nexport function isObjectId(value: unknown): value is ObjectId {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t(value as { _bsontype?: unknown })._bsontype === 'ObjectId'\n\t);\n}\n\n/** Is this the 24-character hex string an `ObjectId` is written as? */\nexport function isObjectIdString(value: unknown): value is string {\n\treturn typeof value === 'string' && HEX_24.test(value);\n}\n\n/** An `ObjectId`, or a string that stands for one. */\nexport function isValidObjectId(value: unknown): boolean {\n\treturn isObjectId(value) || isObjectIdString(value);\n}\n\n/**\n * The `ObjectId` this value stands for, or `undefined`. Never throws.\n *\n * Prefer it to `new ObjectId(value)`, which **invents a fresh id** when it is\n * given `null` or `undefined` — a missing route parameter then reads as a\n * perfectly valid id that matches nothing.\n */\nexport function tryObjectId(value: unknown): ObjectId | undefined {\n\tif (isObjectId(value)) return value;\n\tif (isObjectIdString(value)) return ObjectId.createFromHexString(value);\n\treturn undefined;\n}\n\nfunction describe(value: unknown): string {\n\tif (value === null) return 'null';\n\tif (value === undefined) return 'undefined';\n\tif (typeof value === 'string') return `the string ${JSON.stringify(value)}`;\n\treturn `a ${typeof value}`;\n}\n\n/**\n * The `ObjectId` this value stands for. Throws `InvalidIdError` for anything\n * else, `null` and `undefined` included.\n *\n * ```ts\n * const user = await users.getById(toObjectId(request.params.id));\n * ```\n */\nexport function toObjectId(value: unknown, field = '_id'): ObjectId {\n\tconst made = tryObjectId(value);\n\tif (made) return made;\n\tthrow new InvalidIdError(\n\t\t`${field}: expected an ObjectId or its 24-character hex string, got ${describe(value)}`,\n\t\t{ id: value, keys: [field] },\n\t);\n}\n\n/**\n * The same, for a list — a `$in` filter built from query parameters.\n *\n * ```ts\n * await users.findMany({ filter: { _id: { $in: toObjectIds(ids) } } });\n * ```\n */\nexport function toObjectIds(\n\tvalues: Iterable<unknown>,\n\tfield = '_id',\n): ObjectId[] {\n\treturn [...values].map((value) => toObjectId(value, field));\n}\n\n/**\n * A Zod schema for an id that arrives from outside: it takes an `ObjectId` or\n * its hex string and gives back an `ObjectId`.\n *\n * It belongs in the schema of a route's parameters, **not** in a collection's:\n * a field that parses one type into another has no honest `$jsonSchema`, and\n * what a collection stores is `objectId()`.\n *\n * ```ts\n * const params = z.object({ id: objectIdParam() });\n * const { id } = params.parse(request.params); // ObjectId\n * ```\n */\nexport function objectIdParam() {\n\treturn z\n\t\t.custom<ObjectId | string>(isValidObjectId, {\n\t\t\terror: 'must be an ObjectId or its 24-character hex string',\n\t\t})\n\t\t.transform((value) => toObjectId(value));\n}\n",
|
|
8
|
+
"/** What went wrong, as a string a caller can switch on. */\nexport type DataErrorCode =\n\t| 'DATABASE'\n\t| 'NOT_FOUND'\n\t| 'CONFLICT'\n\t| 'VALIDATION'\n\t| 'OPTIMISTIC_LOCK'\n\t| 'INVALID_CURSOR'\n\t| 'INVALID_ID';\n\n/** One reason a document failed the collection's `$jsonSchema` validator. */\nexport interface ValidationIssue {\n\t/** The dotted path of the field, empty for the document itself. */\n\tpath: string;\n\t/** The rule it broke: `bsonType`, `required`, `minimum`… */\n\treason: string;\n\t/** What the schema asked for, as MongoDB reports it. */\n\tspecifiedAs?: unknown;\n\t/** The value that was refused, when the server names it. */\n\tconsideredValue?: unknown;\n\t/** Its BSON type, when the server names it: `string`, `int`, `double`… */\n\tconsideredType?: string;\n\t/** The schema's `description` for the field, when it has one. */\n\tdescription?: string;\n}\n\nexport interface DataErrorOptions {\n\tcollection?: string | undefined;\n\t/** The `_id` a method by id was given. */\n\tid?: unknown;\n\t/** MongoDB's numeric error code: 11000, 121, 26… */\n\tserverCode?: number | undefined;\n\t/** MongoDB's `codeName`, which write errors do not carry. */\n\tserverCodeName?: string | undefined;\n\t/** The index a conflict names, when the server names one. */\n\tindex?: string | undefined;\n\t/** The fields the error is about: an index's keys, or a validator's paths. */\n\tkeys?: string[];\n\t/** Those fields' values, when the server gives them. */\n\tvalues?: Record<string, unknown> | undefined;\n\tissues?: ValidationIssue[];\n\texpectedVersion?: number | undefined;\n\tactualVersion?: number | undefined;\n\tcause?: unknown;\n}\n\n/**\n * What this package throws. Every method turns a driver error into one of\n * these, so an application catches `ConflictError` instead of reading `11000`\n * off an error whose shape changes with the operation that produced it.\n *\n * A driver error that is none of them reaches the caller as it is.\n */\nexport class DataError extends Error {\n\toverride name = 'DataError';\n\treadonly code: DataErrorCode = 'DATABASE';\n\treadonly collection: string | undefined;\n\treadonly id: unknown;\n\treadonly serverCode: number | undefined;\n\treadonly serverCodeName: string | undefined;\n\treadonly index: string | undefined;\n\treadonly keys: string[];\n\treadonly values: Record<string, unknown> | undefined;\n\treadonly issues: ValidationIssue[];\n\treadonly expectedVersion: number | undefined;\n\treadonly actualVersion: number | undefined;\n\n\tconstructor(message = 'Database error', options: DataErrorOptions = {}) {\n\t\tsuper(\n\t\t\tmessage,\n\t\t\toptions.cause === undefined ? undefined : { cause: options.cause },\n\t\t);\n\t\tthis.collection = options.collection;\n\t\tthis.id = options.id;\n\t\tthis.serverCode = options.serverCode;\n\t\tthis.serverCodeName = options.serverCodeName;\n\t\tthis.index = options.index;\n\t\tthis.keys = options.keys ?? [];\n\t\tthis.values = options.values;\n\t\tthis.issues = options.issues ?? [];\n\t\tthis.expectedVersion = options.expectedVersion;\n\t\tthis.actualVersion = options.actualVersion;\n\t}\n}\n\n/** No document matched, where one was required. */\nexport class NotFoundError extends DataError {\n\toverride name = 'NotFoundError';\n\toverride readonly code = 'NOT_FOUND' as const;\n\n\tconstructor(message = 'Not found', options: DataErrorOptions = {}) {\n\t\tsuper(message, options);\n\t}\n}\n\n/** A unique index refused the write: MongoDB's `E11000`. */\nexport class ConflictError extends DataError {\n\toverride name = 'ConflictError';\n\toverride readonly code = 'CONFLICT' as const;\n\n\tconstructor(message = 'Duplicate key', options: DataErrorOptions = {}) {\n\t\tsuper(message, { serverCode: 11000, ...options });\n\t}\n}\n\n/** The collection's `$jsonSchema` validator refused the document: code 121. */\nexport class ValidationError extends DataError {\n\toverride name = 'ValidationError';\n\toverride readonly code = 'VALIDATION' as const;\n\n\tconstructor(\n\t\tmessage = 'Document failed validation',\n\t\toptions: DataErrorOptions = {},\n\t) {\n\t\tsuper(message, { serverCode: 121, ...options });\n\t}\n}\n\n/**\n * The document changed since it was read: its `version` is no longer the one\n * the update expected, and nothing was written.\n */\nexport class OptimisticLockError extends DataError {\n\toverride name = 'OptimisticLockError';\n\toverride readonly code = 'OPTIMISTIC_LOCK' as const;\n\n\tconstructor(message = 'Version conflict', options: DataErrorOptions = {}) {\n\t\tsuper(message, options);\n\t}\n}\n\n/**\n * A value that is not an `ObjectId` and not the string of one.\n *\n * It is a `DataError` rather than a `TypeError` because it is usually data,\n * not a mistake in the code: an id off a URL or a form reaches `toObjectId`,\n * and a handler wants to answer 400 or 404 rather than crash.\n */\nexport class InvalidIdError extends DataError {\n\toverride name = 'InvalidIdError';\n\toverride readonly code = 'INVALID_ID' as const;\n\n\tconstructor(message = 'Invalid id', options: DataErrorOptions = {}) {\n\t\tsuper(message, options);\n\t}\n}\n\n/** A cursor this package did not write, or one for another ordering. */\nexport class InvalidCursorError extends DataError {\n\toverride name = 'InvalidCursorError';\n\toverride readonly code = 'INVALID_CURSOR' as const;\n\n\tconstructor(message = 'Invalid cursor', options: DataErrorOptions = {}) {\n\t\tsuper(message, options);\n\t}\n}\n",
|
|
7
9
|
"import { z } from 'zod';\n\n/**\n * Every keyword MongoDB's `$jsonSchema` knows. It **rejects** a document that\n * uses any other, rather than ignoring it, so anything not in here is dropped\n * on the way out.\n */\nexport const MONGO_JSON_SCHEMA_KEYWORDS: ReadonlySet<string> = new Set([\n\t'additionalItems',\n\t'additionalProperties',\n\t'allOf',\n\t'anyOf',\n\t'bsonType',\n\t'dependencies',\n\t'description',\n\t'enum',\n\t'exclusiveMaximum',\n\t'exclusiveMinimum',\n\t'items',\n\t'maxItems',\n\t'maxLength',\n\t'maxProperties',\n\t'maximum',\n\t'minItems',\n\t'minLength',\n\t'minProperties',\n\t'minimum',\n\t'multipleOf',\n\t'not',\n\t'oneOf',\n\t'pattern',\n\t'patternProperties',\n\t'properties',\n\t'required',\n\t'title',\n\t'type',\n\t'uniqueItems',\n]);\n\n/** Keywords whose value is a map of names to schemas, not a schema. */\nconst SCHEMA_MAPS = new Set([\n\t'properties',\n\t'patternProperties',\n\t'dependencies',\n]);\n\ntype Node = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is Node {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * A JavaScript number reaches BSON as an `int` when it is a whole number that\n * fits in 32 bits, and as a `double` otherwise — never as a `long`, unless the\n * caller wrapped it. `type: \"integer\"`, which MongoDB has no equivalent for,\n * therefore becomes the three types a whole number can arrive as, with\n * `multipleOf: 1` to refuse a fractional double.\n */\nconst INTEGER_BSON_TYPES = ['int', 'long', 'double'];\n\nfunction convertIntegerType(node: Node): void {\n\tconst type = node.type;\n\tif (type === 'integer') {\n\t\tdelete node.type;\n\t\tnode.bsonType = [...INTEGER_BSON_TYPES];\n\t\tnode.multipleOf ??= 1;\n\t\treturn;\n\t}\n\tif (Array.isArray(type) && type.includes('integer')) {\n\t\tdelete node.type;\n\t\tnode.bsonType = [\n\t\t\t...type.filter((one) => one !== 'integer'),\n\t\t\t...INTEGER_BSON_TYPES,\n\t\t];\n\t\tnode.multipleOf ??= 1;\n\t}\n}\n\nfunction refName(ref: string): string {\n\treturn ref.replace(/^#\\/(definitions|\\$defs)\\//, '');\n}\n\nfunction inline(value: unknown, defs: Node, stack: string[]): unknown {\n\tif (Array.isArray(value)) {\n\t\treturn value.map((one) => inline(one, defs, stack));\n\t}\n\tif (!isRecord(value)) return value;\n\n\tif (typeof value.$ref === 'string') {\n\t\tconst name = refName(value.$ref);\n\t\tif (stack.includes(name)) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`toMongoJsonSchema: \"${name}\" refers to itself. MongoDB's $jsonSchema ` +\n\t\t\t\t\t'has no $ref, so a recursive schema cannot be a validator. Give the ' +\n\t\t\t\t\t'collection no validator, or model the field as an object with no ' +\n\t\t\t\t\t'schema of its own.',\n\t\t\t);\n\t\t}\n\t\tconst target = defs[name];\n\t\tif (!isRecord(target)) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`toMongoJsonSchema: cannot resolve ${value.$ref}, which zod emitted`,\n\t\t\t);\n\t\t}\n\t\tconst { $ref: _ref, ...siblings } = value;\n\t\treturn {\n\t\t\t...(inline(target, defs, [...stack, name]) as Node),\n\t\t\t...(inline(siblings, defs, stack) as Node),\n\t\t};\n\t}\n\n\tconst out: Node = {};\n\tfor (const [key, inner] of Object.entries(value)) {\n\t\tif (!MONGO_JSON_SCHEMA_KEYWORDS.has(key)) continue;\n\t\tif (SCHEMA_MAPS.has(key) && isRecord(inner)) {\n\t\t\tconst mapped: Node = {};\n\t\t\tfor (const [name, schema] of Object.entries(inner)) {\n\t\t\t\tmapped[name] = inline(schema, defs, stack);\n\t\t\t}\n\t\t\tout[key] = mapped;\n\t\t\tcontinue;\n\t\t}\n\t\tout[key] = inline(inner, defs, stack);\n\t}\n\tconvertIntegerType(out);\n\treturn out;\n}\n\n/**\n * A Zod schema as a MongoDB `$jsonSchema`, ready for a collection's validator.\n *\n * `z.toJSONSchema` alone is not one: MongoDB rejects `$schema`, `$ref`,\n * `definitions`, `default`, `format` and `id`, has no `integer` type, and\n * treats a keyword it does not know as an error rather than ignoring it. This\n * resolves every `$ref` by inlining it, keeps only the keywords MongoDB\n * knows, and maps `integer`.\n *\n * `Date` and `ObjectId` have no JSON Schema type: they are declared with\n * `bsonType`, which `date()` and `objectId()` already carry in their metadata.\n * Any schema can do the same with `.meta({ bsonType: 'decimal' })`.\n *\n * ```ts\n * toMongoJsonSchema(z.object({ _id: objectId(), email: z.string() }));\n * // { type: 'object', properties: { … }, required: ['_id', 'email'], … }\n * ```\n */\nexport function toMongoJsonSchema(schema: z.ZodType): Record<string, unknown> {\n\tconst json = z.toJSONSchema(schema, {\n\t\ttarget: 'draft-4',\n\t\tio: 'output',\n\t\t// A `Date` is unrepresentable in JSON Schema; the override below gives\n\t\t// it a bsonType instead, and `{}` is what it starts from.\n\t\tunrepresentable: 'any',\n\t\toverride: (ctx) => {\n\t\t\tconst type = (ctx.zodSchema as { _zod: { def: { type: string } } })._zod\n\t\t\t\t.def.type;\n\t\t\tif (type === 'date' && ctx.jsonSchema.bsonType === undefined) {\n\t\t\t\tctx.jsonSchema.bsonType = 'date';\n\t\t\t}\n\t\t},\n\t}) as Node;\n\n\tconst definitions = isRecord(json.definitions)\n\t\t? json.definitions\n\t\t: isRecord(json.$defs)\n\t\t\t? json.$defs\n\t\t\t: {};\n\treturn inline(json, definitions, []) as Record<string, unknown>;\n}\n",
|
|
8
|
-
"/** What went wrong, as a string a caller can switch on. */\nexport type DataErrorCode =\n\t| 'DATABASE'\n\t| 'NOT_FOUND'\n\t| 'CONFLICT'\n\t| 'VALIDATION'\n\t| 'OPTIMISTIC_LOCK'\n\t| 'INVALID_CURSOR';\n\n/** One reason a document failed the collection's `$jsonSchema` validator. */\nexport interface ValidationIssue {\n\t/** The dotted path of the field, empty for the document itself. */\n\tpath: string;\n\t/** The rule it broke: `bsonType`, `required`, `minimum`… */\n\treason: string;\n\t/** What the schema asked for, as MongoDB reports it. */\n\tspecifiedAs?: unknown;\n\t/** The value that was refused, when the server names it. */\n\tconsideredValue?: unknown;\n\t/** Its BSON type, when the server names it: `string`, `int`, `double`… */\n\tconsideredType?: string;\n\t/** The schema's `description` for the field, when it has one. */\n\tdescription?: string;\n}\n\nexport interface DataErrorOptions {\n\tcollection?: string | undefined;\n\t/** The `_id` a method by id was given. */\n\tid?: unknown;\n\t/** MongoDB's numeric error code: 11000, 121, 26… */\n\tserverCode?: number | undefined;\n\t/** MongoDB's `codeName`, which write errors do not carry. */\n\tserverCodeName?: string | undefined;\n\t/** The index a conflict names, when the server names one. */\n\tindex?: string | undefined;\n\t/** The fields the error is about: an index's keys, or a validator's paths. */\n\tkeys?: string[];\n\t/** Those fields' values, when the server gives them. */\n\tvalues?: Record<string, unknown> | undefined;\n\tissues?: ValidationIssue[];\n\texpectedVersion?: number | undefined;\n\tactualVersion?: number | undefined;\n\tcause?: unknown;\n}\n\n/**\n * What this package throws. Every method turns a driver error into one of\n * these, so an application catches `ConflictError` instead of reading `11000`\n * off an error whose shape changes with the operation that produced it.\n *\n * A driver error that is none of them reaches the caller as it is.\n */\nexport class DataError extends Error {\n\toverride name = 'DataError';\n\treadonly code: DataErrorCode = 'DATABASE';\n\treadonly collection: string | undefined;\n\treadonly id: unknown;\n\treadonly serverCode: number | undefined;\n\treadonly serverCodeName: string | undefined;\n\treadonly index: string | undefined;\n\treadonly keys: string[];\n\treadonly values: Record<string, unknown> | undefined;\n\treadonly issues: ValidationIssue[];\n\treadonly expectedVersion: number | undefined;\n\treadonly actualVersion: number | undefined;\n\n\tconstructor(message = 'Database error', options: DataErrorOptions = {}) {\n\t\tsuper(\n\t\t\tmessage,\n\t\t\toptions.cause === undefined ? undefined : { cause: options.cause },\n\t\t);\n\t\tthis.collection = options.collection;\n\t\tthis.id = options.id;\n\t\tthis.serverCode = options.serverCode;\n\t\tthis.serverCodeName = options.serverCodeName;\n\t\tthis.index = options.index;\n\t\tthis.keys = options.keys ?? [];\n\t\tthis.values = options.values;\n\t\tthis.issues = options.issues ?? [];\n\t\tthis.expectedVersion = options.expectedVersion;\n\t\tthis.actualVersion = options.actualVersion;\n\t}\n}\n\n/** No document matched, where one was required. */\nexport class NotFoundError extends DataError {\n\toverride name = 'NotFoundError';\n\toverride readonly code = 'NOT_FOUND' as const;\n\n\tconstructor(message = 'Not found', options: DataErrorOptions = {}) {\n\t\tsuper(message, options);\n\t}\n}\n\n/** A unique index refused the write: MongoDB's `E11000`. */\nexport class ConflictError extends DataError {\n\toverride name = 'ConflictError';\n\toverride readonly code = 'CONFLICT' as const;\n\n\tconstructor(message = 'Duplicate key', options: DataErrorOptions = {}) {\n\t\tsuper(message, { serverCode: 11000, ...options });\n\t}\n}\n\n/** The collection's `$jsonSchema` validator refused the document: code 121. */\nexport class ValidationError extends DataError {\n\toverride name = 'ValidationError';\n\toverride readonly code = 'VALIDATION' as const;\n\n\tconstructor(\n\t\tmessage = 'Document failed validation',\n\t\toptions: DataErrorOptions = {},\n\t) {\n\t\tsuper(message, { serverCode: 121, ...options });\n\t}\n}\n\n/**\n * The document changed since it was read: its `version` is no longer the one\n * the update expected, and nothing was written.\n */\nexport class OptimisticLockError extends DataError {\n\toverride name = 'OptimisticLockError';\n\toverride readonly code = 'OPTIMISTIC_LOCK' as const;\n\n\tconstructor(message = 'Version conflict', options: DataErrorOptions = {}) {\n\t\tsuper(message, options);\n\t}\n}\n\n/** A cursor this package did not write, or one for another ordering. */\nexport class InvalidCursorError extends DataError {\n\toverride name = 'InvalidCursorError';\n\toverride readonly code = 'INVALID_CURSOR' as const;\n\n\tconstructor(message = 'Invalid cursor', options: DataErrorOptions = {}) {\n\t\tsuper(message, options);\n\t}\n}\n",
|
|
9
10
|
"import {\n\tConflictError,\n\tDataError,\n\ttype DataErrorOptions,\n\tValidationError,\n\ttype ValidationIssue,\n} from './data-error';\n\ntype Record_ = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is Record_ {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction asArray(value: unknown): unknown[] {\n\tif (Array.isArray(value)) return value;\n\treturn value === undefined || value === null ? [] : [value];\n}\n\nfunction text(value: unknown): string | undefined {\n\treturn typeof value === 'string' ? value : undefined;\n}\n\n/**\n * The index a duplicate key names. The message is the only place it is:\n * `E11000 duplicate key error collection: db.users index: users_email_unique\n * dup key: { email: \"a@b.c\" }`.\n */\nfunction indexFromMessage(message: string | undefined): string | undefined {\n\treturn message?.match(/index:\\s*(\\S+)\\s+dup key/)?.[1];\n}\n\n/**\n * The keys of a duplicate key. `keyPattern` carries them for a single write;\n * a bulk write carries neither it nor `keyValue`, and the message is all there\n * is: `dup key: { email: \"a@b.c\", tenant: 1 }`.\n */\nfunction keysOfDuplicate(error: Record_): {\n\tkeys: string[];\n\tvalues: Record_ | undefined;\n} {\n\tconst pattern = error.keyPattern;\n\tif (isRecord(pattern)) {\n\t\tconst values = isRecord(error.keyValue) ? error.keyValue : undefined;\n\t\treturn { keys: Object.keys(pattern), values };\n\t}\n\tconst inMessage = text(error.errmsg)?.match(/dup key:\\s*\\{([^}]*)\\}/)?.[1];\n\tif (!inMessage) return { keys: [], values: undefined };\n\tconst keys = [...inMessage.matchAll(/([\\w.$]+)\\s*:/g)].map(\n\t\t(match) => match[1] as string,\n\t);\n\treturn { keys, values: undefined };\n}\n\n/** The first write error of a bulk result, which may be one object or a list. */\nfunction firstWriteError(error: Record_): Record_ | undefined {\n\tfor (const write of asArray(error.writeErrors)) {\n\t\t// The driver wraps each one; its fields sit on `err` there.\n\t\tconst inner = isRecord(write) && isRecord(write.err) ? write.err : write;\n\t\tif (isRecord(inner)) return inner;\n\t}\n\treturn undefined;\n}\n\n/**\n * The issues of a `$jsonSchema` failure, from `errInfo.details`. The server\n * nests them: `schemaRulesNotSatisfied` holds `propertiesNotSatisfied`, whose\n * `details` hold either leaf rules or another level of properties.\n */\nfunction issuesOf(details: unknown, path: string[] = []): ValidationIssue[] {\n\tconst issues: ValidationIssue[] = [];\n\tfor (const rule of asArray(details)) {\n\t\tif (!isRecord(rule)) continue;\n\n\t\tif (rule.propertiesNotSatisfied !== undefined) {\n\t\t\tfor (const property of asArray(rule.propertiesNotSatisfied)) {\n\t\t\t\tif (!isRecord(property)) continue;\n\t\t\t\tconst name = text(property.propertyName) ?? '';\n\t\t\t\tconst nested = issuesOf(property.details, [...path, name]);\n\t\t\t\tconst description = text(property.description);\n\t\t\t\tissues.push(\n\t\t\t\t\t...(description === undefined\n\t\t\t\t\t\t? nested\n\t\t\t\t\t\t: nested.map((issue) => ({ description, ...issue }))),\n\t\t\t\t);\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (rule.missingProperties !== undefined) {\n\t\t\tfor (const missing of asArray(rule.missingProperties)) {\n\t\t\t\tissues.push({\n\t\t\t\t\tpath: [...path, String(missing)].join('.'),\n\t\t\t\t\treason: 'required',\n\t\t\t\t\tspecifiedAs: rule.specifiedAs,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (rule.schemaRulesNotSatisfied !== undefined) {\n\t\t\tissues.push(...issuesOf(rule.schemaRulesNotSatisfied, path));\n\t\t\tcontinue;\n\t\t}\n\n\t\tissues.push({\n\t\t\tpath: path.join('.'),\n\t\t\treason: text(rule.reason) ?? text(rule.operatorName) ?? 'invalid',\n\t\t\t...(rule.specifiedAs === undefined\n\t\t\t\t? {}\n\t\t\t\t: { specifiedAs: rule.specifiedAs }),\n\t\t\t...(rule.consideredValue === undefined\n\t\t\t\t? {}\n\t\t\t\t: { consideredValue: rule.consideredValue }),\n\t\t\t...(text(rule.consideredType) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { consideredType: text(rule.consideredType) }),\n\t\t});\n\t}\n\treturn issues;\n}\n\n/**\n * A MongoDB error as one of this package's, or the error itself when it is\n * none of them.\n *\n * It reads the error's fields rather than its class: a duplicate key arrives\n * as a `MongoServerError` with `keyPattern` from `insertOne`, and as a\n * `MongoBulkWriteError` whose `writeErrors` carry neither `keyPattern` nor\n * `keyValue` from `insertMany` and `bulkWrite`. Both become a `ConflictError`\n * with the same fields. Reading fields also survives two copies of the driver\n * in one tree, where `instanceof` does not.\n */\nexport function toDataError(\n\terror: unknown,\n\tcontext: { collection?: string | undefined } = {},\n): unknown {\n\tif (error instanceof DataError) return error;\n\tif (!isRecord(error)) return error;\n\n\t// A bulk write carries the detail on its write errors, and only a message\n\t// at the top; a single write carries everything at the top.\n\tconst source = firstWriteError(error) ?? error;\n\tconst code =\n\t\ttypeof source.code === 'number'\n\t\t\t? source.code\n\t\t\t: typeof error.code === 'number'\n\t\t\t\t? error.code\n\t\t\t\t: undefined;\n\tif (typeof code !== 'number') return error;\n\n\tconst message =\n\t\ttext(source.errmsg) ??\n\t\ttext(source.message) ??\n\t\ttext((error as { message?: unknown }).message) ??\n\t\t'';\n\tconst common: DataErrorOptions = {\n\t\tcollection: context.collection,\n\t\tserverCode: code,\n\t\tserverCodeName: text(error.codeName) ?? text(source.codeName),\n\t\tcause: error,\n\t};\n\n\tif (code === 11000) {\n\t\tconst { keys, values } = keysOfDuplicate(source);\n\t\tconst index = indexFromMessage(message);\n\t\tconst named =\n\t\t\tkeys.length > 0 ? keys.join(', ') : (index ?? 'a unique index');\n\t\treturn new ConflictError(\n\t\t\t`Duplicate key on ${named}${\n\t\t\t\tcontext.collection ? ` in \"${context.collection}\"` : ''\n\t\t\t}`,\n\t\t\t{ ...common, index, keys, values },\n\t\t);\n\t}\n\n\tif (code === 121) {\n\t\tconst errInfo = isRecord(source.errInfo) ? source.errInfo : undefined;\n\t\tconst issues = issuesOf(errInfo?.details);\n\t\treturn new ValidationError(\n\t\t\t`Document failed validation${\n\t\t\t\tcontext.collection ? ` in \"${context.collection}\"` : ''\n\t\t\t}${issues.length > 0 ? `: ${issues.map((i) => `${i.path} ${i.reason}`).join(', ')}` : ''}`,\n\t\t\t{ ...common, issues, keys: issues.map((issue) => issue.path) },\n\t\t);\n\t}\n\n\treturn new DataError(message || `MongoDB error ${code}`, common);\n}\n",
|
|
10
11
|
"import { ObjectId } from 'mongodb';\nimport { InvalidCursorError } from '../errors/data-error';\n\n/** What a cursor holds: the ordering values of the last document of a page. */\nexport interface CursorPayload {\n\t/** The ordering it was written for: `<field>:<asc|desc>`. */\n\treadonly key: string;\n\treadonly values: readonly unknown[];\n}\n\n/** An `ObjectId`, read without `instanceof`: two copies of the driver. */\nfunction isObjectId(value: unknown): value is ObjectId {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t(value as { _bsontype?: unknown })._bsontype === 'ObjectId'\n\t);\n}\n\n// JSON has no Date, no bigint and no ObjectId, and a cursor must give back the\n// very value it was written from: a Date compares with a date field, an\n// ObjectId with `_id`. `JSON.stringify` has already called `toJSON` by the time\n// the replacer runs, so the raw value is read off `this`.\nfunction replacer(this: Record<string, unknown>, key: string, value: unknown) {\n\tconst raw = this[key];\n\tif (raw instanceof Date) return { $date: raw.toISOString() };\n\tif (typeof raw === 'bigint') return { $bigint: raw.toString() };\n\tif (isObjectId(raw)) return { $oid: raw.toHexString() };\n\treturn value;\n}\n\nfunction reviver(_key: string, value: unknown): unknown {\n\tif (value && typeof value === 'object' && !Array.isArray(value)) {\n\t\tconst keys = Object.keys(value);\n\t\tif (keys.length === 1) {\n\t\t\tconst tagged = value as {\n\t\t\t\t$date?: unknown;\n\t\t\t\t$bigint?: unknown;\n\t\t\t\t$oid?: unknown;\n\t\t\t};\n\t\t\tif (typeof tagged.$date === 'string') return new Date(tagged.$date);\n\t\t\tif (typeof tagged.$bigint === 'string') return BigInt(tagged.$bigint);\n\t\t\tif (typeof tagged.$oid === 'string') return new ObjectId(tagged.$oid);\n\t\t}\n\t}\n\treturn value;\n}\n\nfunction toBase64Url(text: string): string {\n\tlet binary = '';\n\tfor (const byte of new TextEncoder().encode(text)) {\n\t\tbinary += String.fromCharCode(byte);\n\t}\n\treturn btoa(binary)\n\t\t.replace(/\\+/g, '-')\n\t\t.replace(/\\//g, '_')\n\t\t.replace(/=+$/, '');\n}\n\nfunction fromBase64Url(text: string): string {\n\tconst base64 = text.replace(/-/g, '+').replace(/_/g, '/');\n\tconst binary = atob(base64 + '='.repeat((4 - (base64.length % 4)) % 4));\n\treturn new TextDecoder().decode(\n\t\tUint8Array.from(binary, (char) => char.charCodeAt(0)),\n\t);\n}\n\n/**\n * Writes an opaque, URL-safe cursor. `Date`, `bigint` and `ObjectId` values\n * survive the round trip. It is encoded, not signed: a client can read it,\n * and forge one.\n */\nexport function encodeCursor(payload: CursorPayload): string {\n\treturn toBase64Url(JSON.stringify([payload.key, payload.values], replacer));\n}\n\n/**\n * Reads a cursor `encodeCursor` wrote. Throws `InvalidCursorError` for\n * anything else, and for a cursor written for another ordering when\n * `expectedKey` is given.\n */\nexport function decodeCursor(\n\tcursor: string,\n\texpectedKey?: string,\n): CursorPayload {\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(fromBase64Url(cursor), reviver);\n\t} catch (cause) {\n\t\tthrow new InvalidCursorError('Invalid cursor: it cannot be decoded', {\n\t\t\tcause,\n\t\t});\n\t}\n\tif (\n\t\t!Array.isArray(parsed) ||\n\t\tparsed.length !== 2 ||\n\t\ttypeof parsed[0] !== 'string' ||\n\t\t!Array.isArray(parsed[1])\n\t) {\n\t\tthrow new InvalidCursorError('Invalid cursor: unexpected shape');\n\t}\n\tconst [key, values] = parsed as [string, unknown[]];\n\tif (expectedKey !== undefined && key !== expectedKey) {\n\t\tthrow new InvalidCursorError(\n\t\t\t`Invalid cursor: it was written for the ordering ${key}, not ${expectedKey}`,\n\t\t);\n\t}\n\treturn { key, values };\n}\n",
|
|
11
12
|
"/** One page of an offset pagination. */\nexport interface Page<T> {\n\titems: T[];\n\t/** Every document that matches, across all pages. */\n\ttotal: number;\n\t/** 1-based. */\n\tpage: number;\n\tpageSize: number;\n\t/** `Math.ceil(total / pageSize)`: 0 when nothing matches. */\n\tpageCount: number;\n}\n\n/** One page of a cursor pagination. */\nexport interface CursorPage<T> {\n\titems: T[];\n\t/** Pass it as `after` for the next page; `null` on the last one. */\n\tnextCursor: string | null;\n}\n\nexport interface PageOptions {\n\t/** 1-based. Default `1`. */\n\tpage?: number;\n\t/** Default `20`, at most `maxPageSize`. */\n\tpageSize?: number;\n}\n\nexport interface PageWindow {\n\tpage: number;\n\tpageSize: number;\n\tlimit: number;\n\tskip: number;\n}\n\nexport const DEFAULT_PAGE_SIZE = 20;\nexport const DEFAULT_MAX_PAGE_SIZE = 100;\n\nfunction positiveInteger(name: string, value: number): number {\n\tif (!Number.isInteger(value) || value < 1) {\n\t\tthrow new RangeError(\n\t\t\t`${name} must be an integer of at least 1, not ${value}`,\n\t\t);\n\t}\n\treturn value;\n}\n\n/**\n * Checks `page` and `pageSize` and turns them into a `limit` and a `skip`.\n * A `pageSize` above `maxPageSize` is lowered to it; one that is not a\n * positive integer throws a `RangeError`.\n */\nexport function pageWindow(\n\toptions: PageOptions = {},\n\tmaxPageSize = DEFAULT_MAX_PAGE_SIZE,\n): PageWindow {\n\tconst page = positiveInteger('page', options.page ?? 1);\n\tconst pageSize = Math.min(\n\t\tpositiveInteger('pageSize', options.pageSize ?? DEFAULT_PAGE_SIZE),\n\t\tmaxPageSize,\n\t);\n\treturn { page, pageSize, limit: pageSize, skip: (page - 1) * pageSize };\n}\n\n/** Assembles a `Page` from its documents and the total. */\nexport function toPage<T>(\n\titems: T[],\n\ttotal: number,\n\twindow: PageWindow,\n): Page<T> {\n\treturn {\n\t\titems,\n\t\ttotal,\n\t\tpage: window.page,\n\t\tpageSize: window.pageSize,\n\t\tpageCount: Math.ceil(total / window.pageSize),\n\t};\n}\n\n/** Checks a cursor page's `limit`, as `pageWindow` checks a `pageSize`. */\nexport function cursorLimit(\n\tlimit: number | undefined,\n\tmaxPageSize = DEFAULT_MAX_PAGE_SIZE,\n): number {\n\treturn Math.min(\n\t\tpositiveInteger('limit', limit ?? DEFAULT_PAGE_SIZE),\n\t\tmaxPageSize,\n\t);\n}\n",
|
|
12
13
|
"import type { IndexDescription, IndexDescriptionInfo } from 'mongodb';\n\n/**\n * What MongoDB fills a collation in with. It reads an index's collation back\n * canonical — every field, plus the ICU `version` — so a wanted collation is\n * compared against its own defaults, and `version` is left out: it changes\n * with the server's ICU, and recreating every index over it would be absurd.\n */\nconst COLLATION_DEFAULTS: Record<string, unknown> = {\n\tcaseLevel: false,\n\tcaseFirst: 'off',\n\tstrength: 3,\n\tnumericOrdering: false,\n\talternate: 'non-ignorable',\n\tmaxVariable: 'punct',\n\tnormalization: false,\n\tbackwards: false,\n};\n\n/**\n * Options the server does not read back when they are false, but does when\n * they were sent explicitly. Compared against the default either way.\n */\nconst OPTION_DEFAULTS: Record<string, unknown> = {\n\tunique: false,\n\tsparse: false,\n\thidden: false,\n\tbackground: false,\n};\n\n/** Never part of an index's identity: the server's own bookkeeping. */\nconst IGNORED = new Set(['v', 'ns', 'key', 'name']);\n\ntype Fields = Record<string, unknown>;\n\nfunction keyOf(index: IndexDescription | IndexDescriptionInfo): Fields {\n\tconst key = index.key;\n\treturn key instanceof Map ? Object.fromEntries(key) : { ...key };\n}\n\n/**\n * The name MongoDB gives an index that names none: every field and direction,\n * joined by `_`.\n */\nexport function indexNameOf(key: Fields): string {\n\treturn Object.entries(key)\n\t\t.map(([field, direction]) => `${field}_${String(direction)}`)\n\t\t.join('_');\n}\n\nfunction canonicalCollation(value: unknown): unknown {\n\tif (typeof value !== 'object' || value === null) return value;\n\tconst collation = value as Fields;\n\tconst out: Fields = {};\n\tfor (const [field, fallback] of Object.entries(COLLATION_DEFAULTS)) {\n\t\tout[field] = collation[field] ?? fallback;\n\t}\n\tout.locale = collation.locale;\n\t// `version` is the server's ICU version, never something to sync on.\n\treturn out;\n}\n\n/** An index reduced to what makes two of them the same. */\nexport interface NormalizedIndex {\n\tname: string;\n\t/** In order: a compound index on `{a, b}` is not one on `{b, a}`. */\n\tkey: Fields;\n\toptions: Fields;\n}\n\nexport function normalizeIndex(\n\tindex: IndexDescription | IndexDescriptionInfo,\n): NormalizedIndex {\n\tconst key = keyOf(index);\n\tconst options: Fields = {};\n\tfor (const [name, value] of Object.entries(index)) {\n\t\tif (IGNORED.has(name) || value === undefined) continue;\n\t\tif (name === 'collation') {\n\t\t\toptions.collation = canonicalCollation(value);\n\t\t\tcontinue;\n\t\t}\n\t\tif (OPTION_DEFAULTS[name] === value) continue;\n\t\toptions[name] = value;\n\t}\n\treturn { name: index.name ?? indexNameOf(key), key, options };\n}\n\nfunction canonical(value: unknown): string {\n\treturn JSON.stringify(value, (_name, inner) =>\n\t\tinner && typeof inner === 'object' && !Array.isArray(inner)\n\t\t\t? Object.fromEntries(\n\t\t\t\t\tObject.entries(inner).sort(([a], [b]) => (a < b ? -1 : 1)),\n\t\t\t\t)\n\t\t\t: inner,\n\t);\n}\n\n/** Are two indexes the same index, with the same options? */\nexport function indexMatches(\n\twanted: IndexDescription,\n\tlive: IndexDescriptionInfo,\n): boolean {\n\tconst a = normalizeIndex(wanted);\n\tconst b = normalizeIndex(live);\n\treturn (\n\t\t// The key's order counts, so it is compared as it was written.\n\t\tJSON.stringify(Object.entries(a.key)) ===\n\t\t\tJSON.stringify(Object.entries(b.key)) &&\n\t\tcanonical(a.options) === canonical(b.options)\n\t);\n}\n\nexport interface IndexDiff {\n\t/** Not on the server yet. */\n\tcreate: IndexDescription[];\n\t/**\n\t * There under this name, with other options: MongoDB refuses to change\n\t * one, so it is dropped and created again.\n\t */\n\trecreate: IndexDescription[];\n\t/** Already as the definition wants it. */\n\tunchanged: string[];\n\t/** On the server and in no definition. `_id_` is never one. */\n\textra: string[];\n}\n\n/**\n * What an index sync has to do. Indexes are matched by name, which is what\n * MongoDB keys them on: the same name with other options is error 86, and the\n * same key under another name is error 85.\n */\nexport function diffIndexes(\n\twanted: readonly IndexDescription[],\n\tlive: readonly IndexDescriptionInfo[],\n): IndexDiff {\n\tconst byName = new Map(\n\t\tlive.map((index) => [normalizeIndex(index).name, index]),\n\t);\n\tconst diff: IndexDiff = {\n\t\tcreate: [],\n\t\trecreate: [],\n\t\tunchanged: [],\n\t\textra: [],\n\t};\n\tconst named = new Set<string>();\n\n\tfor (const index of wanted) {\n\t\tconst name = normalizeIndex(index).name;\n\t\tnamed.add(name);\n\t\tconst existing = byName.get(name);\n\t\tif (!existing) diff.create.push({ ...index, name });\n\t\telse if (indexMatches(index, existing)) diff.unchanged.push(name);\n\t\telse diff.recreate.push({ ...index, name });\n\t}\n\n\tfor (const name of byName.keys()) {\n\t\t// The `_id_` index is created with the collection and cannot be dropped.\n\t\tif (name !== '_id_' && !named.has(name)) diff.extra.push(name);\n\t}\n\treturn diff;\n}\n",
|
|
13
14
|
"import type {\n\tValidationAction,\n\tValidationLevel,\n} from '../definition/define-collection';\n\n/** A collection's validation, as `listCollections` reports it in `options`. */\nexport interface LiveValidation {\n\tvalidator?: Record<string, unknown>;\n\tvalidationLevel?: string;\n\tvalidationAction?: string;\n}\n\n/** The validation a definition asks for. `validator` is absent for `off`. */\nexport interface WantedValidation {\n\tvalidator: Record<string, unknown> | undefined;\n\tlevel: ValidationLevel;\n\taction: ValidationAction;\n}\n\nfunction canonical(value: unknown): string {\n\treturn JSON.stringify(value ?? null, (_name, inner) =>\n\t\tinner && typeof inner === 'object' && !Array.isArray(inner)\n\t\t\t? Object.fromEntries(\n\t\t\t\t\tObject.entries(inner).sort(([a], [b]) => (a < b ? -1 : 1)),\n\t\t\t\t)\n\t\t\t: inner,\n\t);\n}\n\n/** Has a collection a validator at all? An empty one is no validator. */\nexport function hasValidator(live: LiveValidation): boolean {\n\treturn live.validator !== undefined && Object.keys(live.validator).length > 0;\n}\n\n/**\n * Does the collection already validate the way the definition says?\n *\n * MongoDB reads a `$jsonSchema` back exactly as it was sent, so the two are\n * compared whole. What it does not read back is a validator that was removed:\n * `collMod` with `validator: {}` leaves **no `validator` key at all**, while\n * `validationLevel` and `validationAction` stay behind. And a collection\n * created without one reports `options: {}`, where the level is `strict` and\n * the action `error` by default.\n */\nexport function validationMatches(\n\twanted: WantedValidation,\n\tlive: LiveValidation,\n): boolean {\n\tif (wanted.validator === undefined) return !hasValidator(live);\n\tif (!hasValidator(live)) return false;\n\treturn (\n\t\tcanonical(live.validator) === canonical(wanted.validator) &&\n\t\t(live.validationLevel ?? 'strict') === wanted.level &&\n\t\t(live.validationAction ?? 'error') === wanted.action\n\t);\n}\n",
|
|
14
15
|
"import type {\n\tClientSession,\n\tDb,\n\tDocument,\n\tIndexDescription,\n\tIndexDescriptionInfo,\n} from 'mongodb';\nimport type { AnyCollectionDefinition } from '../definition/define-collection';\nimport { toMongoJsonSchema } from '../definition/json-schema';\nimport { DataError } from '../errors/data-error';\nimport { toDataError } from '../errors/to-data-error';\nimport { diffIndexes, normalizeIndex } from './index-diff';\nimport {\n\thasValidator,\n\ttype LiveValidation,\n\tvalidationMatches,\n\ttype WantedValidation,\n} from './validator-diff';\n\nexport interface SyncOptions {\n\t/**\n\t * Compare and report, but send nothing: no collection is created, no\n\t * validator written, no index touched. For a check in CI, or a look before\n\t * a deploy.\n\t */\n\tdryRun?: boolean;\n\t/**\n\t * Drop the indexes the server has and no definition names. Off by default:\n\t * an index someone added on purpose is not this package's to remove.\n\t * `_id_` is never dropped, and cannot be.\n\t */\n\tdropUnknownIndexes?: boolean;\n\t/**\n\t * A session for the reads. MongoDB does not allow `collMod` or an index\n\t * build inside a transaction, so do not pass one that is in a transaction.\n\t */\n\tsession?: ClientSession;\n}\n\n/** What `sync` found and did to one collection. */\nexport interface SyncReport {\n\tname: string;\n\t/** The collection did not exist, and was created. */\n\tcreated: boolean;\n\t/** What the `$jsonSchema` validator needed. */\n\tvalidator: 'unchanged' | 'created' | 'updated' | 'removed';\n\tindexes: {\n\t\tcreated: string[];\n\t\t/** There with other options: MongoDB cannot change one, so it is dropped and built again. */\n\t\trecreated: string[];\n\t\tdropped: string[];\n\t\tunchanged: string[];\n\t};\n\tdryRun: boolean;\n}\n\nfunction serverCode(error: unknown): number | undefined {\n\tconst code = (error as { code?: unknown } | null)?.code;\n\treturn typeof code === 'number' ? code : undefined;\n}\n\nasync function collectionOptions(\n\tdb: Db,\n\tname: string,\n\tsession: ClientSession | undefined,\n): Promise<LiveValidation | undefined> {\n\t// `nameOnly: false` is what types the answer as the whole entry: without\n\t// it the driver's overload gives back a name and a type alone.\n\tconst [info] = await db\n\t\t.listCollections(\n\t\t\t{ name },\n\t\t\t{ ...(session ? { session } : {}), nameOnly: false },\n\t\t)\n\t\t.toArray();\n\treturn info ? ((info.options ?? {}) as LiveValidation) : undefined;\n}\n\n/** The indexes of a collection, or none when it does not exist yet. */\nasync function liveIndexes(\n\tdb: Db,\n\tname: string,\n\tsession: ClientSession | undefined,\n): Promise<IndexDescriptionInfo[]> {\n\ttry {\n\t\treturn await db.collection(name).indexes({ session });\n\t} catch (error) {\n\t\t// NamespaceNotFound: nothing is there, so nothing is indexed.\n\t\tif (serverCode(error) === 26) return [];\n\t\tthrow error;\n\t}\n}\n\nfunction validationFor(definition: AnyCollectionDefinition): WantedValidation {\n\tconst { level, action } = definition.validation;\n\treturn {\n\t\tvalidator:\n\t\t\tlevel === 'off'\n\t\t\t\t? undefined\n\t\t\t\t: { $jsonSchema: toMongoJsonSchema(definition.schema) },\n\t\tlevel,\n\t\taction,\n\t};\n}\n\nfunction creationOptions(wanted: WantedValidation): Document {\n\treturn wanted.validator === undefined\n\t\t? {}\n\t\t: {\n\t\t\t\tvalidator: wanted.validator,\n\t\t\t\tvalidationLevel: wanted.level,\n\t\t\t\tvalidationAction: wanted.action,\n\t\t\t};\n}\n\nasync function writeValidation(\n\tdb: Db,\n\tname: string,\n\twanted: WantedValidation,\n\tsession: ClientSession | undefined,\n): Promise<void> {\n\ttry {\n\t\tawait db.command(\n\t\t\t{\n\t\t\t\tcollMod: name,\n\t\t\t\t// An empty validator is how one is removed: the key then goes\n\t\t\t\t// away entirely, and the level and the action stay behind.\n\t\t\t\tvalidator: wanted.validator ?? {},\n\t\t\t\t...(wanted.validator === undefined\n\t\t\t\t\t? {}\n\t\t\t\t\t: { validationLevel: wanted.level, validationAction: wanted.action }),\n\t\t\t},\n\t\t\tsession ? { session } : undefined,\n\t\t);\n\t} catch (error) {\n\t\tif (serverCode(error) === 13) {\n\t\t\tthrow new DataError(\n\t\t\t\t`sync: not allowed to run collMod on \"${name}\". Writing a validator ` +\n\t\t\t\t\t'needs the `collMod` action, which `readWrite` does not grant and ' +\n\t\t\t\t\t'`dbAdmin` does: sync with a role that has it, not with the ' +\n\t\t\t\t\t'application’s own user.',\n\t\t\t\t{ collection: name, serverCode: 13, cause: error },\n\t\t\t);\n\t\t}\n\t\tthrow toDataError(error, { collection: name });\n\t}\n}\n\n/**\n * Brings one collection in line with its definition, and says what it changed:\n *\n * 1. creates the collection, with its validator, when it is missing;\n * 2. writes the validator with `collMod` when it differs from the definition's;\n * 3. creates the indexes that are missing, and rebuilds those whose options\n * changed — MongoDB refuses to alter an index in place.\n *\n * Run it twice and the second run sends nothing.\n *\n * ```ts\n * const report = await syncCollection(db, users);\n * // { created: true, validator: 'created', indexes: { created: ['users_email_unique'], … } }\n * ```\n *\n * It is a deployment step, not a request-time one: `collMod` needs the\n * `dbAdmin` role, and neither it nor an index build may run in a transaction.\n */\nexport async function syncCollection(\n\tdb: Db,\n\tdefinition: AnyCollectionDefinition,\n\toptions: SyncOptions = {},\n): Promise<SyncReport> {\n\tconst { name } = definition;\n\tconst dryRun = options.dryRun ?? false;\n\tconst session = options.session;\n\tconst wanted = validationFor(definition);\n\n\tlet live = await collectionOptions(db, name, session);\n\tlet created = false;\n\tlet validator: SyncReport['validator'] = 'unchanged';\n\n\tif (!live) {\n\t\tcreated = true;\n\t\tif (wanted.validator !== undefined) validator = 'created';\n\t\tif (!dryRun) {\n\t\t\ttry {\n\t\t\t\tawait db.createCollection(name, {\n\t\t\t\t\t...creationOptions(wanted),\n\t\t\t\t\t...(session ? { session } : {}),\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\t// NamespaceExists: another sync created it between the lookup and\n\t\t\t\t// the creation. Go on with theirs, which is compared below.\n\t\t\t\tif (serverCode(error) !== 48) {\n\t\t\t\t\tthrow toDataError(error, { collection: name });\n\t\t\t\t}\n\t\t\t\tcreated = false;\n\t\t\t\tvalidator = 'unchanged';\n\t\t\t\tlive = await collectionOptions(db, name, session);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (live && !validationMatches(wanted, live)) {\n\t\tvalidator =\n\t\t\twanted.validator === undefined\n\t\t\t\t? 'removed'\n\t\t\t\t: hasValidator(live)\n\t\t\t\t\t? 'updated'\n\t\t\t\t\t: 'created';\n\t\tif (!dryRun) await writeValidation(db, name, wanted, session);\n\t}\n\n\tconst existing =\n\t\tdryRun && created ? [] : await liveIndexes(db, name, session);\n\tconst diff = diffIndexes(definition.indexes, existing);\n\tconst dropped = options.dropUnknownIndexes ? diff.extra : [];\n\tconst build: IndexDescription[] = [...diff.create, ...diff.recreate];\n\n\tif (!dryRun) {\n\t\tconst collection = db.collection(name);\n\t\tfor (const index of [\n\t\t\t...diff.recreate.map((i) => normalizeIndex(i).name),\n\t\t\t...dropped,\n\t\t]) {\n\t\t\tawait collection.dropIndex(index, session ? { session } : undefined);\n\t\t}\n\t\tif (build.length > 0) {\n\t\t\ttry {\n\t\t\t\tawait collection.createIndexes(\n\t\t\t\t\tbuild,\n\t\t\t\t\tsession ? { session } : undefined,\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tthrow toDataError(error, { collection: name });\n\t\t\t}\n\t\t}\n\t}\n\n\treturn {\n\t\tname,\n\t\tcreated,\n\t\tvalidator,\n\t\tindexes: {\n\t\t\tcreated: diff.create.map((index) => normalizeIndex(index).name),\n\t\t\trecreated: diff.recreate.map((index) => normalizeIndex(index).name),\n\t\t\tdropped,\n\t\t\tunchanged: diff.unchanged,\n\t\t},\n\t\tdryRun,\n\t};\n}\n\n/**\n * `syncCollection` for each definition, one after the other, in the order\n * given. The first that throws stops the rest.\n */\nexport async function syncCollections(\n\tdb: Db,\n\tdefinitions: readonly AnyCollectionDefinition[],\n\toptions: SyncOptions = {},\n): Promise<SyncReport[]> {\n\tconst reports: SyncReport[] = [];\n\tfor (const definition of definitions) {\n\t\treports.push(await syncCollection(db, definition, options));\n\t}\n\treturn reports;\n}\n",
|
|
15
|
-
"import type { ClientSession, Db, Document } from 'mongodb';\nimport type { z } from 'zod';\nimport {\n\ttype AnyCollectionDefinition,\n\ttype CollectionDefinition,\n\tstampsOf,\n} from '../definition/define-collection';\nimport {\n\tDataError,\n\tNotFoundError,\n\tOptimisticLockError,\n} from '../errors/data-error';\nimport { toDataError } from '../errors/to-data-error';\nimport { decodeCursor, encodeCursor } from '../pagination/cursor';\nimport {\n\ttype CursorPage,\n\tcursorLimit,\n\tDEFAULT_MAX_PAGE_SIZE,\n\ttype Page,\n\tpageWindow,\n\ttoPage,\n} from '../pagination/page';\nimport { type SyncOptions, syncCollection } from '../sync/sync-collection';\nimport type { OrderDirection, Repository, RepositoryOptions } from './types';\n\ntype Fields = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is Fields {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Does this patch speak in MongoDB's operators rather than in fields? */\nfunction isUpdateFilter(patch: Fields): boolean {\n\treturn Object.keys(patch).some((key) => key.startsWith('$'));\n}\n\n/** `a` and `b`, without letting one's `$or` swallow the other's. */\nfunction mergeFilters(a: Fields | undefined, b: Fields | undefined): Fields {\n\tconst left = a && Object.keys(a).length > 0 ? a : undefined;\n\tconst right = b && Object.keys(b).length > 0 ? b : undefined;\n\tif (!left) return right ?? {};\n\tif (!right) return left;\n\treturn { $and: [left, right] };\n}\n\n/**\n * A repository over one collection: typed reads and writes by `_id` or by\n * filter, pagination, soft delete, optimistic locking, audit stamps, and\n * MongoDB errors turned into this package's.\n *\n * ```ts\n * const users = createRepository(db, usersCollection);\n * const ada = await users.create({ email: 'ada@example.com' });\n * await users.update(ada._id, { name: 'Ada' }, { expectedVersion: ada.version });\n * ```\n *\n * Every operation runs in the repository's session, which `with(session)`\n * sets: MongoDB has no ambient session, so a write inside a transaction that\n * was not given one is not part of it and is not rolled back.\n */\nexport function createRepository<Schema extends z.ZodObject>(\n\tdb: Db,\n\tdefinition: CollectionDefinition<Schema>,\n\toptions: RepositoryOptions = {},\n): Repository<CollectionDefinition<Schema>> {\n\treturn build(db, definition, options) as unknown as Repository<\n\t\tCollectionDefinition<Schema>\n\t>;\n}\n\nfunction build(\n\tdb: Db,\n\tdefinition: AnyCollectionDefinition,\n\toptions: RepositoryOptions,\n) {\n\tconst name = definition.name;\n\t// The driver types a collection by its documents; this body works on any\n\t// collection, and the public type above is what callers see.\n\tconst collection = db.collection<any>(name);\n\tconst shape = definition.schema.shape as Record<string, z.ZodType>;\n\tconst stamps = stampsOf(definition);\n\tconst session = options.session;\n\tconst actor = options.actor;\n\tconst maxPageSize = options.maxPageSize ?? DEFAULT_MAX_PAGE_SIZE;\n\tconst parses = (options.validate ?? 'parse') === 'parse';\n\tconst softDeletes = options.softDelete ?? stamps.deletedAt;\n\tconst touches = options.touchUpdatedAt ?? stamps.updatedAt;\n\tconst locks = options.optimisticLock ?? stamps.version;\n\n\tif (options.softDelete === true && !stamps.deletedAt) {\n\t\tthrow new TypeError(\n\t\t\t`createRepository: softDelete needs a \"deletedAt\" field, and \"${name}\" has none`,\n\t\t);\n\t}\n\tif (options.optimisticLock === true && !stamps.version) {\n\t\tthrow new TypeError(\n\t\t\t`createRepository: optimisticLock needs a \"version\" field, and \"${name}\" has none`,\n\t\t);\n\t}\n\n\tconst run = async <T>(fn: () => Promise<T>): Promise<T> => {\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} catch (error) {\n\t\t\tthrow toDataError(error, { collection: name });\n\t\t}\n\t};\n\n\tconst sessionOption = session ? { session } : {};\n\n\t/** The filter that leaves soft-deleted documents out. */\n\tconst live = (withDeleted?: boolean): Fields | undefined =>\n\t\tsoftDeletes && !withDeleted ? { deletedAt: null } : undefined;\n\n\tconst scoped = (filter: unknown, withDeleted?: boolean): Fields =>\n\t\tmergeFilters(isRecord(filter) ? filter : undefined, live(withDeleted));\n\n\tconst notFound = (id: unknown) =>\n\t\tnew NotFoundError(`No document in \"${name}\" with _id ${String(id)}`, {\n\t\t\tcollection: name,\n\t\t\tid,\n\t\t});\n\n\tconst requireFilter = (method: string, filter: unknown): void => {\n\t\tif (!isRecord(filter) || Object.keys(filter).length === 0) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`${method} needs a filter. Pass \\`{ _id: { $exists: true } }\\` to target every document of \"${name}\".`,\n\t\t\t);\n\t\t}\n\t};\n\n\t/** The document to insert: checked against the schema, defaults filled. */\n\tconst toDocument = (values: unknown): Fields => {\n\t\tconst stamped: Fields = { ...(values as Fields) };\n\t\tif (actor !== undefined) {\n\t\t\tif (stamps.createdBy && stamped.createdBy === undefined) {\n\t\t\t\tstamped.createdBy = actor;\n\t\t\t}\n\t\t\tif (stamps.updatedBy && stamped.updatedBy === undefined) {\n\t\t\t\tstamped.updatedBy = actor;\n\t\t\t}\n\t\t}\n\t\treturn parses ? (definition.schema.parse(stamped) as Fields) : stamped;\n\t};\n\n\t/**\n\t * The update to send: a patch of fields becomes `$set`, checked field by\n\t * field against the schema, with the stamps this repository keeps. A patch\n\t * that already speaks in operators is sent as it is, with the stamps added.\n\t */\n\tconst toUpdate = (patch: unknown): Fields => {\n\t\tif (!isRecord(patch)) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`update: expected the document's fields or MongoDB's operators, not ${String(patch)}`,\n\t\t\t);\n\t\t}\n\t\tconst update: Fields = isUpdateFilter(patch) ? { ...patch } : {};\n\t\tconst set: Fields = isRecord(update.$set) ? { ...update.$set } : {};\n\n\t\tif (!isUpdateFilter(patch)) {\n\t\t\tfor (const [field, value] of Object.entries(patch)) {\n\t\t\t\tif (value === undefined) continue;\n\t\t\t\tconst schema = shape[field];\n\t\t\t\tif (!schema) {\n\t\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\t`update: \"${name}\" has no field \"${field}\" in its schema`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tset[field] = parses ? schema.parse(value) : value;\n\t\t\t}\n\t\t}\n\n\t\tif (touches && set.updatedAt === undefined) set.updatedAt = new Date();\n\t\tif (\n\t\t\tactor !== undefined &&\n\t\t\tstamps.updatedBy &&\n\t\t\tset.updatedBy === undefined\n\t\t) {\n\t\t\tset.updatedBy = actor;\n\t\t}\n\t\tif (Object.keys(set).length > 0) update.$set = set;\n\n\t\tif (locks) {\n\t\t\tconst inc = isRecord(update.$inc) ? { ...update.$inc } : {};\n\t\t\tinc.version = (inc.version as number | undefined) ?? 1;\n\t\t\tupdate.$inc = inc;\n\t\t}\n\t\treturn update;\n\t};\n\n\tconst findOne = async (filter: Fields, projection?: unknown) =>\n\t\trun(async () =>\n\t\t\tcollection.findOne(filter, {\n\t\t\t\t...sessionOption,\n\t\t\t\t...(projection ? { projection } : {}),\n\t\t\t}),\n\t\t);\n\n\tasync function findById(id: unknown, opts: { withDeleted?: boolean } = {}) {\n\t\tconst found = await findOne(scoped({ _id: id }, opts.withDeleted));\n\t\treturn found ?? undefined;\n\t}\n\n\tasync function getById(id: unknown, opts: { withDeleted?: boolean } = {}) {\n\t\tconst found = await findById(id, opts);\n\t\tif (!found) throw notFound(id);\n\t\treturn found;\n\t}\n\n\tasync function findMany(opts: Fields = {}): Promise<Fields[]> {\n\t\treturn run(async () => {\n\t\t\tlet cursor = collection.find(\n\t\t\t\tscoped(opts.filter, opts.withDeleted as boolean | undefined),\n\t\t\t\t{\n\t\t\t\t\t...sessionOption,\n\t\t\t\t\t...(opts.projection ? { projection: opts.projection } : {}),\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (opts.sort !== undefined) cursor = cursor.sort(opts.sort as never);\n\t\t\tif (opts.skip !== undefined) cursor = cursor.skip(opts.skip as number);\n\t\t\tif (opts.limit !== undefined) cursor = cursor.limit(opts.limit as number);\n\t\t\treturn cursor.toArray();\n\t\t});\n\t}\n\n\tasync function countDocuments(\n\t\tfilter?: unknown,\n\t\topts: { withDeleted?: boolean } = {},\n\t) {\n\t\treturn run(async () =>\n\t\t\tcollection.countDocuments(scoped(filter, opts.withDeleted), {\n\t\t\t\t...sessionOption,\n\t\t\t}),\n\t\t);\n\t}\n\n\t/**\n\t * `findOneAndUpdate` answers `null` for a document that is not there, one\n\t * that is soft-deleted, and one whose version moved. Only a second read\n\t * tells them apart.\n\t */\n\tasync function updatedOrThrow(\n\t\tid: unknown,\n\t\tfilter: Fields,\n\t\tupdate: Fields,\n\t\texpectedVersion: number | undefined,\n\t): Promise<Fields> {\n\t\tconst updated = await run(async () =>\n\t\t\tcollection.findOneAndUpdate(filter, update, {\n\t\t\t\t...sessionOption,\n\t\t\t\treturnDocument: 'after',\n\t\t\t}),\n\t\t);\n\t\tif (updated) return updated as Fields;\n\n\t\tif (expectedVersion !== undefined) {\n\t\t\tconst current = await findOne({ _id: id });\n\t\t\tif (current) {\n\t\t\t\tthrow new OptimisticLockError(\n\t\t\t\t\t`Document ${String(id)} of \"${name}\" is at version ${String(\n\t\t\t\t\t\tcurrent.version,\n\t\t\t\t\t)}, not ${expectedVersion}: it changed since it was read`,\n\t\t\t\t\t{\n\t\t\t\t\t\tcollection: name,\n\t\t\t\t\t\tid,\n\t\t\t\t\t\texpectedVersion,\n\t\t\t\t\t\tactualVersion:\n\t\t\t\t\t\t\ttypeof current.version === 'number' ? current.version : undefined,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tthrow notFound(id);\n\t}\n\n\tasync function hardDelete(id: unknown): Promise<Fields> {\n\t\tconst deleted = await run(async () =>\n\t\t\tcollection.findOneAndDelete({ _id: id }, { ...sessionOption }),\n\t\t);\n\t\tif (!deleted) throw notFound(id);\n\t\treturn deleted as Fields;\n\t}\n\n\tasync function hardDeleteMany(filter: unknown): Promise<number> {\n\t\trequireFilter('hardDeleteMany', filter);\n\t\treturn run(async () => {\n\t\t\tconst result = await collection.deleteMany(filter as Fields, {\n\t\t\t\t...sessionOption,\n\t\t\t});\n\t\t\treturn result.deletedCount;\n\t\t});\n\t}\n\n\tconst repository = {\n\t\tdefinition,\n\t\tdb,\n\t\tcollection,\n\t\tsession,\n\n\t\twith: (other: ClientSession | undefined) =>\n\t\t\tbuild(db, definition, { ...options, session: other }),\n\t\tas: (who: unknown) => build(db, definition, { ...options, actor: who }),\n\t\tsync: (syncOptions: SyncOptions = {}) =>\n\t\t\tsyncCollection(db, definition, { ...sessionOption, ...syncOptions }),\n\n\t\tfindById,\n\t\tgetById,\n\n\t\tasync findFirst(filter?: unknown, opts: Fields = {}) {\n\t\t\tconst [first] = await findMany({ ...opts, filter, limit: 1 });\n\t\t\treturn first;\n\t\t},\n\n\t\tfindMany,\n\n\t\tasync create(values: unknown) {\n\t\t\tconst document = toDocument(values);\n\t\t\treturn run(async () => {\n\t\t\t\tawait collection.insertOne(document as Document, { ...sessionOption });\n\t\t\t\treturn document;\n\t\t\t});\n\t\t},\n\n\t\tasync createMany(values: readonly unknown[]) {\n\t\t\tif (values.length === 0) return [];\n\t\t\tconst documents = values.map(toDocument);\n\t\t\treturn run(async () => {\n\t\t\t\tawait collection.insertMany(documents as Document[], {\n\t\t\t\t\t...sessionOption,\n\t\t\t\t});\n\t\t\t\treturn documents;\n\t\t\t});\n\t\t},\n\n\t\tasync update(id: unknown, patch: unknown, opts: Fields = {}) {\n\t\t\tconst expectedVersion = opts.expectedVersion as number | undefined;\n\t\t\tif (expectedVersion !== undefined && !locks) {\n\t\t\t\tthrow new TypeError(\n\t\t\t\t\t`update: expectedVersion needs a \"version\" field, and \"${name}\" has none`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst update = toUpdate(patch);\n\t\t\tconst filter = mergeFilters(\n\t\t\t\t{\n\t\t\t\t\t_id: id,\n\t\t\t\t\t...(expectedVersion === undefined\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: { version: expectedVersion }),\n\t\t\t\t},\n\t\t\t\tlive(),\n\t\t\t);\n\t\t\treturn updatedOrThrow(id, filter, update, expectedVersion);\n\t\t},\n\n\t\tasync updateMany(filter: unknown, patch: unknown) {\n\t\t\trequireFilter('updateMany', filter);\n\t\t\tconst update = toUpdate(patch);\n\t\t\treturn run(async () => {\n\t\t\t\tconst result = await collection.updateMany(scoped(filter), update, {\n\t\t\t\t\t...sessionOption,\n\t\t\t\t});\n\t\t\t\treturn result.modifiedCount;\n\t\t\t});\n\t\t},\n\n\t\tasync delete(id: unknown) {\n\t\t\tif (!softDeletes) return hardDelete(id);\n\t\t\tconst set: Fields = { deletedAt: new Date() };\n\t\t\tif (actor !== undefined && stamps.deletedBy) set.deletedBy = actor;\n\t\t\tconst update: Fields = { $set: set };\n\t\t\tif (locks) update.$inc = { version: 1 };\n\t\t\treturn updatedOrThrow(\n\t\t\t\tid,\n\t\t\t\tmergeFilters({ _id: id }, live()),\n\t\t\t\tupdate,\n\t\t\t\tundefined,\n\t\t\t);\n\t\t},\n\n\t\tasync deleteMany(filter: unknown) {\n\t\t\trequireFilter('deleteMany', filter);\n\t\t\tif (!softDeletes) return hardDeleteMany(filter);\n\t\t\tconst set: Fields = { deletedAt: new Date() };\n\t\t\tif (actor !== undefined && stamps.deletedBy) set.deletedBy = actor;\n\t\t\tconst update: Fields = { $set: set };\n\t\t\tif (locks) update.$inc = { version: 1 };\n\t\t\treturn run(async () => {\n\t\t\t\tconst result = await collection.updateMany(scoped(filter), update, {\n\t\t\t\t\t...sessionOption,\n\t\t\t\t});\n\t\t\t\treturn result.modifiedCount;\n\t\t\t});\n\t\t},\n\n\t\thardDelete,\n\t\thardDeleteMany,\n\n\t\tasync restore(id: unknown) {\n\t\t\tif (!stamps.deletedAt) {\n\t\t\t\tthrow new TypeError(`restore: \"${name}\" has no soft delete`);\n\t\t\t}\n\t\t\tconst set: Fields = { deletedAt: null };\n\t\t\tif (stamps.deletedBy) set.deletedBy = null;\n\t\t\tif (touches) set.updatedAt = new Date();\n\t\t\tconst update: Fields = { $set: set };\n\t\t\tif (locks) update.$inc = { version: 1 };\n\t\t\treturn updatedOrThrow(id, { _id: id }, update, undefined);\n\t\t},\n\n\t\tcount: countDocuments,\n\n\t\tasync exists(filter: unknown, opts: { withDeleted?: boolean } = {}) {\n\t\t\tconst found = await findOne(scoped(filter, opts.withDeleted), { _id: 1 });\n\t\t\treturn found !== null && found !== undefined;\n\t\t},\n\n\t\tasync paginate(opts: Fields = {}): Promise<Page<Fields>> {\n\t\t\tconst window = pageWindow(opts, maxPageSize);\n\t\t\tconst [items, total] = await Promise.all([\n\t\t\t\tfindMany({\n\t\t\t\t\tfilter: opts.filter,\n\t\t\t\t\tsort: opts.sort ?? { _id: 1 },\n\t\t\t\t\tlimit: window.limit,\n\t\t\t\t\tskip: window.skip,\n\t\t\t\t\twithDeleted: opts.withDeleted,\n\t\t\t\t}),\n\t\t\t\tcountDocuments(opts.filter, {\n\t\t\t\t\twithDeleted: opts.withDeleted as boolean | undefined,\n\t\t\t\t}),\n\t\t\t]);\n\t\t\treturn toPage(items, total, window);\n\t\t},\n\n\t\tasync paginateByCursor(opts: Fields = {}): Promise<CursorPage<Fields>> {\n\t\t\tconst sortField = (opts.orderBy as string | undefined) ?? '_id';\n\t\t\tif (!shape[sortField] && sortField !== '_id') {\n\t\t\t\tthrow new TypeError(\n\t\t\t\t\t`paginateByCursor: \"${name}\" has no field \"${sortField}\" in its schema`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst direction = (opts.direction as OrderDirection | undefined) ?? 'asc';\n\t\t\tconst fields = sortField === '_id' ? ['_id'] : [sortField, '_id'];\n\t\t\tconst cursorKey = `${sortField}:${direction}`;\n\t\t\tconst limit = cursorLimit(opts.limit as number | undefined, maxPageSize);\n\t\t\tconst past = direction === 'asc' ? '$gt' : '$lt';\n\n\t\t\tlet after: Fields | undefined;\n\t\t\tif (opts.after) {\n\t\t\t\tconst { values } = decodeCursor(opts.after as string, cursorKey);\n\t\t\t\tif (values.length !== fields.length) {\n\t\t\t\t\tthrow new DataError(\n\t\t\t\t\t\t`Invalid cursor: expected ${fields.length} value(s), got ${values.length}`,\n\t\t\t\t\t\t{ collection: name },\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// `a > x OR (a = x AND b > y)`, the keyset of the ordering.\n\t\t\t\tafter = {\n\t\t\t\t\t$or: fields.map((field, index) => ({\n\t\t\t\t\t\t...Object.fromEntries(\n\t\t\t\t\t\t\tfields\n\t\t\t\t\t\t\t\t.slice(0, index)\n\t\t\t\t\t\t\t\t.map((previous, i) => [previous, values[i]]),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t[field]: { [past]: values[index] },\n\t\t\t\t\t})),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst sort = Object.fromEntries(\n\t\t\t\tfields.map((field) => [field, direction === 'asc' ? 1 : -1]),\n\t\t\t);\n\t\t\tconst documents = await findMany({\n\t\t\t\tfilter: mergeFilters(\n\t\t\t\t\tisRecord(opts.filter) ? opts.filter : undefined,\n\t\t\t\t\tafter,\n\t\t\t\t),\n\t\t\t\tsort,\n\t\t\t\tlimit: limit + 1,\n\t\t\t\twithDeleted: opts.withDeleted,\n\t\t\t});\n\n\t\t\tconst items = documents.slice(0, limit);\n\t\t\tconst last = items.at(-1);\n\t\t\tif (documents.length <= limit || !last) {\n\t\t\t\treturn { items, nextCursor: null };\n\t\t\t}\n\n\t\t\tconst values = fields.map((field) => {\n\t\t\t\tconst value = last[field];\n\t\t\t\tif (value === null || value === undefined) {\n\t\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\t`paginateByCursor: \"${field}\" is null in a document of \"${name}\". ` +\n\t\t\t\t\t\t\t'Page along a field every document has.',\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t});\n\t\t\treturn { items, nextCursor: encodeCursor({ key: cursorKey, values }) };\n\t\t},\n\t};\n\n\treturn repository;\n}\n",
|
|
16
|
+
"import type { ClientSession, Db, Document } from 'mongodb';\nimport type { z } from 'zod';\nimport {\n\ttype AnyCollectionDefinition,\n\ttype CollectionDefinition,\n\tstampsOf,\n} from '../definition/define-collection';\nimport {\n\tDataError,\n\tNotFoundError,\n\tOptimisticLockError,\n} from '../errors/data-error';\nimport { toDataError } from '../errors/to-data-error';\nimport { decodeCursor, encodeCursor } from '../pagination/cursor';\nimport {\n\ttype CursorPage,\n\tcursorLimit,\n\tDEFAULT_MAX_PAGE_SIZE,\n\ttype Page,\n\tpageWindow,\n\ttoPage,\n} from '../pagination/page';\nimport { type SyncOptions, syncCollection } from '../sync/sync-collection';\nimport type { OrderDirection, Repository, RepositoryOptions } from './types';\n\ntype Fields = Record<string, unknown>;\n\nfunction isRecord(value: unknown): value is Fields {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Does this patch speak in MongoDB's operators rather than in fields? */\nfunction isUpdateFilter(patch: Fields): boolean {\n\treturn Object.keys(patch).some((key) => key.startsWith('$'));\n}\n\n/** `a` and `b`, without letting one's `$or` swallow the other's. */\nfunction mergeFilters(a: Fields | undefined, b: Fields | undefined): Fields {\n\tconst left = a && Object.keys(a).length > 0 ? a : undefined;\n\tconst right = b && Object.keys(b).length > 0 ? b : undefined;\n\tif (!left) return right ?? {};\n\tif (!right) return left;\n\treturn { $and: [left, right] };\n}\n\n/**\n * A repository over one collection: typed reads and writes by `_id` or by\n * filter, pagination, soft delete, optimistic locking, audit stamps, and\n * MongoDB errors turned into this package's.\n *\n * ```ts\n * const users = createRepository(db, usersCollection);\n * const ada = await users.create({ email: 'ada@example.com' });\n * await users.update(ada._id, { name: 'Ada' }, { expectedVersion: ada.version });\n * ```\n *\n * Every operation runs in the repository's session, which `with(session)`\n * sets: MongoDB has no ambient session, so a write inside a transaction that\n * was not given one is not part of it and is not rolled back.\n */\nexport function createRepository<Schema extends z.ZodObject>(\n\tdb: Db,\n\tdefinition: CollectionDefinition<Schema>,\n\toptions: RepositoryOptions = {},\n): Repository<CollectionDefinition<Schema>> {\n\treturn build(db, definition, options) as unknown as Repository<\n\t\tCollectionDefinition<Schema>\n\t>;\n}\n\nfunction build(\n\tdb: Db,\n\tdefinition: AnyCollectionDefinition,\n\toptions: RepositoryOptions,\n) {\n\tconst name = definition.name;\n\t// The driver types a collection by its documents; this body works on any\n\t// collection, and the public type above is what callers see.\n\tconst collection = db.collection<any>(name);\n\tconst shape = definition.schema.shape as Record<string, z.ZodType>;\n\t// A schema may declare an `id` field of its own; then it is that field's,\n\t// and the repository neither computes it nor drops it.\n\tconst hasOwnId = 'id' in shape;\n\tconst stamps = stampsOf(definition);\n\tconst session = options.session;\n\tconst actor = options.actor;\n\tconst maxPageSize = options.maxPageSize ?? DEFAULT_MAX_PAGE_SIZE;\n\tconst parses = (options.validate ?? 'parse') === 'parse';\n\tconst softDeletes = options.softDelete ?? stamps.deletedAt;\n\tconst touches = options.touchUpdatedAt ?? stamps.updatedAt;\n\tconst locks = options.optimisticLock ?? stamps.version;\n\n\tif (options.softDelete === true && !stamps.deletedAt) {\n\t\tthrow new TypeError(\n\t\t\t`createRepository: softDelete needs a \"deletedAt\" field, and \"${name}\" has none`,\n\t\t);\n\t}\n\tif (options.optimisticLock === true && !stamps.version) {\n\t\tthrow new TypeError(\n\t\t\t`createRepository: optimisticLock needs a \"version\" field, and \"${name}\" has none`,\n\t\t);\n\t}\n\n\tconst run = async <T>(fn: () => Promise<T>): Promise<T> => {\n\t\ttry {\n\t\t\treturn await fn();\n\t\t} catch (error) {\n\t\t\tthrow toDataError(error, { collection: name });\n\t\t}\n\t};\n\n\tconst sessionOption = session ? { session } : {};\n\n\t/** The filter that leaves soft-deleted documents out. */\n\tconst live = (withDeleted?: boolean): Fields | undefined =>\n\t\tsoftDeletes && !withDeleted ? { deletedAt: null } : undefined;\n\n\tconst scoped = (filter: unknown, withDeleted?: boolean): Fields =>\n\t\tmergeFilters(isRecord(filter) ? filter : undefined, live(withDeleted));\n\n\t/**\n\t * `id` on a document the repository gives back: `_id` as a string, computed\n\t * rather than stored — the collection holds `_id` alone.\n\t *\n\t * It is enumerable, so `JSON.stringify` and a spread carry it and a handler\n\t * can return the document as it is. `toDocument` drops it again on a write,\n\t * and it is no part of `DocumentOf`, so nothing can filter on it: the server\n\t * would match nothing.\n\t */\n\tconst withId = <T>(document: T): T => {\n\t\tif (\n\t\t\thasOwnId ||\n\t\t\t!isRecord(document) ||\n\t\t\tdocument._id === undefined ||\n\t\t\tObject.hasOwn(document, 'id')\n\t\t) {\n\t\t\treturn document;\n\t\t}\n\t\tObject.defineProperty(document, 'id', {\n\t\t\tget: () => String((document as Fields)._id),\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\t\t});\n\t\treturn document;\n\t};\n\n\tconst notFound = (id: unknown) =>\n\t\tnew NotFoundError(`No document in \"${name}\" with _id ${String(id)}`, {\n\t\t\tcollection: name,\n\t\t\tid,\n\t\t});\n\n\tconst requireFilter = (method: string, filter: unknown): void => {\n\t\tif (!isRecord(filter) || Object.keys(filter).length === 0) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`${method} needs a filter. Pass \\`{ _id: { $exists: true } }\\` to target every document of \"${name}\".`,\n\t\t\t);\n\t\t}\n\t};\n\n\t/** The document to insert: checked against the schema, defaults filled. */\n\tconst toDocument = (values: unknown): Fields => {\n\t\tconst stamped: Fields = { ...(values as Fields) };\n\t\t// A document that was read carries `id`, which is this repository's view\n\t\t// of `_id` and not a field: writing it back would be refused by the\n\t\t// validator, which allows no property the schema does not declare.\n\t\t// Parsing strips it too, but `validate: 'off'` does not parse.\n\t\tif (!hasOwnId) delete stamped.id;\n\t\tif (actor !== undefined) {\n\t\t\tif (stamps.createdBy && stamped.createdBy === undefined) {\n\t\t\t\tstamped.createdBy = actor;\n\t\t\t}\n\t\t\tif (stamps.updatedBy && stamped.updatedBy === undefined) {\n\t\t\t\tstamped.updatedBy = actor;\n\t\t\t}\n\t\t}\n\t\treturn parses ? (definition.schema.parse(stamped) as Fields) : stamped;\n\t};\n\n\t/**\n\t * The update to send: a patch of fields becomes `$set`, checked field by\n\t * field against the schema, with the stamps this repository keeps. A patch\n\t * that already speaks in operators is sent as it is, with the stamps added.\n\t */\n\tconst toUpdate = (patch: unknown): Fields => {\n\t\tif (!isRecord(patch)) {\n\t\t\tthrow new TypeError(\n\t\t\t\t`update: expected the document's fields or MongoDB's operators, not ${String(patch)}`,\n\t\t\t);\n\t\t}\n\t\tconst update: Fields = isUpdateFilter(patch) ? { ...patch } : {};\n\t\tconst set: Fields = isRecord(update.$set) ? { ...update.$set } : {};\n\n\t\tif (!isUpdateFilter(patch)) {\n\t\t\tfor (const [field, value] of Object.entries(patch)) {\n\t\t\t\tif (value === undefined) continue;\n\t\t\t\tconst schema = shape[field];\n\t\t\t\tif (!schema) {\n\t\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\t`update: \"${name}\" has no field \"${field}\" in its schema`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tset[field] = parses ? schema.parse(value) : value;\n\t\t\t}\n\t\t}\n\n\t\tif (touches && set.updatedAt === undefined) set.updatedAt = new Date();\n\t\tif (\n\t\t\tactor !== undefined &&\n\t\t\tstamps.updatedBy &&\n\t\t\tset.updatedBy === undefined\n\t\t) {\n\t\t\tset.updatedBy = actor;\n\t\t}\n\t\tif (Object.keys(set).length > 0) update.$set = set;\n\n\t\tif (locks) {\n\t\t\tconst inc = isRecord(update.$inc) ? { ...update.$inc } : {};\n\t\t\tinc.version = (inc.version as number | undefined) ?? 1;\n\t\t\tupdate.$inc = inc;\n\t\t}\n\t\treturn update;\n\t};\n\n\tconst findOne = async (filter: Fields, projection?: unknown) =>\n\t\trun(async () => {\n\t\t\tconst found = await collection.findOne(filter, {\n\t\t\t\t...sessionOption,\n\t\t\t\t...(projection ? { projection } : {}),\n\t\t\t});\n\t\t\treturn found === null ? null : withId(found as Fields);\n\t\t});\n\n\tasync function findById(id: unknown, opts: { withDeleted?: boolean } = {}) {\n\t\tconst found = await findOne(scoped({ _id: id }, opts.withDeleted));\n\t\treturn found ?? undefined;\n\t}\n\n\tasync function getById(id: unknown, opts: { withDeleted?: boolean } = {}) {\n\t\tconst found = await findById(id, opts);\n\t\tif (!found) throw notFound(id);\n\t\treturn found;\n\t}\n\n\tasync function findMany(opts: Fields = {}): Promise<Fields[]> {\n\t\treturn run(async () => {\n\t\t\tlet cursor = collection.find(\n\t\t\t\tscoped(opts.filter, opts.withDeleted as boolean | undefined),\n\t\t\t\t{\n\t\t\t\t\t...sessionOption,\n\t\t\t\t\t...(opts.projection ? { projection: opts.projection } : {}),\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (opts.sort !== undefined) cursor = cursor.sort(opts.sort as never);\n\t\t\tif (opts.skip !== undefined) cursor = cursor.skip(opts.skip as number);\n\t\t\tif (opts.limit !== undefined) cursor = cursor.limit(opts.limit as number);\n\t\t\tconst found = await cursor.toArray();\n\t\t\treturn found.map((document) => withId(document as Fields));\n\t\t});\n\t}\n\n\tasync function countDocuments(\n\t\tfilter?: unknown,\n\t\topts: { withDeleted?: boolean } = {},\n\t) {\n\t\treturn run(async () =>\n\t\t\tcollection.countDocuments(scoped(filter, opts.withDeleted), {\n\t\t\t\t...sessionOption,\n\t\t\t}),\n\t\t);\n\t}\n\n\t/**\n\t * `findOneAndUpdate` answers `null` for a document that is not there, one\n\t * that is soft-deleted, and one whose version moved. Only a second read\n\t * tells them apart.\n\t */\n\tasync function updatedOrThrow(\n\t\tid: unknown,\n\t\tfilter: Fields,\n\t\tupdate: Fields,\n\t\texpectedVersion: number | undefined,\n\t): Promise<Fields> {\n\t\tconst updated = await run(async () =>\n\t\t\tcollection.findOneAndUpdate(filter, update, {\n\t\t\t\t...sessionOption,\n\t\t\t\treturnDocument: 'after',\n\t\t\t}),\n\t\t);\n\t\tif (updated) return withId(updated as Fields);\n\n\t\tif (expectedVersion !== undefined) {\n\t\t\tconst current = await findOne({ _id: id });\n\t\t\tif (current) {\n\t\t\t\tthrow new OptimisticLockError(\n\t\t\t\t\t`Document ${String(id)} of \"${name}\" is at version ${String(\n\t\t\t\t\t\tcurrent.version,\n\t\t\t\t\t)}, not ${expectedVersion}: it changed since it was read`,\n\t\t\t\t\t{\n\t\t\t\t\t\tcollection: name,\n\t\t\t\t\t\tid,\n\t\t\t\t\t\texpectedVersion,\n\t\t\t\t\t\tactualVersion:\n\t\t\t\t\t\t\ttypeof current.version === 'number' ? current.version : undefined,\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tthrow notFound(id);\n\t}\n\n\tasync function hardDelete(id: unknown): Promise<Fields> {\n\t\tconst deleted = await run(async () =>\n\t\t\tcollection.findOneAndDelete({ _id: id }, { ...sessionOption }),\n\t\t);\n\t\tif (!deleted) throw notFound(id);\n\t\treturn withId(deleted as Fields);\n\t}\n\n\tasync function hardDeleteMany(filter: unknown): Promise<number> {\n\t\trequireFilter('hardDeleteMany', filter);\n\t\treturn run(async () => {\n\t\t\tconst result = await collection.deleteMany(filter as Fields, {\n\t\t\t\t...sessionOption,\n\t\t\t});\n\t\t\treturn result.deletedCount;\n\t\t});\n\t}\n\n\tconst repository = {\n\t\tdefinition,\n\t\tdb,\n\t\tcollection,\n\t\tsession,\n\n\t\twith: (other: ClientSession | undefined) =>\n\t\t\tbuild(db, definition, { ...options, session: other }),\n\t\tas: (who: unknown) => build(db, definition, { ...options, actor: who }),\n\t\tsync: (syncOptions: SyncOptions = {}) =>\n\t\t\tsyncCollection(db, definition, { ...sessionOption, ...syncOptions }),\n\n\t\tfindById,\n\t\tgetById,\n\n\t\tasync findFirst(filter?: unknown, opts: Fields = {}) {\n\t\t\tconst [first] = await findMany({ ...opts, filter, limit: 1 });\n\t\t\treturn first;\n\t\t},\n\n\t\tfindMany,\n\n\t\tasync create(values: unknown) {\n\t\t\tconst document = toDocument(values);\n\t\t\treturn run(async () => {\n\t\t\t\tawait collection.insertOne(document as Document, { ...sessionOption });\n\t\t\t\treturn withId(document);\n\t\t\t});\n\t\t},\n\n\t\tasync createMany(values: readonly unknown[]) {\n\t\t\tif (values.length === 0) return [];\n\t\t\tconst documents = values.map(toDocument);\n\t\t\treturn run(async () => {\n\t\t\t\tawait collection.insertMany(documents as Document[], {\n\t\t\t\t\t...sessionOption,\n\t\t\t\t});\n\t\t\t\treturn documents.map((document) => withId(document));\n\t\t\t});\n\t\t},\n\n\t\tasync update(id: unknown, patch: unknown, opts: Fields = {}) {\n\t\t\tconst expectedVersion = opts.expectedVersion as number | undefined;\n\t\t\tif (expectedVersion !== undefined && !locks) {\n\t\t\t\tthrow new TypeError(\n\t\t\t\t\t`update: expectedVersion needs a \"version\" field, and \"${name}\" has none`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst update = toUpdate(patch);\n\t\t\tconst filter = mergeFilters(\n\t\t\t\t{\n\t\t\t\t\t_id: id,\n\t\t\t\t\t...(expectedVersion === undefined\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: { version: expectedVersion }),\n\t\t\t\t},\n\t\t\t\tlive(),\n\t\t\t);\n\t\t\treturn updatedOrThrow(id, filter, update, expectedVersion);\n\t\t},\n\n\t\tasync updateMany(filter: unknown, patch: unknown) {\n\t\t\trequireFilter('updateMany', filter);\n\t\t\tconst update = toUpdate(patch);\n\t\t\treturn run(async () => {\n\t\t\t\tconst result = await collection.updateMany(scoped(filter), update, {\n\t\t\t\t\t...sessionOption,\n\t\t\t\t});\n\t\t\t\treturn result.modifiedCount;\n\t\t\t});\n\t\t},\n\n\t\tasync delete(id: unknown) {\n\t\t\tif (!softDeletes) return hardDelete(id);\n\t\t\tconst set: Fields = { deletedAt: new Date() };\n\t\t\tif (actor !== undefined && stamps.deletedBy) set.deletedBy = actor;\n\t\t\tconst update: Fields = { $set: set };\n\t\t\tif (locks) update.$inc = { version: 1 };\n\t\t\treturn updatedOrThrow(\n\t\t\t\tid,\n\t\t\t\tmergeFilters({ _id: id }, live()),\n\t\t\t\tupdate,\n\t\t\t\tundefined,\n\t\t\t);\n\t\t},\n\n\t\tasync deleteMany(filter: unknown) {\n\t\t\trequireFilter('deleteMany', filter);\n\t\t\tif (!softDeletes) return hardDeleteMany(filter);\n\t\t\tconst set: Fields = { deletedAt: new Date() };\n\t\t\tif (actor !== undefined && stamps.deletedBy) set.deletedBy = actor;\n\t\t\tconst update: Fields = { $set: set };\n\t\t\tif (locks) update.$inc = { version: 1 };\n\t\t\treturn run(async () => {\n\t\t\t\tconst result = await collection.updateMany(scoped(filter), update, {\n\t\t\t\t\t...sessionOption,\n\t\t\t\t});\n\t\t\t\treturn result.modifiedCount;\n\t\t\t});\n\t\t},\n\n\t\thardDelete,\n\t\thardDeleteMany,\n\n\t\tasync restore(id: unknown) {\n\t\t\tif (!stamps.deletedAt) {\n\t\t\t\tthrow new TypeError(`restore: \"${name}\" has no soft delete`);\n\t\t\t}\n\t\t\tconst set: Fields = { deletedAt: null };\n\t\t\tif (stamps.deletedBy) set.deletedBy = null;\n\t\t\tif (touches) set.updatedAt = new Date();\n\t\t\tconst update: Fields = { $set: set };\n\t\t\tif (locks) update.$inc = { version: 1 };\n\t\t\treturn updatedOrThrow(id, { _id: id }, update, undefined);\n\t\t},\n\n\t\tcount: countDocuments,\n\n\t\tasync exists(filter: unknown, opts: { withDeleted?: boolean } = {}) {\n\t\t\tconst found = await findOne(scoped(filter, opts.withDeleted), { _id: 1 });\n\t\t\treturn found !== null && found !== undefined;\n\t\t},\n\n\t\tasync paginate(opts: Fields = {}): Promise<Page<Fields>> {\n\t\t\tconst window = pageWindow(opts, maxPageSize);\n\t\t\tconst [items, total] = await Promise.all([\n\t\t\t\tfindMany({\n\t\t\t\t\tfilter: opts.filter,\n\t\t\t\t\tsort: opts.sort ?? { _id: 1 },\n\t\t\t\t\tlimit: window.limit,\n\t\t\t\t\tskip: window.skip,\n\t\t\t\t\twithDeleted: opts.withDeleted,\n\t\t\t\t}),\n\t\t\t\tcountDocuments(opts.filter, {\n\t\t\t\t\twithDeleted: opts.withDeleted as boolean | undefined,\n\t\t\t\t}),\n\t\t\t]);\n\t\t\treturn toPage(items, total, window);\n\t\t},\n\n\t\tasync paginateByCursor(opts: Fields = {}): Promise<CursorPage<Fields>> {\n\t\t\tconst sortField = (opts.orderBy as string | undefined) ?? '_id';\n\t\t\tif (!shape[sortField] && sortField !== '_id') {\n\t\t\t\tthrow new TypeError(\n\t\t\t\t\t`paginateByCursor: \"${name}\" has no field \"${sortField}\" in its schema`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst direction = (opts.direction as OrderDirection | undefined) ?? 'asc';\n\t\t\tconst fields = sortField === '_id' ? ['_id'] : [sortField, '_id'];\n\t\t\tconst cursorKey = `${sortField}:${direction}`;\n\t\t\tconst limit = cursorLimit(opts.limit as number | undefined, maxPageSize);\n\t\t\tconst past = direction === 'asc' ? '$gt' : '$lt';\n\n\t\t\tlet after: Fields | undefined;\n\t\t\tif (opts.after) {\n\t\t\t\tconst { values } = decodeCursor(opts.after as string, cursorKey);\n\t\t\t\tif (values.length !== fields.length) {\n\t\t\t\t\tthrow new DataError(\n\t\t\t\t\t\t`Invalid cursor: expected ${fields.length} value(s), got ${values.length}`,\n\t\t\t\t\t\t{ collection: name },\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\t// `a > x OR (a = x AND b > y)`, the keyset of the ordering.\n\t\t\t\tafter = {\n\t\t\t\t\t$or: fields.map((field, index) => ({\n\t\t\t\t\t\t...Object.fromEntries(\n\t\t\t\t\t\t\tfields\n\t\t\t\t\t\t\t\t.slice(0, index)\n\t\t\t\t\t\t\t\t.map((previous, i) => [previous, values[i]]),\n\t\t\t\t\t\t),\n\t\t\t\t\t\t[field]: { [past]: values[index] },\n\t\t\t\t\t})),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst sort = Object.fromEntries(\n\t\t\t\tfields.map((field) => [field, direction === 'asc' ? 1 : -1]),\n\t\t\t);\n\t\t\tconst documents = await findMany({\n\t\t\t\tfilter: mergeFilters(\n\t\t\t\t\tisRecord(opts.filter) ? opts.filter : undefined,\n\t\t\t\t\tafter,\n\t\t\t\t),\n\t\t\t\tsort,\n\t\t\t\tlimit: limit + 1,\n\t\t\t\twithDeleted: opts.withDeleted,\n\t\t\t});\n\n\t\t\tconst items = documents.slice(0, limit);\n\t\t\tconst last = items.at(-1);\n\t\t\tif (documents.length <= limit || !last) {\n\t\t\t\treturn { items, nextCursor: null };\n\t\t\t}\n\n\t\t\tconst values = fields.map((field) => {\n\t\t\t\tconst value = last[field];\n\t\t\t\tif (value === null || value === undefined) {\n\t\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\t`paginateByCursor: \"${field}\" is null in a document of \"${name}\". ` +\n\t\t\t\t\t\t\t'Page along a field every document has.',\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t});\n\t\t\treturn { items, nextCursor: encodeCursor({ key: cursorKey, values }) };\n\t\t},\n\t};\n\n\treturn repository;\n}\n",
|
|
16
17
|
"import type { ClientSession, MongoClient, TransactionOptions } from 'mongodb';\nimport { toDataError } from '../errors/to-data-error';\n\n/** What a transaction can be started from: a client, or a session. */\nexport type TransactionHost = MongoClient | ClientSession;\n\n/** A session, read without `instanceof`: two copies of the driver. */\nfunction isSession(host: TransactionHost): host is ClientSession {\n\treturn typeof (host as ClientSession).inTransaction === 'function';\n}\n\n/**\n * Runs `fn` in a transaction: committed when it resolves, aborted when it\n * throws, and a MongoDB error turned into a `DataError` on the way out. The\n * session is the argument, and **every operation inside has to be given it**:\n * MongoDB has no ambient session, so an operation without one runs outside the\n * transaction and is not rolled back. `repository.with(session)` is how a\n * repository takes it.\n *\n * ```ts\n * await withTransaction(client, async (session) => {\n * \tconst team = await teams.with(session).create({ name: 'Core' });\n * \tawait users.with(session).update(userId, { teamId: team._id });\n * });\n * ```\n *\n * Given a session that is already in a transaction, it **joins** it: `fn` runs\n * with that session and nothing is committed until the outer one commits.\n * MongoDB has no savepoints, so an inner failure cannot be rolled back on its\n * own, and starting a second transaction on one session throws\n * `MongoTransactionError`.\n *\n * Two things the driver does that are easy to be surprised by:\n *\n * - it **retries `fn`** from the start on a `TransientTransactionError`, and\n * the commit alone on an `UnknownTransactionCommitResult`, until 120 seconds\n * have passed. `fn` must therefore be safe to run twice.\n * - `session.abortTransaction()` inside `fn` ends the transaction without\n * throwing: `withTransaction` then resolves.\n */\nexport async function withTransaction<T>(\n\thost: TransactionHost,\n\tfn: (session: ClientSession) => Promise<T>,\n\toptions?: TransactionOptions,\n): Promise<T> {\n\ttry {\n\t\tif (isSession(host)) {\n\t\t\tif (host.inTransaction()) {\n\t\t\t\tif (options) {\n\t\t\t\t\tthrow new TypeError(\n\t\t\t\t\t\t'withTransaction: this session is already in a transaction, which ' +\n\t\t\t\t\t\t\t'this call joins. MongoDB has no savepoints, so the read ' +\n\t\t\t\t\t\t\t'concern, the write concern and the read preference are the ' +\n\t\t\t\t\t\t\t'outer transaction’s.',\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn await fn(host);\n\t\t\t}\n\t\t\treturn await host.withTransaction(fn, options);\n\t\t}\n\n\t\tconst session = host.startSession();\n\t\ttry {\n\t\t\treturn await session.withTransaction(fn, options);\n\t\t} finally {\n\t\t\tawait session.endSession();\n\t\t}\n\t} catch (error) {\n\t\tthrow toDataError(error);\n\t}\n}\n"
|
|
17
18
|
],
|
|
18
|
-
"mappings": "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",
|
|
19
|
-
"debugId": "
|
|
19
|
+
"mappings": "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",
|
|
20
|
+
"debugId": "5C569B791BADEA5664756E2164756E21",
|
|
20
21
|
"names": []
|
|
21
22
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ClientSession, Collection, Db, Filter, Sort, UpdateFilter } from 'mongodb';
|
|
2
|
-
import type { DocumentOf, FieldOf, IdOf, NewDocumentOf } from '../definition/define-collection';
|
|
2
|
+
import type { DocumentOf, FieldOf, IdOf, NewDocumentOf, ReadDocumentOf } from '../definition/define-collection';
|
|
3
3
|
import type { CursorPage, Page, PageOptions } from '../pagination/page';
|
|
4
4
|
import type { SyncOptions, SyncReport } from '../sync/sync-collection';
|
|
5
5
|
export type OrderDirection = 'asc' | 'desc';
|
|
@@ -44,6 +44,8 @@ export interface CursorPaginateOptions<Def> extends ReadOptions {
|
|
|
44
44
|
*/
|
|
45
45
|
export type Patch<Def> = Partial<DocumentOf<Def>> | (UpdateFilter<DocumentOf<Def>> & {
|
|
46
46
|
[K in keyof DocumentOf<Def>]?: never;
|
|
47
|
+
} & {
|
|
48
|
+
id?: never;
|
|
47
49
|
});
|
|
48
50
|
export interface UpdateOptions {
|
|
49
51
|
/**
|
|
@@ -105,41 +107,41 @@ export interface Repository<Def> {
|
|
|
105
107
|
/** Creates the collection, its validator and its indexes. See `syncCollection`. */
|
|
106
108
|
sync(options?: SyncOptions): Promise<SyncReport>;
|
|
107
109
|
/** The document with this `_id`, or `undefined`. */
|
|
108
|
-
findById(id: IdOf<Def>, options?: ReadOptions): Promise<
|
|
110
|
+
findById(id: IdOf<Def>, options?: ReadOptions): Promise<ReadDocumentOf<Def> | undefined>;
|
|
109
111
|
/** The document with this `_id`. Throws `NotFoundError`. */
|
|
110
|
-
getById(id: IdOf<Def>, options?: ReadOptions): Promise<
|
|
112
|
+
getById(id: IdOf<Def>, options?: ReadOptions): Promise<ReadDocumentOf<Def>>;
|
|
111
113
|
/** The first document that matches, or `undefined`. */
|
|
112
|
-
findFirst(filter?: Filter<DocumentOf<Def>>, options?: FindFirstOptions<Def>): Promise<
|
|
114
|
+
findFirst(filter?: Filter<DocumentOf<Def>>, options?: FindFirstOptions<Def>): Promise<ReadDocumentOf<Def> | undefined>;
|
|
113
115
|
/** Every document that matches. */
|
|
114
|
-
findMany(options?: FindManyOptions<Def>): Promise<
|
|
116
|
+
findMany(options?: FindManyOptions<Def>): Promise<ReadDocumentOf<Def>[]>;
|
|
115
117
|
/** Checks the document against the schema, fills its defaults, inserts it. */
|
|
116
|
-
create(values: NewDocumentOf<Def>): Promise<
|
|
118
|
+
create(values: NewDocumentOf<Def>): Promise<ReadDocumentOf<Def>>;
|
|
117
119
|
/** The same, in one insert. `[]` sends nothing. */
|
|
118
|
-
createMany(values: readonly NewDocumentOf<Def>[]): Promise<
|
|
120
|
+
createMany(values: readonly NewDocumentOf<Def>[]): Promise<ReadDocumentOf<Def>[]>;
|
|
119
121
|
/** Updates the document with this `_id` and returns it. Throws `NotFoundError`. */
|
|
120
|
-
update(id: IdOf<Def>, patch: Patch<Def>, options?: UpdateOptions): Promise<
|
|
122
|
+
update(id: IdOf<Def>, patch: Patch<Def>, options?: UpdateOptions): Promise<ReadDocumentOf<Def>>;
|
|
121
123
|
/** Updates every document that matches, and returns how many changed. */
|
|
122
124
|
updateMany(filter: Filter<DocumentOf<Def>>, patch: Patch<Def>): Promise<number>;
|
|
123
125
|
/**
|
|
124
126
|
* Deletes the document with this `_id` and returns it: a soft delete on a
|
|
125
127
|
* collection with `deletedAt`. Throws `NotFoundError`.
|
|
126
128
|
*/
|
|
127
|
-
delete(id: IdOf<Def>): Promise<
|
|
129
|
+
delete(id: IdOf<Def>): Promise<ReadDocumentOf<Def>>;
|
|
128
130
|
/** Deletes every document that matches, and returns how many. */
|
|
129
131
|
deleteMany(filter: Filter<DocumentOf<Def>>): Promise<number>;
|
|
130
132
|
/** A real delete, of a live or a soft-deleted document. */
|
|
131
|
-
hardDelete(id: IdOf<Def>): Promise<
|
|
133
|
+
hardDelete(id: IdOf<Def>): Promise<ReadDocumentOf<Def>>;
|
|
132
134
|
/** A real delete of every document that matches, soft-deleted ones included. */
|
|
133
135
|
hardDeleteMany(filter: Filter<DocumentOf<Def>>): Promise<number>;
|
|
134
136
|
/** Clears `deletedAt` and returns the document. Throws `NotFoundError`. */
|
|
135
|
-
restore(id: IdOf<Def>): Promise<
|
|
137
|
+
restore(id: IdOf<Def>): Promise<ReadDocumentOf<Def>>;
|
|
136
138
|
/** How many documents match. */
|
|
137
139
|
count(filter?: Filter<DocumentOf<Def>>, options?: ReadOptions): Promise<number>;
|
|
138
140
|
/** Whether any document matches. */
|
|
139
141
|
exists(filter: Filter<DocumentOf<Def>>, options?: ReadOptions): Promise<boolean>;
|
|
140
142
|
/** One page of the documents that match, and how many there are. */
|
|
141
|
-
paginate(options?: PaginateOptions<Def>): Promise<Page<
|
|
143
|
+
paginate(options?: PaginateOptions<Def>): Promise<Page<ReadDocumentOf<Def>>>;
|
|
142
144
|
/** One page of the documents that match, after a cursor. */
|
|
143
|
-
paginateByCursor(options?: CursorPaginateOptions<Def>): Promise<CursorPage<
|
|
145
|
+
paginateByCursor(options?: CursorPaginateOptions<Def>): Promise<CursorPage<ReadDocumentOf<Def>>>;
|
|
144
146
|
}
|
|
145
147
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/repository/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/repository/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxgt/mongo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A typed MongoDB collection from a Zod schema: its indexes and $jsonSchema validator synced idempotently, a typed repository with pagination, transactions, optimistic locking, soft delete and its own errors",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|