@nxgt/mongo 0.2.0 → 0.3.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 +89 -26
- package/dist/collection/get-collection.d.ts +26 -0
- package/dist/collection/get-collection.d.ts.map +1 -0
- package/dist/collection/types.d.ts +270 -0
- package/dist/collection/types.d.ts.map +1 -0
- package/dist/definition/define-collection.d.ts +2 -2
- package/dist/definition/fields.d.ts +5 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +248 -224
- package/dist/index.js.map +9 -9
- package/dist/transaction/with-transaction.d.ts +4 -4
- package/package.json +1 -1
- package/dist/repository/create-repository.d.ts +0 -21
- package/dist/repository/create-repository.d.ts.map +0 -1
- package/dist/repository/types.d.ts +0 -147
- package/dist/repository/types.d.ts.map +0 -1
package/dist/index.js
CHANGED
|
@@ -25,13 +25,6 @@ function stampsOf(definition) {
|
|
|
25
25
|
deletedBy: has("deletedBy")
|
|
26
26
|
};
|
|
27
27
|
}
|
|
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
|
|
33
|
-
import { ObjectId } from "mongodb";
|
|
34
|
-
import { z } from "zod";
|
|
35
28
|
|
|
36
29
|
// src/errors/data-error.ts
|
|
37
30
|
class DataError extends Error {
|
|
@@ -100,201 +93,8 @@ class InvalidCursorError extends DataError {
|
|
|
100
93
|
}
|
|
101
94
|
}
|
|
102
95
|
|
|
103
|
-
// src/definition/object-id.ts
|
|
104
|
-
var HEX_24 = /^[0-9a-fA-F]{24}$/;
|
|
105
|
-
function isObjectId(value) {
|
|
106
|
-
return typeof value === "object" && value !== null && value._bsontype === "ObjectId";
|
|
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
|
|
146
|
-
function objectId() {
|
|
147
|
-
return z2.custom(isObjectId, { error: "must be an ObjectId" }).meta({ bsonType: "objectId" });
|
|
148
|
-
}
|
|
149
|
-
function id() {
|
|
150
|
-
return objectId().default(() => new ObjectId2);
|
|
151
|
-
}
|
|
152
|
-
function timestamps() {
|
|
153
|
-
return {
|
|
154
|
-
createdAt: z2.date().default(() => new Date),
|
|
155
|
-
updatedAt: z2.date().default(() => new Date)
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
function softDelete() {
|
|
159
|
-
return { deletedAt: z2.date().nullable().default(null) };
|
|
160
|
-
}
|
|
161
|
-
function optimisticLock() {
|
|
162
|
-
return { version: z2.int().nonnegative().default(0) };
|
|
163
|
-
}
|
|
164
|
-
function actors(actor = objectId()) {
|
|
165
|
-
return {
|
|
166
|
-
createdBy: actor.nullable().default(null),
|
|
167
|
-
updatedBy: actor.nullable().default(null),
|
|
168
|
-
deletedBy: actor.nullable().default(null)
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
var STAMP_FIELDS = {
|
|
172
|
-
id: "_id",
|
|
173
|
-
createdAt: "createdAt",
|
|
174
|
-
updatedAt: "updatedAt",
|
|
175
|
-
deletedAt: "deletedAt",
|
|
176
|
-
version: "version",
|
|
177
|
-
createdBy: "createdBy",
|
|
178
|
-
updatedBy: "updatedBy",
|
|
179
|
-
deletedBy: "deletedBy"
|
|
180
|
-
};
|
|
181
|
-
// src/definition/json-schema.ts
|
|
182
|
-
import { z as z3 } from "zod";
|
|
183
|
-
var MONGO_JSON_SCHEMA_KEYWORDS = new Set([
|
|
184
|
-
"additionalItems",
|
|
185
|
-
"additionalProperties",
|
|
186
|
-
"allOf",
|
|
187
|
-
"anyOf",
|
|
188
|
-
"bsonType",
|
|
189
|
-
"dependencies",
|
|
190
|
-
"description",
|
|
191
|
-
"enum",
|
|
192
|
-
"exclusiveMaximum",
|
|
193
|
-
"exclusiveMinimum",
|
|
194
|
-
"items",
|
|
195
|
-
"maxItems",
|
|
196
|
-
"maxLength",
|
|
197
|
-
"maxProperties",
|
|
198
|
-
"maximum",
|
|
199
|
-
"minItems",
|
|
200
|
-
"minLength",
|
|
201
|
-
"minProperties",
|
|
202
|
-
"minimum",
|
|
203
|
-
"multipleOf",
|
|
204
|
-
"not",
|
|
205
|
-
"oneOf",
|
|
206
|
-
"pattern",
|
|
207
|
-
"patternProperties",
|
|
208
|
-
"properties",
|
|
209
|
-
"required",
|
|
210
|
-
"title",
|
|
211
|
-
"type",
|
|
212
|
-
"uniqueItems"
|
|
213
|
-
]);
|
|
214
|
-
var SCHEMA_MAPS = new Set([
|
|
215
|
-
"properties",
|
|
216
|
-
"patternProperties",
|
|
217
|
-
"dependencies"
|
|
218
|
-
]);
|
|
219
|
-
function isRecord(value) {
|
|
220
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
221
|
-
}
|
|
222
|
-
var INTEGER_BSON_TYPES = ["int", "long", "double"];
|
|
223
|
-
function convertIntegerType(node) {
|
|
224
|
-
const type = node.type;
|
|
225
|
-
if (type === "integer") {
|
|
226
|
-
delete node.type;
|
|
227
|
-
node.bsonType = [...INTEGER_BSON_TYPES];
|
|
228
|
-
node.multipleOf ??= 1;
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
if (Array.isArray(type) && type.includes("integer")) {
|
|
232
|
-
delete node.type;
|
|
233
|
-
node.bsonType = [
|
|
234
|
-
...type.filter((one) => one !== "integer"),
|
|
235
|
-
...INTEGER_BSON_TYPES
|
|
236
|
-
];
|
|
237
|
-
node.multipleOf ??= 1;
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
function refName(ref) {
|
|
241
|
-
return ref.replace(/^#\/(definitions|\$defs)\//, "");
|
|
242
|
-
}
|
|
243
|
-
function inline(value, defs, stack) {
|
|
244
|
-
if (Array.isArray(value)) {
|
|
245
|
-
return value.map((one) => inline(one, defs, stack));
|
|
246
|
-
}
|
|
247
|
-
if (!isRecord(value))
|
|
248
|
-
return value;
|
|
249
|
-
if (typeof value.$ref === "string") {
|
|
250
|
-
const name = refName(value.$ref);
|
|
251
|
-
if (stack.includes(name)) {
|
|
252
|
-
throw new TypeError(`toMongoJsonSchema: "${name}" refers to itself. MongoDB's $jsonSchema ` + "has no $ref, so a recursive schema cannot be a validator. Give the " + "collection no validator, or model the field as an object with no " + "schema of its own.");
|
|
253
|
-
}
|
|
254
|
-
const target = defs[name];
|
|
255
|
-
if (!isRecord(target)) {
|
|
256
|
-
throw new TypeError(`toMongoJsonSchema: cannot resolve ${value.$ref}, which zod emitted`);
|
|
257
|
-
}
|
|
258
|
-
const { $ref: _ref, ...siblings } = value;
|
|
259
|
-
return {
|
|
260
|
-
...inline(target, defs, [...stack, name]),
|
|
261
|
-
...inline(siblings, defs, stack)
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
const out = {};
|
|
265
|
-
for (const [key, inner] of Object.entries(value)) {
|
|
266
|
-
if (!MONGO_JSON_SCHEMA_KEYWORDS.has(key))
|
|
267
|
-
continue;
|
|
268
|
-
if (SCHEMA_MAPS.has(key) && isRecord(inner)) {
|
|
269
|
-
const mapped = {};
|
|
270
|
-
for (const [name, schema] of Object.entries(inner)) {
|
|
271
|
-
mapped[name] = inline(schema, defs, stack);
|
|
272
|
-
}
|
|
273
|
-
out[key] = mapped;
|
|
274
|
-
continue;
|
|
275
|
-
}
|
|
276
|
-
out[key] = inline(inner, defs, stack);
|
|
277
|
-
}
|
|
278
|
-
convertIntegerType(out);
|
|
279
|
-
return out;
|
|
280
|
-
}
|
|
281
|
-
function toMongoJsonSchema(schema) {
|
|
282
|
-
const json = z3.toJSONSchema(schema, {
|
|
283
|
-
target: "draft-4",
|
|
284
|
-
io: "output",
|
|
285
|
-
unrepresentable: "any",
|
|
286
|
-
override: (ctx) => {
|
|
287
|
-
const type = ctx.zodSchema._zod.def.type;
|
|
288
|
-
if (type === "date" && ctx.jsonSchema.bsonType === undefined) {
|
|
289
|
-
ctx.jsonSchema.bsonType = "date";
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
const definitions = isRecord(json.definitions) ? json.definitions : isRecord(json.$defs) ? json.$defs : {};
|
|
294
|
-
return inline(json, definitions, []);
|
|
295
|
-
}
|
|
296
96
|
// src/errors/to-data-error.ts
|
|
297
|
-
function
|
|
97
|
+
function isRecord(value) {
|
|
298
98
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
299
99
|
}
|
|
300
100
|
function asArray(value) {
|
|
@@ -310,8 +110,8 @@ function indexFromMessage(message) {
|
|
|
310
110
|
}
|
|
311
111
|
function keysOfDuplicate(error) {
|
|
312
112
|
const pattern = error.keyPattern;
|
|
313
|
-
if (
|
|
314
|
-
const values =
|
|
113
|
+
if (isRecord(pattern)) {
|
|
114
|
+
const values = isRecord(error.keyValue) ? error.keyValue : undefined;
|
|
315
115
|
return { keys: Object.keys(pattern), values };
|
|
316
116
|
}
|
|
317
117
|
const inMessage = text(error.errmsg)?.match(/dup key:\s*\{([^}]*)\}/)?.[1];
|
|
@@ -322,8 +122,8 @@ function keysOfDuplicate(error) {
|
|
|
322
122
|
}
|
|
323
123
|
function firstWriteError(error) {
|
|
324
124
|
for (const write of asArray(error.writeErrors)) {
|
|
325
|
-
const inner =
|
|
326
|
-
if (
|
|
125
|
+
const inner = isRecord(write) && isRecord(write.err) ? write.err : write;
|
|
126
|
+
if (isRecord(inner))
|
|
327
127
|
return inner;
|
|
328
128
|
}
|
|
329
129
|
return;
|
|
@@ -331,11 +131,11 @@ function firstWriteError(error) {
|
|
|
331
131
|
function issuesOf(details, path = []) {
|
|
332
132
|
const issues = [];
|
|
333
133
|
for (const rule of asArray(details)) {
|
|
334
|
-
if (!
|
|
134
|
+
if (!isRecord(rule))
|
|
335
135
|
continue;
|
|
336
136
|
if (rule.propertiesNotSatisfied !== undefined) {
|
|
337
137
|
for (const property of asArray(rule.propertiesNotSatisfied)) {
|
|
338
|
-
if (!
|
|
138
|
+
if (!isRecord(property))
|
|
339
139
|
continue;
|
|
340
140
|
const name = text(property.propertyName) ?? "";
|
|
341
141
|
const nested = issuesOf(property.details, [...path, name]);
|
|
@@ -371,7 +171,7 @@ function issuesOf(details, path = []) {
|
|
|
371
171
|
function toDataError(error, context = {}) {
|
|
372
172
|
if (error instanceof DataError)
|
|
373
173
|
return error;
|
|
374
|
-
if (!
|
|
174
|
+
if (!isRecord(error))
|
|
375
175
|
return error;
|
|
376
176
|
const source = firstWriteError(error) ?? error;
|
|
377
177
|
const code = typeof source.code === "number" ? source.code : typeof error.code === "number" ? error.code : undefined;
|
|
@@ -391,15 +191,16 @@ function toDataError(error, context = {}) {
|
|
|
391
191
|
return new ConflictError(`Duplicate key on ${named}${context.collection ? ` in "${context.collection}"` : ""}`, { ...common, index, keys, values });
|
|
392
192
|
}
|
|
393
193
|
if (code === 121) {
|
|
394
|
-
const errInfo =
|
|
194
|
+
const errInfo = isRecord(source.errInfo) ? source.errInfo : undefined;
|
|
395
195
|
const issues = issuesOf(errInfo?.details);
|
|
396
196
|
return new ValidationError(`Document failed validation${context.collection ? ` in "${context.collection}"` : ""}${issues.length > 0 ? `: ${issues.map((i) => `${i.path} ${i.reason}`).join(", ")}` : ""}`, { ...common, issues, keys: issues.map((issue) => issue.path) });
|
|
397
197
|
}
|
|
398
198
|
return new DataError(message || `MongoDB error ${code}`, common);
|
|
399
199
|
}
|
|
200
|
+
|
|
400
201
|
// src/pagination/cursor.ts
|
|
401
|
-
import { ObjectId
|
|
402
|
-
function
|
|
202
|
+
import { ObjectId } from "mongodb";
|
|
203
|
+
function isObjectId(value) {
|
|
403
204
|
return typeof value === "object" && value !== null && value._bsontype === "ObjectId";
|
|
404
205
|
}
|
|
405
206
|
function replacer(key, value) {
|
|
@@ -408,7 +209,7 @@ function replacer(key, value) {
|
|
|
408
209
|
return { $date: raw.toISOString() };
|
|
409
210
|
if (typeof raw === "bigint")
|
|
410
211
|
return { $bigint: raw.toString() };
|
|
411
|
-
if (
|
|
212
|
+
if (isObjectId(raw))
|
|
412
213
|
return { $oid: raw.toHexString() };
|
|
413
214
|
return value;
|
|
414
215
|
}
|
|
@@ -422,7 +223,7 @@ function reviver(_key, value) {
|
|
|
422
223
|
if (typeof tagged.$bigint === "string")
|
|
423
224
|
return BigInt(tagged.$bigint);
|
|
424
225
|
if (typeof tagged.$oid === "string")
|
|
425
|
-
return new
|
|
226
|
+
return new ObjectId(tagged.$oid);
|
|
426
227
|
}
|
|
427
228
|
}
|
|
428
229
|
return value;
|
|
@@ -460,6 +261,7 @@ function decodeCursor(cursor, expectedKey) {
|
|
|
460
261
|
}
|
|
461
262
|
return { key, values };
|
|
462
263
|
}
|
|
264
|
+
|
|
463
265
|
// src/pagination/page.ts
|
|
464
266
|
var DEFAULT_PAGE_SIZE = 20;
|
|
465
267
|
var DEFAULT_MAX_PAGE_SIZE = 100;
|
|
@@ -486,6 +288,123 @@ function toPage(items, total, window) {
|
|
|
486
288
|
function cursorLimit(limit, maxPageSize = DEFAULT_MAX_PAGE_SIZE) {
|
|
487
289
|
return Math.min(positiveInteger("limit", limit ?? DEFAULT_PAGE_SIZE), maxPageSize);
|
|
488
290
|
}
|
|
291
|
+
|
|
292
|
+
// src/definition/json-schema.ts
|
|
293
|
+
import { z } from "zod";
|
|
294
|
+
var MONGO_JSON_SCHEMA_KEYWORDS = new Set([
|
|
295
|
+
"additionalItems",
|
|
296
|
+
"additionalProperties",
|
|
297
|
+
"allOf",
|
|
298
|
+
"anyOf",
|
|
299
|
+
"bsonType",
|
|
300
|
+
"dependencies",
|
|
301
|
+
"description",
|
|
302
|
+
"enum",
|
|
303
|
+
"exclusiveMaximum",
|
|
304
|
+
"exclusiveMinimum",
|
|
305
|
+
"items",
|
|
306
|
+
"maxItems",
|
|
307
|
+
"maxLength",
|
|
308
|
+
"maxProperties",
|
|
309
|
+
"maximum",
|
|
310
|
+
"minItems",
|
|
311
|
+
"minLength",
|
|
312
|
+
"minProperties",
|
|
313
|
+
"minimum",
|
|
314
|
+
"multipleOf",
|
|
315
|
+
"not",
|
|
316
|
+
"oneOf",
|
|
317
|
+
"pattern",
|
|
318
|
+
"patternProperties",
|
|
319
|
+
"properties",
|
|
320
|
+
"required",
|
|
321
|
+
"title",
|
|
322
|
+
"type",
|
|
323
|
+
"uniqueItems"
|
|
324
|
+
]);
|
|
325
|
+
var SCHEMA_MAPS = new Set([
|
|
326
|
+
"properties",
|
|
327
|
+
"patternProperties",
|
|
328
|
+
"dependencies"
|
|
329
|
+
]);
|
|
330
|
+
function isRecord2(value) {
|
|
331
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
332
|
+
}
|
|
333
|
+
var INTEGER_BSON_TYPES = ["int", "long", "double"];
|
|
334
|
+
function convertIntegerType(node) {
|
|
335
|
+
const type = node.type;
|
|
336
|
+
if (type === "integer") {
|
|
337
|
+
delete node.type;
|
|
338
|
+
node.bsonType = [...INTEGER_BSON_TYPES];
|
|
339
|
+
node.multipleOf ??= 1;
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
if (Array.isArray(type) && type.includes("integer")) {
|
|
343
|
+
delete node.type;
|
|
344
|
+
node.bsonType = [
|
|
345
|
+
...type.filter((one) => one !== "integer"),
|
|
346
|
+
...INTEGER_BSON_TYPES
|
|
347
|
+
];
|
|
348
|
+
node.multipleOf ??= 1;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
function refName(ref) {
|
|
352
|
+
return ref.replace(/^#\/(definitions|\$defs)\//, "");
|
|
353
|
+
}
|
|
354
|
+
function inline(value, defs, stack) {
|
|
355
|
+
if (Array.isArray(value)) {
|
|
356
|
+
return value.map((one) => inline(one, defs, stack));
|
|
357
|
+
}
|
|
358
|
+
if (!isRecord2(value))
|
|
359
|
+
return value;
|
|
360
|
+
if (typeof value.$ref === "string") {
|
|
361
|
+
const name = refName(value.$ref);
|
|
362
|
+
if (stack.includes(name)) {
|
|
363
|
+
throw new TypeError(`toMongoJsonSchema: "${name}" refers to itself. MongoDB's $jsonSchema ` + "has no $ref, so a recursive schema cannot be a validator. Give the " + "collection no validator, or model the field as an object with no " + "schema of its own.");
|
|
364
|
+
}
|
|
365
|
+
const target = defs[name];
|
|
366
|
+
if (!isRecord2(target)) {
|
|
367
|
+
throw new TypeError(`toMongoJsonSchema: cannot resolve ${value.$ref}, which zod emitted`);
|
|
368
|
+
}
|
|
369
|
+
const { $ref: _ref, ...siblings } = value;
|
|
370
|
+
return {
|
|
371
|
+
...inline(target, defs, [...stack, name]),
|
|
372
|
+
...inline(siblings, defs, stack)
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
const out = {};
|
|
376
|
+
for (const [key, inner] of Object.entries(value)) {
|
|
377
|
+
if (!MONGO_JSON_SCHEMA_KEYWORDS.has(key))
|
|
378
|
+
continue;
|
|
379
|
+
if (SCHEMA_MAPS.has(key) && isRecord2(inner)) {
|
|
380
|
+
const mapped = {};
|
|
381
|
+
for (const [name, schema] of Object.entries(inner)) {
|
|
382
|
+
mapped[name] = inline(schema, defs, stack);
|
|
383
|
+
}
|
|
384
|
+
out[key] = mapped;
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
out[key] = inline(inner, defs, stack);
|
|
388
|
+
}
|
|
389
|
+
convertIntegerType(out);
|
|
390
|
+
return out;
|
|
391
|
+
}
|
|
392
|
+
function toMongoJsonSchema(schema) {
|
|
393
|
+
const json = z.toJSONSchema(schema, {
|
|
394
|
+
target: "draft-4",
|
|
395
|
+
io: "output",
|
|
396
|
+
unrepresentable: "any",
|
|
397
|
+
override: (ctx) => {
|
|
398
|
+
const type = ctx.zodSchema._zod.def.type;
|
|
399
|
+
if (type === "date" && ctx.jsonSchema.bsonType === undefined) {
|
|
400
|
+
ctx.jsonSchema.bsonType = "date";
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
});
|
|
404
|
+
const definitions = isRecord2(json.definitions) ? json.definitions : isRecord2(json.$defs) ? json.$defs : {};
|
|
405
|
+
return inline(json, definitions, []);
|
|
406
|
+
}
|
|
407
|
+
|
|
489
408
|
// src/sync/index-diff.ts
|
|
490
409
|
var COLLATION_DEFAULTS = {
|
|
491
410
|
caseLevel: false,
|
|
@@ -709,7 +628,7 @@ async function syncCollections(db, definitions, options = {}) {
|
|
|
709
628
|
return reports;
|
|
710
629
|
}
|
|
711
630
|
|
|
712
|
-
// src/
|
|
631
|
+
// src/collection/get-collection.ts
|
|
713
632
|
function isRecord3(value) {
|
|
714
633
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
715
634
|
}
|
|
@@ -725,7 +644,18 @@ function mergeFilters(a, b) {
|
|
|
725
644
|
return left;
|
|
726
645
|
return { $and: [left, right] };
|
|
727
646
|
}
|
|
728
|
-
function
|
|
647
|
+
function databaseOf(source, name) {
|
|
648
|
+
const client = source;
|
|
649
|
+
if (typeof client.db === "function")
|
|
650
|
+
return client.db(name);
|
|
651
|
+
const db = source;
|
|
652
|
+
if (name !== undefined && db.databaseName !== name) {
|
|
653
|
+
throw new TypeError(`getCollection: given a Db for "${db.databaseName}", and a db option of ` + `"${name}". Pass the client, or the database you mean.`);
|
|
654
|
+
}
|
|
655
|
+
return db;
|
|
656
|
+
}
|
|
657
|
+
function getCollection(source, definition, options = {}) {
|
|
658
|
+
const db = databaseOf(source, options.db);
|
|
729
659
|
return build(db, definition, options);
|
|
730
660
|
}
|
|
731
661
|
function build(db, definition, options) {
|
|
@@ -742,10 +672,10 @@ function build(db, definition, options) {
|
|
|
742
672
|
const touches = options.touchUpdatedAt ?? stamps.updatedAt;
|
|
743
673
|
const locks = options.optimisticLock ?? stamps.version;
|
|
744
674
|
if (options.softDelete === true && !stamps.deletedAt) {
|
|
745
|
-
throw new TypeError(`
|
|
675
|
+
throw new TypeError(`getCollection: softDelete needs a "deletedAt" field, and "${name}" has none`);
|
|
746
676
|
}
|
|
747
677
|
if (options.optimisticLock === true && !stamps.version) {
|
|
748
|
-
throw new TypeError(`
|
|
678
|
+
throw new TypeError(`getCollection: optimisticLock needs a "version" field, and "${name}" has none`);
|
|
749
679
|
}
|
|
750
680
|
const run = async (fn) => {
|
|
751
681
|
try {
|
|
@@ -895,12 +825,12 @@ function build(db, definition, options) {
|
|
|
895
825
|
return result.deletedCount;
|
|
896
826
|
});
|
|
897
827
|
}
|
|
898
|
-
const
|
|
828
|
+
const api = {
|
|
899
829
|
definition,
|
|
900
830
|
db,
|
|
901
|
-
collection,
|
|
831
|
+
raw: collection,
|
|
902
832
|
session,
|
|
903
|
-
|
|
833
|
+
withSession: (other) => build(db, definition, { ...options, session: other }),
|
|
904
834
|
as: (who) => build(db, definition, { ...options, actor: who }),
|
|
905
835
|
sync: (syncOptions = {}) => syncCollection(db, definition, { ...sessionOption, ...syncOptions }),
|
|
906
836
|
findById,
|
|
@@ -1060,8 +990,102 @@ function build(db, definition, options) {
|
|
|
1060
990
|
return { items, nextCursor: encodeCursor({ key: cursorKey, values }) };
|
|
1061
991
|
}
|
|
1062
992
|
};
|
|
1063
|
-
return
|
|
993
|
+
return new Proxy(api, {
|
|
994
|
+
get(target, key, receiver) {
|
|
995
|
+
if (Reflect.has(target, key))
|
|
996
|
+
return Reflect.get(target, key, receiver);
|
|
997
|
+
const value = collection[key];
|
|
998
|
+
return typeof value === "function" ? value.bind(collection) : value;
|
|
999
|
+
},
|
|
1000
|
+
has(target, key) {
|
|
1001
|
+
return Reflect.has(target, key) || key in collection;
|
|
1002
|
+
}
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
// src/definition/fields.ts
|
|
1006
|
+
import { ObjectId as ObjectId3 } from "mongodb";
|
|
1007
|
+
import { z as z3 } from "zod";
|
|
1008
|
+
|
|
1009
|
+
// src/definition/object-id.ts
|
|
1010
|
+
import { ObjectId as ObjectId2 } from "mongodb";
|
|
1011
|
+
import { z as z2 } from "zod";
|
|
1012
|
+
var HEX_24 = /^[0-9a-fA-F]{24}$/;
|
|
1013
|
+
function isObjectId2(value) {
|
|
1014
|
+
return typeof value === "object" && value !== null && value._bsontype === "ObjectId";
|
|
1015
|
+
}
|
|
1016
|
+
function isObjectIdString(value) {
|
|
1017
|
+
return typeof value === "string" && HEX_24.test(value);
|
|
1018
|
+
}
|
|
1019
|
+
function isValidObjectId(value) {
|
|
1020
|
+
return isObjectId2(value) || isObjectIdString(value);
|
|
1021
|
+
}
|
|
1022
|
+
function tryObjectId(value) {
|
|
1023
|
+
if (isObjectId2(value))
|
|
1024
|
+
return value;
|
|
1025
|
+
if (isObjectIdString(value))
|
|
1026
|
+
return ObjectId2.createFromHexString(value);
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
1029
|
+
function describe(value) {
|
|
1030
|
+
if (value === null)
|
|
1031
|
+
return "null";
|
|
1032
|
+
if (value === undefined)
|
|
1033
|
+
return "undefined";
|
|
1034
|
+
if (typeof value === "string")
|
|
1035
|
+
return `the string ${JSON.stringify(value)}`;
|
|
1036
|
+
return `a ${typeof value}`;
|
|
1037
|
+
}
|
|
1038
|
+
function toObjectId(value, field = "_id") {
|
|
1039
|
+
const made = tryObjectId(value);
|
|
1040
|
+
if (made)
|
|
1041
|
+
return made;
|
|
1042
|
+
throw new InvalidIdError(`${field}: expected an ObjectId or its 24-character hex string, got ${describe(value)}`, { id: value, keys: [field] });
|
|
1043
|
+
}
|
|
1044
|
+
function toObjectIds(values, field = "_id") {
|
|
1045
|
+
return [...values].map((value) => toObjectId(value, field));
|
|
1046
|
+
}
|
|
1047
|
+
function objectIdParam() {
|
|
1048
|
+
return z2.custom(isValidObjectId, {
|
|
1049
|
+
error: "must be an ObjectId or its 24-character hex string"
|
|
1050
|
+
}).transform((value) => toObjectId(value));
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
// src/definition/fields.ts
|
|
1054
|
+
function objectId() {
|
|
1055
|
+
return z3.custom(isObjectId2, { error: "must be an ObjectId" }).meta({ bsonType: "objectId" });
|
|
1056
|
+
}
|
|
1057
|
+
function id() {
|
|
1058
|
+
return objectId().default(() => new ObjectId3);
|
|
1059
|
+
}
|
|
1060
|
+
function timestamps() {
|
|
1061
|
+
return {
|
|
1062
|
+
createdAt: z3.date().default(() => new Date),
|
|
1063
|
+
updatedAt: z3.date().default(() => new Date)
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
function softDelete() {
|
|
1067
|
+
return { deletedAt: z3.date().nullable().default(null) };
|
|
1068
|
+
}
|
|
1069
|
+
function optimisticLock() {
|
|
1070
|
+
return { version: z3.int().nonnegative().default(0) };
|
|
1071
|
+
}
|
|
1072
|
+
function actors(actor = objectId()) {
|
|
1073
|
+
return {
|
|
1074
|
+
createdBy: actor.nullable().default(null),
|
|
1075
|
+
updatedBy: actor.nullable().default(null),
|
|
1076
|
+
deletedBy: actor.nullable().default(null)
|
|
1077
|
+
};
|
|
1064
1078
|
}
|
|
1079
|
+
var STAMP_FIELDS = {
|
|
1080
|
+
id: "_id",
|
|
1081
|
+
createdAt: "createdAt",
|
|
1082
|
+
updatedAt: "updatedAt",
|
|
1083
|
+
deletedAt: "deletedAt",
|
|
1084
|
+
version: "version",
|
|
1085
|
+
createdBy: "createdBy",
|
|
1086
|
+
updatedBy: "updatedBy",
|
|
1087
|
+
deletedBy: "deletedBy"
|
|
1088
|
+
};
|
|
1065
1089
|
// src/transaction/with-transaction.ts
|
|
1066
1090
|
function isSession(host) {
|
|
1067
1091
|
return typeof host.inTransaction === "function";
|
|
@@ -1100,17 +1124,17 @@ export {
|
|
|
1100
1124
|
STAMP_FIELDS,
|
|
1101
1125
|
ValidationError,
|
|
1102
1126
|
actors,
|
|
1103
|
-
createRepository,
|
|
1104
1127
|
cursorLimit,
|
|
1105
1128
|
decodeCursor,
|
|
1106
1129
|
defineCollection,
|
|
1107
1130
|
diffIndexes,
|
|
1108
1131
|
encodeCursor,
|
|
1132
|
+
getCollection,
|
|
1109
1133
|
hasValidator,
|
|
1110
1134
|
id,
|
|
1111
1135
|
indexMatches,
|
|
1112
1136
|
indexNameOf,
|
|
1113
|
-
isObjectId,
|
|
1137
|
+
isObjectId2 as isObjectId,
|
|
1114
1138
|
isObjectIdString,
|
|
1115
1139
|
isValidObjectId,
|
|
1116
1140
|
normalizeIndex,
|
|
@@ -1133,5 +1157,5 @@ export {
|
|
|
1133
1157
|
withTransaction
|
|
1134
1158
|
};
|
|
1135
1159
|
|
|
1136
|
-
//# debugId=
|
|
1160
|
+
//# debugId=3B847E76D4AAF66F64756E2164756E21
|
|
1137
1161
|
//# sourceMappingURL=index.js.map
|