@terreno/api 0.1.0 → 0.2.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 (40) hide show
  1. package/dist/api.d.ts +28 -2
  2. package/dist/api.js +20 -7
  3. package/dist/betterAuth.d.ts +91 -0
  4. package/dist/betterAuth.js +8 -0
  5. package/dist/betterAuth.test.d.ts +1 -0
  6. package/dist/betterAuth.test.js +181 -0
  7. package/dist/betterAuthApp.d.ts +22 -0
  8. package/dist/betterAuthApp.js +38 -0
  9. package/dist/betterAuthApp.test.d.ts +1 -0
  10. package/dist/betterAuthApp.test.js +242 -0
  11. package/dist/betterAuthSetup.d.ts +60 -0
  12. package/dist/betterAuthSetup.js +278 -0
  13. package/dist/betterAuthSetup.test.d.ts +1 -0
  14. package/dist/betterAuthSetup.test.js +684 -0
  15. package/dist/expressServer.js +2 -2
  16. package/dist/index.d.ts +4 -0
  17. package/dist/index.js +4 -0
  18. package/dist/terrenoApp.d.ts +189 -0
  19. package/dist/terrenoApp.js +352 -0
  20. package/dist/terrenoApp.test.d.ts +1 -0
  21. package/dist/terrenoApp.test.js +264 -0
  22. package/dist/terrenoPlugin.d.ts +34 -0
  23. package/package.json +6 -3
  24. package/src/api.ts +61 -3
  25. package/src/betterAuth.test.ts +160 -0
  26. package/src/betterAuth.ts +104 -0
  27. package/src/betterAuthApp.test.ts +114 -0
  28. package/src/betterAuthApp.ts +60 -0
  29. package/src/betterAuthSetup.test.ts +485 -0
  30. package/src/betterAuthSetup.ts +251 -0
  31. package/src/expressServer.ts +4 -5
  32. package/src/index.ts +4 -0
  33. package/src/openApiValidator.ts +1 -1
  34. package/src/terrenoApp.test.ts +201 -0
  35. package/src/terrenoApp.ts +347 -0
  36. package/src/terrenoPlugin.ts +34 -0
  37. package/.claude/CLAUDE.local.md +0 -204
  38. package/.cursor/rules/00-root.mdc +0 -338
  39. package/.github/copilot-instructions.md +0 -333
  40. package/AGENTS.md +0 -333
@@ -285,7 +285,7 @@ function initializeRoutes(UserModel, addRoutes, options) {
285
285
  app.use("/swagger", oapi.swaggerui());
286
286
  }
287
287
  (0, auth_1.addMeRoutes)(app, UserModel, options === null || options === void 0 ? void 0 : options.authOptions);
288
- // Set up GitHub OAuth if configured
288
+ // Set up GitHub OAuth if configured (works with JWT auth)
289
289
  if (options.githubAuth) {
290
290
  (0, githubAuth_1.setupGitHubAuth)(app, UserModel, options.githubAuth);
291
291
  (0, githubAuth_1.addGitHubAuthRoutes)(app, UserModel, options.githubAuth, options.authOptions);
@@ -303,7 +303,7 @@ function initializeRoutes(UserModel, addRoutes, options) {
303
303
  });
304
304
  return app;
305
305
  }
