@terreno/api 0.0.18 → 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.
- package/README.md +73 -3
- package/dist/api.d.ts +96 -3
- package/dist/api.js +159 -11
- package/dist/api.test.js +906 -2
- package/dist/auth.js +3 -1
- package/dist/betterAuth.d.ts +91 -0
- package/dist/betterAuth.js +8 -0
- package/dist/betterAuth.test.d.ts +1 -0
- package/dist/betterAuth.test.js +181 -0
- package/dist/betterAuthApp.d.ts +22 -0
- package/dist/betterAuthApp.js +38 -0
- package/dist/betterAuthApp.test.d.ts +1 -0
- package/dist/betterAuthApp.test.js +242 -0
- package/dist/betterAuthSetup.d.ts +60 -0
- package/dist/betterAuthSetup.js +278 -0
- package/dist/betterAuthSetup.test.d.ts +1 -0
- package/dist/betterAuthSetup.test.js +684 -0
- package/dist/errors.js +14 -11
- package/dist/example.js +7 -7
- package/dist/expressServer.js +2 -2
- package/dist/githubAuth.test.js +3 -3
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/openApi.test.js +8 -5
- package/dist/openApiBuilder.d.ts +69 -1
- package/dist/openApiBuilder.js +109 -5
- package/dist/openApiValidator.d.ts +296 -0
- package/dist/openApiValidator.js +698 -0
- package/dist/openApiValidator.test.d.ts +1 -0
- package/dist/openApiValidator.test.js +346 -0
- package/dist/plugins.test.js +3 -3
- package/dist/terrenoApp.d.ts +189 -0
- package/dist/terrenoApp.js +352 -0
- package/dist/terrenoApp.test.d.ts +1 -0
- package/dist/terrenoApp.test.js +264 -0
- package/dist/terrenoPlugin.d.ts +38 -0
- package/dist/terrenoPlugin.js +2 -0
- package/dist/tests.js +34 -24
- package/package.json +8 -2
- package/src/__snapshots__/openApi.test.ts.snap +399 -0
- package/src/__snapshots__/openApiBuilder.test.ts.snap +108 -0
- package/src/api.test.ts +743 -2
- package/src/api.ts +270 -6
- package/src/auth.ts +3 -1
- package/src/betterAuth.test.ts +160 -0
- package/src/betterAuth.ts +104 -0
- package/src/betterAuthApp.test.ts +114 -0
- package/src/betterAuthApp.ts +60 -0
- package/src/betterAuthSetup.test.ts +485 -0
- package/src/betterAuthSetup.ts +251 -0
- package/src/errors.ts +14 -11
- package/src/example.ts +7 -7
- package/src/expressServer.ts +4 -5
- package/src/githubAuth.test.ts +3 -3
- package/src/index.ts +6 -0
- package/src/openApi.test.ts +8 -5
- package/src/openApiBuilder.ts +188 -15
- package/src/openApiValidator.test.ts +241 -0
- package/src/openApiValidator.ts +860 -0
- package/src/plugins.test.ts +3 -3
- package/src/terrenoApp.test.ts +201 -0
- package/src/terrenoApp.ts +347 -0
- package/src/terrenoPlugin.ts +39 -0
- package/src/tests.ts +34 -24
- package/.cursorrules +0 -107
- package/.windsurfrules +0 -107
- package/AGENTS.md +0 -313
- package/dist/response.d.ts +0 -0
- package/dist/response.js +0 -1
- package/index.ts +0 -1
- package/src/response.ts +0 -0
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Better Auth setup and initialization for @terreno/api.
|
|
4
|
+
*
|
|
5
|
+
* This module provides functions to initialize Better Auth with MongoDB,
|
|
6
|
+
* create session middleware, and sync users with the application User model.
|
|
7
|
+
*/
|
|
8
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
9
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
10
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
11
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
12
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
13
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
14
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
15
|
+
});
|
|
16
|
+
};
|
|
17
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
18
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
19
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
20
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
21
|
+
function step(op) {
|
|
22
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
23
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
24
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
25
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
26
|
+
switch (op[0]) {
|
|
27
|
+
case 0: case 1: t = op; break;
|
|
28
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
29
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
30
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
31
|
+
default:
|
|
32
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
33
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
34
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
35
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
36
|
+
if (t[2]) _.ops.pop();
|
|
37
|
+
_.trys.pop(); continue;
|
|
38
|
+
}
|
|
39
|
+
op = body.call(thisArg, _);
|
|
40
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
41
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.hasBetterAuthSession = exports.getBetterAuthSession = exports.setupBetterAuthUserSync = exports.getMongoClientFromMongoose = exports.mountBetterAuthRoutes = exports.syncBetterAuthUser = exports.createBetterAuthSessionMiddleware = exports.createBetterAuth = void 0;
|
|
49
|
+
var better_auth_1 = require("better-auth");
|
|
50
|
+
var mongodb_1 = require("better-auth/adapters/mongodb");
|
|
51
|
+
var node_1 = require("better-auth/node");
|
|
52
|
+
var mongoose_1 = __importDefault(require("mongoose"));
|
|
53
|
+
var logger_1 = require("./logger");
|
|
54
|
+
/**
|
|
55
|
+
* Creates a Better Auth instance with MongoDB adapter.
|
|
56
|
+
*/
|
|
57
|
+
var createBetterAuth = function (options) {
|
|
58
|
+
var _a, _b;
|
|
59
|
+
var config = options.config, mongoClient = options.mongoClient;
|
|
60
|
+
var secret = config.secret || process.env.BETTER_AUTH_SECRET;
|
|
61
|
+
if (!secret) {
|
|
62
|
+
throw new Error("BETTER_AUTH_SECRET must be set in env or config.secret must be provided.");
|
|
63
|
+
}
|
|
64
|
+
var baseURL = config.baseURL || process.env.BETTER_AUTH_URL;
|
|
65
|
+
if (!baseURL) {
|
|
66
|
+
throw new Error("BETTER_AUTH_URL must be set in env or config.baseURL must be provided.");
|
|
67
|
+
}
|
|
68
|
+
var basePath = (_a = config.basePath) !== null && _a !== void 0 ? _a : "/api/auth";
|
|
69
|
+
var socialProviders = {};
|
|
70
|
+
if (config.googleOAuth) {
|
|
71
|
+
socialProviders.google = {
|
|
72
|
+
clientId: config.googleOAuth.clientId,
|
|
73
|
+
clientSecret: config.googleOAuth.clientSecret,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (config.appleOAuth) {
|
|
77
|
+
socialProviders.apple = {
|
|
78
|
+
clientId: config.appleOAuth.clientId,
|
|
79
|
+
clientSecret: config.appleOAuth.clientSecret,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
if (config.githubOAuth) {
|
|
83
|
+
socialProviders.github = {
|
|
84
|
+
clientId: config.githubOAuth.clientId,
|
|
85
|
+
clientSecret: config.githubOAuth.clientSecret,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
var auth = (0, better_auth_1.betterAuth)({
|
|
89
|
+
basePath: basePath,
|
|
90
|
+
baseURL: baseURL,
|
|
91
|
+
database: (0, mongodb_1.mongodbAdapter)(mongoClient.db()),
|
|
92
|
+
emailAndPassword: {
|
|
93
|
+
enabled: true,
|
|
94
|
+
},
|
|
95
|
+
secret: secret,
|
|
96
|
+
session: {
|
|
97
|
+
cookieCache: {
|
|
98
|
+
enabled: true,
|
|
99
|
+
maxAge: 5 * 60, // 5 minutes
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
socialProviders: Object.keys(socialProviders).length > 0 ? socialProviders : undefined,
|
|
103
|
+
trustedOrigins: (_b = config.trustedOrigins) !== null && _b !== void 0 ? _b : [],
|
|
104
|
+
});
|
|
105
|
+
return auth;
|
|
106
|
+
};
|
|
107
|
+
exports.createBetterAuth = createBetterAuth;
|
|
108
|
+
/**
|
|
109
|
+
* Creates Express middleware that extracts the Better Auth session
|
|
110
|
+
* and populates req.user with the application User model.
|
|
111
|
+
*/
|
|
112
|
+
var createBetterAuthSessionMiddleware = function (auth, userModel) {
|
|
113
|
+
return function (req, _res, next) { return __awaiter(void 0, void 0, void 0, function () {
|
|
114
|
+
var session, betterAuthUser, appUser, newUser, error_1;
|
|
115
|
+
return __generator(this, function (_a) {
|
|
116
|
+
switch (_a.label) {
|
|
117
|
+
case 0:
|
|
118
|
+
_a.trys.push([0, 8, , 9]);
|
|
119
|
+
return [4 /*yield*/, auth.api.getSession({
|
|
120
|
+
headers: req.headers,
|
|
121
|
+
})];
|
|
122
|
+
case 1:
|
|
123
|
+
session = _a.sent();
|
|
124
|
+
if (!((session === null || session === void 0 ? void 0 : session.user) && (session === null || session === void 0 ? void 0 : session.session))) return [3 /*break*/, 7];
|
|
125
|
+
betterAuthUser = session.user;
|
|
126
|
+
if (!userModel) return [3 /*break*/, 6];
|
|
127
|
+
return [4 /*yield*/, userModel.findOne({ betterAuthId: betterAuthUser.id })];
|
|
128
|
+
case 2:
|
|
129
|
+
appUser = _a.sent();
|
|
130
|
+
if (!appUser) return [3 /*break*/, 3];
|
|
131
|
+
req.user = appUser;
|
|
132
|
+
req.betterAuthSession = session;
|
|
133
|
+
return [3 /*break*/, 5];
|
|
134
|
+
case 3: return [4 /*yield*/, (0, exports.syncBetterAuthUser)(userModel, betterAuthUser)];
|
|
135
|
+
case 4:
|
|
136
|
+
newUser = _a.sent();
|
|
137
|
+
req.user = newUser;
|
|
138
|
+
req.betterAuthSession = session;
|
|
139
|
+
_a.label = 5;
|
|
140
|
+
case 5: return [3 /*break*/, 7];
|
|
141
|
+
case 6:
|
|
142
|
+
// No user model - just attach the Better Auth user directly
|
|
143
|
+
req.user = {
|
|
144
|
+
_id: betterAuthUser.id,
|
|
145
|
+
admin: false,
|
|
146
|
+
betterAuthId: betterAuthUser.id,
|
|
147
|
+
email: betterAuthUser.email,
|
|
148
|
+
id: betterAuthUser.id,
|
|
149
|
+
name: betterAuthUser.name,
|
|
150
|
+
};
|
|
151
|
+
req.betterAuthSession = session;
|
|
152
|
+
_a.label = 7;
|
|
153
|
+
case 7:
|
|
154
|
+
next();
|
|
155
|
+
return [3 /*break*/, 9];
|
|
156
|
+
case 8:
|
|
157
|
+
error_1 = _a.sent();
|
|
158
|
+
logger_1.logger.debug("Better Auth session extraction error: ".concat(error_1));
|
|
159
|
+
next();
|
|
160
|
+
return [3 /*break*/, 9];
|
|
161
|
+
case 9: return [2 /*return*/];
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}); };
|
|
165
|
+
};
|
|
166
|
+
exports.createBetterAuthSessionMiddleware = createBetterAuthSessionMiddleware;
|
|
167
|
+
/**
|
|
168
|
+
* Syncs a Better Auth user to the application User model.
|
|
169
|
+
* Creates or updates the user as needed.
|
|
170
|
+
*/
|
|
171
|
+
var syncBetterAuthUser = function (userModel, betterAuthUser, oauthProvider) { return __awaiter(void 0, void 0, void 0, function () {
|
|
172
|
+
var existingUser, userByEmail, newUser, error_2;
|
|
173
|
+
return __generator(this, function (_a) {
|
|
174
|
+
switch (_a.label) {
|
|
175
|
+
case 0:
|
|
176
|
+
_a.trys.push([0, 8, , 9]);
|
|
177
|
+
return [4 /*yield*/, userModel.findOne({ betterAuthId: betterAuthUser.id })];
|
|
178
|
+
case 1:
|
|
179
|
+
existingUser = _a.sent();
|
|
180
|
+
if (!existingUser) return [3 /*break*/, 3];
|
|
181
|
+
// Update existing user if needed
|
|
182
|
+
existingUser.email = betterAuthUser.email;
|
|
183
|
+
if (betterAuthUser.name) {
|
|
184
|
+
existingUser.name = betterAuthUser.name;
|
|
185
|
+
}
|
|
186
|
+
return [4 /*yield*/, existingUser.save()];
|
|
187
|
+
case 2:
|
|
188
|
+
_a.sent();
|
|
189
|
+
return [2 /*return*/, existingUser];
|
|
190
|
+
case 3: return [4 /*yield*/, userModel.findOne({ email: betterAuthUser.email })];
|
|
191
|
+
case 4:
|
|
192
|
+
userByEmail = _a.sent();
|
|
193
|
+
if (!userByEmail) return [3 /*break*/, 6];
|
|
194
|
+
// Link existing user to Better Auth
|
|
195
|
+
userByEmail.betterAuthId = betterAuthUser.id;
|
|
196
|
+
if (oauthProvider) {
|
|
197
|
+
userByEmail.oauthProvider = oauthProvider;
|
|
198
|
+
}
|
|
199
|
+
return [4 /*yield*/, userByEmail.save()];
|
|
200
|
+
case 5:
|
|
201
|
+
_a.sent();
|
|
202
|
+
return [2 /*return*/, userByEmail];
|
|
203
|
+
case 6:
|
|
204
|
+
newUser = new userModel({
|
|
205
|
+
admin: false,
|
|
206
|
+
betterAuthId: betterAuthUser.id,
|
|
207
|
+
email: betterAuthUser.email,
|
|
208
|
+
name: betterAuthUser.name || betterAuthUser.email.split("@")[0],
|
|
209
|
+
oauthProvider: oauthProvider || null,
|
|
210
|
+
});
|
|
211
|
+
return [4 /*yield*/, newUser.save()];
|
|
212
|
+
case 7:
|
|
213
|
+
_a.sent();
|
|
214
|
+
logger_1.logger.info("Created new user from Better Auth: ".concat(newUser.id));
|
|
215
|
+
return [2 /*return*/, newUser];
|
|
216
|
+
case 8:
|
|
217
|
+
error_2 = _a.sent();
|
|
218
|
+
logger_1.logger.error("Error syncing Better Auth user: ".concat(error_2));
|
|
219
|
+
throw error_2;
|
|
220
|
+
case 9: return [2 /*return*/];
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
}); };
|
|
224
|
+
exports.syncBetterAuthUser = syncBetterAuthUser;
|
|
225
|
+
/**
|
|
226
|
+
* Mounts Better Auth routes on the Express app.
|
|
227
|
+
*/
|
|
228
|
+
var mountBetterAuthRoutes = function (app, auth, basePath) {
|
|
229
|
+
if (basePath === void 0) { basePath = "/api/auth"; }
|
|
230
|
+
var handler = (0, node_1.toNodeHandler)(auth);
|
|
231
|
+
// Mount at the base path with wildcard
|
|
232
|
+
app.all("".concat(basePath, "/*"), function (req, res) {
|
|
233
|
+
return handler(req, res);
|
|
234
|
+
});
|
|
235
|
+
logger_1.logger.info("Better Auth routes mounted at ".concat(basePath, "/*"));
|
|
236
|
+
};
|
|
237
|
+
exports.mountBetterAuthRoutes = mountBetterAuthRoutes;
|
|
238
|
+
/**
|
|
239
|
+
* Gets the MongoDB client from the mongoose connection.
|
|
240
|
+
*/
|
|
241
|
+
var getMongoClientFromMongoose = function () {
|
|
242
|
+
var connection = mongoose_1.default.connection;
|
|
243
|
+
var client = connection.client;
|
|
244
|
+
if (!client) {
|
|
245
|
+
throw new Error("Mongoose is not connected. Ensure MongoDB connection is established first.");
|
|
246
|
+
}
|
|
247
|
+
return client;
|
|
248
|
+
};
|
|
249
|
+
exports.getMongoClientFromMongoose = getMongoClientFromMongoose;
|
|
250
|
+
/**
|
|
251
|
+
* Sets up Better Auth user sync hooks.
|
|
252
|
+
* This ensures users created/updated in Better Auth are synced to the application User model.
|
|
253
|
+
*
|
|
254
|
+
* Note: Better Auth doesn't have built-in event hooks, so we rely on the session middleware
|
|
255
|
+
* to create users on first session access.
|
|
256
|
+
*/
|
|
257
|
+
var setupBetterAuthUserSync = function (_auth, _userModel) {
|
|
258
|
+
// Better Auth v1.x doesn't expose event hooks for user creation.
|
|
259
|
+
// User sync is handled in createBetterAuthSessionMiddleware when a session is accessed.
|
|
260
|
+
// This function is a placeholder for future versions that may support hooks.
|
|
261
|
+
logger_1.logger.debug("Better Auth user sync configured (via session middleware)");
|
|
262
|
+
};
|
|
263
|
+
exports.setupBetterAuthUserSync = setupBetterAuthUserSync;
|
|
264
|
+
/**
|
|
265
|
+
* Extracts Better Auth session data from the request.
|
|
266
|
+
*/
|
|
267
|
+
var getBetterAuthSession = function (req) {
|
|
268
|
+
var _a;
|
|
269
|
+
return (_a = req.betterAuthSession) !== null && _a !== void 0 ? _a : null;
|
|
270
|
+
};
|
|
271
|
+
exports.getBetterAuthSession = getBetterAuthSession;
|
|
272
|
+
/**
|
|
273
|
+
* Checks if the request has a valid Better Auth session.
|
|
274
|
+
*/
|
|
275
|
+
var hasBetterAuthSession = function (req) {
|
|
276
|
+
return Boolean(req.betterAuthSession);
|
|
277
|
+
};
|
|
278
|
+
exports.hasBetterAuthSession = hasBetterAuthSession;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|