@terreno/api 0.20.2 → 0.21.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.
Files changed (65) hide show
  1. package/.ai/guidelines/core.md +71 -0
  2. package/.ai/skills/mongoose-schema-safety/SKILL.md +143 -0
  3. package/README.md +54 -1
  4. package/dist/__tests__/versionCheckPlugin.test.js +29 -7
  5. package/dist/actions.openApi.test.js +13 -11
  6. package/dist/api.js +98 -11
  7. package/dist/api.query.test.js +31 -1
  8. package/dist/api.test.js +211 -0
  9. package/dist/auth.test.js +10 -10
  10. package/dist/betterAuth.d.ts +1 -1
  11. package/dist/consentApp.test.js +1 -0
  12. package/dist/example.js +4 -4
  13. package/dist/expressServer.d.ts +0 -22
  14. package/dist/expressServer.js +1 -125
  15. package/dist/expressServer.test.js +90 -91
  16. package/dist/githubAuth.test.js +22 -22
  17. package/dist/logger.d.ts +154 -0
  18. package/dist/logger.js +445 -26
  19. package/dist/logger.test.js +435 -0
  20. package/dist/middleware.d.ts +7 -0
  21. package/dist/middleware.js +58 -1
  22. package/dist/middleware.test.js +159 -0
  23. package/dist/openApi.test.js +10 -17
  24. package/dist/openApiBuilder.test.js +18 -10
  25. package/dist/realtime/changeStreamWatcher.d.ts +4 -4
  26. package/dist/realtime/changeStreamWatcher.js +2 -4
  27. package/dist/realtime/queryMatcher.d.ts +1 -1
  28. package/dist/realtime/queryMatcher.js +39 -14
  29. package/dist/realtime/types.d.ts +3 -3
  30. package/dist/requestContext.d.ts +61 -0
  31. package/dist/requestContext.js +74 -0
  32. package/dist/secretProviders.test.js +335 -0
  33. package/dist/terrenoApp.d.ts +27 -15
  34. package/dist/terrenoApp.js +24 -14
  35. package/dist/terrenoApp.test.js +52 -0
  36. package/dist/tests/bunSetup.js +61 -7
  37. package/dist/tests.js +27 -4
  38. package/package.json +1 -1
  39. package/src/__tests__/versionCheckPlugin.test.ts +43 -15
  40. package/src/actions.openApi.test.ts +12 -10
  41. package/src/api.query.test.ts +24 -1
  42. package/src/api.test.ts +169 -0
  43. package/src/api.ts +71 -0
  44. package/src/auth.test.ts +10 -10
  45. package/src/betterAuth.ts +1 -1
  46. package/src/consentApp.test.ts +1 -0
  47. package/src/example.ts +4 -4
  48. package/src/expressServer.test.ts +82 -85
  49. package/src/expressServer.ts +1 -213
  50. package/src/githubAuth.test.ts +22 -22
  51. package/src/logger.test.ts +466 -1
  52. package/src/logger.ts +477 -14
  53. package/src/middleware.test.ts +74 -2
  54. package/src/middleware.ts +57 -0
  55. package/src/openApi.test.ts +10 -17
  56. package/src/openApiBuilder.test.ts +18 -10
  57. package/src/realtime/changeStreamWatcher.ts +15 -10
  58. package/src/realtime/queryMatcher.ts +54 -27
  59. package/src/realtime/types.ts +4 -4
  60. package/src/requestContext.ts +86 -0
  61. package/src/secretProviders.test.ts +219 -1
  62. package/src/terrenoApp.test.ts +38 -0
  63. package/src/terrenoApp.ts +37 -15
  64. package/src/tests/bunSetup.ts +16 -3
  65. package/src/tests.ts +17 -4
@@ -97,24 +97,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
97
97
  return (mod && mod.__esModule) ? mod : { "default": mod };
98
98
  };
99
99
  Object.defineProperty(exports, "__esModule", { value: true });
