@terreno/api 0.0.11 → 0.0.13
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.d.ts
CHANGED
|
@@ -181,16 +181,6 @@ export interface ModelRouterOptions<T> {
|
|
|
181
181
|
* keys. Throw an APIError to return a 400 with an error message.
|
|
182
182
|
*/
|
|
183
183
|
responseHandler?: (value: (Document<any, any, any> & T) | (Document<any, any, any> & T)[], method: "list" | "create" | "read" | "update" | "delete", request: express.Request, options: ModelRouterOptions<T>) => Promise<JSONValue>;
|
|
184
|
-
/**
|
|
185
|
-
* The discriminatorKey that you passed when creating the Mongoose models. Defaults to __t. See:
|
|
186
|
-
* https://mongoosejs.com/docs/discriminators.html If this key is provided,
|
|
187
|
-
* you must provide the same key as part of the top level of the body when making performing
|
|
188
|
-
* update or delete operations on this model.
|
|
189
|
-
* \{discriminatorKey: "__t"\}
|
|
190
|
-
*
|
|
191
|
-
* PATCH \{__t: "SuperUser", name: "Foo"\} // __t is required or there will be a 404 error.
|
|
192
|
-
*/
|
|
193
|
-
discriminatorKey?: string;
|
|
194
184
|
/**
|
|
195
185
|
* The OpenAPI generator for this server. This is used to generate the OpenAPI documentation.
|
|
196
186
|
*/
|
|
@@ -214,14 +204,13 @@ export interface ModelRouterOptions<T> {
|
|
|
214
204
|
*/
|
|
215
205
|
openApiExtraModelProperties?: any;
|
|
216
206
|
}
|
|
217
|
-
export declare function getModel(baseModel: Model<any>, body?: any, options?: ModelRouterOptions<any>): mongoose.Model<any, {}, {}, {}, any, any, any>;
|
|
218
207
|
/**
|
|
219
|
-
* Create a set of CRUD routes given a Mongoose model
|
|
208
|
+
* Create a set of CRUD routes given a Mongoose model and configuration options.
|
|
220
209
|
*
|
|
221
|
-
* @param
|
|
210
|
+
* @param model A Mongoose Model
|
|
222
211
|
* @param options Options for configuring the REST API, such as permissions, transformers, and hooks.
|
|
223
212
|
*/
|
|
224
|
-
export declare function modelRouter<T>(
|
|
213
|
+
export declare function modelRouter<T>(model: Model<T>, options: ModelRouterOptions<T>): express.Router;
|
|
225
214
|
export declare const asyncHandler: (fn: any) => (req: Request, res: Response, next: NextFunction) => Promise<any>;
|
|
226
215
|
export declare const gooseRestRouter: typeof modelRouter;
|
|
227
216
|
export type GooseRESTOptions<T> = ModelRouterOptions<T>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
13
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
+
function step(op) {
|
|
16
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
18
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
19
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
+
switch (op[0]) {
|
|
21
|
+
case 0: case 1: t = op; break;
|
|
22
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
+
default:
|
|
26
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
+
if (t[2]) _.ops.pop();
|
|
31
|
+
_.trys.pop(); continue;
|
|
32
|
+
}
|
|
33
|
+
op = body.call(thisArg, _);
|
|
34
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
+
};
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
var bun_test_1 = require("bun:test");
|
|
43
|
+
var mongoose_1 = __importDefault(require("mongoose"));
|
|
44
|
+
var errors_1 = require("./errors");
|
|
45
|
+
(0, bun_test_1.describe)("errors module", function () {
|
|
46
|
+
(0, bun_test_1.describe)("APIError", function () {
|
|
47
|
+
(0, bun_test_1.it)("sets default status to 500 when not provided", function () {
|
|
48
|
+
var error = new errors_1.APIError({ title: "Test error" });
|
|
49
|
+
(0, bun_test_1.expect)(error.status).toBe(500);
|
|
50
|
+
});
|
|
51
|
+
(0, bun_test_1.it)("sets status to 500 for invalid status codes below 400", function () {
|
|
52
|
+
var error = new errors_1.APIError({ status: 200, title: "Test error" });
|
|
53
|
+
(0, bun_test_1.expect)(error.status).toBe(500);
|
|
54
|
+
});
|
|
55
|
+
(0, bun_test_1.it)("sets status to 500 for invalid status codes above 599", function () {
|
|
56
|
+
var error = new errors_1.APIError({ status: 600, title: "Test error" });
|
|
57
|
+
(0, bun_test_1.expect)(error.status).toBe(500);
|
|
58
|
+
});
|
|
59
|
+
(0, bun_test_1.it)("includes error stack in message when error is provided", function () {
|
|
60
|
+
var originalError = new Error("Original error");
|
|
61
|
+
var apiError = new errors_1.APIError({
|
|
62
|
+
error: originalError,
|
|
63
|
+
title: "Wrapped error",
|
|
64
|
+
});
|
|
65
|
+
(0, bun_test_1.expect)(apiError.message).toContain("Wrapped error");
|
|
66
|
+
(0, bun_test_1.expect)(originalError.stack).toBeDefined();
|
|
67
|
+
(0, bun_test_1.expect)(apiError.message).toContain(originalError.stack);
|
|
68
|
+
});
|
|
69
|
+
(0, bun_test_1.it)("includes detail in message when provided", function () {
|
|
70
|
+
var error = new errors_1.APIError({
|
|
71
|
+
detail: "More details here",
|
|
72
|
+
title: "Test error",
|
|
73
|
+
});
|
|
74
|
+
(0, bun_test_1.expect)(error.message).toContain("Test error");
|
|
75
|
+
(0, bun_test_1.expect)(error.message).toContain("More details here");
|
|
76
|
+
});
|
|
77
|
+
(0, bun_test_1.it)("sets fields in meta when provided", function () {
|
|
78
|
+
var _a;
|
|
79
|
+
var error = new errors_1.APIError({
|
|
80
|
+
fields: { email: "Invalid email format" },
|
|
81
|
+
title: "Validation error",
|
|
82
|
+
});
|
|
83
|
+
(0, bun_test_1.expect)((_a = error.meta) === null || _a === void 0 ? void 0 : _a.fields).toEqual({ email: "Invalid email format" });
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
(0, bun_test_1.describe)("errorsPlugin", function () {
|
|
87
|
+
(0, bun_test_1.it)("adds apiErrors field to schema", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
88
|
+
var testSchema;
|
|
89
|
+
return __generator(this, function (_a) {
|
|
90
|
+
testSchema = new mongoose_1.default.Schema({ name: String });
|
|
91
|
+
(0, errors_1.errorsPlugin)(testSchema);
|
|
92
|
+
(0, bun_test_1.expect)(testSchema.path("apiErrors")).toBeDefined();
|
|
93
|
+
return [2 /*return*/];
|
|
94
|
+
});
|
|
95
|
+
}); });
|
|
96
|
+
});
|
|
97
|
+
(0, bun_test_1.describe)("isAPIError", function () {
|
|
98
|
+
(0, bun_test_1.it)("returns true for APIError instances", function () {
|
|
99
|
+
var error = new errors_1.APIError({ title: "Test" });
|
|
100
|
+
(0, bun_test_1.expect)((0, errors_1.isAPIError)(error)).toBe(true);
|
|
101
|
+
});
|
|
102
|
+
(0, bun_test_1.it)("returns false for regular Error instances", function () {
|
|
103
|
+
var error = new Error("Test");
|
|
104
|
+
(0, bun_test_1.expect)((0, errors_1.isAPIError)(error)).toBe(false);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
(0, bun_test_1.describe)("getDisableExternalErrorTracking", function () {
|
|
108
|
+
(0, bun_test_1.it)("returns undefined for non-objects", function () {
|
|
109
|
+
(0, bun_test_1.expect)((0, errors_1.getDisableExternalErrorTracking)(null)).toBeUndefined();
|
|
110
|
+
(0, bun_test_1.expect)((0, errors_1.getDisableExternalErrorTracking)("string")).toBeUndefined();
|
|
111
|
+
});
|
|
112
|
+
(0, bun_test_1.it)("returns value from APIError", function () {
|
|
113
|
+
var error = new errors_1.APIError({ disableExternalErrorTracking: true, title: "Test" });
|
|
114
|
+
(0, bun_test_1.expect)((0, errors_1.getDisableExternalErrorTracking)(error)).toBe(true);
|
|
115
|
+
});
|
|
116
|
+
(0, bun_test_1.it)("returns value from plain object with property", function () {
|
|
117
|
+
var obj = { disableExternalErrorTracking: true };
|
|
118
|
+
(0, bun_test_1.expect)((0, errors_1.getDisableExternalErrorTracking)(obj)).toBe(true);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
(0, bun_test_1.describe)("getAPIErrorBody", function () {
|
|
122
|
+
(0, bun_test_1.it)("includes all non-undefined fields", function () {
|
|
123
|
+
var error = new errors_1.APIError({
|
|
124
|
+
code: "TEST_CODE",
|
|
125
|
+
detail: "Test detail",
|
|
126
|
+
id: "error-123",
|
|
127
|
+
links: { about: "http://example.com" },
|
|
128
|
+
meta: { extra: "data" },
|
|
129
|
+
source: { parameter: "id" },
|
|
130
|
+
status: 400,
|
|
131
|
+
title: "Test error",
|
|
132
|
+
});
|
|
133
|
+
var body = (0, errors_1.getAPIErrorBody)(error);
|
|
134
|
+
(0, bun_test_1.expect)(body.title).toBe("Test error");
|
|
135
|
+
(0, bun_test_1.expect)(body.status).toBe(400);
|
|
136
|
+
(0, bun_test_1.expect)(body.code).toBe("TEST_CODE");
|
|
137
|
+
(0, bun_test_1.expect)(body.detail).toBe("Test detail");
|
|
138
|
+
(0, bun_test_1.expect)(body.id).toBe("error-123");
|
|
139
|
+
(0, bun_test_1.expect)(body.links).toEqual({ about: "http://example.com" });
|
|
140
|
+
(0, bun_test_1.expect)(body.source).toEqual({ parameter: "id" });
|
|
141
|
+
(0, bun_test_1.expect)(body.meta).toEqual({ extra: "data" });
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
(0, bun_test_1.describe)("apiUnauthorizedMiddleware", function () {
|
|
145
|
+
(0, bun_test_1.it)("returns 401 for Unauthorized errors", function () {
|
|
146
|
+
var err = new Error("Unauthorized");
|
|
147
|
+
var res = {
|
|
148
|
+
json: function (data) {
|
|
149
|
+
this.body = data;
|
|
150
|
+
return this;
|
|
151
|
+
},
|
|
152
|
+
send: function () {
|
|
153
|
+
return this;
|
|
154
|
+
},
|
|
155
|
+
status: function (code) {
|
|
156
|
+
this.statusCode = code;
|
|
157
|
+
return this;
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
var next = function () { };
|
|
161
|
+
(0, errors_1.apiUnauthorizedMiddleware)(err, {}, res, next);
|
|
162
|
+
(0, bun_test_1.expect)(res.statusCode).toBe(401);
|
|
163
|
+
(0, bun_test_1.expect)(res.body.title).toBe("Unauthorized");
|
|
164
|
+
});
|
|
165
|
+
(0, bun_test_1.it)("calls next for non-Unauthorized errors", function () {
|
|
166
|
+
var err = new Error("Some other error");
|
|
167
|
+
var nextCalled = false;
|
|
168
|
+
var next = function () {
|
|
169
|
+
nextCalled = true;
|
|
170
|
+
};
|
|
171
|
+
(0, errors_1.apiUnauthorizedMiddleware)(err, {}, {}, next);
|
|
172
|
+
(0, bun_test_1.expect)(nextCalled).toBe(true);
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|