306
- // Sets up the routes and returns a function to launch the API.
306
+ // Sets up the routes and returns the app.
307
307
  function setupServer(options) {
308
308
  var UserModel = options.userModel;
309
309
  var addRoutes = options.addRoutes;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  export * from "./api";
2
2
  export * from "./auth";
3
+ export * from "./betterAuth";
4
+ export * from "./betterAuthApp";
5
+ export * from "./betterAuthSetup";
3
6
  export * from "./errors";
4
7
  export * from "./expressServer";
5
8
  export * from "./githubAuth";
@@ -12,6 +15,7 @@ export * from "./openApiValidator";
12
15
  export * from "./permissions";
13
16
  export * from "./plugins";
14
17
  export * from "./populate";
18
+ export * from "./terrenoApp";
15
19
  export * from "./terrenoPlugin";
16
20
  export * from "./transformers";
17
21
  export * from "./utils";
package/dist/index.js CHANGED
@@ -16,6 +16,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./api"), exports);
18
18
  __exportStar(require("./auth"), exports);
19
+ __exportStar(require("./betterAuth"), exports);
20
+ __exportStar(require("./betterAuthApp"), exports);
21
+ __exportStar(require("./betterAuthSetup"), exports);
19
22
  __exportStar(require("./errors"), exports);
20
23
  __exportStar(require("./expressServer"), exports);
21
24
  __exportStar(require("./githubAuth"), exports);
@@ -28,6 +31,7 @@ __exportStar(require("./openApiValidator"), exports);
28
31
  __exportStar(require("./permissions"), exports);
29
32
  __exportStar(require("./plugins"), exports);
30
33
  __exportStar(require("./populate"), exports);
34
+ __exportStar(require("./terrenoApp"), exports);
31
35
  __exportStar(require("./terrenoPlugin"), exports);
32
36
  __exportStar(require("./transformers"), exports);
33
37
  __exportStar(require("./utils"), exports);
@@ -0,0 +1,189 @@
1
+ import * as Sentry from "@sentry/bun";
2
+ import express from "express";
3
+ import type { ModelRouterRegistration } from "./api";
4
+ import { type UserModel as UserMongooseModel } from "./auth";
5
+ import { type AuthOptions } from "./expressServer";
6
+ import { type GitHubAuthOptions } from "./githubAuth";
7
+ import { type LoggingOptions } from "./logger";
8
+ import type { TerrenoPlugin } from "./terrenoPlugin";
9
+ type CorsOrigin = string | boolean | RegExp | Array<boolean | string | RegExp> | ((requestOrigin: string | undefined, callback: (err: Error | null, origin?: boolean | string | RegExp | Array<boolean | string | RegExp>) => void) => void);
10
+ /**
11
+ * Configuration options for TerrenoApp.
12
+ */
13
+ export interface TerrenoAppOptions {
14
+ /** Mongoose User model with passport-local-mongoose plugin */
15
+ userModel: UserMongooseModel;
16
+ /** CORS origin configuration (default: "*") */
17
+ corsOrigin?: CorsOrigin;
18
+ /** Logging configuration options */
19
+ loggingOptions?: LoggingOptions;
20
+ /** Authentication configuration options */
21
+ authOptions?: AuthOptions;
22
+ /** GitHub OAuth configuration (enables GitHub authentication if provided) */
23
+ githubAuth?: GitHubAuthOptions;
24
+ /** Skip calling app.listen() in start() method (useful for testing) */
25
+ skipListen?: boolean;
26
+ /** Sentry configuration options */
27
+ sentryOptions?: Sentry.BunOptions;
28
+ /** Maximum number of array items in query parameters (default: 200) */
29
+ arrayLimit?: number;
30
+ /** Whether to log all incoming requests (default: true) */
31
+ logRequests?: boolean;
32
+ }
33
+ /**
34
+ * Fluent API for building Express applications with Terreno framework.
35
+ *
36
+ * TerrenoApp provides an alternative to `setupServer` using a registration
37
+ * pattern instead of callbacks. Build applications by registering model
38
+ * routers and plugins, then calling `start()` to begin listening.
39
+ *
40
+ * The middleware stack is configured in this order:
41
+ * 1. CORS
42
+ * 2. Custom middleware (via addMiddleware)
43
+ * 3. JSON body parser
44
+ * 4. Auth routes (/auth/login, /auth/signup, etc.)
45
+ * 5. JWT authentication setup
46
+ * 6. Request logging
47
+ * 7. Sentry scopes
48
+ * 8. OpenAPI middleware
49
+ * 9. /auth/me routes
50
+ * 10. GitHub OAuth routes (if enabled)
51
+ * 11. Registered model routers and plugins
52
+ * 12. Error handling middleware
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * // Basic usage with model routers
57
+ * const todoRouter = modelRouter("/todos", Todo, {
58
+ * permissions: { list: [Permissions.IsAuthenticated], ... },
59
+ * });
60
+ *
61
+ * const app = new TerrenoApp({ userModel: User })
62
+ * .register(todoRouter)
63
+ * .register(new HealthApp())
64
+ * .start();
65
+ * ```
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * // With custom middleware
70
+ * const app = new TerrenoApp({
71
+ * userModel: User,
72
+ * corsOrigin: ["https://app.example.com"],
73
+ * loggingOptions: { logRequests: true },
74
+ * githubAuth: {
75
+ * clientId: process.env.GITHUB_CLIENT_ID!,
76
+ * clientSecret: process.env.GITHUB_CLIENT_SECRET!,
77
+ * callbackURL: process.env.GITHUB_CALLBACK_URL!,
78
+ * },
79
+ * })
80
+ * .addMiddleware((req, res, next) => {
81
+ * res.setHeader("X-Custom-Header", "value");
82
+ * next();
83
+ * })
84
+ * .register(todoRouter)
85
+ * .register(userRouter)
86
+ * .start();
87
+ * ```
88
+ *
89
+ * @see setupServer for the callback-based alternative
90
+ * @see TerrenoPlugin for creating reusable plugins
91
+ * @see modelRouter for creating CRUD route registrations
92
+ */
93
+ export declare class TerrenoApp {
94
+ private options;
95
+ private registrations;
96
+ private middlewareFns;
97
+ /**
98
+ * Create a new TerrenoApp builder.
99
+ *
100
+ * @param options - Application configuration options including user model and auth settings
101
+ */
102
+ constructor(options: TerrenoAppOptions);
103
+ /**
104
+ * Register a model router or plugin with the application.
105
+ *
106
+ * Model routers are created with `modelRouter("/path", Model, options)` and
107
+ * provide CRUD endpoints. Plugins implement `TerrenoPlugin` interface and
108
+ * can register custom routes and middleware.
109
+ *
110
+ * Registrations are mounted in the order they are added.
111
+ *
112
+ * @param registration - A ModelRouterRegistration from modelRouter() or a TerrenoPlugin instance
113
+ * @returns This TerrenoApp instance for method chaining
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * const todoRouter = modelRouter("/todos", Todo, options);
118
+ * const healthPlugin = new HealthApp({ path: "/health" });
119
+ *
120
+ * app.register(todoRouter).register(healthPlugin);
121
+ * ```
122
+ */
123
+ register(registration: ModelRouterRegistration | TerrenoPlugin): this;
124
+ /**
125
+ * Add custom Express middleware to the application.
126
+ *
127
+ * Middleware is added BEFORE JSON body parsing and authentication setup,
128
+ * allowing you to modify incoming requests early in the middleware stack.
129
+ *
130
+ * @param fn - Express middleware function or a function that configures the app
131
+ * @returns This TerrenoApp instance for method chaining
132
+ *
133
+ * @example
134
+ * ```typescript
135
+ * app.addMiddleware((req, res, next) => {
136
+ * res.setHeader("X-Request-ID", req.id);
137
+ * next();
138
+ * });
139
+ * ```
140
+ */
141
+ addMiddleware(fn: express.RequestHandler | ((app: express.Application) => void)): this;
142
+ /**
143
+ * Build the Express application without starting the server.
144
+ *
145
+ * Configures the complete middleware stack including:
146
+ * - CORS, JSON parsing, authentication, logging, Sentry, OpenAPI
147
+ * - All registered model routers and plugins
148
+ * - Error handling middleware
149
+ *
150
+ * Use this method when you need the Express app instance for testing
151
+ * or custom server setup. For normal use, call `start()` instead.
152
+ *
153
+ * @returns Configured Express application instance
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * const app = new TerrenoApp({ userModel: User })
158
+ * .register(todoRouter)
159
+ * .build();
160
+ *
161
+ * // Use app for testing with supertest
162
+ * await request(app).get("/todos").expect(200);
163
+ * ```
164
+ */
165
+ build(): express.Application;
166
+ /**
167
+ * Build the Express application and start listening on the configured port.
168
+ *
169
+ * Calls `build()` to configure the application, then starts an HTTP server
170
+ * listening on the port specified by the `PORT` environment variable (default: 9000).
171
+ * If `skipListen` option is true, the app is built but the server is not started.
172
+ *
173
+ * @returns Configured Express application instance
174
+ *
175
+ * @throws Process exits with code 1 if the server fails to start
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * // Start server on port 3000
180
+ * process.env.PORT = "3000";
181
+ * const app = new TerrenoApp({ userModel: User })
182
+ * .register(todoRouter)
183
+ * .start();
184
+ * ```
185
+ */
186
+ start(): express.Application;
187
+ private isModelRouterRegistration;
188
+ }
189
+ export {};
@@ -0,0 +1,352 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __values = (this && this.__values) || function(o) {
36
+ var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
37
+ if (m) return m.call(o);
38
+ if (o && typeof o.length === "number") return {
39
+ next: function () {
40
+ if (o && i >= o.length) o = void 0;
41
+ return { value: o && o[i++], done: !o };
42
+ }
43
+ };
44
+ throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
45
+ };
46
+ var __importDefault = (this && this.__importDefault) || function (mod) {
47
+ return (mod && mod.__esModule) ? mod : { "default": mod };
48
+ };
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.TerrenoApp = void 0;
51
+ var Sentry = __importStar(require("@sentry/bun"));
52
+ var openapi_1 = __importDefault(require("@wesleytodd/openapi"));
53
+ var cors_1 = __importDefault(require("cors"));
54
+ var express_1 = __importDefault(require("express"));
55
+ var qs_1 = __importDefault(require("qs"));
56
+ var auth_1 = require("./auth");
57
+ var errors_1 = require("./errors");
58
+ var expressServer_1 = require("./expressServer");
59
+ var githubAuth_1 = require("./githubAuth");
60
+ var logger_1 = require("./logger");
61
+ var openApiEtag_1 = require("./openApiEtag");
62
+ /**
63
+ * Fluent API for building Express applications with Terreno framework.
64
+ *
65
+ * TerrenoApp provides an alternative to `setupServer` using a registration
66
+ * pattern instead of callbacks. Build applications by registering model
67
+ * routers and plugins, then calling `start()` to begin listening.
68
+ *
69
+ * The middleware stack is configured in this order:
70
+ * 1. CORS
71
+ * 2. Custom middleware (via addMiddleware)
72
+ * 3. JSON body parser
73
+ * 4. Auth routes (/auth/login, /auth/signup, etc.)
74
+ * 5. JWT authentication setup
75
+ * 6. Request logging
76
+ * 7. Sentry scopes
77
+ * 8. OpenAPI middleware
78
+ * 9. /auth/me routes
79
+ * 10. GitHub OAuth routes (if enabled)
80
+ * 11. Registered model routers and plugins
81
+ * 12. Error handling middleware
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * // Basic usage with model routers
86
+ * const todoRouter = modelRouter("/todos", Todo, {
87
+ * permissions: { list: [Permissions.IsAuthenticated], ... },
88
+ * });
89
+ *
90
+ * const app = new TerrenoApp({ userModel: User })
91
+ * .register(todoRouter)
92
+ * .register(new HealthApp())
93
+ * .start();
94
+ * ```
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * // With custom middleware
99
+ * const app = new TerrenoApp({
100
+ * userModel: User,
101
+ * corsOrigin: ["https://app.example.com"],
102
+ * loggingOptions: { logRequests: true },
103
+ * githubAuth: {
104
+ * clientId: process.env.GITHUB_CLIENT_ID!,
105
+ * clientSecret: process.env.GITHUB_CLIENT_SECRET!,
106
+ * callbackURL: process.env.GITHUB_CALLBACK_URL!,
107
+ * },
108
+ * })
109
+ * .addMiddleware((req, res, next) => {
110
+ * res.setHeader("X-Custom-Header", "value");
111
+ * next();
112
+ * })
113
+ * .register(todoRouter)
114
+ * .register(userRouter)
115
+ * .start();
116
+ * ```
117
+ *
118
+ * @see setupServer for the callback-based alternative
119
+ * @see TerrenoPlugin for creating reusable plugins
120
+ * @see modelRouter for creating CRUD route registrations
121
+ */
122
+ var TerrenoApp = /** @class */ (function () {
123
+ /**
124
+ * Create a new TerrenoApp builder.
125
+ *
126
+ * @param options - Application configuration options including user model and auth settings
127
+ */
128
+ function TerrenoApp(options) {
129
+ this.registrations = [];
130
+ this.middlewareFns = [];
131
+ this.options = options;
132
+ }
133
+ /**
134
+ * Register a model router or plugin with the application.
135
+ *
136
+ * Model routers are created with `modelRouter("/path", Model, options)` and
137
+ * provide CRUD endpoints. Plugins implement `TerrenoPlugin` interface and
138
+ * can register custom routes and middleware.
139
+ *
140
+ * Registrations are mounted in the order they are added.
141
+ *
142
+ * @param registration - A ModelRouterRegistration from modelRouter() or a TerrenoPlugin instance
143
+ * @returns This TerrenoApp instance for method chaining
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * const todoRouter = modelRouter("/todos", Todo, options);
148
+ * const healthPlugin = new HealthApp({ path: "/health" });
149
+ *
150
+ * app.register(todoRouter).register(healthPlugin);
151
+ * ```
152
+ */
153
+ TerrenoApp.prototype.register = function (registration) {
154
+ this.registrations.push(registration);
155
+ return this;
156
+ };
157
+ /**
158
+ * Add custom Express middleware to the application.
159
+ *
160
+ * Middleware is added BEFORE JSON body parsing and authentication setup,
161
+ * allowing you to modify incoming requests early in the middleware stack.
162
+ *
163
+ * @param fn - Express middleware function or a function that configures the app
164
+ * @returns This TerrenoApp instance for method chaining
165
+ *
166
+ * @example
167
+ * ```typescript
168
+ * app.addMiddleware((req, res, next) => {
169
+ * res.setHeader("X-Request-ID", req.id);
170
+ * next();
171
+ * });
172
+ * ```
173
+ */
174
+ TerrenoApp.prototype.addMiddleware = function (fn) {
175
+ this.middlewareFns.push(fn);
176
+ return this;
177
+ };
178
+ /**
179
+ * Build the Express application without starting the server.
180
+ *
181
+ * Configures the complete middleware stack including:
182
+ * - CORS, JSON parsing, authentication, logging, Sentry, OpenAPI
183
+ * - All registered model routers and plugins
184
+ * - Error handling middleware
185
+ *
186
+ * Use this method when you need the Express app instance for testing
187
+ * or custom server setup. For normal use, call `start()` instead.
188
+ *
189
+ * @returns Configured Express application instance
190
+ *
191
+ * @example
192
+ * ```typescript
193
+ * const app = new TerrenoApp({ userModel: User })
194
+ * .register(todoRouter)
195
+ * .build();
196
+ *
197
+ * // Use app for testing with supertest
198
+ * await request(app).get("/todos").expect(200);
199
+ * ```
200
+ */
201
+ TerrenoApp.prototype.build = function () {
202
+ var e_1, _a, e_2, _b;
203
+ var _c;
204
+ (0, logger_1.setupLogging)(this.options.loggingOptions);
205
+ var app = (0, express_1.default)();
206
+ var options = this.options;
207
+ app.set("query parser", function (str) { var _a; return qs_1.default.parse(str, { arrayLimit: (_a = options.arrayLimit) !== null && _a !== void 0 ? _a : 200 }); });
208
+ app.use((0, cors_1.default)({ origin: (_c = options.corsOrigin) !== null && _c !== void 0 ? _c : "*" }));
209
+ try {
210
+ // Apply custom middleware before JSON parsing
211
+ for (var _d = __values(this.middlewareFns), _e = _d.next(); !_e.done; _e = _d.next()) {
212
+ var fn = _e.value;
213
+ if (fn.length <= 3) {
214
+ // express.RequestHandler (req, res, next)
215
+ app.use(fn);
216
+ }
217
+ else {
218
+ // Function that receives the app
219
+ fn(app);
220
+ }
221
+ }
222
+ }
223
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
224
+ finally {
225
+ try {
226
+ if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
227
+ }
228
+ finally { if (e_1) throw e_1.error; }
229
+ }
230
+ app.use(express_1.default.json());
231
+ // Auth routes (login/signup/refresh_token) before JWT middleware
232
+ (0, auth_1.addAuthRoutes)(app, options.userModel, options.authOptions);
233
+ (0, auth_1.setupAuth)(app, options.userModel);
234
+ if (options.logRequests !== false) {
235
+ app.use(expressServer_1.logRequests);
236
+ }
237
+ // Store logging options on the response locals
238
+ app.use(function (_req, res, next) {
239
+ res.locals.loggingOptions = options.loggingOptions;
240
+ next();
241
+ });
242
+ // Sentry scopes
243
+ app.all("*", function (req, _res, next) {
244
+ var _a;
245
+ var transactionId = req.header("X-Transaction-ID");
246
+ var sessionId = req.header("X-Session-ID");
247
+ if (transactionId) {
248
+ Sentry.getCurrentScope().setTag("transaction_id", transactionId);
249
+ }
250
+ if (sessionId) {
251
+ Sentry.getCurrentScope().setTag("session_id", sessionId);
252
+ }
253
+ if ((_a = req.user) === null || _a === void 0 ? void 0 : _a._id) {
254
+ Sentry.getCurrentScope().setTag("user", req.user._id);
255
+ }
256
+ next();
257
+ });
258
+ // OpenAPI
259
+ app.use(openApiEtag_1.openApiEtagMiddleware);
260
+ var oapi = (0, openapi_1.default)({
261
+ info: {
262
+ description: "Generated docs from an Express api",
263
+ title: "Express Application",
264
+ version: "1.0.0",
265
+ },
266
+ openapi: "3.0.0",
267
+ });
268
+ app.use(oapi);
269
+ if (process.env.ENABLE_SWAGGER === "true") {
270
+ app.use("/swagger", oapi.swaggerui());
271
+ }
272
+ (0, auth_1.addMeRoutes)(app, options.userModel, options.authOptions);
273
+ // GitHub OAuth
274
+ if (options.githubAuth) {
275
+ (0, githubAuth_1.setupGitHubAuth)(app, options.userModel, options.githubAuth);
276
+ (0, githubAuth_1.addGitHubAuthRoutes)(app, options.userModel, options.githubAuth, options.authOptions);
277
+ }
278
+ try {
279
+ // Mount registered model routers and plugins
280
+ for (var _f = __values(this.registrations), _g = _f.next(); !_g.done; _g = _f.next()) {
281
+ var registration = _g.value;
282
+ if (this.isModelRouterRegistration(registration)) {
283
+ app.use(registration.path, registration.router);
284
+ }
285
+ else {
286
+ registration.register(app);
287
+ }
288
+ }
289
+ }
290
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
291
+ finally {
292
+ try {
293
+ if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
294
+ }
295
+ finally { if (e_2) throw e_2.error; }
296
+ }
297
+ // Inject openApi into model router options for registered routers
298
+ // The openApi middleware handles this via the oapi instance already mounted on the app
299
+ Sentry.setupExpressErrorHandler(app);
300
+ // Error middleware
301
+ app.use(errors_1.apiUnauthorizedMiddleware);
302
+ app.use(errors_1.apiErrorMiddleware);
303
+ app.use(function onError(err, _req, res, _next) {
304
+ logger_1.logger.error("Fallthrough error: ".concat(err).concat((err === null || err === void 0 ? void 0 : err.stack) ? "\n".concat(err.stack) : "", "}"));
305
+ Sentry.captureException(err);
306
+ res.statusCode = 500;
307
+ res.end("".concat(res.sentry, "\n"));
308
+ });
309
+ return app;
310
+ };
311
+ /**
312
+ * Build the Express application and start listening on the configured port.
313
+ *
314
+ * Calls `build()` to configure the application, then starts an HTTP server
315
+ * listening on the port specified by the `PORT` environment variable (default: 9000).
316
+ * If `skipListen` option is true, the app is built but the server is not started.
317
+ *
318
+ * @returns Configured Express application instance
319
+ *
320
+ * @throws Process exits with code 1 if the server fails to start
321
+ *
322
+ * @example
323
+ * ```typescript
324
+ * // Start server on port 3000
325
+ * process.env.PORT = "3000";
326
+ * const app = new TerrenoApp({ userModel: User })
327
+ * .register(todoRouter)
328
+ * .start();
329
+ * ```
330
+ */
331
+ TerrenoApp.prototype.start = function () {
332
+ var app = this.build();
333
+ if (!this.options.skipListen) {
334
+ var port_1 = process.env.PORT || "9000";
335
+ try {
336
+ app.listen(port_1, function () {
337
+ logger_1.logger.info("Listening on port ".concat(port_1));
338
+ });
339
+ }
340
+ catch (error) {
341
+ logger_1.logger.error("Error trying to start HTTP server: ".concat(error, "\n").concat(error.stack));
342
+ process.exit(1);
343
+ }
344
+ }
345
+ return app;
346
+ };
347
+ TerrenoApp.prototype.isModelRouterRegistration = function (registration) {
348
+ return registration.__type === "modelRouter";
349
+ };
350
+ return TerrenoApp;
351
+ }());
352
+ exports.TerrenoApp = TerrenoApp;
@@ -0,0 +1 @@
1
+ export {};