100
- exports.wrapScript = exports.cronjob = exports.setupServer = exports.createRouterWithAuth = exports.createRouter = exports.logRequests = exports.setupEnvironment = void 0;
100
+ exports.wrapScript = exports.cronjob = exports.createRouterWithAuth = exports.createRouter = exports.logRequests = exports.setupEnvironment = void 0;
101
101
  var Sentry = __importStar(require("@sentry/bun"));
102
- var cors_1 = __importDefault(require("cors"));
103
102
  var cron_1 = __importDefault(require("cron"));
104
103
  var express_1 = __importDefault(require("express"));
105
104
  var cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
106
105
  var on_finished_1 = __importDefault(require("on-finished"));
107
106
  var passport_1 = __importDefault(require("passport"));
108
- var qs_1 = __importDefault(require("qs"));
109
- var auth_1 = require("./auth");
110
- var errors_1 = require("./errors");
111
- var githubAuth_1 = require("./githubAuth");
112
107
  var logger_1 = require("./logger");
113
108
  var notifiers_1 = require("./notifiers");
114
- var openApiCompat_1 = require("./openApiCompat");
115
- var openApiEtag_1 = require("./openApiEtag");
116
- var requestContext_1 = require("./requestContext");
117
- var index_1 = __importDefault(require("./vendor/wesleytodd-openapi/index"));
118
109
  var SLOW_READ_MAX = 200;
119
110
  var SLOW_WRITE_MAX = 500;
120
111
  var IS_JEST = process.env.JEST_WORKER_ID !== undefined;
@@ -232,121 +223,6 @@ var createRouterWithAuth = function (rootPath, addRoutes, middleware) {
232
223
  ], __read(middleware), false));
233
224
  };
234
225
  exports.createRouterWithAuth = createRouterWithAuth;
