@terreno/api 0.0.11-beta.1 → 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/biome.jsonc +1 -1
- package/dist/api.arrayOperations.test.d.ts +1 -0
- package/dist/api.arrayOperations.test.js +868 -0
- 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.query.test.d.ts +1 -0
- package/dist/api.query.test.js +805 -0
- package/dist/api.test.js +310 -3182
- 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.test.js +57 -0
- package/dist/populate.test.js +52 -0
- package/dist/tests.d.ts +9 -27
- package/dist/utils.test.js +66 -0
- package/package.json +2 -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 +273 -2658
- 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/populate.test.ts +58 -0
- package/src/utils.test.ts +26 -1
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
16
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
17
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
18
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
19
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
+
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);
|
|
24
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
+
function step(op) {
|
|
27
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
29
|
+
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;
|
|
30
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
+
switch (op[0]) {
|
|
32
|
+
case 0: case 1: t = op; break;
|
|
33
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
+
default:
|
|
37
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
+
if (t[2]) _.ops.pop();
|
|
42
|
+
_.trys.pop(); continue;
|
|
43
|
+
}
|
|
44
|
+
op = body.call(thisArg, _);
|
|
45
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
var __read = (this && this.__read) || function (o, n) {
|
|
50
|
+
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
51
|
+
if (!m) return o;
|
|
52
|
+
var i = m.call(o), r, ar = [], e;
|
|
53
|
+
try {
|
|
54
|
+
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
55
|
+
}
|
|
56
|
+
catch (error) { e = { error: error }; }
|
|
57
|
+
finally {
|
|
58
|
+
try {
|
|
59
|
+
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
60
|
+
}
|
|
61
|
+
finally { if (e) throw e.error; }
|
|
62
|
+
}
|
|
63
|
+
return ar;
|
|
64
|
+
};
|
|
65
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
66
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
67
|
+
if (ar || !(i in from)) {
|
|
68
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
69
|
+
ar[i] = from[i];
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
73
|
+
};
|
|
74
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
75
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
76
|
+
};
|
|
77
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
78
|
+
var bun_test_1 = require("bun:test");
|
|
79
|
+
var express_1 = __importDefault(require("express"));
|
|
80
|
+
var supertest_1 = __importDefault(require("supertest"));
|
|
81
|
+
var expressServer_1 = require("./expressServer");
|
|
82
|
+
var tests_1 = require("./tests");
|
|
83
|
+
(0, bun_test_1.describe)("expressServer", function () {
|
|
84
|
+
(0, bun_test_1.describe)("setupEnvironment", function () {
|
|
85
|
+
var originalEnv = process.env;
|
|
86
|
+
(0, bun_test_1.beforeEach)(function () {
|
|
87
|
+
// Reset env to a clean state with required values
|
|
88
|
+
process.env = __assign(__assign({}, originalEnv), { REFRESH_TOKEN_SECRET: "test-refresh-secret", SESSION_SECRET: "test-session-secret", TOKEN_ISSUER: "test-issuer", TOKEN_SECRET: "test-secret" });
|
|
89
|
+
});
|
|
90
|
+
(0, bun_test_1.afterEach)(function () {
|
|
91
|
+
process.env = originalEnv;
|
|
92
|
+
});
|
|
93
|
+
(0, bun_test_1.it)("throws error when TOKEN_ISSUER is not set", function () {
|
|
94
|
+
process.env.TOKEN_ISSUER = "";
|
|
95
|
+
(0, bun_test_1.expect)(function () { return (0, expressServer_1.setupEnvironment)(); }).toThrow("TOKEN_ISSUER must be set in env.");
|
|
96
|
+
});
|
|
97
|
+
(0, bun_test_1.it)("throws error when TOKEN_SECRET is not set", function () {
|
|
98
|
+
process.env.TOKEN_SECRET = "";
|
|
99
|
+
(0, bun_test_1.expect)(function () { return (0, expressServer_1.setupEnvironment)(); }).toThrow("TOKEN_SECRET must be set.");
|
|
100
|
+
});
|
|
101
|
+
(0, bun_test_1.it)("throws error when REFRESH_TOKEN_SECRET is not set", function () {
|
|
102
|
+
process.env.REFRESH_TOKEN_SECRET = "";
|
|
103
|
+
(0, bun_test_1.expect)(function () { return (0, expressServer_1.setupEnvironment)(); }).toThrow("REFRESH_TOKEN_SECRET must be set.");
|
|
104
|
+
});
|
|
105
|
+
(0, bun_test_1.it)("throws error when SESSION_SECRET is not set", function () {
|
|
106
|
+
process.env.SESSION_SECRET = "";
|
|
107
|
+
(0, bun_test_1.expect)(function () { return (0, expressServer_1.setupEnvironment)(); }).toThrow("SESSION_SECRET must be set.");
|
|
108
|
+
});
|
|
109
|
+
(0, bun_test_1.it)("does not throw when all required env vars are set", function () {
|
|
110
|
+
(0, bun_test_1.expect)(function () { return (0, expressServer_1.setupEnvironment)(); }).not.toThrow();
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
(0, bun_test_1.describe)("logRequests", function () {
|
|
114
|
+
(0, bun_test_1.it)("logs request with admin user type", function () {
|
|
115
|
+
var req = {
|
|
116
|
+
body: {},
|
|
117
|
+
method: "GET",
|
|
118
|
+
url: "/test",
|
|
119
|
+
user: { admin: true, id: "admin-123" },
|
|
120
|
+
};
|
|
121
|
+
var res = {
|
|
122
|
+
locals: {},
|
|
123
|
+
on: function () { },
|
|
124
|
+
};
|
|
125
|
+
var nextCalled = false;
|
|
126
|
+
var next = function () {
|
|
127
|
+
nextCalled = true;
|
|
128
|
+
};
|
|
129
|
+
(0, expressServer_1.logRequests)(req, res, next);
|
|
130
|
+
(0, bun_test_1.expect)(nextCalled).toBe(true);
|
|
131
|
+
});
|
|
132
|
+
(0, bun_test_1.it)("logs request with test user type", function () {
|
|
133
|
+
var req = {
|
|
134
|
+
body: {},
|
|
135
|
+
method: "GET",
|
|
136
|
+
url: "/test",
|
|
137
|
+
user: { id: "test-123", testUser: true },
|
|
138
|
+
};
|
|
139
|
+
var res = {
|
|
140
|
+
locals: {},
|
|
141
|
+
on: function () { },
|
|
142
|
+
};
|
|
143
|
+
var nextCalled = false;
|
|
144
|
+
var next = function () {
|
|
145
|
+
nextCalled = true;
|
|
146
|
+
};
|
|
147
|
+
(0, expressServer_1.logRequests)(req, res, next);
|
|
148
|
+
(0, bun_test_1.expect)(nextCalled).toBe(true);
|
|
149
|
+
});
|
|
150
|
+
(0, bun_test_1.it)("logs request with custom user type", function () {
|
|
151
|
+
var req = {
|
|
152
|
+
body: {},
|
|
153
|
+
method: "GET",
|
|
154
|
+
url: "/test",
|
|
155
|
+
user: { id: "user-123", type: "CustomType" },
|
|
156
|
+
};
|
|
157
|
+
var res = {
|
|
158
|
+
locals: {},
|
|
159
|
+
on: function () { },
|
|
160
|
+
};
|
|
161
|
+
var nextCalled = false;
|
|
162
|
+
var next = function () {
|
|
163
|
+
nextCalled = true;
|
|
164
|
+
};
|
|
165
|
+
(0, expressServer_1.logRequests)(req, res, next);
|
|
166
|
+
(0, bun_test_1.expect)(nextCalled).toBe(true);
|
|
167
|
+
});
|
|
168
|
+
(0, bun_test_1.it)("masks password in body", function () {
|
|
169
|
+
var req = {
|
|
170
|
+
body: { password: "secret123", username: "testuser" },
|
|
171
|
+
method: "POST",
|
|
172
|
+
url: "/login",
|
|
173
|
+
};
|
|
174
|
+
var res = {
|
|
175
|
+
locals: {},
|
|
176
|
+
on: function () { },
|
|
177
|
+
};
|
|
178
|
+
var nextCalled = false;
|
|
179
|
+
var next = function () {
|
|
180
|
+
nextCalled = true;
|
|
181
|
+
};
|
|
182
|
+
(0, expressServer_1.logRequests)(req, res, next);
|
|
183
|
+
(0, bun_test_1.expect)(nextCalled).toBe(true);
|
|
184
|
+
// Original body should not be modified
|
|
185
|
+
(0, bun_test_1.expect)(req.body.password).toBe("secret123");
|
|
186
|
+
});
|
|
187
|
+
(0, bun_test_1.it)("triggers onFinished callback with route info", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
188
|
+
var app;
|
|
189
|
+
return __generator(this, function (_a) {
|
|
190
|
+
switch (_a.label) {
|
|
191
|
+
case 0:
|
|
192
|
+
app = (0, express_1.default)();
|
|
193
|
+
app.use(expressServer_1.logRequests);
|
|
194
|
+
app.get("/test", function (req, res) {
|
|
195
|
+
req.route = { path: "/test" };
|
|
196
|
+
req.routeMount = "/api";
|
|
197
|
+
res.json({ ok: true });
|
|
198
|
+
});
|
|
199
|
+
return [4 /*yield*/, (0, supertest_1.default)(app).get("/test").expect(200)];
|
|
200
|
+
case 1:
|
|
201
|
+
_a.sent();
|
|
202
|
+
return [2 /*return*/];
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}); });
|
|
206
|
+
(0, bun_test_1.it)("triggers onFinished callback without route (for 404)", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
207
|
+
var app;
|
|
208
|
+
return __generator(this, function (_a) {
|
|
209
|
+
switch (_a.label) {
|
|
210
|
+
case 0:
|
|
211
|
+
app = (0, express_1.default)();
|
|
212
|
+
app.use(expressServer_1.logRequests);
|
|
213
|
+
// No routes defined, so it will 404
|
|
214
|
+
return [4 /*yield*/, (0, supertest_1.default)(app).get("/nonexistent").expect(404)];
|
|
215
|
+
case 1:
|
|
216
|
+
// No routes defined, so it will 404
|
|
217
|
+
_a.sent();
|
|
218
|
+
return [2 /*return*/];
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
}); });
|
|
222
|
+
(0, bun_test_1.it)("logs slow GET requests when enabled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
223
|
+
var app;
|
|
224
|
+
return __generator(this, function (_a) {
|
|
225
|
+
switch (_a.label) {
|
|
226
|
+
case 0:
|
|
227
|
+
app = (0, express_1.default)();
|
|
228
|
+
// Store logging options
|
|
229
|
+
app.use(function (_req, res, next) {
|
|
230
|
+
res.locals.loggingOptions = {
|
|
231
|
+
logSlowRequests: true,
|
|
232
|
+
logSlowRequestsReadMs: 1, // Very low threshold to trigger slow request warning
|
|
233
|
+
};
|
|
234
|
+
next();
|
|
235
|
+
});
|
|
236
|
+
app.use(expressServer_1.logRequests);
|
|
237
|
+
app.get("/slow", function (_req, res) { return __awaiter(void 0, void 0, void 0, function () {
|
|
238
|
+
return __generator(this, function (_a) {
|
|
239
|
+
switch (_a.label) {
|
|
240
|
+
case 0:
|
|
241
|
+
// Add small delay to exceed threshold
|
|
242
|
+
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 10); })];
|
|
243
|
+
case 1:
|
|
244
|
+
// Add small delay to exceed threshold
|
|
245
|
+
_a.sent();
|
|
246
|
+
res.json({ ok: true });
|
|
247
|
+
return [2 /*return*/];
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
}); });
|
|
251
|
+
return [4 /*yield*/, (0, supertest_1.default)(app).get("/slow").expect(200)];
|
|
252
|
+
case 1:
|
|
253
|
+
_a.sent();
|
|
254
|
+
return [2 /*return*/];
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
}); });
|
|
258
|
+
(0, bun_test_1.it)("logs slow write requests when enabled", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
259
|
+
var app;
|
|
260
|
+
return __generator(this, function (_a) {
|
|
261
|
+
switch (_a.label) {
|
|
262
|
+
case 0:
|
|
263
|
+
app = (0, express_1.default)();
|
|
264
|
+
app.use(express_1.default.json());
|
|
265
|
+
app.use(function (_req, res, next) {
|
|
266
|
+
res.locals.loggingOptions = {
|
|
267
|
+
logSlowRequests: true,
|
|
268
|
+
logSlowRequestsWriteMs: 1, // Very low threshold
|
|
269
|
+
};
|
|
270
|
+
next();
|
|
271
|
+
});
|
|
272
|
+
app.use(expressServer_1.logRequests);
|
|
273
|
+
app.post("/slow", function (_req, res) { return __awaiter(void 0, void 0, void 0, function () {
|
|
274
|
+
return __generator(this, function (_a) {
|
|
275
|
+
switch (_a.label) {
|
|
276
|
+
case 0: return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 10); })];
|
|
277
|
+
case 1:
|
|
278
|
+
_a.sent();
|
|
279
|
+
res.json({ ok: true });
|
|
280
|
+
return [2 /*return*/];
|
|
281
|
+
}
|
|
282
|
+
});
|
|
283
|
+
}); });
|
|
284
|
+
return [4 /*yield*/, (0, supertest_1.default)(app).post("/slow").send({ data: "test" }).expect(200)];
|
|
285
|
+
case 1:
|
|
286
|
+
_a.sent();
|
|
287
|
+
return [2 /*return*/];
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}); });
|
|
291
|
+
(0, bun_test_1.it)("handles request with route path only (no routeMount)", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
292
|
+
var app;
|
|
293
|
+
return __generator(this, function (_a) {
|
|
294
|
+
switch (_a.label) {
|
|
295
|
+
case 0:
|
|
296
|
+
app = (0, express_1.default)();
|
|
297
|
+
app.use(expressServer_1.logRequests);
|
|
298
|
+
app.get("/test", function (req, res) {
|
|
299
|
+
req.route = { path: "/test" };
|
|
300
|
+
// No routeMount set
|
|
301
|
+
res.json({ ok: true });
|
|
302
|
+
});
|
|
303
|
+
return [4 /*yield*/, (0, supertest_1.default)(app).get("/test").expect(200)];
|
|
304
|
+
case 1:
|
|
305
|
+
_a.sent();
|
|
306
|
+
return [2 /*return*/];
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
}); });
|
|
310
|
+
});
|
|
311
|
+
(0, bun_test_1.describe)("createRouter", function () {
|
|
312
|
+
(0, bun_test_1.it)("creates router with root path and adds routes", function () {
|
|
313
|
+
var routesCalled = false;
|
|
314
|
+
var addRoutes = function (router) {
|
|
315
|
+
routesCalled = true;
|
|
316
|
+
router.get("/test", function (_req, res) { return res.send("ok"); });
|
|
317
|
+
};
|
|
318
|
+
var result = (0, expressServer_1.createRouter)("/api", addRoutes);
|
|
319
|
+
(0, bun_test_1.expect)(result[0]).toBe("/api");
|
|
320
|
+
(0, bun_test_1.expect)(routesCalled).toBe(true);
|
|
321
|
+
(0, bun_test_1.expect)(result.length).toBe(2); // [path, router]
|
|
322
|
+
});
|
|
323
|
+
(0, bun_test_1.it)("creates router with middleware", function () {
|
|
324
|
+
var middleware1 = function (_req, _res, next) { return next(); };
|
|
325
|
+
var middleware2 = function (_req, _res, next) { return next(); };
|
|
326
|
+
var addRoutes = function () { };
|
|
327
|
+
var result = (0, expressServer_1.createRouter)("/api", addRoutes, [middleware1, middleware2]);
|
|
328
|
+
(0, bun_test_1.expect)(result[0]).toBe("/api");
|
|
329
|
+
(0, bun_test_1.expect)(result.length).toBe(4); // [path, middleware1, middleware2, router]
|
|
330
|
+
});
|
|
331
|
+
(0, bun_test_1.it)("routePathMiddleware sets routeMount on request", function () {
|
|
332
|
+
var addRoutes = function (router) {
|
|
333
|
+
router.get("/test", function (req, res) {
|
|
334
|
+
res.json({ routeMount: req.routeMount });
|
|
335
|
+
});
|
|
336
|
+
};
|
|
337
|
+
var result = (0, expressServer_1.createRouter)("/api", addRoutes);
|
|
338
|
+
var app = (0, express_1.default)();
|
|
339
|
+
app.use.apply(app, __spreadArray([], __read(result), false));
|
|
340
|
+
// The routePathMiddleware is internal, but we can verify the router works
|
|
341
|
+
(0, bun_test_1.expect)(result[0]).toBe("/api");
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
(0, bun_test_1.describe)("createRouterWithAuth", function () {
|
|
345
|
+
(0, bun_test_1.it)("creates router with passport authentication middleware", function () {
|
|
346
|
+
var routesCalled = false;
|
|
347
|
+
var addRoutes = function (router) {
|
|
348
|
+
routesCalled = true;
|
|
349
|
+
router.get("/protected", function (_req, res) { return res.send("ok"); });
|
|
350
|
+
};
|
|
351
|
+
var result = (0, expressServer_1.createRouterWithAuth)("/secure", addRoutes);
|
|
352
|
+
(0, bun_test_1.expect)(result[0]).toBe("/secure");
|
|
353
|
+
(0, bun_test_1.expect)(routesCalled).toBe(true);
|
|
354
|
+
// Should have path + passport middleware + router = 3 elements minimum
|
|
355
|
+
(0, bun_test_1.expect)(result.length).toBeGreaterThanOrEqual(2);
|
|
356
|
+
});
|
|
357
|
+
(0, bun_test_1.it)("includes additional middleware", function () {
|
|
358
|
+
var customMiddleware = function (_req, _res, next) { return next(); };
|
|
359
|
+
var addRoutes = function () { };
|
|
360
|
+
var result = (0, expressServer_1.createRouterWithAuth)("/secure", addRoutes, [customMiddleware]);
|
|
361
|
+
(0, bun_test_1.expect)(result[0]).toBe("/secure");
|
|
362
|
+
// path + passport + customMiddleware + router
|
|
363
|
+
(0, bun_test_1.expect)(result.length).toBeGreaterThanOrEqual(3);
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
(0, bun_test_1.describe)("cronjob", function () {
|
|
367
|
+
(0, bun_test_1.it)("accepts custom cron schedule for hourly", function () {
|
|
368
|
+
var callback = function () { };
|
|
369
|
+
// Every hour at minute 0
|
|
370
|
+
(0, bun_test_1.expect)(function () { return (0, expressServer_1.cronjob)("test-hourly", "0 * * * *", callback); }).not.toThrow();
|
|
371
|
+
});
|
|
372
|
+
(0, bun_test_1.it)("accepts custom cron schedule for minutely", function () {
|
|
373
|
+
var callback = function () { };
|
|
374
|
+
// Every minute
|
|
375
|
+
(0, bun_test_1.expect)(function () { return (0, expressServer_1.cronjob)("test-minutely", "* * * * *", callback); }).not.toThrow();
|
|
376
|
+
});
|
|
377
|
+
(0, bun_test_1.it)("accepts custom cron schedule", function () {
|
|
378
|
+
var callback = function () { };
|
|
379
|
+
// Every day at midnight
|
|
380
|
+
(0, bun_test_1.expect)(function () { return (0, expressServer_1.cronjob)("test-custom", "0 0 * * *", callback); }).not.toThrow();
|
|
381
|
+
});
|
|
382
|
+
(0, bun_test_1.it)("throws error for invalid cron schedule", function () {
|
|
383
|
+
var callback = function () { };
|
|
384
|
+
(0, bun_test_1.expect)(function () { return (0, expressServer_1.cronjob)("test-invalid", "invalid-cron", callback); }).toThrow("Failed to create cronjob");
|
|
385
|
+
});
|
|
386
|
+
// Note: The "hourly" and "minutely" aliases have a bug - they convert the
|
|
387
|
+
// schedule to a cron expression but then use the original schedule string.
|
|
388
|
+
// This test documents that current (buggy) behavior.
|
|
389
|
+
(0, bun_test_1.it)("hourly alias fails due to bug in implementation", function () {
|
|
390
|
+
var callback = function () { };
|
|
391
|
+
(0, bun_test_1.expect)(function () { return (0, expressServer_1.cronjob)("test-hourly-alias", "hourly", callback); }).toThrow("Failed to create cronjob");
|
|
392
|
+
});
|
|
393
|
+
(0, bun_test_1.it)("minutely alias fails due to bug in implementation", function () {
|
|
394
|
+
var callback = function () { };
|
|
395
|
+
(0, bun_test_1.expect)(function () { return (0, expressServer_1.cronjob)("test-minutely-alias", "minutely", callback); }).toThrow("Failed to create cronjob");
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
(0, bun_test_1.describe)("createRouter routePathMiddleware", function () {
|
|
399
|
+
(0, bun_test_1.it)("initializes routeMount array when not present", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
400
|
+
var addRoutes, result, app, response;
|
|
401
|
+
return __generator(this, function (_a) {
|
|
402
|
+
switch (_a.label) {
|
|
403
|
+
case 0:
|
|
404
|
+
addRoutes = function (router) {
|
|
405
|
+
router.get("/test", function (req, res) {
|
|
406
|
+
res.json({ routeMount: req.routeMount });
|
|
407
|
+
});
|
|
408
|
+
};
|
|
409
|
+
result = (0, expressServer_1.createRouter)("/api", addRoutes);
|
|
410
|
+
app = (0, express_1.default)();
|
|
411
|
+
app.use.apply(app, __spreadArray([], __read(result), false));
|
|
412
|
+
return [4 /*yield*/, (0, supertest_1.default)(app).get("/api/test").expect(200)];
|
|
413
|
+
case 1:
|
|
414
|
+
response = _a.sent();
|
|
415
|
+
(0, bun_test_1.expect)(response.body.routeMount).toEqual(["/api"]);
|
|
416
|
+
return [2 /*return*/];
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
}); });
|
|
420
|
+
(0, bun_test_1.it)("appends to existing routeMount array", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
421
|
+
var addRoutes, innerResult, outerAddRoutes, outerResult, app, response;
|
|
422
|
+
return __generator(this, function (_a) {
|
|
423
|
+
switch (_a.label) {
|
|
424
|
+
case 0:
|
|
425
|
+
addRoutes = function (router) {
|
|
426
|
+
router.get("/test", function (req, res) {
|
|
427
|
+
res.json({ routeMount: req.routeMount });
|
|
428
|
+
});
|
|
429
|
+
};
|
|
430
|
+
innerResult = (0, expressServer_1.createRouter)("/inner", addRoutes);
|
|
431
|
+
outerAddRoutes = function (router) {
|
|
432
|
+
router.use.apply(router, __spreadArray([], __read(innerResult), false));
|
|
433
|
+
};
|
|
434
|
+
outerResult = (0, expressServer_1.createRouter)("/outer", outerAddRoutes);
|
|
435
|
+
app = (0, express_1.default)();
|
|
436
|
+
app.use.apply(app, __spreadArray([], __read(outerResult), false));
|
|
437
|
+
return [4 /*yield*/, (0, supertest_1.default)(app).get("/outer/inner/test").expect(200)];
|
|
438
|
+
case 1:
|
|
439
|
+
response = _a.sent();
|
|
440
|
+
(0, bun_test_1.expect)(response.body.routeMount).toEqual(["/outer", "/inner"]);
|
|
441
|
+
return [2 /*return*/];
|
|
442
|
+
}
|
|
443
|
+
});
|
|
444
|
+
}); });
|
|
445
|
+
});
|
|
446
|
+
(0, bun_test_1.describe)("setupServer", function () {
|
|
447
|
+
var originalEnv = process.env;
|
|
448
|
+
(0, bun_test_1.beforeEach)(function () {
|
|
449
|
+
process.env = __assign(__assign({}, originalEnv), { REFRESH_TOKEN_SECRET: "test-refresh-secret", SESSION_SECRET: "test-session-secret", TOKEN_EXPIRES_IN: "1h", TOKEN_ISSUER: "test-issuer", TOKEN_SECRET: "test-secret" });
|
|
450
|
+
});
|
|
451
|
+
(0, bun_test_1.afterEach)(function () {
|
|
452
|
+
process.env = originalEnv;
|
|
453
|
+
});
|
|
454
|
+
(0, bun_test_1.it)("creates server with skipListen option", function () {
|
|
455
|
+
var addRoutes = function () { };
|
|
456
|
+
var app = (0, expressServer_1.setupServer)({
|
|
457
|
+
addRoutes: addRoutes,
|
|
458
|
+
skipListen: true,
|
|
459
|
+
userModel: tests_1.UserModel,
|
|
460
|
+
});
|
|
461
|
+
(0, bun_test_1.expect)(app).toBeDefined();
|
|
462
|
+
});
|
|
463
|
+
(0, bun_test_1.it)("creates server with addMiddleware option", function () {
|
|
464
|
+
var middlewareCalled = false;
|
|
465
|
+
var addMiddleware = function (app) {
|
|
466
|
+
middlewareCalled = true;
|
|
467
|
+
app.use(function (_req, _res, next) { return next(); });
|
|
468
|
+
};
|
|
469
|
+
var addRoutes = function () { };
|
|
470
|
+
var app = (0, expressServer_1.setupServer)({
|
|
471
|
+
addMiddleware: addMiddleware,
|
|
472
|
+
addRoutes: addRoutes,
|
|
473
|
+
skipListen: true,
|
|
474
|
+
userModel: tests_1.UserModel,
|
|
475
|
+
});
|
|
476
|
+
(0, bun_test_1.expect)(app).toBeDefined();
|
|
477
|
+
(0, bun_test_1.expect)(middlewareCalled).toBe(true);
|
|
478
|
+
});
|
|
479
|
+
(0, bun_test_1.it)("creates server with custom corsOrigin", function () {
|
|
480
|
+
var addRoutes = function () { };
|
|
481
|
+
var app = (0, expressServer_1.setupServer)({
|
|
482
|
+
addRoutes: addRoutes,
|
|
483
|
+
corsOrigin: "https://example.com",
|
|
484
|
+
skipListen: true,
|
|
485
|
+
userModel: tests_1.UserModel,
|
|
486
|
+
});
|
|
487
|
+
(0, bun_test_1.expect)(app).toBeDefined();
|
|
488
|
+
});
|
|
489
|
+
(0, bun_test_1.it)("creates server with authOptions", function () {
|
|
490
|
+
var addRoutes = function () { };
|
|
491
|
+
var app = (0, expressServer_1.setupServer)({
|
|
492
|
+
addRoutes: addRoutes,
|
|
493
|
+
authOptions: {
|
|
494
|
+
generateJWTPayload: function (user) { return ({ customField: "test", id: user._id }); },
|
|
495
|
+
generateTokenExpiration: function () { return "2h"; },
|
|
496
|
+
},
|
|
497
|
+
skipListen: true,
|
|
498
|
+
userModel: tests_1.UserModel,
|
|
499
|
+
});
|
|
500
|
+
(0, bun_test_1.expect)(app).toBeDefined();
|
|
501
|
+
});
|
|
502
|
+
});
|
|
503
|
+
(0, bun_test_1.describe)("logRequests edge cases", function () {
|
|
504
|
+
(0, bun_test_1.it)("warns for request without route but with success status code", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
505
|
+
var app;
|
|
506
|
+
return __generator(this, function (_a) {
|
|
507
|
+
switch (_a.label) {
|
|
508
|
+
case 0:
|
|
509
|
+
app = (0, express_1.default)();
|
|
510
|
+
app.use(expressServer_1.logRequests);
|
|
511
|
+
// Middleware that sets statusCode < 400 but doesn't define route
|
|
512
|
+
app.use(function (_req, res) {
|
|
513
|
+
res.status(200).json({ ok: true });
|
|
514
|
+
});
|
|
515
|
+
return [4 /*yield*/, (0, supertest_1.default)(app).get("/no-route").expect(200)];
|
|
516
|
+
case 1:
|
|
517
|
+
_a.sent();
|
|
518
|
+
return [2 /*return*/];
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
}); });
|
|
522
|
+
(0, bun_test_1.it)("handles request with routeMount as string (legacy)", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
523
|
+
var app;
|
|
524
|
+
return __generator(this, function (_a) {
|
|
525
|
+
switch (_a.label) {
|
|
526
|
+
case 0:
|
|
527
|
+
app = (0, express_1.default)();
|
|
528
|
+
app.use(expressServer_1.logRequests);
|
|
529
|
+
app.get("/test", function (req, res) {
|
|
530
|
+
req.route = { path: "/test" };
|
|
531
|
+
req.routeMount = "/api"; // String instead of array
|
|
532
|
+
res.json({ ok: true });
|
|
533
|
+
});
|
|
534
|
+
return [4 /*yield*/, (0, supertest_1.default)(app).get("/test").expect(200)];
|
|
535
|
+
case 1:
|
|
536
|
+
_a.sent();
|
|
537
|
+
return [2 /*return*/];
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
}); });
|
|
541
|
+
});
|
|
542
|
+
(0, bun_test_1.describe)("setupServer with full integration", function () {
|
|
543
|
+
var originalEnv = process.env;
|
|
544
|
+
(0, bun_test_1.beforeEach)(function () {
|
|
545
|
+
process.env = __assign(__assign({}, originalEnv), { REFRESH_TOKEN_SECRET: "test-refresh-secret", SESSION_SECRET: "test-session-secret", TOKEN_EXPIRES_IN: "1h", TOKEN_ISSUER: "test-issuer", TOKEN_SECRET: "test-secret" });
|
|
546
|
+
});
|
|
547
|
+
(0, bun_test_1.afterEach)(function () {
|
|
548
|
+
process.env = originalEnv;
|
|
549
|
+
});
|
|
550
|
+
(0, bun_test_1.it)("sets Sentry transaction ID tag from header", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
551
|
+
var addRoutes, app;
|
|
552
|
+
return __generator(this, function (_a) {
|
|
553
|
+
switch (_a.label) {
|
|
554
|
+
case 0:
|
|
555
|
+
addRoutes = function (app) {
|
|
556
|
+
app.get("/test", function (_req, res) {
|
|
557
|
+
res.json({ ok: true });
|
|
558
|
+
});
|
|
559
|
+
};
|
|
560
|
+
app = (0, expressServer_1.setupServer)({
|
|
561
|
+
addRoutes: addRoutes,
|
|
562
|
+
skipListen: true,
|
|
563
|
+
userModel: tests_1.UserModel,
|
|
564
|
+
});
|
|
565
|
+
return [4 /*yield*/, (0, supertest_1.default)(app).get("/test").set("X-Transaction-ID", "txn-123").expect(200)];
|
|
566
|
+
case 1:
|
|
567
|
+
_a.sent();
|
|
568
|
+
return [2 /*return*/];
|
|
569
|
+
}
|
|
570
|
+
});
|
|
571
|
+
}); });
|
|
572
|
+
(0, bun_test_1.it)("sets Sentry session ID tag from header", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
573
|
+
var addRoutes, app;
|
|
574
|
+
return __generator(this, function (_a) {
|
|
575
|
+
switch (_a.label) {
|
|
576
|
+
case 0:
|
|
577
|
+
addRoutes = function (app) {
|
|
578
|
+
app.get("/test", function (_req, res) {
|
|
579
|
+
res.json({ ok: true });
|
|
580
|
+
});
|
|
581
|
+
};
|
|
582
|
+
app = (0, expressServer_1.setupServer)({
|
|
583
|
+
addRoutes: addRoutes,
|
|
584
|
+
skipListen: true,
|
|
585
|
+
userModel: tests_1.UserModel,
|
|
586
|
+
});
|
|
587
|
+
return [4 /*yield*/, (0, supertest_1.default)(app).get("/test").set("X-Session-ID", "session-456").expect(200)];
|
|
588
|
+
case 1:
|
|
589
|
+
_a.sent();
|
|
590
|
+
return [2 /*return*/];
|
|
591
|
+
}
|
|
592
|
+
});
|
|
593
|
+
}); });
|
|
594
|
+
(0, bun_test_1.it)("sets both transaction and session ID tags", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
595
|
+
var addRoutes, app;
|
|
596
|
+
return __generator(this, function (_a) {
|
|
597
|
+
switch (_a.label) {
|
|
598
|
+
case 0:
|
|
599
|
+
addRoutes = function (app) {
|
|
600
|
+
app.get("/test", function (_req, res) {
|
|
601
|
+
res.json({ ok: true });
|
|
602
|
+
});
|
|
603
|
+
};
|
|
604
|
+
app = (0, expressServer_1.setupServer)({
|
|
605
|
+
addRoutes: addRoutes,
|
|
606
|
+
skipListen: true,
|
|
607
|
+
userModel: tests_1.UserModel,
|
|
608
|
+
});
|
|
609
|
+
return [4 /*yield*/, (0, supertest_1.default)(app)
|
|
610
|
+
.get("/test")
|
|
611
|
+
.set("X-Transaction-ID", "txn-123")
|
|
612
|
+
.set("X-Session-ID", "session-456")
|
|
613
|
+
.expect(200)];
|
|
614
|
+
case 1:
|
|
615
|
+
_a.sent();
|
|
616
|
+
return [2 /*return*/];
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
}); });
|
|
620
|
+
(0, bun_test_1.it)("handles fallthrough error handler", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
621
|
+
var addRoutes, app;
|
|
622
|
+
return __generator(this, function (_a) {
|
|
623
|
+
switch (_a.label) {
|
|
624
|
+
case 0:
|
|
625
|
+
addRoutes = function (app) {
|
|
626
|
+
app.get("/error", function (_req, _res) {
|
|
627
|
+
throw new Error("Unexpected error");
|
|
628
|
+
});
|
|
629
|
+
};
|
|
630
|
+
app = (0, expressServer_1.setupServer)({
|
|
631
|
+
addRoutes: addRoutes,
|
|
632
|
+
skipListen: true,
|
|
633
|
+
userModel: tests_1.UserModel,
|
|
634
|
+
});
|
|
635
|
+
return [4 /*yield*/, (0, supertest_1.default)(app).get("/error").expect(500)];
|
|
636
|
+
case 1:
|
|
637
|
+
_a.sent();
|
|
638
|
+
return [2 /*return*/];
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
}); });
|
|
642
|
+
(0, bun_test_1.it)("handles loggingOptions passed to setupServer", function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
643
|
+
var addRoutes, app;
|
|
644
|
+
return __generator(this, function (_a) {
|
|
645
|
+
switch (_a.label) {
|
|
646
|
+
case 0:
|
|
647
|
+
addRoutes = function (app) {
|
|
648
|
+
app.get("/test", function (_req, res) {
|
|
649
|
+
res.json({ ok: true });
|
|
650
|
+
});
|
|
651
|
+
};
|
|
652
|
+
app = (0, expressServer_1.setupServer)({
|
|
653
|
+
addRoutes: addRoutes,
|
|
654
|
+
loggingOptions: {
|
|
655
|
+
logSlowRequests: true,
|
|
656
|
+
logSlowRequestsReadMs: 100,
|
|
657
|
+
},
|
|
658
|
+
skipListen: true,
|
|
659
|
+
userModel: tests_1.UserModel,
|
|
660
|
+
});
|
|
661
|
+
return [4 /*yield*/, (0, supertest_1.default)(app).get("/test").expect(200)];
|
|
662
|
+
case 1:
|
|
663
|
+
_a.sent();
|
|
664
|
+
return [2 /*return*/];
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
}); });
|
|
668
|
+
});
|
|
669
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export declare function sendToSlack(text: string, { slackChannel, shouldThrow, env, }?: {
|
|
1
|
+
export declare function sendToSlack(text: string, { slackChannel, shouldThrow, env, url, }?: {
|
|
2
2
|
slackChannel?: string;
|
|
3
3
|
shouldThrow?: boolean;
|
|
4
4
|
env?: string;
|
|
5
|
+
url?: string;
|
|
5
6
|
}): Promise<void>;
|