@terreno/api 0.13.3 → 0.14.1

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 (172) hide show
  1. package/dist/__tests__/versionCheckPlugin.test.js +136 -3
  2. package/dist/api.arrayOperations.test.js +1 -0
  3. package/dist/api.d.ts +15 -4
  4. package/dist/api.errors.test.js +1 -0
  5. package/dist/api.hooks.test.js +1 -0
  6. package/dist/api.js +153 -104
  7. package/dist/api.query.test.js +1 -0
  8. package/dist/api.test.js +174 -0
  9. package/dist/auth.d.ts +10 -5
  10. package/dist/auth.js +163 -90
  11. package/dist/auth.test.js +159 -0
  12. package/dist/betterAuthApp.test.js +1 -0
  13. package/dist/betterAuthSetup.d.ts +5 -6
  14. package/dist/betterAuthSetup.js +30 -17
  15. package/dist/betterAuthSetup.test.js +1 -0
  16. package/dist/config.d.ts +48 -0
  17. package/dist/config.js +257 -0
  18. package/dist/config.test.d.ts +1 -0
  19. package/dist/config.test.js +328 -0
  20. package/dist/configuration.test.js +1 -0
  21. package/dist/configurationApp.d.ts +1 -1
  22. package/dist/configurationApp.js +17 -13
  23. package/dist/configurationPlugin.test.js +1 -0
  24. package/dist/consentApp.test.js +1 -0
  25. package/dist/envConfigurationPlugin.d.ts +2 -0
  26. package/dist/envConfigurationPlugin.js +173 -0
  27. package/dist/envConfigurationPlugin.test.d.ts +1 -0
  28. package/dist/envConfigurationPlugin.test.js +322 -0
  29. package/dist/errors.d.ts +18 -7
  30. package/dist/errors.js +111 -12
  31. package/dist/errors.test.js +16 -1
  32. package/dist/example.js +19 -7
  33. package/dist/expressServer.d.ts +10 -9
  34. package/dist/expressServer.js +62 -53
  35. package/dist/expressServer.test.js +165 -2
  36. package/dist/githubAuth.d.ts +2 -1
  37. package/dist/githubAuth.js +41 -26
  38. package/dist/githubAuth.test.js +1 -0
  39. package/dist/index.d.ts +4 -0
  40. package/dist/index.js +4 -0
  41. package/dist/logger.d.ts +1 -1
  42. package/dist/logger.js +42 -20
  43. package/dist/models/versionConfig.d.ts +2 -0
  44. package/dist/models/versionConfig.js +8 -0
  45. package/dist/notifiers/googleChatNotifier.js +14 -16
  46. package/dist/notifiers/googleChatNotifier.test.js +1 -0
  47. package/dist/notifiers/slackNotifier.js +16 -14
  48. package/dist/notifiers/slackNotifier.test.js +41 -3
  49. package/dist/notifiers/zoomNotifier.js +7 -10
  50. package/dist/notifiers/zoomNotifier.test.js +1 -0
  51. package/dist/openApi.d.ts +1 -1
  52. package/dist/openApi.test.js +1 -0
  53. package/dist/openApiBuilder.d.ts +39 -6
  54. package/dist/openApiBuilder.js +1 -31
  55. package/dist/openApiBuilder.test.js +1 -0
  56. package/dist/openApiValidator.js +1 -0
  57. package/dist/openApiValidator.test.js +1 -0
  58. package/dist/permissions.d.ts +4 -4
  59. package/dist/permissions.js +67 -65
  60. package/dist/permissions.middleware.test.js +1 -0
  61. package/dist/permissions.test.js +1 -0
  62. package/dist/plugins.d.ts +5 -5
  63. package/dist/plugins.js +18 -9
  64. package/dist/plugins.test.js +1 -1
  65. package/dist/populate.d.ts +15 -8
  66. package/dist/populate.js +23 -24
  67. package/dist/populate.test.js +1 -0
  68. package/dist/realtime/changeStreamWatcher.d.ts +73 -0
  69. package/dist/realtime/changeStreamWatcher.js +724 -0
  70. package/dist/realtime/index.d.ts +6 -0
  71. package/dist/realtime/index.js +27 -0
  72. package/dist/realtime/queryMatcher.d.ts +14 -0
  73. package/dist/realtime/queryMatcher.js +250 -0
  74. package/dist/realtime/queryStore.d.ts +37 -0
  75. package/dist/realtime/queryStore.js +195 -0
  76. package/dist/realtime/realtime.test.d.ts +10 -0
  77. package/dist/realtime/realtime.test.js +3066 -0
  78. package/dist/realtime/realtimeApp.d.ts +93 -0
  79. package/dist/realtime/realtimeApp.js +560 -0
  80. package/dist/realtime/registry.d.ts +40 -0
  81. package/dist/realtime/registry.js +38 -0
  82. package/dist/realtime/socketUser.d.ts +10 -0
  83. package/dist/realtime/socketUser.js +17 -0
  84. package/dist/realtime/types.d.ts +100 -0
  85. package/dist/realtime/types.js +2 -0
  86. package/dist/requestContext.d.ts +37 -0
  87. package/dist/requestContext.js +344 -0
  88. package/dist/requestContext.test.d.ts +1 -0
  89. package/dist/requestContext.test.js +384 -0
  90. package/dist/terrenoApp.d.ts +8 -0
  91. package/dist/terrenoApp.js +50 -13
  92. package/dist/terrenoApp.test.js +194 -21
  93. package/dist/terrenoPlugin.d.ts +11 -0
  94. package/dist/tests/bunSetup.js +1 -0
  95. package/dist/tests.js +1 -1
  96. package/dist/transformers.d.ts +2 -2
  97. package/dist/transformers.js +5 -3
  98. package/dist/transformers.test.js +90 -0
  99. package/dist/types/consentResponse.d.ts +6 -3
  100. package/dist/versionCheckPlugin.d.ts +2 -0
  101. package/dist/versionCheckPlugin.js +18 -12
  102. package/package.json +4 -2
  103. package/src/__tests__/versionCheckPlugin.test.ts +94 -3
  104. package/src/api.arrayOperations.test.ts +1 -0
  105. package/src/api.errors.test.ts +1 -0
  106. package/src/api.hooks.test.ts +1 -0
  107. package/src/api.query.test.ts +1 -0
  108. package/src/api.test.ts +132 -0
  109. package/src/api.ts +199 -84
  110. package/src/auth.test.ts +160 -0
  111. package/src/auth.ts +120 -50
  112. package/src/betterAuthApp.test.ts +1 -0
  113. package/src/betterAuthSetup.test.ts +1 -0
  114. package/src/betterAuthSetup.ts +59 -22
  115. package/src/config.test.ts +255 -0
  116. package/src/config.ts +216 -0
  117. package/src/configuration.test.ts +1 -0
  118. package/src/configurationApp.ts +59 -24
  119. package/src/configurationPlugin.test.ts +1 -0
  120. package/src/consentApp.test.ts +1 -0
  121. package/src/envConfigurationPlugin.test.ts +143 -0
  122. package/src/envConfigurationPlugin.ts +100 -0
  123. package/src/errors.test.ts +19 -1
  124. package/src/errors.ts +118 -38
  125. package/src/example.ts +49 -21
  126. package/src/express.d.ts +18 -1
  127. package/src/expressServer.test.ts +147 -2
  128. package/src/expressServer.ts +80 -50
  129. package/src/githubAuth.test.ts +1 -0
  130. package/src/githubAuth.ts +59 -38
  131. package/src/index.ts +4 -0
  132. package/src/logger.ts +47 -17
  133. package/src/models/versionConfig.ts +13 -2
  134. package/src/notifiers/googleChatNotifier.test.ts +1 -0
  135. package/src/notifiers/googleChatNotifier.ts +7 -9
  136. package/src/notifiers/slackNotifier.test.ts +29 -3
  137. package/src/notifiers/slackNotifier.ts +9 -7
  138. package/src/notifiers/zoomNotifier.test.ts +1 -0
  139. package/src/notifiers/zoomNotifier.ts +8 -11
  140. package/src/openApi.test.ts +1 -0
  141. package/src/openApi.ts +4 -4
  142. package/src/openApiBuilder.test.ts +1 -0
  143. package/src/openApiBuilder.ts +14 -11
  144. package/src/openApiValidator.test.ts +1 -0
  145. package/src/openApiValidator.ts +3 -2
  146. package/src/permissions.middleware.test.ts +1 -0
  147. package/src/permissions.test.ts +1 -0
  148. package/src/permissions.ts +30 -25
  149. package/src/plugins.test.ts +1 -1
  150. package/src/plugins.ts +21 -14
  151. package/src/populate.test.ts +1 -0
  152. package/src/populate.ts +44 -36
  153. package/src/realtime/changeStreamWatcher.ts +572 -0
  154. package/src/realtime/index.ts +34 -0
  155. package/src/realtime/queryMatcher.ts +179 -0
  156. package/src/realtime/queryStore.ts +132 -0
  157. package/src/realtime/realtime.test.ts +2465 -0
  158. package/src/realtime/realtimeApp.ts +478 -0
  159. package/src/realtime/registry.ts +64 -0
  160. package/src/realtime/socketUser.ts +25 -0
  161. package/src/realtime/types.ts +112 -0
  162. package/src/requestContext.test.ts +321 -0
  163. package/src/requestContext.ts +368 -0
  164. package/src/terrenoApp.test.ts +137 -11
  165. package/src/terrenoApp.ts +64 -17
  166. package/src/terrenoPlugin.ts +12 -0
  167. package/src/tests/bunSetup.ts +1 -0
  168. package/src/tests.ts +7 -2
  169. package/src/transformers.test.ts +70 -2
  170. package/src/transformers.ts +15 -7
  171. package/src/types/consentResponse.ts +8 -10
  172. package/src/versionCheckPlugin.ts +15 -7