235
- var initializeRoutes = function (UserModel, addRoutes, options) {
236
- var _a;
237
- if (options === void 0) { options = {}; }
238
- var app = (0, express_1.default)();
239
- // Record mount paths on layers for Express 5 → OpenAPI compat
240
- (0, openApiCompat_1.patchAppUse)(app);
241
- app.set("query parser", function (str) { var _a; return qs_1.default.parse(str, { arrayLimit: (_a = options.arrayLimit) !== null && _a !== void 0 ? _a : 200 }); });
242
- app.use(requestContext_1.requestContextMiddleware);
243
- app.use((0, cors_1.default)({
244
- origin: (_a = options.corsOrigin) !== null && _a !== void 0 ? _a : "*",
245
- }));
246
- if (options.addMiddleware) {
247
- options.addMiddleware(app);
248
- }
249
- app.use(express_1.default.json({ limit: "50mb" }));
250
- // Add login/signup/refresh_token before the JWT/auth middlewares
251
- (0, auth_1.addAuthRoutes)(app, UserModel, options === null || options === void 0 ? void 0 : options.authOptions);
252
- (0, auth_1.setupAuth)(app, UserModel);
253
- app.use(function (req, res, next) {
254
- (0, requestContext_1.updateRequestContextFromRequest)(req, res);
255
- next();
256
- });
257
- if (options.logRequests !== false) {
258
- app.use(exports.logRequests);
259
- }
260
- // Store the logging options on the request so we can access them later.
261
- app.use(function (_req, res, next) {
262
- res.locals.loggingOptions = options.loggingOptions;
263
- next();
264
- });
265
- // Add Sentry scopes for session, transaction, and userId if any are set
266
- app.use(function (req, _res, next) {
267
- var _a, _b;
268
- var context = (0, requestContext_1.getCurrentRequestContext)();
269
- var transactionId = req.header("X-Transaction-ID");
270
- var sessionId = (_a = context === null || context === void 0 ? void 0 : context.sessionId) !== null && _a !== void 0 ? _a : req.header("X-Session-ID");
271
- if (context === null || context === void 0 ? void 0 : context.requestId) {
272
- Sentry.getCurrentScope().setTag("request_id", context.requestId);
273
- }
274
- if (transactionId) {
275
- Sentry.getCurrentScope().setTag("transaction_id", transactionId);
276
- }
277
- if (sessionId) {
278
- Sentry.getCurrentScope().setTag("session_id", sessionId);
279
- }
280
- if ((_b = req.user) === null || _b === void 0 ? void 0 : _b._id) {
281
- Sentry.getCurrentScope().setTag("user", String(req.user._id));
282
- }
283
- next();
284
- });
285
- // Add ETag middleware for OpenAPI JSON endpoint before the openapi middleware
286
- app.use(openApiCompat_1.openApiCompatMiddleware);
287
- app.use(openApiEtag_1.openApiEtagMiddleware);
288
- var oapi = (0, index_1.default)({
289
- info: {
290
- description: "Generated docs from an Express api",
291
- title: "Express Application",
292
- version: "1.0.0",
293
- },
294
- openapi: "3.0.0",
295
- });
296
- app.use(oapi);
297
- if (process.env.ENABLE_SWAGGER === "true") {
298
- app.use("/swagger", oapi.swaggerui());
299
- }
300
- (0, auth_1.addMeRoutes)(app, UserModel, options === null || options === void 0 ? void 0 : options.authOptions);
301
- // Set up GitHub OAuth if configured (works with JWT auth)
302
- if (options.githubAuth) {
303
- (0, githubAuth_1.setupGitHubAuth)(app, UserModel, options.githubAuth);
304
- (0, githubAuth_1.addGitHubAuthRoutes)(app, UserModel, options.githubAuth, options.authOptions);
305
- }
306
- addRoutes(app, { openApi: oapi });
307
- Sentry.setupExpressErrorHandler(app);
308
- // Catch any thrown APIErrors and return them in an OpenAPI compatible format
309
- app.use(errors_1.apiUnauthorizedMiddleware);
310
- app.use(errors_1.apiErrorMiddleware);
311
- app.use(errors_1.apiFallthroughErrorMiddleware);
312
- return app;
313
- };
314
- var setupServer = function (options) {
315
- var UserModel = options.userModel;
316
- var addRoutes = options.addRoutes;
317
- (0, logger_1.setupLogging)(options.loggingOptions);
318
- var app;
319
- try {
320
- app = initializeRoutes(UserModel, addRoutes, {
321
- addMiddleware: options.addMiddleware,
322
- authOptions: options.authOptions,
323
- corsOrigin: options.corsOrigin,
324
- githubAuth: options.githubAuth,
325
- loggingOptions: options.loggingOptions,
326
- logRequests: options.logRequests,
327
- });
328
- }
329
- catch (error) {
330
- var stack = error instanceof Error && error.stack ? error.stack : String(error);
331
- logger_1.logger.error("Error initializing routes: ".concat(stack));
332
- throw error;
333
- }
334
- if (!options.skipListen) {
335
- var port_1 = process.env.PORT || "9000";
336
- try {
337
- app.listen(port_1, function () {
338
- logger_1.logger.info("Listening on port ".concat(port_1));
339
- });
340
- }
341
- catch (error) {
342
- var stack = error instanceof Error ? error.stack : String(error);
343
- logger_1.logger.error("Error trying to start HTTP server: ".concat(error, "\n").concat(stack));
344
- process.exit(1);
345
- }
346
- }
347
- return app;
348
- };
349
- exports.setupServer = setupServer;
350
226
  var cronjob = function (name, schedule, callback) {
351
227
  var cronSchedule = schedule === "hourly" ? "0 * * * *" : schedule === "minutely" ? "* * * * *" : schedule;
352
228
  logger_1.logger.info("Adding cronjob ".concat(name, ", running at: ").concat(cronSchedule));
@@ -127,6 +127,7 @@ var supertest_1 = __importDefault(require("supertest"));
127
127
  var winston_1 = __importDefault(require("winston"));
128
128
  var expressServer_1 = require("./expressServer");
129
129
  var logger_1 = require("./logger");
130
+ var terrenoApp_1 = require("./terrenoApp");
130
131
  var tests_1 = require("./tests");
131
132
  (0, bun_test_1.describe)("expressServer", function () {
132
133
  (0, bun_test_1.describe)("setupEnvironment", function () {
@@ -175,8 +176,8 @@ var tests_1 = require("./tests");
175
176
  format: winston_1.default.format.json(),
176
177
  stream: logStream,
177
178
  });
178
- app = (0, expressServer_1.setupServer)({
179
- addRoutes: function (router) {
179
+ app = new terrenoApp_1.TerrenoApp({
180
+ configureApp: function (router) {
180
181
  router.get("/context-test", function (req, res) {
181
182
  logger_1.logger.info("context route log");
182
183
  return res.json({ requestId: req.requestId, sessionId: req.sessionId });
@@ -185,7 +186,7 @@ var tests_1 = require("./tests");
185
186
  logRequests: false,
186
187
  skipListen: true,
187
188
  userModel: tests_1.UserModel,
188
- });
189
+ }).build();
189
190
  logger_1.winstonLogger.add(transport);
190
191
  return [4 /*yield*/, (0, supertest_1.default)(app)
191
192
  .get("/context-test")
@@ -537,7 +538,7 @@ var tests_1 = require("./tests");
537
538
  });
538
539
  }); });
539
540
  });
