@terreno/api 0.13.3 → 0.14.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/dist/__tests__/versionCheckPlugin.test.js +53 -3
- package/dist/api.arrayOperations.test.js +1 -0
- package/dist/api.d.ts +15 -4
- package/dist/api.errors.test.js +1 -0
- package/dist/api.hooks.test.js +1 -0
- package/dist/api.js +153 -104
- package/dist/api.query.test.js +1 -0
- package/dist/api.test.js +174 -0
- package/dist/auth.d.ts +10 -5
- package/dist/auth.js +163 -90
- package/dist/auth.test.js +159 -0
- package/dist/betterAuthApp.test.js +1 -0
- package/dist/betterAuthSetup.d.ts +5 -6
- package/dist/betterAuthSetup.js +17 -14
- package/dist/betterAuthSetup.test.js +1 -0
- package/dist/config.d.ts +48 -0
- package/dist/config.js +248 -0
- package/dist/config.test.d.ts +1 -0
- package/dist/config.test.js +328 -0
- package/dist/configuration.test.js +1 -0
- package/dist/configurationApp.d.ts +1 -1
- package/dist/configurationApp.js +17 -13
- package/dist/configurationPlugin.test.js +1 -0
- package/dist/consentApp.test.js +1 -0
- package/dist/envConfigurationPlugin.d.ts +2 -0
- package/dist/envConfigurationPlugin.js +173 -0
- package/dist/envConfigurationPlugin.test.d.ts +1 -0
- package/dist/envConfigurationPlugin.test.js +322 -0
- package/dist/errors.d.ts +18 -7
- package/dist/errors.js +106 -10
- package/dist/errors.test.js +16 -1
- package/dist/example.js +16 -7
- package/dist/expressServer.d.ts +10 -9
- package/dist/expressServer.js +62 -53
- package/dist/expressServer.test.js +53 -2
- package/dist/githubAuth.d.ts +2 -1
- package/dist/githubAuth.js +41 -26
- package/dist/githubAuth.test.js +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/logger.d.ts +1 -1
- package/dist/logger.js +42 -20
- package/dist/models/versionConfig.d.ts +2 -0
- package/dist/models/versionConfig.js +8 -0
- package/dist/notifiers/googleChatNotifier.js +14 -16
- package/dist/notifiers/googleChatNotifier.test.js +1 -0
- package/dist/notifiers/slackNotifier.js +16 -14
- package/dist/notifiers/slackNotifier.test.js +41 -3
- package/dist/notifiers/zoomNotifier.js +7 -10
- package/dist/notifiers/zoomNotifier.test.js +1 -0
- package/dist/openApi.d.ts +1 -1
- package/dist/openApi.test.js +1 -0
- package/dist/openApiBuilder.d.ts +39 -6
- package/dist/openApiBuilder.js +1 -31
- package/dist/openApiBuilder.test.js +1 -0
- package/dist/openApiValidator.js +1 -0
- package/dist/openApiValidator.test.js +1 -0
- package/dist/permissions.d.ts +4 -4
- package/dist/permissions.js +67 -65
- package/dist/permissions.middleware.test.js +1 -0
- package/dist/permissions.test.js +1 -0
- package/dist/plugins.d.ts +5 -5
- package/dist/plugins.js +18 -9
- package/dist/plugins.test.js +1 -1
- package/dist/populate.d.ts +15 -8
- package/dist/populate.js +23 -24
- package/dist/populate.test.js +1 -0
- package/dist/realtime/changeStreamWatcher.d.ts +73 -0
- package/dist/realtime/changeStreamWatcher.js +720 -0
- package/dist/realtime/index.d.ts +6 -0
- package/dist/realtime/index.js +27 -0
- package/dist/realtime/queryMatcher.d.ts +14 -0
- package/dist/realtime/queryMatcher.js +250 -0
- package/dist/realtime/queryStore.d.ts +37 -0
- package/dist/realtime/queryStore.js +195 -0
- package/dist/realtime/realtime.test.d.ts +10 -0
- package/dist/realtime/realtime.test.js +2158 -0
- package/dist/realtime/realtimeApp.d.ts +93 -0
- package/dist/realtime/realtimeApp.js +560 -0
- package/dist/realtime/registry.d.ts +40 -0
- package/dist/realtime/registry.js +38 -0
- package/dist/realtime/socketUser.d.ts +10 -0
- package/dist/realtime/socketUser.js +17 -0
- package/dist/realtime/types.d.ts +100 -0
- package/dist/realtime/types.js +2 -0
- package/dist/requestContext.d.ts +37 -0
- package/dist/requestContext.js +344 -0
- package/dist/requestContext.test.d.ts +1 -0
- package/dist/requestContext.test.js +241 -0
- package/dist/terrenoApp.d.ts +8 -0
- package/dist/terrenoApp.js +50 -13
- package/dist/terrenoApp.test.js +194 -21
- package/dist/terrenoPlugin.d.ts +11 -0
- package/dist/tests/bunSetup.js +1 -0
- package/dist/tests.js +1 -1
- package/dist/transformers.d.ts +2 -2
- package/dist/transformers.js +5 -3
- package/dist/transformers.test.js +90 -0
- package/dist/types/consentResponse.d.ts +6 -3
- package/dist/versionCheckPlugin.d.ts +2 -0
- package/dist/versionCheckPlugin.js +18 -12
- package/package.json +4 -2
- package/src/__tests__/versionCheckPlugin.test.ts +37 -3
- package/src/api.arrayOperations.test.ts +1 -0
- package/src/api.errors.test.ts +1 -0
- package/src/api.hooks.test.ts +1 -0
- package/src/api.query.test.ts +1 -0
- package/src/api.test.ts +132 -0
- package/src/api.ts +199 -84
- package/src/auth.test.ts +160 -0
- package/src/auth.ts +120 -50
- package/src/betterAuthApp.test.ts +1 -0
- package/src/betterAuthSetup.test.ts +1 -0
- package/src/betterAuthSetup.ts +46 -19
- package/src/config.test.ts +255 -0
- package/src/config.ts +206 -0
- package/src/configuration.test.ts +1 -0
- package/src/configurationApp.ts +59 -24
- package/src/configurationPlugin.test.ts +1 -0
- package/src/consentApp.test.ts +1 -0
- package/src/envConfigurationPlugin.test.ts +143 -0
- package/src/envConfigurationPlugin.ts +100 -0
- package/src/errors.test.ts +19 -1
- package/src/errors.ts +94 -20
- package/src/example.ts +46 -21
- package/src/express.d.ts +18 -1
- package/src/expressServer.test.ts +50 -2
- package/src/expressServer.ts +80 -50
- package/src/githubAuth.test.ts +1 -0
- package/src/githubAuth.ts +59 -38
- package/src/index.ts +4 -0
- package/src/logger.ts +47 -17
- package/src/models/versionConfig.ts +13 -2
- package/src/notifiers/googleChatNotifier.test.ts +1 -0
- package/src/notifiers/googleChatNotifier.ts +7 -9
- package/src/notifiers/slackNotifier.test.ts +29 -3
- package/src/notifiers/slackNotifier.ts +9 -7
- package/src/notifiers/zoomNotifier.test.ts +1 -0
- package/src/notifiers/zoomNotifier.ts +8 -11
- package/src/openApi.test.ts +1 -0
- package/src/openApi.ts +4 -4
- package/src/openApiBuilder.test.ts +1 -0
- package/src/openApiBuilder.ts +14 -11
- package/src/openApiValidator.test.ts +1 -0
- package/src/openApiValidator.ts +3 -2
- package/src/permissions.middleware.test.ts +1 -0
- package/src/permissions.test.ts +1 -0
- package/src/permissions.ts +30 -25
- package/src/plugins.test.ts +1 -1
- package/src/plugins.ts +21 -14
- package/src/populate.test.ts +1 -0
- package/src/populate.ts +44 -36
- package/src/realtime/changeStreamWatcher.ts +568 -0
- package/src/realtime/index.ts +34 -0
- package/src/realtime/queryMatcher.ts +179 -0
- package/src/realtime/queryStore.ts +132 -0
- package/src/realtime/realtime.test.ts +1755 -0
- package/src/realtime/realtimeApp.ts +478 -0
- package/src/realtime/registry.ts +64 -0
- package/src/realtime/socketUser.ts +25 -0
- package/src/realtime/types.ts +112 -0
- package/src/requestContext.test.ts +196 -0
- package/src/requestContext.ts +368 -0
- package/src/terrenoApp.test.ts +137 -11
- package/src/terrenoApp.ts +64 -17
- package/src/terrenoPlugin.ts +12 -0
- package/src/tests/bunSetup.ts +1 -0
- package/src/tests.ts +7 -2
- package/src/transformers.test.ts +70 -2
- package/src/transformers.ts +15 -7
- package/src/types/consentResponse.ts +8 -10
- package/src/versionCheckPlugin.ts +15 -7
package/dist/api.js
CHANGED
|
@@ -129,6 +129,7 @@ exports.modelRouter = modelRouter;
|
|
|
129
129
|
var Sentry = __importStar(require("@sentry/bun"));
|
|
130
130
|
var express_1 = __importDefault(require("express"));
|
|
131
131
|
var cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
|
|
132
|
+
var luxon_1 = require("luxon");
|
|
132
133
|
var mongoose_1 = __importDefault(require("mongoose"));
|
|
133
134
|
var auth_1 = require("./auth");
|
|
134
135
|
var errors_1 = require("./errors");
|
|
@@ -136,9 +137,12 @@ var logger_1 = require("./logger");
|
|
|
136
137
|
var openApi_1 = require("./openApi");
|
|
137
138
|
var openApiValidator_1 = require("./openApiValidator");
|
|
138
139
|
var permissions_1 = require("./permissions");
|
|
140
|
+
var registry_1 = require("./realtime/registry");
|
|
139
141
|
var transformers_1 = require("./transformers");
|
|
140
142
|
var utils_1 = require("./utils");
|
|
141
|
-
var addPopulateToQuery = function (
|
|
143
|
+
var addPopulateToQuery = function (
|
|
144
|
+
// biome-ignore lint/suspicious/noExplicitAny: mongoose Query type parameters vary widely across populated/unpopulated documents — caller passes concrete types
|
|
145
|
+
builtQuery, populatePaths) {
|
|
142
146
|
var e_1, _a;
|
|
143
147
|
var paths = populatePaths !== null && populatePaths !== void 0 ? populatePaths : [];
|
|
144
148
|
var query = builtQuery;
|
|
@@ -172,13 +176,15 @@ var COMPLEX_QUERY_PARAMS = ["$and", "$or"];
|
|
|
172
176
|
var checkQueryParamAllowed = function (queryParam, queryParamValue, queryFields) {
|
|
173
177
|
var e_2, _a, e_3, _b;
|
|
174
178
|
if (queryFields === void 0) { queryFields = []; }
|
|
179
|
+
// Cast for iteration through complex query values
|
|
180
|
+
var complexValue = queryParamValue;
|
|
175
181
|
// Check the values of each of the complex query params. We don't support recursive queries here,
|
|
176
182
|
// just one level of and/or
|
|
177
183
|
if (COMPLEX_QUERY_PARAMS.includes(queryParam)) {
|
|
178
184
|
try {
|
|
179
185
|
// Complex query of the form `$and: [{key1: value1}, {key2: value2}]`
|
|
180
|
-
for (var
|
|
181
|
-
var subQuery =
|
|
186
|
+
for (var complexValue_1 = __values(complexValue), complexValue_1_1 = complexValue_1.next(); !complexValue_1_1.done; complexValue_1_1 = complexValue_1.next()) {
|
|
187
|
+
var subQuery = complexValue_1_1.value;
|
|
182
188
|
try {
|
|
183
189
|
for (var _c = (e_3 = void 0, __values(Object.keys(subQuery))), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
184
190
|
var subKey = _d.value;
|
|
@@ -197,7 +203,7 @@ var checkQueryParamAllowed = function (queryParam, queryParamValue, queryFields)
|
|
|
197
203
|
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
198
204
|
finally {
|
|
199
205
|
try {
|
|
200
|
-
if (
|
|
206
|
+
if (complexValue_1_1 && !complexValue_1_1.done && (_a = complexValue_1.return)) _a.call(complexValue_1);
|
|
201
207
|
}
|
|
202
208
|
finally { if (e_2) throw e_2.error; }
|
|
203
209
|
}
|
|
@@ -299,13 +305,29 @@ function modelRouter(pathOrModel, modelOrOptions, maybeOptions) {
|
|
|
299
305
|
}
|
|
300
306
|
var router = _buildModelRouter(model, options);
|
|
301
307
|
if (path !== undefined) {
|
|
308
|
+
// Register for real-time sync if configured
|
|
309
|
+
if (options.realtime) {
|
|
310
|
+
(0, registry_1.registerRealtime)({
|
|
311
|
+
collectionName: model.collection.collectionName,
|
|
312
|
+
config: options.realtime,
|
|
313
|
+
modelName: model.modelName,
|
|
314
|
+
options: options,
|
|
315
|
+
routePath: path,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
302
318
|
return {
|
|
303
319
|
__type: "modelRouter",
|
|
304
|
-
_buildWithOpenApi: function (openApi) {
|
|
320
|
+
_buildWithOpenApi: function (openApi) {
|
|
321
|
+
return _buildModelRouter(model, __assign(__assign({}, options), { openApi: openApi }));
|
|
322
|
+
},
|
|
305
323
|
path: path,
|
|
306
324
|
router: router,
|
|
307
325
|
};
|
|
308
326
|
}
|
|
327
|
+
if (options.realtime) {
|
|
328
|
+
logger_1.logger.warn("modelRouter for ".concat(model.modelName, " has realtime config but was called without a path. ") +
|
|
329
|
+
"Realtime sync only works with the three-argument form: modelRouter('/path', Model, options)");
|
|
330
|
+
}
|
|
309
331
|
return router;
|
|
310
332
|
}
|
|
311
333
|
function _buildModelRouter(model, options) {
|
|
@@ -342,7 +364,7 @@ function _buildModelRouter(model, options) {
|
|
|
342
364
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error),
|
|
343
365
|
error: error,
|
|
344
366
|
status: 400,
|
|
345
|
-
title: error
|
|
367
|
+
title: (0, errors_1.errorMessage)(error),
|
|
346
368
|
});
|
|
347
369
|
}
|
|
348
370
|
if (!options.preCreate) return [3 /*break*/, 5];
|
|
@@ -362,7 +384,7 @@ function _buildModelRouter(model, options) {
|
|
|
362
384
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_1),
|
|
363
385
|
error: error_1,
|
|
364
386
|
status: 400,
|
|
365
|
-
title: "preCreate hook error: ".concat(
|
|
387
|
+
title: "preCreate hook error: ".concat((0, errors_1.errorMessage)(error_1)),
|
|
366
388
|
});
|
|
367
389
|
case 4:
|
|
368
390
|
if (body === undefined) {
|
|
@@ -393,7 +415,7 @@ function _buildModelRouter(model, options) {
|
|
|
393
415
|
_a.trys.push([6, 8, , 9]);
|
|
394
416
|
return [4 /*yield*/, model.create(body)];
|
|
395
417
|
case 7:
|
|
396
|
-
data = _a.sent();
|
|
418
|
+
data = (_a.sent());
|
|
397
419
|
return [3 /*break*/, 9];
|
|
398
420
|
case 8:
|
|
399
421
|
error_2 = _a.sent();
|
|
@@ -401,7 +423,7 @@ function _buildModelRouter(model, options) {
|
|
|
401
423
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_2),
|
|
402
424
|
error: error_2,
|
|
403
425
|
status: 400,
|
|
404
|
-
title: error_2
|
|
426
|
+
title: (0, errors_1.errorMessage)(error_2),
|
|
405
427
|
});
|
|
406
428
|
case 9:
|
|
407
429
|
if (!options.populatePaths) return [3 /*break*/, 13];
|
|
@@ -420,7 +442,7 @@ function _buildModelRouter(model, options) {
|
|
|
420
442
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_3),
|
|
421
443
|
error: error_3,
|
|
422
444
|
status: 400,
|
|
423
|
-
title: "Populate error: ".concat(
|
|
445
|
+
title: "Populate error: ".concat((0, errors_1.errorMessage)(error_3)),
|
|
424
446
|
});
|
|
425
447
|
case 13:
|
|
426
448
|
if (!options.postCreate) return [3 /*break*/, 17];
|
|
@@ -437,7 +459,7 @@ function _buildModelRouter(model, options) {
|
|
|
437
459
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_4),
|
|
438
460
|
error: error_4,
|
|
439
461
|
status: 400,
|
|
440
|
-
title: "postCreate hook error: ".concat(
|
|
462
|
+
title: "postCreate hook error: ".concat((0, errors_1.errorMessage)(error_4)),
|
|
441
463
|
});
|
|
442
464
|
case 17:
|
|
443
465
|
_a.trys.push([17, 19, , 20]);
|
|
@@ -450,7 +472,7 @@ function _buildModelRouter(model, options) {
|
|
|
450
472
|
throw new errors_1.APIError({
|
|
451
473
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_5),
|
|
452
474
|
error: error_5,
|
|
453
|
-
title: "responseHandler error: ".concat(
|
|
475
|
+
title: "responseHandler error: ".concat((0, errors_1.errorMessage)(error_5)),
|
|
454
476
|
});
|
|
455
477
|
case 20: return [2 /*return*/];
|
|
456
478
|
}
|
|
@@ -577,14 +599,14 @@ function _buildModelRouter(model, options) {
|
|
|
577
599
|
_o.trys.push([7, 9, , 10]);
|
|
578
600
|
return [4 /*yield*/, populatedQuery.exec()];
|
|
579
601
|
case 8:
|
|
580
|
-
data = _o.sent();
|
|
602
|
+
data = (_o.sent());
|
|
581
603
|
return [3 /*break*/, 10];
|
|
582
604
|
case 9:
|
|
583
605
|
error_7 = _o.sent();
|
|
584
606
|
throw new errors_1.APIError({
|
|
585
607
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_7),
|
|
586
608
|
error: error_7,
|
|
587
|
-
title: "List error: ".concat(
|
|
609
|
+
title: "List error: ".concat((0, errors_1.errorStack)(error_7)),
|
|
588
610
|
});
|
|
589
611
|
case 10:
|
|
590
612
|
_o.trys.push([10, 12, , 13]);
|
|
@@ -597,7 +619,7 @@ function _buildModelRouter(model, options) {
|
|
|
597
619
|
throw new errors_1.APIError({
|
|
598
620
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_8),
|
|
599
621
|
error: error_8,
|
|
600
|
-
title: "responseHandler error: ".concat(
|
|
622
|
+
title: "responseHandler error: ".concat((0, errors_1.errorMessage)(error_8)),
|
|
601
623
|
});
|
|
602
624
|
case 13:
|
|
603
625
|
try {
|
|
@@ -631,7 +653,7 @@ function _buildModelRouter(model, options) {
|
|
|
631
653
|
throw new errors_1.APIError({
|
|
632
654
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error),
|
|
633
655
|
error: error,
|
|
634
|
-
title: "Serialization error: ".concat(
|
|
656
|
+
title: "Serialization error: ".concat((0, errors_1.errorMessage)(error)),
|
|
635
657
|
});
|
|
636
658
|
}
|
|
637
659
|
return [2 /*return*/];
|
|
@@ -660,7 +682,7 @@ function _buildModelRouter(model, options) {
|
|
|
660
682
|
throw new errors_1.APIError({
|
|
661
683
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_9),
|
|
662
684
|
error: error_9,
|
|
663
|
-
title: "responseHandler error: ".concat(
|
|
685
|
+
title: "responseHandler error: ".concat((0, errors_1.errorMessage)(error_9)),
|
|
664
686
|
});
|
|
665
687
|
case 4: return [2 /*return*/];
|
|
666
688
|
}
|
|
@@ -680,10 +702,10 @@ function _buildModelRouter(model, options) {
|
|
|
680
702
|
(0, permissions_1.permissionMiddleware)(model, options),
|
|
681
703
|
updateValidation,
|
|
682
704
|
], (0, exports.asyncHandler)(function (req, res) { return __awaiter(_this, void 0, void 0, function () {
|
|
683
|
-
var doc, body, error_10, prevDoc, error_11, populateQuery, error_12, serialized, error_13;
|
|
684
|
-
var _a;
|
|
685
|
-
return __generator(this, function (
|
|
686
|
-
switch (
|
|
705
|
+
var doc, body, bodyUpdatedAt, error_10, preciseUnmodifiedSince, httpUnmodifiedSince, timestampValue, httpTimestampValue, usingPreciseHeader, usingHttpHeader, clientTimestamp, docRecord, serverTimestamp, serverTimestampValue, serialized, prevDoc, error_11, populateQuery, error_12, serialized, error_13;
|
|
706
|
+
var _a, _b;
|
|
707
|
+
return __generator(this, function (_c) {
|
|
708
|
+
switch (_c.label) {
|
|
687
709
|
case 0:
|
|
688
710
|
doc = req.obj;
|
|
689
711
|
try {
|
|
@@ -697,23 +719,24 @@ function _buildModelRouter(model, options) {
|
|
|
697
719
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error),
|
|
698
720
|
error: error,
|
|
699
721
|
status: 403,
|
|
700
|
-
title: "PATCH failed on ".concat(req.params.id, " for user ").concat((_a = req.user) === null || _a === void 0 ? void 0 : _a.id, ": ").concat(
|
|
722
|
+
title: "PATCH failed on ".concat(req.params.id, " for user ").concat((_a = req.user) === null || _a === void 0 ? void 0 : _a.id, ": ").concat((0, errors_1.errorMessage)(error)),
|
|
701
723
|
});
|
|
702
724
|
}
|
|
725
|
+
bodyUpdatedAt = req.body._updatedAt;
|
|
726
|
+
delete req.body._updatedAt;
|
|
727
|
+
if (body && typeof body === "object") {
|
|
728
|
+
delete body._updatedAt;
|
|
729
|
+
}
|
|
703
730
|
if (!options.preUpdate) return [3 /*break*/, 5];
|
|
704
|
-
|
|
731
|
+
_c.label = 1;
|
|
705
732
|
case 1:
|
|
706
|
-
|
|
733
|
+
_c.trys.push([1, 3, , 4]);
|
|
707
734
|
return [4 /*yield*/, options.preUpdate(body, req)];
|
|
708
735
|
case 2:
|
|
709
|
-
|
|
710
|
-
// with the original body, maintaining the dot notation. This way we don't have to write
|
|
711
|
-
// two preUpdate branches downstream, one looking at the dot notation style and
|
|
712
|
-
// one looking at normal object style.
|
|
713
|
-
body = _b.sent();
|
|
736
|
+
body = _c.sent();
|
|
714
737
|
return [3 /*break*/, 4];
|
|
715
738
|
case 3:
|
|
716
|
-
error_10 =
|
|
739
|
+
error_10 = _c.sent();
|
|
717
740
|
if ((0, errors_1.isAPIError)(error_10)) {
|
|
718
741
|
throw error_10;
|
|
719
742
|
}
|
|
@@ -721,7 +744,7 @@ function _buildModelRouter(model, options) {
|
|
|
721
744
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_10),
|
|
722
745
|
error: error_10,
|
|
723
746
|
status: 400,
|
|
724
|
-
title: "preUpdate hook error on ".concat(req.params.id, ": ").concat(
|
|
747
|
+
title: "preUpdate hook error on ".concat(req.params.id, ": ").concat((0, errors_1.errorMessage)(error_10)),
|
|
725
748
|
});
|
|
726
749
|
case 4:
|
|
727
750
|
if (body === undefined) {
|
|
@@ -738,64 +761,117 @@ function _buildModelRouter(model, options) {
|
|
|
738
761
|
title: "Update not allowed",
|
|
739
762
|
});
|
|
740
763
|
}
|
|
741
|
-
|
|
764
|
+
_c.label = 5;
|
|
742
765
|
case 5:
|
|
743
|
-
|
|
744
|
-
|
|
766
|
+
preciseUnmodifiedSince = req.headers["x-unmodified-since-iso"];
|
|
767
|
+
httpUnmodifiedSince = req.headers["if-unmodified-since"];
|
|
768
|
+
timestampValue = Array.isArray(preciseUnmodifiedSince)
|
|
769
|
+
? preciseUnmodifiedSince[0]
|
|
770
|
+
: preciseUnmodifiedSince;
|
|
771
|
+
httpTimestampValue = Array.isArray(httpUnmodifiedSince)
|
|
772
|
+
? httpUnmodifiedSince[0]
|
|
773
|
+
: httpUnmodifiedSince;
|
|
774
|
+
if (!(timestampValue || httpTimestampValue || bodyUpdatedAt)) return [3 /*break*/, 7];
|
|
775
|
+
usingPreciseHeader = Boolean(timestampValue);
|
|
776
|
+
usingHttpHeader = !usingPreciseHeader && Boolean(httpTimestampValue);
|
|
777
|
+
clientTimestamp = timestampValue
|
|
778
|
+
? luxon_1.DateTime.fromISO(timestampValue)
|
|
779
|
+
: httpTimestampValue
|
|
780
|
+
? luxon_1.DateTime.fromHTTP(httpTimestampValue)
|
|
781
|
+
: luxon_1.DateTime.fromISO(bodyUpdatedAt);
|
|
782
|
+
if (!clientTimestamp.isValid) {
|
|
783
|
+
throw new errors_1.APIError({
|
|
784
|
+
detail: usingPreciseHeader
|
|
785
|
+
? "X-Unmodified-Since-ISO header could not be parsed as an ISO date"
|
|
786
|
+
: usingHttpHeader
|
|
787
|
+
? "If-Unmodified-Since header could not be parsed as an HTTP date"
|
|
788
|
+
: "_updatedAt body field could not be parsed as an ISO date",
|
|
789
|
+
status: 400,
|
|
790
|
+
title: "Invalid conflict-detection timestamp",
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
docRecord = doc;
|
|
794
|
+
serverTimestamp = null;
|
|
795
|
+
serverTimestampValue = (_b = docRecord.updated) !== null && _b !== void 0 ? _b : docRecord.created;
|
|
796
|
+
if (serverTimestampValue instanceof Date) {
|
|
797
|
+
serverTimestamp = luxon_1.DateTime.fromJSDate(serverTimestampValue);
|
|
798
|
+
}
|
|
799
|
+
else if (typeof serverTimestampValue === "string") {
|
|
800
|
+
serverTimestamp = luxon_1.DateTime.fromISO(serverTimestampValue);
|
|
801
|
+
}
|
|
802
|
+
if (serverTimestamp && !serverTimestamp.isValid) {
|
|
803
|
+
throw new errors_1.APIError({
|
|
804
|
+
detail: "Document timestamp could not be parsed as a date",
|
|
805
|
+
status: 400,
|
|
806
|
+
title: "Invalid server timestamp",
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
if (!(serverTimestamp && clientTimestamp < serverTimestamp)) return [3 /*break*/, 7];
|
|
810
|
+
return [4 /*yield*/, responseHandler(doc, "update", req, options)];
|
|
745
811
|
case 6:
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
812
|
+
serialized = _c.sent();
|
|
813
|
+
return [2 /*return*/, res.status(409).json({
|
|
814
|
+
data: serialized,
|
|
815
|
+
error: "Conflict",
|
|
816
|
+
message: "Document was modified since your last read",
|
|
817
|
+
})];
|
|
749
818
|
case 7:
|
|
750
|
-
|
|
751
|
-
|
|
819
|
+
prevDoc = (0, cloneDeep_1.default)(doc);
|
|
820
|
+
_c.label = 8;
|
|
752
821
|
case 8:
|
|
753
|
-
|
|
822
|
+
_c.trys.push([8, 10, , 11]);
|
|
823
|
+
doc.set(body);
|
|
824
|
+
return [4 /*yield*/, doc.save()];
|
|
825
|
+
case 9:
|
|
826
|
+
_c.sent();
|
|
827
|
+
return [3 /*break*/, 11];
|
|
828
|
+
case 10:
|
|
829
|
+
error_11 = _c.sent();
|
|
754
830
|
throw new errors_1.APIError({
|
|
755
831
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_11),
|
|
756
832
|
error: error_11,
|
|
757
833
|
status: 400,
|
|
758
|
-
title: "preUpdate hook save error on ".concat(req.params.id, ": ").concat(
|
|
834
|
+
title: "preUpdate hook save error on ".concat(req.params.id, ": ").concat((0, errors_1.errorMessage)(error_11)),
|
|
759
835
|
});
|
|
760
|
-
case
|
|
761
|
-
if (!options.populatePaths) return [3 /*break*/,
|
|
836
|
+
case 11:
|
|
837
|
+
if (!options.populatePaths) return [3 /*break*/, 13];
|
|
762
838
|
populateQuery = model.findById(doc._id);
|
|
763
839
|
populateQuery = (0, exports.addPopulateToQuery)(populateQuery, options.populatePaths);
|
|
764
840
|
return [4 /*yield*/, populateQuery.exec()];
|
|
765
|
-
case 10:
|
|
766
|
-
doc = _b.sent();
|
|
767
|
-
_b.label = 11;
|
|
768
|
-
case 11:
|
|
769
|
-
if (!options.postUpdate) return [3 /*break*/, 15];
|
|
770
|
-
_b.label = 12;
|
|
771
841
|
case 12:
|
|
772
|
-
|
|
773
|
-
|
|
842
|
+
doc = _c.sent();
|
|
843
|
+
_c.label = 13;
|
|
774
844
|
case 13:
|
|
775
|
-
|
|
776
|
-
|
|
845
|
+
if (!options.postUpdate) return [3 /*break*/, 17];
|
|
846
|
+
_c.label = 14;
|
|
777
847
|
case 14:
|
|
778
|
-
|
|
848
|
+
_c.trys.push([14, 16, , 17]);
|
|
849
|
+
return [4 /*yield*/, options.postUpdate(doc, body, req, prevDoc)];
|
|
850
|
+
case 15:
|
|
851
|
+
_c.sent();
|
|
852
|
+
return [3 /*break*/, 17];
|
|
853
|
+
case 16:
|
|
854
|
+
error_12 = _c.sent();
|
|
779
855
|
throw new errors_1.APIError({
|
|
780
856
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_12),
|
|
781
857
|
error: error_12,
|
|
782
858
|
status: 400,
|
|
783
|
-
title: "postUpdate hook error on ".concat(req.params.id, ": ").concat(
|
|
859
|
+
title: "postUpdate hook error on ".concat(req.params.id, ": ").concat((0, errors_1.errorMessage)(error_12)),
|
|
784
860
|
});
|
|
785
|
-
case
|
|
786
|
-
|
|
861
|
+
case 17:
|
|
862
|
+
_c.trys.push([17, 19, , 20]);
|
|
787
863
|
return [4 /*yield*/, responseHandler(doc, "update", req, options)];
|
|
788
|
-
case
|
|
789
|
-
serialized =
|
|
864
|
+
case 18:
|
|
865
|
+
serialized = _c.sent();
|
|
790
866
|
return [2 /*return*/, res.json({ data: serialized })];
|
|
791
|
-
case
|
|
792
|
-
error_13 =
|
|
867
|
+
case 19:
|
|
868
|
+
error_13 = _c.sent();
|
|
793
869
|
throw new errors_1.APIError({
|
|
794
870
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_13),
|
|
795
871
|
error: error_13,
|
|
796
|
-
title: "responseHandler error: ".concat(
|
|
872
|
+
title: "responseHandler error: ".concat((0, errors_1.errorMessage)(error_13)),
|
|
797
873
|
});
|
|
798
|
-
case
|
|
874
|
+
case 20: return [2 /*return*/];
|
|
799
875
|
}
|
|
800
876
|
});
|
|
801
877
|
}); }));
|
|
@@ -827,7 +903,7 @@ function _buildModelRouter(model, options) {
|
|
|
827
903
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_14),
|
|
828
904
|
error: error_14,
|
|
829
905
|
status: 403,
|
|
830
|
-
title: "preDelete hook error on ".concat(req.params.id, ": ").concat(
|
|
906
|
+
title: "preDelete hook error on ".concat(req.params.id, ": ").concat((0, errors_1.errorMessage)(error_14)),
|
|
831
907
|
});
|
|
832
908
|
case 4:
|
|
833
909
|
if (body === undefined) {
|
|
@@ -865,7 +941,7 @@ function _buildModelRouter(model, options) {
|
|
|
865
941
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_15),
|
|
866
942
|
error: error_15,
|
|
867
943
|
status: 400,
|
|
868
|
-
title: error_15
|
|
944
|
+
title: (0, errors_1.errorMessage)(error_15),
|
|
869
945
|
});
|
|
870
946
|
case 10:
|
|
871
947
|
if (!options.postDelete) return [3 /*break*/, 14];
|
|
@@ -882,7 +958,7 @@ function _buildModelRouter(model, options) {
|
|
|
882
958
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_16),
|
|
883
959
|
error: error_16,
|
|
884
960
|
status: 400,
|
|
885
|
-
title: "postDelete hook error: ".concat(
|
|
961
|
+
title: "postDelete hook error: ".concat((0, errors_1.errorMessage)(error_16)),
|
|
886
962
|
});
|
|
887
963
|
case 14: return [2 /*return*/, res.status(204).json({})];
|
|
888
964
|
}
|
|
@@ -939,10 +1015,10 @@ function _buildModelRouter(model, options) {
|
|
|
939
1015
|
else if (operation === "PATCH" || operation === "DELETE") {
|
|
940
1016
|
index = void 0;
|
|
941
1017
|
if ((0, utils_1.isValidObjectId)(itemId)) {
|
|
942
|
-
index = array.findIndex(function (x) { return x.id === itemId; });
|
|
1018
|
+
index = array.findIndex(function (x) { return (x === null || x === void 0 ? void 0 : x.id) === itemId; });
|
|
943
1019
|
}
|
|
944
1020
|
else {
|
|
945
|
-
index = array.
|
|
1021
|
+
index = array.indexOf(itemId);
|
|
946
1022
|
}
|
|
947
1023
|
if (index === -1) {
|
|
948
1024
|
throw new errors_1.APIError({
|
|
@@ -981,7 +1057,7 @@ function _buildModelRouter(model, options) {
|
|
|
981
1057
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error),
|
|
982
1058
|
error: error,
|
|
983
1059
|
status: 403,
|
|
984
|
-
title: error
|
|
1060
|
+
title: (0, errors_1.errorMessage)(error),
|
|
985
1061
|
});
|
|
986
1062
|
}
|
|
987
1063
|
if (!options.preUpdate) return [3 /*break*/, 8];
|
|
@@ -998,7 +1074,7 @@ function _buildModelRouter(model, options) {
|
|
|
998
1074
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_17),
|
|
999
1075
|
error: error_17,
|
|
1000
1076
|
status: 400,
|
|
1001
|
-
title: "preUpdate hook error on ".concat(req.params.id, ": ").concat(
|
|
1077
|
+
title: "preUpdate hook error on ".concat(req.params.id, ": ").concat((0, errors_1.errorMessage)(error_17)),
|
|
1002
1078
|
});
|
|
1003
1079
|
case 7:
|
|
1004
1080
|
if (body === undefined) {
|
|
@@ -1029,7 +1105,7 @@ function _buildModelRouter(model, options) {
|
|
|
1029
1105
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_18),
|
|
1030
1106
|
error: error_18,
|
|
1031
1107
|
status: 400,
|
|
1032
|
-
title: "PATCH Pre Update error on ".concat(req.params.id, ": ").concat(
|
|
1108
|
+
title: "PATCH Pre Update error on ".concat(req.params.id, ": ").concat((0, errors_1.errorMessage)(error_18)),
|
|
1033
1109
|
});
|
|
1034
1110
|
case 11:
|
|
1035
1111
|
if (!options.postUpdate) return [3 /*break*/, 15];
|
|
@@ -1046,9 +1122,11 @@ function _buildModelRouter(model, options) {
|
|
|
1046
1122
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_19),
|
|
1047
1123
|
error: error_19,
|
|
1048
1124
|
status: 400,
|
|
1049
|
-
title: "PATCH Post Update error on ".concat(req.params.id, ": ").concat(
|
|
1125
|
+
title: "PATCH Post Update error on ".concat(req.params.id, ": ").concat((0, errors_1.errorMessage)(error_19)),
|
|
1050
1126
|
});
|
|
1051
|
-
case 15: return [2 /*return*/, res.json({
|
|
1127
|
+
case 15: return [2 /*return*/, res.json({
|
|
1128
|
+
data: (0, transformers_1.serialize)(req, options, doc),
|
|
1129
|
+
})];
|
|
1052
1130
|
}
|
|
1053
1131
|
});
|
|
1054
1132
|
});
|
|
@@ -1083,35 +1161,6 @@ function _buildModelRouter(model, options) {
|
|
|
1083
1161
|
router.use(errors_1.apiErrorMiddleware);
|
|
1084
1162
|
return router;
|
|
1085
1163
|
}
|
|
1086
|
-
/**
|
|
1087
|
-
* Wraps async route handlers to properly catch and forward errors.
|
|
1088
|
-
*
|
|
1089
|
-
* Since Express doesn't handle async routes well, wrap them with this function.
|
|
1090
|
-
* Optionally supports integrated request validation.
|
|
1091
|
-
*
|
|
1092
|
-
* @param fn - The async route handler function
|
|
1093
|
-
* @param options - Optional configuration for validation
|
|
1094
|
-
* @returns Express middleware function
|
|
1095
|
-
*
|
|
1096
|
-
* @example
|
|
1097
|
-
* ```typescript
|
|
1098
|
-
* // Basic usage without validation
|
|
1099
|
-
* router.post("/users", asyncHandler(async (req, res) => {
|
|
1100
|
-
* // handler code
|
|
1101
|
-
* }));
|
|
1102
|
-
*
|
|
1103
|
-
* // With integrated validation
|
|
1104
|
-
* router.post("/users", asyncHandler(async (req, res) => {
|
|
1105
|
-
* // handler code - body is already validated
|
|
1106
|
-
* }, {
|
|
1107
|
-
* bodySchema: {
|
|
1108
|
-
* name: {type: "string", required: true},
|
|
1109
|
-
* email: {type: "string", format: "email", required: true},
|
|
1110
|
-
* },
|
|
1111
|
-
* validate: true,
|
|
1112
|
-
* }));
|
|
1113
|
-
* ```
|
|
1114
|
-
*/
|
|
1115
1164
|
var asyncHandler = function (fn, options) {
|
|
1116
1165
|
var _a, _b;
|
|
1117
1166
|
// If no validation options, return simple handler
|
|
@@ -1143,13 +1192,13 @@ var asyncHandler = function (fn, options) {
|
|
|
1143
1192
|
return;
|
|
1144
1193
|
}
|
|
1145
1194
|
try {
|
|
1146
|
-
validators[index](req, res, function (err) {
|
|
1195
|
+
validators[index](req, res, (function (err) {
|
|
1147
1196
|
if (err) {
|
|
1148
1197
|
next(err);
|
|
1149
1198
|
return;
|
|
1150
1199
|
}
|
|
1151
1200
|
runValidators(index + 1);
|
|
1152
|
-
});
|
|
1201
|
+
}));
|
|
1153
1202
|
}
|
|
1154
1203
|
catch (err) {
|
|
1155
1204
|
next(err);
|
package/dist/api.query.test.js
CHANGED
|
@@ -88,6 +88,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
88
88
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
89
89
|
};
|
|
90
90
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
91
|
+
// biome-ignore-all lint/suspicious/noExplicitAny: test mock typing
|
|
91
92
|
var bun_test_1 = require("bun:test");
|
|
92
93
|
var Sentry = __importStar(require("@sentry/bun"));
|
|
93
94
|
var qs_1 = __importDefault(require("qs"));
|