package/dist/auth.test.js CHANGED
@@ -99,22 +99,30 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
99
99
  return (mod && mod.__esModule) ? mod : { "default": mod };
100
100
  };
101
101
  Object.defineProperty(exports, "__esModule", { value: true });
102
+ // biome-ignore-all lint/suspicious/noExplicitAny: test mock typing
102
103
  var bun_test_1 = require("bun:test");
103
104
  var supertest_1 = __importDefault(require("supertest"));
104
105
  var api_1 = require("./api");
105
106
  var auth_1 = require("./auth");
106
107
  var expressServer_1 = require("./expressServer");
107
108
  var permissions_1 = require("./permissions");
109
+ var requestContext_1 = require("./requestContext");
108
110
  var tests_1 = require("./tests");
109
111
  var transformers_1 = require("./transformers");
110
112
  var utils_1 = require("./utils");
113
+ var decodeTokenPayload = function (token) {
114
+ var encodedPayload = token.split(".")[1];
115
+ return JSON.parse(Buffer.from(encodedPayload, "base64url").toString("utf8"));
116
+ };
111
117
  (0, bun_test_1.describe)("auth tests", function () {
112
118
  var app;
113
119
  var admin;
120
+ var contextEvents;
114
121
  var notAdmin;
115
122
  var agent;
116
123
  (0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
117
124
  function addRoutes(router) {
125
+ var _this = this;
118
126
  router.use("/food", (0, api_1.modelRouter)(tests_1.FoodModel, {
119
127
  allowAnonymous: true,
120
128
  permissions: {
@@ -141,6 +149,58 @@ var utils_1 = require("./utils");
141
149
  ownerWriteFields: ["name", "calories", "created"],
142
150
  }),
143
151
  }));
152
+ router.use("/context-food", (0, api_1.modelRouter)(tests_1.FoodModel, {
153
+ permissions: {
154
+ create: [permissions_1.Permissions.IsAuthenticated],
155
+ delete: [],
156
+ list: [],
157
+ read: [],
158
+ update: [],
159
+ },
160
+ postCreate: function (_value, req) { return __awaiter(_this, void 0, void 0, function () {
161
+ var _a, _b;
162
+ return __generator(this, function (_c) {
163
+ contextEvents.push({
164
+ currentSessionId: (_a = (0, requestContext_1.getCurrentRequestContext)()) === null || _a === void 0 ? void 0 : _a.sessionId,
165
+ requestId: req.requestId,
166
+ sessionId: req.sessionId,
167
+ stage: "postCreate",
168
+ userId: (_b = req.user) === null || _b === void 0 ? void 0 : _b.id,
169
+ });
170
+ return [2 /*return*/];
171
+ });
172
+ }); },
173
+ preCreate: function (body, req) {
174
+ var _a, _b, _c, _d;
175
+ contextEvents.push({
176
+ currentSessionId: (_a = (0, requestContext_1.getCurrentRequestContext)()) === null || _a === void 0 ? void 0 : _a.sessionId,
177
+ requestId: req.requestId,
178
+ sessionId: req.sessionId,
179
+ stage: "preCreate",
180
+ userId: (_b = req.user) === null || _b === void 0 ? void 0 : _b.id,
181
+ });
182
+ return __assign(__assign({}, body), { categories: [], eatenBy: [(_c = req.user) === null || _c === void 0 ? void 0 : _c._id], expiration: "2026-01-01", lastEatenWith: {}, likesIds: [], ownerId: (_d = req.user) === null || _d === void 0 ? void 0 : _d._id, source: { name: "context-test" }, tags: [] });
183
+ },
184
+ responseHandler: function (value, method, req) { return __awaiter(_this, void 0, void 0, function () {
185
+ var _a, _b, _c, _d, _e, _f, _g, _h;
186
+ return __generator(this, function (_j) {
187
+ contextEvents.push({
188
+ currentSessionId: (_a = (0, requestContext_1.getCurrentRequestContext)()) === null || _a === void 0 ? void 0 : _a.sessionId,
189
+ requestId: req.requestId,
190
+ sessionId: req.sessionId,
191
+ stage: "responseHandler:".concat(method),
192
+ userId: (_b = req.user) === null || _b === void 0 ? void 0 : _b.id,
193
+ });
194
+ return [2 /*return*/, {
195
+ id: String(value._id),
196
+ requestId: (_c = req.requestId) !== null && _c !== void 0 ? _c : null,
197
+ sessionContext: (_e = (_d = (0, requestContext_1.getCurrentRequestContext)()) === null || _d === void 0 ? void 0 : _d.sessionId) !== null && _e !== void 0 ? _e : null,
198
+ sessionId: (_f = req.sessionId) !== null && _f !== void 0 ? _f : null,
199
+ userId: (_h = (_g = req.user) === null || _g === void 0 ? void 0 : _g.id) !== null && _h !== void 0 ? _h : null,
200
+ }];
201
+ });
202
+ }); },
203
+ }));
144
204
  }
145
205
  var _a;
146
206
  return __generator(this, function (_b) {
@@ -152,6 +212,7 @@ var utils_1 = require("./utils");
152
212
  return [4 /*yield*/, (0, tests_1.setupDb)()];
153
213
  case 1:
154
214
  _a = __read.apply(void 0, [_b.sent(), 2]), admin = _a[0], notAdmin = _a[1];
215
+ contextEvents = [];
155
216
  return [4 /*yield*/, Promise.all([
156
217
  tests_1.FoodModel.create({
157
218
  calories: 1,
@@ -346,6 +407,104 @@ var utils_1 = require("./utils");
346
407
  }
347
408
  });
348
409
  }); });
410
+ (0, bun_test_1.it)("passes request and session context through modelRouter hooks", function () { return __awaiter(void 0, void 0, void 0, function () {
411
+ var loginRes, loginTokenPayload, createRes, sessionId;
412
+ return __generator(this, function (_a) {
413
+ switch (_a.label) {
414
+ case 0: return [4 /*yield*/, agent
415
+ .post("/auth/login")
416
+ .send({ email: "admin@example.com", password: "securePassword" })
417
+ .expect(200)];
418
+ case 1:
419
+ loginRes = _a.sent();
420
+ loginTokenPayload = decodeTokenPayload(loginRes.body.data.token);
421
+ return [4 /*yield*/, agent
422
+ .post("/context-food")
423
+ .set("authorization", "Bearer ".concat(loginRes.body.data.token))
424
+ .set("X-Request-ID", "model-router-request-1")
425
+ .send({ calories: 10, name: "Context Apple" })
426
+ .expect(201)];
427
+ case 2:
428
+ createRes = _a.sent();
429
+ (0, bun_test_1.expect)(loginTokenPayload.sid).toBeDefined();
430
+ sessionId = loginTokenPayload.sid;
431
+ if (!sessionId) {
432
+ throw new Error("Expected login token to include a session id");
433
+ }
434
+ (0, bun_test_1.expect)(createRes.headers["x-request-id"]).toBe("model-router-request-1");
435
+ (0, bun_test_1.expect)(createRes.headers["x-session-id"]).toBe(sessionId);
436
+ (0, bun_test_1.expect)(createRes.body.data.requestId).toBe("model-router-request-1");
437
+ (0, bun_test_1.expect)(createRes.body.data.sessionId).toBe(sessionId);
438
+ (0, bun_test_1.expect)(createRes.body.data.sessionContext).toBe(sessionId);
439
+ (0, bun_test_1.expect)(createRes.body.data.userId).toBe(String(admin._id));
440
+ (0, bun_test_1.expect)(contextEvents).toEqual([
441
+ {
442
+ currentSessionId: sessionId,
443
+ requestId: "model-router-request-1",
444
+ sessionId: sessionId,
445
+ stage: "preCreate",
446
+ userId: String(admin._id),
447
+ },
448
+ {
449
+ currentSessionId: sessionId,
450
+ requestId: "model-router-request-1",
451
+ sessionId: sessionId,
452
+ stage: "postCreate",
453
+ userId: String(admin._id),
454
+ },
455
+ {
456
+ currentSessionId: sessionId,
457
+ requestId: "model-router-request-1",
458
+ sessionId: sessionId,
459
+ stage: "responseHandler:create",
460
+ userId: String(admin._id),
461
+ },
462
+ ]);
463
+ return [2 /*return*/];
464
+ }
465
+ });
466
+ }); });
467
+ (0, bun_test_1.it)("preserves JWT session id across refresh and request context", function () { return __awaiter(void 0, void 0, void 0, function () {
468
+ var loginRes, loginTokenPayload, loginRefreshPayload, loginSessionId, refreshRes, refreshedTokenPayload, refreshedRefreshPayload, foodRes;
469
+ return __generator(this, function (_a) {
470
+ switch (_a.label) {
471
+ case 0: return [4 /*yield*/, agent
472
+ .post("/auth/login")
473
+ .send({ email: "admin@example.com", password: "securePassword" })
474
+ .expect(200)];
475
+ case 1:
476
+ loginRes = _a.sent();
477
+ loginTokenPayload = decodeTokenPayload(loginRes.body.data.token);
478
+ loginRefreshPayload = decodeTokenPayload(loginRes.body.data.refreshToken);
479
+ (0, bun_test_1.expect)(loginTokenPayload.sid).toBeDefined();
480
+ loginSessionId = loginTokenPayload.sid;
481
+ if (!loginSessionId) {
482
+ throw new Error("Expected login token to include a session id");
483
+ }
484
+ (0, bun_test_1.expect)(loginRefreshPayload.sid).toBe(loginSessionId);
485
+ (0, bun_test_1.expect)(loginRes.headers["x-session-id"]).toBe(loginSessionId);
486
+ return [4 /*yield*/, agent
487
+ .post("/auth/refresh_token")
488
+ .send({ refreshToken: loginRes.body.data.refreshToken })
489
+ .expect(200)];
490
+ case 2:
491
+ refreshRes = _a.sent();
492
+ refreshedTokenPayload = decodeTokenPayload(refreshRes.body.data.token);
493
+ refreshedRefreshPayload = decodeTokenPayload(refreshRes.body.data.refreshToken);
494
+ (0, bun_test_1.expect)(refreshedTokenPayload.sid).toBe(loginSessionId);
495
+ (0, bun_test_1.expect)(refreshedRefreshPayload.sid).toBe(loginSessionId);
496
+ (0, bun_test_1.expect)(refreshRes.headers["x-session-id"]).toBe(loginSessionId);
497
+ return [4 /*yield*/, agent
498
+ .get("/food")
499
+ .set("authorization", "Bearer ".concat(refreshRes.body.data.token))
500
+ .expect(200)];
501
+ case 3:
502
+ foodRes = _a.sent();
503
+ (0, bun_test_1.expect)(foodRes.headers["x-session-id"]).toBe(loginSessionId);
504
+ return [2 /*return*/];
505
+ }
506
+ });
507
+ }); });
349
508
  (0, bun_test_1.it)("completes token login e2e", function () { return __awaiter(void 0, void 0, void 0, function () {
350
509
  var res, _a, userId, token, meRes, mePatchRes, getRes, food, updateRes;
351
510
  return __generator(this, function (_b) {
@@ -83,6 +83,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
83
83
  return (mod && mod.__esModule) ? mod : { "default": mod };
84
84
  };
85
85
  Object.defineProperty(exports, "__esModule", { value: true });
86
+ // biome-ignore-all lint/suspicious/noExplicitAny: test mock typing
86
87
  var bun_test_1 = require("bun:test");
87
88
  var express_1 = __importDefault(require("express"));
88
89
  var mongodb_memory_server_1 = require("mongodb-memory-server");
@@ -15,9 +15,12 @@ export type BetterAuthInstance = ReturnType<typeof betterAuth>;
15
15
  /**
16
16
  * Options for creating a Better Auth instance.
17
17
  */
18
+ export interface MongoClientLike {
19
+ db: () => any;
20
+ }
18
21
  export interface CreateBetterAuthOptions {
19
22
  config: BetterAuthConfig;
20
- mongoClient: any;
23
+ mongoClient: MongoClientLike;
21
24
  userModel?: UserModel;
22
25
  }
23
26
  /**
@@ -29,10 +32,6 @@ export declare const createBetterAuth: (options: CreateBetterAuthOptions) => Bet
29
32
  * and populates req.user with the application User model.
30
33
  */
31
34
  export declare const createBetterAuthSessionMiddleware: (auth: BetterAuthInstance, userModel?: UserModel) => (req: Request, _res: Response, next: NextFunction) => Promise<void>;
32
- /**
33
- * Syncs a Better Auth user to the application User model.
34
- * Creates or updates the user as needed.
35
- */
36
35
  export declare const syncBetterAuthUser: (userModel: UserModel, betterAuthUser: BetterAuthUser, oauthProvider?: string) => Promise<any>;
37
36
  /**
38
37
  * Mounts Better Auth routes on the Express app.
@@ -41,7 +40,7 @@ export declare const mountBetterAuthRoutes: (app: Application, auth: BetterAuthI
41
40
  /**
42
41
  * Gets the MongoDB client from the mongoose connection.
43
42
  */
44
- export declare const getMongoClientFromMongoose: () => any;
43
+ export declare const getMongoClientFromMongoose: () => MongoClientLike;
45
44
  /**
46
45
  * Sets up Better Auth user sync hooks.
47
46
  * This ensures users created/updated in Better Auth are synced to the application User model.
@@ -61,8 +61,10 @@ var better_auth_1 = require("better-auth");
61
61
  var mongodb_1 = require("better-auth/adapters/mongodb");
62
62
  var node_1 = require("better-auth/node");
63
63
  var mongoose_1 = __importDefault(require("mongoose"));
64
+ var errors_1 = require("./errors");
64
65
  var logger_1 = require("./logger");
65
66
  var plugins_1 = require("./plugins");
67
+ var requestContext_1 = require("./requestContext");
66
68
  /**
67
69
  * Creates a Better Auth instance with MongoDB adapter.
68
70
  */
@@ -71,11 +73,17 @@ var createBetterAuth = function (options) {
71
73
  var config = options.config, mongoClient = options.mongoClient;
72
74
  var secret = config.secret || process.env.BETTER_AUTH_SECRET;
73
75
  if (!secret) {
74
- throw new Error("BETTER_AUTH_SECRET must be set in env or config.secret must be provided.");
76
+ throw new errors_1.APIError({
77
+ status: 500,
78
+ title: "BETTER_AUTH_SECRET must be set in env or config.secret must be provided.",
79
+ });
75
80
  }
76
81
  var baseURL = config.baseURL || process.env.BETTER_AUTH_URL;
77
82
  if (!baseURL) {
78
- throw new Error("BETTER_AUTH_URL must be set in env or config.baseURL must be provided.");
83
+ throw new errors_1.APIError({
84
+ status: 500,
85
+ title: "BETTER_AUTH_URL must be set in env or config.baseURL must be provided.",
86
+ });
79
87
  }
80
88
  var basePath = (_a = config.basePath) !== null && _a !== void 0 ? _a : "/api/auth";
81
89
  var socialProviders = {};
@@ -123,7 +131,7 @@ exports.createBetterAuth = createBetterAuth;
123
131
  */
124
132
  var createBetterAuthSessionMiddleware = function (auth, userModel) {
125
133
  return function (req, _res, next) { return __awaiter(void 0, void 0, void 0, function () {
126
- var session, betterAuthUser, appUser, newUser, error_1;
134
+ var session, betterAuthUser, reqWithSession, appUser, newUser, error_1;
127
135
  return __generator(this, function (_a) {
128
136
  switch (_a.label) {
129
137
  case 0:
@@ -135,6 +143,7 @@ var createBetterAuthSessionMiddleware = function (auth, userModel) {
135
143
  session = _a.sent();
136
144
  if (!((session === null || session === void 0 ? void 0 : session.user) && (session === null || session === void 0 ? void 0 : session.session))) return [3 /*break*/, 7];
137
145
  betterAuthUser = session.user;
146
+ reqWithSession = req;
138
147
  if (!userModel) return [3 /*break*/, 6];
139
148
  return [4 /*yield*/, (0, plugins_1.findOneOrNoneFor)(userModel, {
140
149
  betterAuthId: betterAuthUser.id,
@@ -142,19 +151,21 @@ var createBetterAuthSessionMiddleware = function (auth, userModel) {
142
151
  case 2:
143
152
  appUser = _a.sent();
144
153
  if (!appUser) return [3 /*break*/, 3];
145
- req.user = appUser;
146
- req.betterAuthSession = session;
154
+ reqWithSession.user = appUser;
155
+ reqWithSession.betterAuthSession = session;
156
+ (0, requestContext_1.updateRequestContextFromRequest)(req);
147
157
  return [3 /*break*/, 5];
148
158
  case 3: return [4 /*yield*/, (0, exports.syncBetterAuthUser)(userModel, betterAuthUser)];
149
159
  case 4:
150
160
  newUser = _a.sent();
151
- req.user = newUser;
152
- req.betterAuthSession = session;
161
+ reqWithSession.user = newUser;
162
+ reqWithSession.betterAuthSession = session;
163
+ (0, requestContext_1.updateRequestContextFromRequest)(req);
153
164
  _a.label = 5;
154
165
  case 5: return [3 /*break*/, 7];
155
166
  case 6:
156
167
  // No user model - just attach the Better Auth user directly
157
- req.user = {
168
+ reqWithSession.user = {
158
169
  _id: betterAuthUser.id,
159
170
  admin: false,
160
171
  betterAuthId: betterAuthUser.id,
@@ -162,7 +173,8 @@ var createBetterAuthSessionMiddleware = function (auth, userModel) {
162
173
  id: betterAuthUser.id,
163
174
  name: betterAuthUser.name,
164
175
  };
165
- req.betterAuthSession = session;
176
+ reqWithSession.betterAuthSession = session;
177
+ (0, requestContext_1.updateRequestContextFromRequest)(req);
166
178
  _a.label = 7;
167
179
  case 7:
168
180
  next();
@@ -178,11 +190,9 @@ var createBetterAuthSessionMiddleware = function (auth, userModel) {
178
190
  }); };
179
191
  };
180
192
  exports.createBetterAuthSessionMiddleware = createBetterAuthSessionMiddleware;
181
- /**
182
- * Syncs a Better Auth user to the application User model.
183
- * Creates or updates the user as needed.
184
- */
185
- var syncBetterAuthUser = function (userModel, betterAuthUser, oauthProvider) { return __awaiter(void 0, void 0, void 0, function () {
193
+ var syncBetterAuthUser = function (userModel, betterAuthUser, oauthProvider
194
+ // biome-ignore lint/suspicious/noExplicitAny: return is a consumer-defined user document; tests inspect varied fields
195
+ ) { return __awaiter(void 0, void 0, void 0, function () {
186
196
  var existingUser, userByEmail, useAsId, newUser, error_2;
187
197
  return __generator(this, function (_a) {
188
198
  switch (_a.label) {
@@ -192,7 +202,7 @@ var syncBetterAuthUser = function (userModel, betterAuthUser, oauthProvider) { r
192
202
  betterAuthId: betterAuthUser.id,
193
203
  })];
194
204
  case 1:
195
- existingUser = _a.sent();
205
+ existingUser = (_a.sent());
196
206
  if (!existingUser) return [3 /*break*/, 3];
197
207
  // Update existing user if needed
198
208
  existingUser.email = betterAuthUser.email;
@@ -207,7 +217,7 @@ var syncBetterAuthUser = function (userModel, betterAuthUser, oauthProvider) { r
207
217
  email: betterAuthUser.email,
208
218
  })];
209
219
  case 4:
210
- userByEmail = _a.sent();
220
+ userByEmail = (_a.sent());
211
221
  if (!userByEmail) return [3 /*break*/, 6];
212
222
  // Link existing user to Better Auth
213
223
  userByEmail.betterAuthId = betterAuthUser.id;
@@ -255,7 +265,10 @@ var getMongoClientFromMongoose = function () {
255
265
  var connection = mongoose_1.default.connection;
256
266
  var client = connection.client;
257
267
  if (!client) {
258
- throw new Error("Mongoose is not connected. Ensure MongoDB connection is established first.");
268
+ throw new errors_1.APIError({
269
+ status: 500,
270
+ title: "Mongoose is not connected. Ensure MongoDB connection is established first.",
271
+ });
259
272
  }
260
273
  return client;
261
274
  };
@@ -83,6 +83,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
83
83
  return (mod && mod.__esModule) ? mod : { "default": mod };
84
84
  };
85
85
  Object.defineProperty(exports, "__esModule", { value: true });
86
+ // biome-ignore-all lint/suspicious/noExplicitAny: test mock typing
86
87
  var bun_test_1 = require("bun:test");
87
88
  var express_1 = __importDefault(require("express"));
88
89
  var mongodb_memory_server_1 = require("mongodb-memory-server");
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Runtime configuration registry with a fixed resolution order:
3
+ *
4
+ * 1. In-process override (Config.setOverride) — highest, for tests/bootstrap
5
+ * 2. Cached env map — typically loaded from an admin-editable Mongoose document
6
+ * 3. process.env
7
+ * 4. Registered default
8
+ *
9
+ * Why a registry: every key migrating off raw `process.env` declares its type
10
+ * and default in one place. That keeps the admin UI honest (no surprise keys),
11
+ * gives synchronous access without scattered `?? "default"` literals at call
12
+ * sites, and lets tests assert behavior against a single source of truth.
13
+ *
14
+ * Why sync: hundreds of call sites read configuration during request handling
15
+ * and module init; an async API would force enormous refactors. Callers load
16
+ * the env map once via `Config.refresh()` after Mongo connects, then read
17
+ * synchronously from cache.
18
+ *
19
+ * The mechanism is agnostic to where the env map comes from. Apps wire up
20
+ * their backing store with `Config.setEnvLoader(fn)`. The optional
21
+ * `envConfigurationPlugin` provides a drop-in Mongoose schema integration.
22
+ */
23
+ export interface ConfigRegistration {
24
+ /** Default returned when neither override, cache, nor process.env supplies a value. */
25
+ default?: string;
26
+ /** Documentation surfaced in the admin UI. */
27
+ description?: string;
28
+ /** Marks the key as a secret so admin UI can mask the value. */
29
+ secret?: boolean;
30
+ }
31
+ export declare const Config: {
32
+ clearOverrides: () => void;
33
+ clearRegistryForTesting: () => void;
34
+ get: (key: string) => string | undefined;
35
+ getBoolean: (key: string) => boolean;
36
+ getDefault: (key: string) => string | undefined;
37
+ getJSON: <T = unknown>(key: string) => T | undefined;
38
+ getNumber: (key: string) => number | undefined;
39
+ getRegisteredKeys: () => string[];
40
+ getRegistration: (key: string) => ConfigRegistration | undefined;
41
+ isRegistered: (key: string) => boolean;
42
+ refresh: () => Promise<void>;
43
+ register: (key: string, registration?: ConfigRegistration) => void;
44
+ setCachedEnv: (env: Record<string, string> | null) => void;
45
+ setEnvLoader: (loader: (() => Promise<Record<string, string>>) | null) => void;
46
+ setOverride: (key: string, value: string | undefined) => void;
47
+ };
48
+ export type ConfigType = typeof Config;