540
- (0, bun_test_1.describe)("setupServer", function () {
541
+ (0, bun_test_1.describe)("TerrenoApp", function () {
541
542
  var originalEnv = process.env;
542
543
  (0, bun_test_1.beforeEach)(function () {
543
544
  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,51 +547,50 @@ var tests_1 = require("./tests");
546
547
  process.env = originalEnv;
547
548
  });
548
549
  (0, bun_test_1.it)("creates server with skipListen option", function () {
549
- var addRoutes = function () { };
550
- var app = (0, expressServer_1.setupServer)({
551
- addRoutes: addRoutes,
550
+ var configureApp = function () { };
551
+ var app = new terrenoApp_1.TerrenoApp({
552
+ configureApp: configureApp,
552
553
  skipListen: true,
553
554
  userModel: tests_1.UserModel,
554
- });
555
+ }).build();
555
556
  (0, bun_test_1.expect)(app).toBeDefined();
556
557
  });
557
- (0, bun_test_1.it)("creates server with addMiddleware option", function () {
558
+ (0, bun_test_1.it)("creates server with beforeJsonSetup option", function () {
558
559
  var middlewareCalled = false;
559
- var addMiddleware = function (app) {
560
- middlewareCalled = true;
561
- app.use(function (_req, _res, next) { return next(); });
562
- };
563
- var addRoutes = function () { };
564
- var app = (0, expressServer_1.setupServer)({
565
- addMiddleware: addMiddleware,
566
- addRoutes: addRoutes,
560
+ var configureApp = function () { };
561
+ var app = new terrenoApp_1.TerrenoApp({
562
+ beforeJsonSetup: function (httpApp) {
563
+ middlewareCalled = true;
564
+ httpApp.use(function (_req, _res, next) { return next(); });
565
+ },
566
+ configureApp: configureApp,
567
567
  skipListen: true,
568
568
  userModel: tests_1.UserModel,
569
- });
569
+ }).build();
570
570
  (0, bun_test_1.expect)(app).toBeDefined();
571
571
  (0, bun_test_1.expect)(middlewareCalled).toBe(true);
572
572
  });
573
573
  (0, bun_test_1.it)("creates server with custom corsOrigin", function () {
574
- var addRoutes = function () { };
575
- var app = (0, expressServer_1.setupServer)({
576
- addRoutes: addRoutes,
574
+ var configureApp = function () { };
575
+ var app = new terrenoApp_1.TerrenoApp({
576
+ configureApp: configureApp,
577
577
  corsOrigin: "https://example.com",
578
578
  skipListen: true,
579
579
  userModel: tests_1.UserModel,
580
- });
580
+ }).build();
581
581
  (0, bun_test_1.expect)(app).toBeDefined();
582
582
  });
583
583
  (0, bun_test_1.it)("creates server with authOptions", function () {
584
- var addRoutes = function () { };
585
- var app = (0, expressServer_1.setupServer)({
586
- addRoutes: addRoutes,
584
+ var configureApp = function () { };
585
+ var app = new terrenoApp_1.TerrenoApp({
587
586
  authOptions: {
588
587
  generateJWTPayload: function (user) { return ({ customField: "test", id: user._id }); },
589
588
  generateTokenExpiration: function () { return "2h"; },
590
589
  },
590
+ configureApp: configureApp,
591
591
  skipListen: true,
592
592
  userModel: tests_1.UserModel,
593
- });
593
+ }).build();
594
594
  (0, bun_test_1.expect)(app).toBeDefined();
595
595
  });
596
596
  });
@@ -633,7 +633,7 @@ var tests_1 = require("./tests");
633
633
  });
634
634
  }); });
