@terreno/api 0.0.11 → 0.0.12
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/CLAUDE.md +107 -0
- package/biome.jsonc +1 -1
- package/bunfig.toml +3 -2
- package/dist/api.arrayOperations.test.d.ts +1 -0
- package/dist/api.arrayOperations.test.js +868 -0
- package/dist/api.d.ts +3 -14
- package/dist/api.errors.test.d.ts +1 -0
- package/dist/api.errors.test.js +175 -0
- package/dist/api.hooks.test.d.ts +1 -0
- package/dist/api.hooks.test.js +891 -0
- package/dist/api.js +44 -68
- package/dist/api.query.test.d.ts +1 -0
- package/dist/api.query.test.js +805 -0
- package/dist/api.test.js +691 -1678
- package/dist/auth.test.js +135 -0
- package/dist/expressServer.test.d.ts +1 -0
- package/dist/expressServer.test.js +669 -0
- package/dist/notifiers/slackNotifier.d.ts +2 -1
- package/dist/notifiers/slackNotifier.js +20 -13
- package/dist/permissions.d.ts +1 -1
- package/dist/permissions.js +17 -25
- package/dist/permissions.test.js +57 -0
- package/dist/populate.test.js +52 -0
- package/dist/tests.d.ts +9 -27
- package/dist/utils.test.js +235 -7
- package/package.json +3 -2
- package/src/api.arrayOperations.test.ts +690 -0
- package/src/api.errors.test.ts +156 -0
- package/src/api.hooks.test.ts +704 -0
- package/src/api.query.test.ts +538 -0
- package/src/api.test.ts +510 -1301
- package/src/api.ts +19 -61
- package/src/auth.test.ts +72 -0
- package/src/expressServer.test.ts +579 -0
- package/src/notifiers/slackNotifier.ts +28 -17
- package/src/permissions.test.ts +70 -1
- package/src/permissions.ts +4 -14
- package/src/populate.test.ts +58 -0
- package/src/utils.test.ts +214 -9
package/dist/api.js
CHANGED
|
@@ -121,7 +121,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
121
121
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
122
122
|
exports.gooseRestRouter = exports.asyncHandler = void 0;
|
|
123
123
|
exports.addPopulateToQuery = addPopulateToQuery;
|
|
124
|
-
exports.getModel = getModel;
|
|
125
124
|
exports.modelRouter = modelRouter;
|
|
126
125
|
/**
|
|
127
126
|
* This is the doc comment for api.ts
|
|
@@ -168,21 +167,6 @@ function addPopulateToQuery(builtQuery, populatePaths) {
|
|
|
168
167
|
var PAGINATION_QUERY_PARAMS = ["limit", "page", "sort"];
|
|
169
168
|
// Add support for more complex queries.
|
|
170
169
|
var COMPLEX_QUERY_PARAMS = ["$and", "$or"];
|
|
171
|
-
// A function to decide which model to use. If no discriminators are provided,
|
|
172
|
-
// just returns the base model. If
|
|
173
|
-
function getModel(baseModel, body, options) {
|
|
174
|
-
var _a, _b;
|
|
175
|
-
var discriminatorKey = (_a = options === null || options === void 0 ? void 0 : options.discriminatorKey) !== null && _a !== void 0 ? _a : "__t";
|
|
176
|
-
var modelName = body === null || body === void 0 ? void 0 : body[discriminatorKey];
|
|
177
|
-
if (!modelName) {
|
|
178
|
-
return baseModel;
|
|
179
|
-
}
|
|
180
|
-
var model = (_b = baseModel.discriminators) === null || _b === void 0 ? void 0 : _b[modelName];
|
|
181
|
-
if (!model) {
|
|
182
|
-
throw new Error("Could not find discriminator model for key ".concat(modelName, ", baseModel: ").concat(baseModel));
|
|
183
|
-
}
|
|
184
|
-
return model;
|
|
185
|
-
}
|
|
186
170
|
// Ensures query params are allowed. Also checks nested query params when using $and/$or.
|
|
187
171
|
function checkQueryParamAllowed(queryParam, queryParamValue, queryFields) {
|
|
188
172
|
var e_2, _a, e_3, _b;
|
|
@@ -244,12 +228,12 @@ function checkQueryParamAllowed(queryParam, queryParamValue, queryFields) {
|
|
|
244
228
|
// return result;
|
|
245
229
|
// }
|
|
246
230
|
/**
|
|
247
|
-
* Create a set of CRUD routes given a Mongoose model
|
|
231
|
+
* Create a set of CRUD routes given a Mongoose model and configuration options.
|
|
248
232
|
*
|
|
249
|
-
* @param
|
|
233
|
+
* @param model A Mongoose Model
|
|
250
234
|
* @param options Options for configuring the REST API, such as permissions, transformers, and hooks.
|
|
251
235
|
*/
|
|
252
|
-
function modelRouter(
|
|
236
|
+
function modelRouter(model, options) {
|
|
253
237
|
var _this = this;
|
|
254
238
|
var _a;
|
|
255
239
|
var router = express_1.default.Router();
|
|
@@ -260,15 +244,13 @@ function modelRouter(baseModel, options) {
|
|
|
260
244
|
var responseHandler = (_a = options.responseHandler) !== null && _a !== void 0 ? _a : transformers_1.defaultResponseHandler;
|
|
261
245
|
router.post("/", [
|
|
262
246
|
(0, auth_1.authenticateMiddleware)(options.allowAnonymous),
|
|
263
|
-
(0, openApi_1.createOpenApiMiddleware)(
|
|
264
|
-
(0, permissions_1.permissionMiddleware)(
|
|
247
|
+
(0, openApi_1.createOpenApiMiddleware)(model, options),
|
|
248
|
+
(0, permissions_1.permissionMiddleware)(model, options),
|
|
265
249
|
], (0, exports.asyncHandler)(function (req, res) { return __awaiter(_this, void 0, void 0, function () {
|
|
266
|
-
var
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
switch (_b.label) {
|
|
250
|
+
var body, error_1, data, error_2, populateQuery, error_3, error_4, serialized, error_5;
|
|
251
|
+
return __generator(this, function (_a) {
|
|
252
|
+
switch (_a.label) {
|
|
270
253
|
case 0:
|
|
271
|
-
model = getModel(baseModel, (_a = req.body) === null || _a === void 0 ? void 0 : _a.__t, options);
|
|
272
254
|
try {
|
|
273
255
|
body = (0, transformers_1.transform)(options, req.body, "create", req.user);
|
|
274
256
|
}
|
|
@@ -281,15 +263,15 @@ function modelRouter(baseModel, options) {
|
|
|
281
263
|
});
|
|
282
264
|
}
|
|
283
265
|
if (!options.preCreate) return [3 /*break*/, 5];
|
|
284
|
-
|
|
266
|
+
_a.label = 1;
|
|
285
267
|
case 1:
|
|
286
|
-
|
|
268
|
+
_a.trys.push([1, 3, , 4]);
|
|
287
269
|
return [4 /*yield*/, options.preCreate(body, req)];
|
|
288
270
|
case 2:
|
|
289
|
-
body =
|
|
271
|
+
body = _a.sent();
|
|
290
272
|
return [3 /*break*/, 4];
|
|
291
273
|
case 3:
|
|
292
|
-
error_1 =
|
|
274
|
+
error_1 = _a.sent();
|
|
293
275
|
if ((0, errors_1.isAPIError)(error_1)) {
|
|
294
276
|
throw error_1;
|
|
295
277
|
}
|
|
@@ -314,7 +296,7 @@ function modelRouter(baseModel, options) {
|
|
|
314
296
|
title: "Create not allowed",
|
|
315
297
|
});
|
|
316
298
|
}
|
|
317
|
-
|
|
299
|
+
_a.label = 5;
|
|
318
300
|
case 5:
|
|
319
301
|
if (body === undefined) {
|
|
320
302
|
throw new errors_1.APIError({
|
|
@@ -323,15 +305,15 @@ function modelRouter(baseModel, options) {
|
|
|
323
305
|
title: "Invalid request body",
|
|
324
306
|
});
|
|
325
307
|
}
|
|
326
|
-
|
|
308
|
+
_a.label = 6;
|
|
327
309
|
case 6:
|
|
328
|
-
|
|
310
|
+
_a.trys.push([6, 8, , 9]);
|
|
329
311
|
return [4 /*yield*/, model.create(body)];
|
|
330
312
|
case 7:
|
|
331
|
-
data =
|
|
313
|
+
data = _a.sent();
|
|
332
314
|
return [3 /*break*/, 9];
|
|
333
315
|
case 8:
|
|
334
|
-
error_2 =
|
|
316
|
+
error_2 = _a.sent();
|
|
335
317
|
throw new errors_1.APIError({
|
|
336
318
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_2),
|
|
337
319
|
error: error_2,
|
|
@@ -340,17 +322,17 @@ function modelRouter(baseModel, options) {
|
|
|
340
322
|
});
|
|
341
323
|
case 9:
|
|
342
324
|
if (!options.populatePaths) return [3 /*break*/, 13];
|
|
343
|
-
|
|
325
|
+
_a.label = 10;
|
|
344
326
|
case 10:
|
|
345
|
-
|
|
327
|
+
_a.trys.push([10, 12, , 13]);
|
|
346
328
|
populateQuery = model.findById(data._id);
|
|
347
329
|
populateQuery = addPopulateToQuery(populateQuery, options.populatePaths);
|
|
348
330
|
return [4 /*yield*/, populateQuery.exec()];
|
|
349
331
|
case 11:
|
|
350
|
-
data =
|
|
332
|
+
data = _a.sent();
|
|
351
333
|
return [3 /*break*/, 13];
|
|
352
334
|
case 12:
|
|
353
|
-
error_3 =
|
|
335
|
+
error_3 = _a.sent();
|
|
354
336
|
throw new errors_1.APIError({
|
|
355
337
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_3),
|
|
356
338
|
error: error_3,
|
|
@@ -359,15 +341,15 @@ function modelRouter(baseModel, options) {
|
|
|
359
341
|
});
|
|
360
342
|
case 13:
|
|
361
343
|
if (!options.postCreate) return [3 /*break*/, 17];
|
|
362
|
-
|
|
344
|
+
_a.label = 14;
|
|
363
345
|
case 14:
|
|
364
|
-
|
|
346
|
+
_a.trys.push([14, 16, , 17]);
|
|
365
347
|
return [4 /*yield*/, options.postCreate(data, req)];
|
|
366
348
|
case 15:
|
|
367
|
-
|
|
349
|
+
_a.sent();
|
|
368
350
|
return [3 /*break*/, 17];
|
|
369
351
|
case 16:
|
|
370
|
-
error_4 =
|
|
352
|
+
error_4 = _a.sent();
|
|
371
353
|
throw new errors_1.APIError({
|
|
372
354
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_4),
|
|
373
355
|
error: error_4,
|
|
@@ -375,13 +357,13 @@ function modelRouter(baseModel, options) {
|
|
|
375
357
|
title: "postCreate hook error: ".concat(error_4.message),
|
|
376
358
|
});
|
|
377
359
|
case 17:
|
|
378
|
-
|
|
360
|
+
_a.trys.push([17, 19, , 20]);
|
|
379
361
|
return [4 /*yield*/, responseHandler(data, "create", req, options)];
|
|
380
362
|
case 18:
|
|
381
|
-
serialized =
|
|
363
|
+
serialized = _a.sent();
|
|
382
364
|
return [2 /*return*/, res.status(201).json({ data: serialized })];
|
|
383
365
|
case 19:
|
|
384
|
-
error_5 =
|
|
366
|
+
error_5 = _a.sent();
|
|
385
367
|
throw new errors_1.APIError({
|
|
386
368
|
disableExternalErrorTracking: (0, errors_1.getDisableExternalErrorTracking)(error_5),
|
|
387
369
|
error: error_5,
|
|
@@ -394,16 +376,15 @@ function modelRouter(baseModel, options) {
|
|
|
394
376
|
// TODO add rate limit
|
|
395
377
|
router.get("/", [
|
|
396
378
|
(0, auth_1.authenticateMiddleware)(options.allowAnonymous),
|
|
397
|
-
(0, permissions_1.permissionMiddleware)(
|
|
398
|
-
(0, openApi_1.listOpenApiMiddleware)(
|
|
379
|
+
(0, permissions_1.permissionMiddleware)(model, options),
|
|
380
|
+
(0, openApi_1.listOpenApiMiddleware)(model, options),
|
|
399
381
|
], (0, exports.asyncHandler)(function (req, res) { return __awaiter(_this, void 0, void 0, function () {
|
|
400
|
-
var
|
|
382
|
+
var query, _a, _b, queryParam, _c, _d, queryParam, queryFilter, error_6, limit, builtQuery, total, populatedQuery, data, error_7, serialized, error_8, more, msg;
|
|
401
383
|
var e_4, _e, e_5, _f;
|
|
402
384
|
var _g, _h, _j, _k, _l, _m;
|
|
403
385
|
return __generator(this, function (_o) {
|
|
404
386
|
switch (_o.label) {
|
|
405
387
|
case 0:
|
|
406
|
-
model = baseModel;
|
|
407
388
|
query = {};
|
|
408
389
|
try {
|
|
409
390
|
for (_a = __values(Object.keys((_g = options.defaultQueryParams) !== null && _g !== void 0 ? _g : [])), _b = _a.next(); !_b.done; _b = _a.next()) {
|
|
@@ -575,8 +556,8 @@ function modelRouter(baseModel, options) {
|
|
|
575
556
|
}); }));
|
|
576
557
|
router.get("/:id", [
|
|
577
558
|
(0, auth_1.authenticateMiddleware)(options.allowAnonymous),
|
|
578
|
-
(0, openApi_1.getOpenApiMiddleware)(
|
|
579
|
-
(0, permissions_1.permissionMiddleware)(
|
|
559
|
+
(0, openApi_1.getOpenApiMiddleware)(model, options),
|
|
560
|
+
(0, permissions_1.permissionMiddleware)(model, options),
|
|
580
561
|
], (0, exports.asyncHandler)(function (req, res) { return __awaiter(_this, void 0, void 0, function () {
|
|
581
562
|
var data, serialized, error_9;
|
|
582
563
|
return __generator(this, function (_a) {
|
|
@@ -611,15 +592,14 @@ function modelRouter(baseModel, options) {
|
|
|
611
592
|
}); }));
|
|
612
593
|
router.patch("/:id", [
|
|
613
594
|
(0, auth_1.authenticateMiddleware)(options.allowAnonymous),
|
|
614
|
-
(0, openApi_1.patchOpenApiMiddleware)(
|
|
615
|
-
(0, permissions_1.permissionMiddleware)(
|
|
595
|
+
(0, openApi_1.patchOpenApiMiddleware)(model, options),
|
|
596
|
+
(0, permissions_1.permissionMiddleware)(model, options),
|
|
616
597
|
], (0, exports.asyncHandler)(function (req, res) { return __awaiter(_this, void 0, void 0, function () {
|
|
617
|
-
var
|
|
598
|
+
var doc, body, error_10, prevDoc, error_11, populateQuery, error_12, serialized, error_13;
|
|
618
599
|
var _a;
|
|
619
600
|
return __generator(this, function (_b) {
|
|
620
601
|
switch (_b.label) {
|
|
621
602
|
case 0:
|
|
622
|
-
model = getModel(baseModel, req.body, options);
|
|
623
603
|
doc = req.obj;
|
|
624
604
|
try {
|
|
625
605
|
body = (0, transformers_1.transform)(options, req.body, "update", req.user);
|
|
@@ -733,14 +713,13 @@ function modelRouter(baseModel, options) {
|
|
|
733
713
|
}); }));
|
|
734
714
|
router.delete("/:id", [
|
|
735
715
|
(0, auth_1.authenticateMiddleware)(options.allowAnonymous),
|
|
736
|
-
(0, openApi_1.deleteOpenApiMiddleware)(
|
|
737
|
-
(0, permissions_1.permissionMiddleware)(
|
|
716
|
+
(0, openApi_1.deleteOpenApiMiddleware)(model, options),
|
|
717
|
+
(0, permissions_1.permissionMiddleware)(model, options),
|
|
738
718
|
], (0, exports.asyncHandler)(function (req, res) { return __awaiter(_this, void 0, void 0, function () {
|
|
739
|
-
var
|
|
719
|
+
var doc, body, error_14, error_15, error_16;
|
|
740
720
|
return __generator(this, function (_a) {
|
|
741
721
|
switch (_a.label) {
|
|
742
722
|
case 0:
|
|
743
|
-
model = getModel(baseModel, req.body, options);
|
|
744
723
|
doc = req.obj;
|
|
745
724
|
if (!options.preDelete) return [3 /*break*/, 5];
|
|
746
725
|
body = void 0;
|
|
@@ -823,15 +802,14 @@ function modelRouter(baseModel, options) {
|
|
|
823
802
|
}); }));
|
|
824
803
|
function arrayOperation(req, res, operation) {
|
|
825
804
|
return __awaiter(this, void 0, void 0, function () {
|
|
826
|
-
var
|
|
805
|
+
var doc, prevDoc, field, array, index, body, error_17, error_18, error_19;
|
|
827
806
|
var _a;
|
|
828
807
|
var _b, _c;
|
|
829
808
|
return __generator(this, function (_d) {
|
|
830
809
|
switch (_d.label) {
|
|
831
|
-
case 0:
|
|
832
|
-
model = getModel(baseModel, req.body, options);
|
|
833
|
-
return [4 /*yield*/, (0, permissions_1.checkPermissions)("update", options.permissions.update, req.user)];
|
|
810
|
+
case 0: return [4 /*yield*/, (0, permissions_1.checkPermissions)("update", options.permissions.update, req.user)];
|
|
834
811
|
case 1:
|
|
812
|
+
// TODO Combine array operations and .patch(), as they are very similar.
|
|
835
813
|
if (!(_d.sent())) {
|
|
836
814
|
throw new errors_1.APIError({
|
|
837
815
|
status: 405,
|
|
@@ -842,9 +820,7 @@ function modelRouter(baseModel, options) {
|
|
|
842
820
|
case 2:
|
|
843
821
|
doc = _d.sent();
|
|
844
822
|
prevDoc = (0, cloneDeep_1.default)(doc);
|
|
845
|
-
|
|
846
|
-
// hooks.
|
|
847
|
-
if (!doc || (doc.__t && !req.body.__t)) {
|
|
823
|
+
if (!doc) {
|
|
848
824
|
throw new errors_1.APIError({
|
|
849
825
|
status: 404,
|
|
850
826
|
title: "Could not find document to PATCH: ".concat(req.params.id),
|
|
@@ -1007,7 +983,7 @@ function modelRouter(baseModel, options) {
|
|
|
1007
983
|
});
|
|
1008
984
|
}
|
|
1009
985
|
// Set up routes for managing array fields. Check if there any array fields to add this for.
|
|
1010
|
-
if (Object.values(
|
|
986
|
+
if (Object.values(model.schema.paths).find(function (config) { return config.instance === "Array"; })) {
|
|
1011
987
|
router.post("/:id/:field", (0, auth_1.authenticateMiddleware)(options.allowAnonymous), (0, exports.asyncHandler)(arrayPost));
|
|
1012
988
|
router.patch("/:id/:field/:itemId", (0, auth_1.authenticateMiddleware)(options.allowAnonymous), (0, exports.asyncHandler)(arrayPatch));
|
|
1013
989
|
router.delete("/:id/:field/:itemId", (0, auth_1.authenticateMiddleware)(options.allowAnonymous), (0, exports.asyncHandler)(arrayDelete));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|