@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.
- package/dist/__tests__/versionCheckPlugin.test.js +136 -3
- package/dist/api.arrayOperations.test.js +1 -0
- package/dist/api.d.ts +15 -4
- package/dist/api.errors.test.js +1 -0
- package/dist/api.hooks.test.js +1 -0
- package/dist/api.js +153 -104
- package/dist/api.query.test.js +1 -0
- package/dist/api.test.js +174 -0
- package/dist/auth.d.ts +10 -5
- package/dist/auth.js +163 -90
- package/dist/auth.test.js +159 -0
- package/dist/betterAuthApp.test.js +1 -0
- package/dist/betterAuthSetup.d.ts +5 -6
- package/dist/betterAuthSetup.js +30 -17
- package/dist/betterAuthSetup.test.js +1 -0
- package/dist/config.d.ts +48 -0
- package/dist/config.js +257 -0
- package/dist/config.test.d.ts +1 -0
- package/dist/config.test.js +328 -0
- package/dist/configuration.test.js +1 -0
- package/dist/configurationApp.d.ts +1 -1
- package/dist/configurationApp.js +17 -13
- package/dist/configurationPlugin.test.js +1 -0
- package/dist/consentApp.test.js +1 -0
- package/dist/envConfigurationPlugin.d.ts +2 -0
- package/dist/envConfigurationPlugin.js +173 -0
- package/dist/envConfigurationPlugin.test.d.ts +1 -0
- package/dist/envConfigurationPlugin.test.js +322 -0
- package/dist/errors.d.ts +18 -7
- package/dist/errors.js +111 -12
- package/dist/errors.test.js +16 -1
- package/dist/example.js +19 -7
- package/dist/expressServer.d.ts +10 -9
- package/dist/expressServer.js +62 -53
- package/dist/expressServer.test.js +165 -2
- package/dist/githubAuth.d.ts +2 -1
- package/dist/githubAuth.js +41 -26
- package/dist/githubAuth.test.js +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/logger.d.ts +1 -1
- package/dist/logger.js +42 -20
- package/dist/models/versionConfig.d.ts +2 -0
- package/dist/models/versionConfig.js +8 -0
- package/dist/notifiers/googleChatNotifier.js +14 -16
- package/dist/notifiers/googleChatNotifier.test.js +1 -0
- package/dist/notifiers/slackNotifier.js +16 -14
- package/dist/notifiers/slackNotifier.test.js +41 -3
- package/dist/notifiers/zoomNotifier.js +7 -10
- package/dist/notifiers/zoomNotifier.test.js +1 -0
- package/dist/openApi.d.ts +1 -1
- package/dist/openApi.test.js +1 -0
- package/dist/openApiBuilder.d.ts +39 -6
- package/dist/openApiBuilder.js +1 -31
- package/dist/openApiBuilder.test.js +1 -0
- package/dist/openApiValidator.js +1 -0
- package/dist/openApiValidator.test.js +1 -0
- package/dist/permissions.d.ts +4 -4
- package/dist/permissions.js +67 -65
- package/dist/permissions.middleware.test.js +1 -0
- package/dist/permissions.test.js +1 -0
- package/dist/plugins.d.ts +5 -5
- package/dist/plugins.js +18 -9
- package/dist/plugins.test.js +1 -1
- package/dist/populate.d.ts +15 -8
- package/dist/populate.js +23 -24
- package/dist/populate.test.js +1 -0
- package/dist/realtime/changeStreamWatcher.d.ts +73 -0
- package/dist/realtime/changeStreamWatcher.js +724 -0
- package/dist/realtime/index.d.ts +6 -0
- package/dist/realtime/index.js +27 -0
- package/dist/realtime/queryMatcher.d.ts +14 -0
- package/dist/realtime/queryMatcher.js +250 -0
- package/dist/realtime/queryStore.d.ts +37 -0
- package/dist/realtime/queryStore.js +195 -0
- package/dist/realtime/realtime.test.d.ts +10 -0
- package/dist/realtime/realtime.test.js +3066 -0
- package/dist/realtime/realtimeApp.d.ts +93 -0
- package/dist/realtime/realtimeApp.js +560 -0
- package/dist/realtime/registry.d.ts +40 -0
- package/dist/realtime/registry.js +38 -0
- package/dist/realtime/socketUser.d.ts +10 -0
- package/dist/realtime/socketUser.js +17 -0
- package/dist/realtime/types.d.ts +100 -0
- package/dist/realtime/types.js +2 -0
- package/dist/requestContext.d.ts +37 -0
- package/dist/requestContext.js +344 -0
- package/dist/requestContext.test.d.ts +1 -0
- package/dist/requestContext.test.js +384 -0
- package/dist/terrenoApp.d.ts +8 -0
- package/dist/terrenoApp.js +50 -13
- package/dist/terrenoApp.test.js +194 -21
- package/dist/terrenoPlugin.d.ts +11 -0
- package/dist/tests/bunSetup.js +1 -0
- package/dist/tests.js +1 -1
- package/dist/transformers.d.ts +2 -2
- package/dist/transformers.js +5 -3
- package/dist/transformers.test.js +90 -0
- package/dist/types/consentResponse.d.ts +6 -3
- package/dist/versionCheckPlugin.d.ts +2 -0
- package/dist/versionCheckPlugin.js +18 -12
- package/package.json +4 -2
- package/src/__tests__/versionCheckPlugin.test.ts +94 -3
- package/src/api.arrayOperations.test.ts +1 -0
- package/src/api.errors.test.ts +1 -0
- package/src/api.hooks.test.ts +1 -0
- package/src/api.query.test.ts +1 -0
- package/src/api.test.ts +132 -0
- package/src/api.ts +199 -84
- package/src/auth.test.ts +160 -0
- package/src/auth.ts +120 -50
- package/src/betterAuthApp.test.ts +1 -0
- package/src/betterAuthSetup.test.ts +1 -0
- package/src/betterAuthSetup.ts +59 -22
- package/src/config.test.ts +255 -0
- package/src/config.ts +216 -0
- package/src/configuration.test.ts +1 -0
- package/src/configurationApp.ts +59 -24
- package/src/configurationPlugin.test.ts +1 -0
- package/src/consentApp.test.ts +1 -0
- package/src/envConfigurationPlugin.test.ts +143 -0
- package/src/envConfigurationPlugin.ts +100 -0
- package/src/errors.test.ts +19 -1
- package/src/errors.ts +118 -38
- package/src/example.ts +49 -21
- package/src/express.d.ts +18 -1
- package/src/expressServer.test.ts +147 -2
- package/src/expressServer.ts +80 -50
- package/src/githubAuth.test.ts +1 -0
- package/src/githubAuth.ts +59 -38
- package/src/index.ts +4 -0
- package/src/logger.ts +47 -17
- package/src/models/versionConfig.ts +13 -2
- package/src/notifiers/googleChatNotifier.test.ts +1 -0
- package/src/notifiers/googleChatNotifier.ts +7 -9
- package/src/notifiers/slackNotifier.test.ts +29 -3
- package/src/notifiers/slackNotifier.ts +9 -7
- package/src/notifiers/zoomNotifier.test.ts +1 -0
- package/src/notifiers/zoomNotifier.ts +8 -11
- package/src/openApi.test.ts +1 -0
- package/src/openApi.ts +4 -4
- package/src/openApiBuilder.test.ts +1 -0
- package/src/openApiBuilder.ts +14 -11
- package/src/openApiValidator.test.ts +1 -0
- package/src/openApiValidator.ts +3 -2
- package/src/permissions.middleware.test.ts +1 -0
- package/src/permissions.test.ts +1 -0
- package/src/permissions.ts +30 -25
- package/src/plugins.test.ts +1 -1
- package/src/plugins.ts +21 -14
- package/src/populate.test.ts +1 -0
- package/src/populate.ts +44 -36
- package/src/realtime/changeStreamWatcher.ts +572 -0
- package/src/realtime/index.ts +34 -0
- package/src/realtime/queryMatcher.ts +179 -0
- package/src/realtime/queryStore.ts +132 -0
- package/src/realtime/realtime.test.ts +2465 -0
- package/src/realtime/realtimeApp.ts +478 -0
- package/src/realtime/registry.ts +64 -0
- package/src/realtime/socketUser.ts +25 -0
- package/src/realtime/types.ts +112 -0
- package/src/requestContext.test.ts +321 -0
- package/src/requestContext.ts +368 -0
- package/src/terrenoApp.test.ts +137 -11
- package/src/terrenoApp.ts +64 -17
- package/src/terrenoPlugin.ts +12 -0
- package/src/tests/bunSetup.ts +1 -0
- package/src/tests.ts +7 -2
- package/src/transformers.test.ts +70 -2
- package/src/transformers.ts +15 -7
- package/src/types/consentResponse.ts +8 -10
- 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:
|
|
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: () =>
|
|
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.
|
package/dist/betterAuthSetup.js
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
|
|
146
|
-
|
|
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
|
-
|
|
152
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
183
|
-
|
|
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
|
|
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");
|
package/dist/config.d.ts
ADDED
|
@@ -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;
|