635
635
  });
636
- (0, bun_test_1.describe)("setupServer with full integration", function () {
636
+ (0, bun_test_1.describe)("TerrenoApp with full integration", function () {
637
637
  var originalEnv = process.env;
638
638
  (0, bun_test_1.beforeEach)(function () {
639
639
  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" });
@@ -642,20 +642,20 @@ var tests_1 = require("./tests");
642
642
  process.env = originalEnv;
643
643
  });
644
644
  (0, bun_test_1.it)("sets Sentry transaction ID tag from header", function () { return __awaiter(void 0, void 0, void 0, function () {
645
- var addRoutes, app;
645
+ var configureApp, app;
646
646
  return __generator(this, function (_a) {
647
647
  switch (_a.label) {
648
648
  case 0:
649
- addRoutes = function (app) {
650
- app.get("/test", function (_req, res) {
649
+ configureApp = function (httpApp) {
650
+ httpApp.get("/test", function (_req, res) {
651
651
  res.json({ ok: true });
652
652
  });
653
653
  };
654
- app = (0, expressServer_1.setupServer)({
655
- addRoutes: addRoutes,
654
+ app = new terrenoApp_1.TerrenoApp({
655
+ configureApp: configureApp,
656
656
  skipListen: true,
657
657
  userModel: tests_1.UserModel,
658
- });
658
+ }).build();
659
659
  return [4 /*yield*/, (0, supertest_1.default)(app).get("/test").set("X-Transaction-ID", "txn-123").expect(200)];
660
660
  case 1:
661
661
  _a.sent();
@@ -664,20 +664,20 @@ var tests_1 = require("./tests");
664
664
  });
665
665
  }); });
666
666
  (0, bun_test_1.it)("sets Sentry session ID tag from header", function () { return __awaiter(void 0, void 0, void 0, function () {
667
- var addRoutes, app;
667
+ var configureApp, app;
668
668
  return __generator(this, function (_a) {
669
669
  switch (_a.label) {
670
670
  case 0:
671
- addRoutes = function (app) {
672
- app.get("/test", function (_req, res) {
671
+ configureApp = function (httpApp) {
672
+ httpApp.get("/test", function (_req, res) {
673
673
  res.json({ ok: true });
674
674
  });
675
675
  };
676
- app = (0, expressServer_1.setupServer)({
677
- addRoutes: addRoutes,
676
+ app = new terrenoApp_1.TerrenoApp({
677
+ configureApp: configureApp,
678
678
  skipListen: true,
679
679
  userModel: tests_1.UserModel,
680
- });
680
+ }).build();
681
681
  return [4 /*yield*/, (0, supertest_1.default)(app).get("/test").set("X-Session-ID", "session-456").expect(200)];
682
682
  case 1:
683
683
  _a.sent();
@@ -686,20 +686,20 @@ var tests_1 = require("./tests");
686
686
  });
687
687
  }); });
688
688
  (0, bun_test_1.it)("sets both transaction and session ID tags", function () { return __awaiter(void 0, void 0, void 0, function () {
689
- var addRoutes, app;
689
+ var configureApp, app;
690
690
  return __generator(this, function (_a) {
691
691
  switch (_a.label) {
692
692
  case 0:
693
- addRoutes = function (app) {
694
- app.get("/test", function (_req, res) {
693
+ configureApp = function (httpApp) {
694
+ httpApp.get("/test", function (_req, res) {
695
695
  res.json({ ok: true });
696
696
  });
697
697
  };
698
- app = (0, expressServer_1.setupServer)({
699
- addRoutes: addRoutes,
698
+ app = new terrenoApp_1.TerrenoApp({
699
+ configureApp: configureApp,
700
700
  skipListen: true,
701
701
  userModel: tests_1.UserModel,
702
- });
702
+ }).build();
703
703
  return [4 /*yield*/, (0, supertest_1.default)(app)
704
704
  .get("/test")
705
705
  .set("X-Transaction-ID", "txn-123")
@@ -712,20 +712,20 @@ var tests_1 = require("./tests");
712
712
  });
713
713
  }); });
714
714
  (0, bun_test_1.it)("handles fallthrough error handler", function () { return __awaiter(void 0, void 0, void 0, function () {
715
- var addRoutes, app;
715
+ var configureApp, app;
716
716
  return __generator(this, function (_a) {
717
717
  switch (_a.label) {
718
718
  case 0:
719
- addRoutes = function (app) {
720
- app.get("/error", function (_req, _res) {
719
+ configureApp = function (httpApp) {
720
+ httpApp.get("/error", function (_req, _res) {
721
721
  throw new Error("Unexpected error");
722
722
  });
723
723
  };
724
- app = (0, expressServer_1.setupServer)({
725
- addRoutes: addRoutes,
724
+ app = new terrenoApp_1.TerrenoApp({
725
+ configureApp: configureApp,
726
726
  skipListen: true,
727
727
  userModel: tests_1.UserModel,
728
- });
728
+ }).build();
729
729
  return [4 /*yield*/, (0, supertest_1.default)(app).get("/error").expect(500)];
730
730
  case 1:
731
731
  _a.sent();
@@ -733,25 +733,25 @@ var tests_1 = require("./tests");
733
733
  }
734
734
  });
735
735
  }); });
736
- (0, bun_test_1.it)("handles loggingOptions passed to setupServer", function () { return __awaiter(void 0, void 0, void 0, function () {
737
- var addRoutes, app;
736
+ (0, bun_test_1.it)("handles loggingOptions passed to TerrenoApp", function () { return __awaiter(void 0, void 0, void 0, function () {
737
+ var configureApp, app;
738
738
  return __generator(this, function (_a) {
739
739
  switch (_a.label) {
740
740
  case 0:
741
- addRoutes = function (app) {
742
- app.get("/test", function (_req, res) {
741
+ configureApp = function (httpApp) {
742
+ httpApp.get("/test", function (_req, res) {
743
743
  res.json({ ok: true });
744
744
  });
745
745
  };
746
- app = (0, expressServer_1.setupServer)({
747
- addRoutes: addRoutes,
746
+ app = new terrenoApp_1.TerrenoApp({
747
+ configureApp: configureApp,
748
748
  loggingOptions: {
749
749
  logSlowRequests: true,
750
750
  logSlowRequestsReadMs: 100,
751
751
  },
752
752
  skipListen: true,
753
753
  userModel: tests_1.UserModel,
754
- });
754
+ }).build();
755
755
  return [4 /*yield*/, (0, supertest_1.default)(app).get("/test").expect(200)];
756
756
  case 1:
757
757
  _a.sent();
@@ -759,16 +759,16 @@ var tests_1 = require("./tests");
759
759
  }
760
760
  });
761
761
  }); });
762
- (0, bun_test_1.it)("re-throws when addRoutes throws during route initialization", function () {
763
- var addRoutes = function () {
762
+ (0, bun_test_1.it)("re-throws when configureApp throws during build", function () {
763
+ var configureApp = function () {
764
764
  throw new Error("Route init boom");
765
765
  };
766
766
  (0, bun_test_1.expect)(function () {
767
- return (0, expressServer_1.setupServer)({
768
- addRoutes: addRoutes,
767
+ return new terrenoApp_1.TerrenoApp({
768
+ configureApp: configureApp,
769
769
  skipListen: true,
770
770
  userModel: tests_1.UserModel,
771
- });
771
+ }).build();
772
772
  }).toThrow("Route init boom");
773
773
  });
774
774
  });
@@ -1021,7 +1021,7 @@ var tests_1 = require("./tests");
1021
1021
  });
1022
1022
  }); });
1023
1023
  });
1024
- (0, bun_test_1.describe)("setupServer with listen (skipListen false)", function () {
1024
+ (0, bun_test_1.describe)("TerrenoApp with listen (skipListen false)", function () {
1025
1025
  var originalEnv = process.env;
1026
1026
  (0, bun_test_1.beforeEach)(function () {
1027
1027
  process.env = __assign(__assign({}, originalEnv), { PORT: "0", REFRESH_TOKEN_SECRET: "test-refresh-secret", SESSION_SECRET: "test-session-secret", TOKEN_EXPIRES_IN: "1h", TOKEN_ISSUER: "test-issuer", TOKEN_SECRET: "test-secret" });
@@ -1030,16 +1030,16 @@ var tests_1 = require("./tests");
1030
1030
  process.env = originalEnv;
1031
1031
  });
1032
1032
  (0, bun_test_1.it)("starts the server when skipListen is false", function () { return __awaiter(void 0, void 0, void 0, function () {
1033
- var addRoutes, express, originalListen, app;
1033
+ var configureApp, http, originalListen, app;
1034
1034
  return __generator(this, function (_a) {
1035
1035
  switch (_a.label) {
1036
1036
  case 0:
1037
- addRoutes = function () { };
1038
- return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("express")); })];
1037
+ configureApp = function () { };
1038
+ return [4 /*yield*/, Promise.resolve().then(function () { return __importStar(require("node:http")); })];
1039
1039
  case 1:
1040
- express = _a.sent();
1041
- originalListen = express.default.application.listen;
1042
- express.default.application.listen = (0, bun_test_1.mock)(function () {
1040
+ http = _a.sent();
1041
+ originalListen = http.Server.prototype.listen;
1042
+ http.Server.prototype.listen = (0, bun_test_1.mock)(function () {
1043
1043
  var args = [];
1044
1044
  for (var _i = 0; _i < arguments.length; _i++) {
1045
1045
  args[_i] = arguments[_i];
@@ -1051,15 +1051,15 @@ var tests_1 = require("./tests");
1051
1051
  return this;
1052
1052
  });
1053
1053
  try {
1054
- app = (0, expressServer_1.setupServer)({
1055
- addRoutes: addRoutes,
1054
+ app = new terrenoApp_1.TerrenoApp({
1055
+ configureApp: configureApp,
1056
1056
  skipListen: false,
1057
1057
  userModel: tests_1.UserModel,
1058
- });
1058
+ }).start();
1059
1059
  (0, bun_test_1.expect)(app).toBeDefined();
1060
1060
  }
1061
1061
  finally {
1062
- express.default.application.listen = originalListen;
1062
+ http.Server.prototype.listen = originalListen;
1063
1063
  }
1064
1064
  return [2 /*return*/];
1065
1065
  }
@@ -1067,16 +1067,15 @@ var tests_1 = require("./tests");
1067
1067
  }); });
1068
1068
  (0, bun_test_1.it)("handles listen error with invalid port", function () {
1069
1069
  process.env.PORT = "-1";
1070
- var addRoutes = function () { };
1071
- // Using an invalid port should trigger the catch block and process.exit(1)
1070
+ var configureApp = function () { };
1072
1071
  var originalExit = process.exit;
1073
1072
  process.exit = (function () { });
1074
1073
  try {
1075
- (0, expressServer_1.setupServer)({
1076
- addRoutes: addRoutes,
1074
+ new terrenoApp_1.TerrenoApp({
1075
+ configureApp: configureApp,
1077
1076
  skipListen: false,
1078
1077
  userModel: tests_1.UserModel,
1079
- });
1078
+ }).start();
1080
1079
  }
1081
1080
  catch (_a) {
1082
1081
  // May throw
@@ -1084,7 +1083,7 @@ var tests_1 = require("./tests");
1084
1083
  process.exit = originalExit;
1085
1084
  });
1086
1085
  });
1087
- (0, bun_test_1.describe)("setupServer with listen", function () {
1086
+ (0, bun_test_1.describe)("TerrenoApp with listen", function () {
1088
1087
  var originalEnv = process.env;
1089
1088
  var http = require("node:http");
1090
1089
  var activeServer = null;
@@ -1118,16 +1117,16 @@ var tests_1 = require("./tests");
1118
1117
  });
1119
1118
  }); });
1120
1119
  (0, bun_test_1.it)("starts listening on a port when skipListen is false", function () { return __awaiter(void 0, void 0, void 0, function () {
1121
- var addRoutes, app;
1120
+ var configureApp, app;
1122
1121
  return __generator(this, function (_a) {
1123
1122
  switch (_a.label) {
1124
1123
  case 0:
1125
- addRoutes = function () { };
1126
- app = (0, expressServer_1.setupServer)({
1127
- addRoutes: addRoutes,
1124
+ configureApp = function () { };
1125
+ app = new terrenoApp_1.TerrenoApp({
1126
+ configureApp: configureApp,
1128
1127
  skipListen: false,
1129
1128
  userModel: tests_1.UserModel,
1130
- });
1129
+ }).start();
1131
1130
  (0, bun_test_1.expect)(app).toBeDefined();
1132
1131
  return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 100); })];
1133
1132
  case 1:
@@ -1196,7 +1195,7 @@ var tests_1 = require("./tests");
1196
1195
  });
1197
1196
  }); });
1198
1197
  });
1199
- (0, bun_test_1.describe)("setupServer error handling", function () {
1198
+ (0, bun_test_1.describe)("TerrenoApp error handling", function () {
1200
1199
  var originalEnv = process.env;
1201
1200
  (0, bun_test_1.beforeEach)(function () {
1202
1201
  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" });
@@ -1204,16 +1203,16 @@ var tests_1 = require("./tests");
1204
1203
  (0, bun_test_1.afterEach)(function () {
1205
1204
  process.env = originalEnv;
1206
1205
  });
1207
- (0, bun_test_1.it)("catches and rethrows errors from initializeRoutes", function () {
1208
- var addRoutes = function () {
1206
+ (0, bun_test_1.it)("throws when configureApp throws during build", function () {
1207
+ var configureApp = function () {
1209
1208
  throw new Error("route initialization failed");
1210
1209
  };
1211
1210
  (0, bun_test_1.expect)(function () {
1212
- return (0, expressServer_1.setupServer)({
1213
- addRoutes: addRoutes,
1211
+ return new terrenoApp_1.TerrenoApp({
1212
+ configureApp: configureApp,
1214
1213
  skipListen: true,
1215
1214
  userModel: tests_1.UserModel,
1216
- });
1215
+ }).build();
1217
1216
  }).toThrow("route initialization failed");
1218
1217
  });
1219
1218
  });