nestjs-slightly-better-auth 1.0.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/LICENSE +7 -0
- package/README.md +57 -0
- package/dist/admin.cjs +88 -0
- package/dist/admin.cjs.map +1 -0
- package/dist/admin.d.cts +14 -0
- package/dist/admin.d.cts.map +1 -0
- package/dist/admin.d.mts +14 -0
- package/dist/admin.d.mts.map +1 -0
- package/dist/admin.mjs +85 -0
- package/dist/admin.mjs.map +1 -0
- package/dist/api-key.cjs +163 -0
- package/dist/api-key.cjs.map +1 -0
- package/dist/api-key.d.cts +42 -0
- package/dist/api-key.d.cts.map +1 -0
- package/dist/api-key.d.mts +42 -0
- package/dist/api-key.d.mts.map +1 -0
- package/dist/api-key.mjs +159 -0
- package/dist/api-key.mjs.map +1 -0
- package/dist/auth-contracts-BBA1C1gj.d.cts +1635 -0
- package/dist/auth-contracts-BBA1C1gj.d.cts.map +1 -0
- package/dist/auth-contracts-tqsfBZ8B.d.mts +1635 -0
- package/dist/auth-contracts-tqsfBZ8B.d.mts.map +1 -0
- package/dist/auth-decorators-CwW5JY4y.cjs +1274 -0
- package/dist/auth-decorators-CwW5JY4y.cjs.map +1 -0
- package/dist/auth-decorators-DfAJbHar.mjs +849 -0
- package/dist/auth-decorators-DfAJbHar.mjs.map +1 -0
- package/dist/auth-errors-CQjfgjaO.mjs +283 -0
- package/dist/auth-errors-CQjfgjaO.mjs.map +1 -0
- package/dist/auth-errors-CsERBNWI.cjs +348 -0
- package/dist/auth-errors-CsERBNWI.cjs.map +1 -0
- package/dist/express.cjs +247 -0
- package/dist/express.cjs.map +1 -0
- package/dist/express.d.cts +37 -0
- package/dist/express.d.cts.map +1 -0
- package/dist/express.d.mts +37 -0
- package/dist/express.d.mts.map +1 -0
- package/dist/express.mjs +245 -0
- package/dist/express.mjs.map +1 -0
- package/dist/fastify.cjs +215 -0
- package/dist/fastify.cjs.map +1 -0
- package/dist/fastify.d.cts +28 -0
- package/dist/fastify.d.cts.map +1 -0
- package/dist/fastify.d.mts +28 -0
- package/dist/fastify.d.mts.map +1 -0
- package/dist/fastify.mjs +213 -0
- package/dist/fastify.mjs.map +1 -0
- package/dist/index.cjs +2634 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +2556 -0
- package/dist/index.mjs.map +1 -0
- package/dist/organization.cjs +191 -0
- package/dist/organization.cjs.map +1 -0
- package/dist/organization.d.cts +40 -0
- package/dist/organization.d.cts.map +1 -0
- package/dist/organization.d.mts +40 -0
- package/dist/organization.d.mts.map +1 -0
- package/dist/organization.mjs +177 -0
- package/dist/organization.mjs.map +1 -0
- package/dist/platform.cjs +393 -0
- package/dist/platform.cjs.map +1 -0
- package/dist/platform.d.cts +43 -0
- package/dist/platform.d.cts.map +1 -0
- package/dist/platform.d.mts +43 -0
- package/dist/platform.d.mts.map +1 -0
- package/dist/platform.mjs +385 -0
- package/dist/platform.mjs.map +1 -0
- package/dist/plugin.cjs +312 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +26 -0
- package/dist/plugin.d.cts.map +1 -0
- package/dist/plugin.d.mts +26 -0
- package/dist/plugin.d.mts.map +1 -0
- package/dist/plugin.mjs +310 -0
- package/dist/plugin.mjs.map +1 -0
- package/package.json +186 -0
package/dist/plugin.cjs
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let better_auth_api = require("better-auth/api");
|
|
3
|
+
let better_auth_cookies = require("better-auth/cookies");
|
|
4
|
+
let defu = require("defu");
|
|
5
|
+
//#region src/bridge-protocol.ts
|
|
6
|
+
const BRIDGE_HANDLE = Symbol.for("nestjs-slightly-better-auth:bridge");
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/database-hook-dispatcher.ts
|
|
9
|
+
/** Construct all dispatchers once; bindings supply only the late-bound methods. */
|
|
10
|
+
function createDatabaseDispatchers(getBinding, countUnbound) {
|
|
11
|
+
function operation(target) {
|
|
12
|
+
const before = async (...[data, ctx]) => {
|
|
13
|
+
const binding = getBinding();
|
|
14
|
+
if (!binding) {
|
|
15
|
+
countUnbound();
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
const hooks = binding.database[target].before;
|
|
19
|
+
let accumulated = {};
|
|
20
|
+
let changed = false;
|
|
21
|
+
for (const hook of hooks) {
|
|
22
|
+
const result = await hook(target.endsWith(".create") ? {
|
|
23
|
+
...data,
|
|
24
|
+
...accumulated
|
|
25
|
+
} : data, ctx);
|
|
26
|
+
if (result === false) return false;
|
|
27
|
+
if (!target.endsWith(".delete") && result && typeof result === "object" && "data" in result) {
|
|
28
|
+
accumulated = {
|
|
29
|
+
...accumulated,
|
|
30
|
+
...result.data
|
|
31
|
+
};
|
|
32
|
+
changed = true;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return changed ? { data: accumulated } : void 0;
|
|
36
|
+
};
|
|
37
|
+
const after = async (...[data, ctx]) => {
|
|
38
|
+
const binding = getBinding();
|
|
39
|
+
if (!binding) {
|
|
40
|
+
countUnbound();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
for (const hook of binding.database[target].after) await hook(data, ctx);
|
|
44
|
+
};
|
|
45
|
+
return {
|
|
46
|
+
before,
|
|
47
|
+
after
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
user: {
|
|
52
|
+
create: operation("user.create"),
|
|
53
|
+
update: operation("user.update"),
|
|
54
|
+
delete: operation("user.delete")
|
|
55
|
+
},
|
|
56
|
+
session: {
|
|
57
|
+
create: operation("session.create"),
|
|
58
|
+
update: operation("session.update"),
|
|
59
|
+
delete: operation("session.delete")
|
|
60
|
+
},
|
|
61
|
+
account: {
|
|
62
|
+
create: operation("account.create"),
|
|
63
|
+
update: operation("account.update"),
|
|
64
|
+
delete: operation("account.delete")
|
|
65
|
+
},
|
|
66
|
+
verification: {
|
|
67
|
+
create: operation("verification.create"),
|
|
68
|
+
update: operation("verification.update"),
|
|
69
|
+
delete: operation("verification.delete")
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/hook-dispatcher.ts
|
|
75
|
+
const API_ERROR_HEADERS = Symbol.for("better-call:api-error-headers");
|
|
76
|
+
const mergeContext = (0, defu.createDefu)((object, key, value) => {
|
|
77
|
+
if (Array.isArray(object[key]) && Array.isArray(value)) {
|
|
78
|
+
object[key] = value;
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
function mergeHeaders(target, source) {
|
|
83
|
+
source?.forEach((value, key) => {
|
|
84
|
+
if (key === "set-cookie") target.append(key, value);
|
|
85
|
+
else target.set(key, value);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
function errorHeaders(error) {
|
|
89
|
+
const attached = error[API_ERROR_HEADERS];
|
|
90
|
+
if (!attached && !error.headers) return;
|
|
91
|
+
const headers = new Headers(attached);
|
|
92
|
+
if (error.headers && error.headers !== attached) mergeHeaders(headers, new Headers(error.headers));
|
|
93
|
+
return headers;
|
|
94
|
+
}
|
|
95
|
+
/** Run each method through the SDK middleware so its cookie/header state is isolated. */
|
|
96
|
+
async function runBefore(binding, ctx, scope) {
|
|
97
|
+
let accumulated = {};
|
|
98
|
+
for (const hook of binding.before) {
|
|
99
|
+
let matched;
|
|
100
|
+
try {
|
|
101
|
+
matched = hook.matches(ctx, scope);
|
|
102
|
+
} catch (error) {
|
|
103
|
+
ctx.context.logger.error("An error occurred during Nest hook matcher execution:", error);
|
|
104
|
+
throw new better_auth_api.APIError("INTERNAL_SERVER_ERROR", { message: "An error occurred during hook matcher execution. Check the logs for more details." });
|
|
105
|
+
}
|
|
106
|
+
if (!matched) continue;
|
|
107
|
+
let result;
|
|
108
|
+
try {
|
|
109
|
+
result = await (0, better_auth_api.createAuthMiddleware)(hook.run)({
|
|
110
|
+
...ctx,
|
|
111
|
+
returnHeaders: true
|
|
112
|
+
});
|
|
113
|
+
} catch (error) {
|
|
114
|
+
if ((0, better_auth_api.isAPIError)(error)) ctx.responseHeaders = error[API_ERROR_HEADERS] ?? new Headers();
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
ctx.context.responseHeaders ??= new Headers();
|
|
118
|
+
mergeHeaders(ctx.context.responseHeaders, result.headers);
|
|
119
|
+
const value = result.response;
|
|
120
|
+
if (value && typeof value === "object") {
|
|
121
|
+
if ("context" in value && typeof value.context === "object") {
|
|
122
|
+
const { headers, ...rest } = value.context;
|
|
123
|
+
if (headers instanceof Headers) {
|
|
124
|
+
const requestHeaders = accumulated.headers instanceof Headers ? accumulated.headers : new Headers();
|
|
125
|
+
headers.forEach((header, key) => {
|
|
126
|
+
requestHeaders.set(key, header);
|
|
127
|
+
});
|
|
128
|
+
accumulated.headers = requestHeaders;
|
|
129
|
+
}
|
|
130
|
+
accumulated = mergeContext(rest, accumulated);
|
|
131
|
+
} else return value;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return Object.keys(accumulated).length ? { context: accumulated } : void 0;
|
|
135
|
+
}
|
|
136
|
+
async function runAfter(binding, ctx, scope, relayMatcherError) {
|
|
137
|
+
for (const hook of binding.after) {
|
|
138
|
+
let matched;
|
|
139
|
+
try {
|
|
140
|
+
matched = hook.matches(ctx, scope);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
if (!relayMatcherError) throw error;
|
|
143
|
+
relayMatcherError(error);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (!matched) continue;
|
|
147
|
+
let result;
|
|
148
|
+
try {
|
|
149
|
+
result = await (0, better_auth_api.createAuthMiddleware)(hook.run)({
|
|
150
|
+
...ctx,
|
|
151
|
+
returnHeaders: true
|
|
152
|
+
});
|
|
153
|
+
} catch (error) {
|
|
154
|
+
if (!(0, better_auth_api.isAPIError)(error)) throw error;
|
|
155
|
+
result = {
|
|
156
|
+
response: error,
|
|
157
|
+
headers: errorHeaders(error)
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
if (result.headers) {
|
|
161
|
+
ctx.context.responseHeaders ??= new Headers();
|
|
162
|
+
mergeHeaders(ctx.context.responseHeaders, result.headers);
|
|
163
|
+
}
|
|
164
|
+
if (result.response !== void 0) ctx.context.returned = result.response;
|
|
165
|
+
}
|
|
166
|
+
return ctx.context.returned;
|
|
167
|
+
}
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/plugin.ts
|
|
170
|
+
const NESTJS_PLUGIN_ID = "nestjs-slightly-better-auth";
|
|
171
|
+
const isRouter = (ctx) => "_flag" in ctx && ctx._flag === "router";
|
|
172
|
+
const separator = "\0";
|
|
173
|
+
function sessionToken(headers, ctx) {
|
|
174
|
+
return (0, better_auth_cookies.parseCookies)(headers?.get("cookie") ?? "").get(ctx.context.authCookies.sessionToken.name) ?? "";
|
|
175
|
+
}
|
|
176
|
+
function credential(headers, ctx, extra) {
|
|
177
|
+
return [
|
|
178
|
+
sessionToken(headers, ctx),
|
|
179
|
+
headers?.get("authorization") ?? "",
|
|
180
|
+
...extra.map((name) => headers?.get(name) ?? "")
|
|
181
|
+
].join(separator);
|
|
182
|
+
}
|
|
183
|
+
function sameCredential(ctx, scope, extra) {
|
|
184
|
+
const call = credential(ctx.headers, ctx, extra);
|
|
185
|
+
return call === separator.repeat(extra.length + 1) || call === credential(scope.inbound?.(), ctx, extra);
|
|
186
|
+
}
|
|
187
|
+
/** Pure construction-time Better Auth plugin; the Nest kernel binds through a global symbol. */
|
|
188
|
+
function nestjs(options = {}) {
|
|
189
|
+
let binding = null;
|
|
190
|
+
let registration;
|
|
191
|
+
let unboundDispatches = 0;
|
|
192
|
+
const endpointResults = /* @__PURE__ */ new WeakSet();
|
|
193
|
+
const afterMatcherErrors = /* @__PURE__ */ new WeakMap();
|
|
194
|
+
const scope = () => binding?.current();
|
|
195
|
+
const clientIpHeader = options.clientIpHeader === false ? null : options.clientIpHeader ?? `x-nsba-ip-${globalThis.crypto.randomUUID().replaceAll("-", "")}`;
|
|
196
|
+
const handle = {
|
|
197
|
+
protocol: 4,
|
|
198
|
+
clientIpHeader,
|
|
199
|
+
get state() {
|
|
200
|
+
return binding === null ? "unbound" : binding.state === "closed" ? "closed" : "bound";
|
|
201
|
+
},
|
|
202
|
+
get unboundDispatches() {
|
|
203
|
+
return unboundDispatches;
|
|
204
|
+
},
|
|
205
|
+
bind(next) {
|
|
206
|
+
if (binding && binding.instance !== next.instance) throw new Error(`PLUGIN_SHARED_BETWEEN_INSTANCES: '${binding.instance}' and '${next.instance}'`);
|
|
207
|
+
if (binding?.owner === next.owner && registration) return registration;
|
|
208
|
+
if (binding?.state === "bootstrapped") throw new Error(`INSTANCE_ALREADY_BOUND: bound to ${binding.owner.description}`);
|
|
209
|
+
const tookOverFrom = binding?.state === "initialized" ? binding.owner.description : void 0;
|
|
210
|
+
binding = next;
|
|
211
|
+
unboundDispatches = 0;
|
|
212
|
+
registration = {
|
|
213
|
+
tookOverFrom,
|
|
214
|
+
close: () => {
|
|
215
|
+
next.state = "closed";
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
return registration;
|
|
219
|
+
},
|
|
220
|
+
producedByEndpoint(value) {
|
|
221
|
+
return typeof value === "object" && value !== null && endpointResults.has(value);
|
|
222
|
+
}
|
|
223
|
+
};
|
|
224
|
+
return {
|
|
225
|
+
id: NESTJS_PLUGIN_ID,
|
|
226
|
+
[BRIDGE_HANDLE]: handle,
|
|
227
|
+
init: () => ({ options: {
|
|
228
|
+
databaseHooks: createDatabaseDispatchers(() => binding, () => {
|
|
229
|
+
unboundDispatches++;
|
|
230
|
+
}),
|
|
231
|
+
...clientIpHeader ? { advanced: { ipAddress: { ipAddressHeaders: [clientIpHeader] } } } : {}
|
|
232
|
+
} }),
|
|
233
|
+
hooks: {
|
|
234
|
+
before: [
|
|
235
|
+
{
|
|
236
|
+
matcher: (ctx) => {
|
|
237
|
+
if (!binding) {
|
|
238
|
+
unboundDispatches++;
|
|
239
|
+
return false;
|
|
240
|
+
}
|
|
241
|
+
return !isRouter(ctx) && scope()?.cookies === null;
|
|
242
|
+
},
|
|
243
|
+
handler: (0, better_auth_api.createAuthMiddleware)(async () => {
|
|
244
|
+
await (0, better_auth_api.setShouldSkipSessionRefresh)(true);
|
|
245
|
+
})
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
matcher: (ctx) => {
|
|
249
|
+
if (!binding || isRouter(ctx)) return false;
|
|
250
|
+
const current = scope();
|
|
251
|
+
if (!current || current.internal) return false;
|
|
252
|
+
const check = current.checkCallerSession;
|
|
253
|
+
const inbound = current.inbound?.();
|
|
254
|
+
const browser = current.browserHeaders?.();
|
|
255
|
+
const token = sessionToken(ctx.headers, ctx);
|
|
256
|
+
return !!check && token !== "" && (token === sessionToken(inbound, ctx) || token === sessionToken(browser, ctx));
|
|
257
|
+
},
|
|
258
|
+
handler: (0, better_auth_api.createAuthMiddleware)(async (ctx) => {
|
|
259
|
+
scope()?.checkCallerSession?.(ctx.path, binding.instance);
|
|
260
|
+
})
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
matcher: () => binding !== null && binding.before.length > 0,
|
|
264
|
+
handler: (0, better_auth_api.createAuthMiddleware)((ctx) => runBefore(binding, ctx, scope()))
|
|
265
|
+
}
|
|
266
|
+
],
|
|
267
|
+
after: [
|
|
268
|
+
{
|
|
269
|
+
matcher: () => binding !== null && binding.after.length > 0,
|
|
270
|
+
handler: (0, better_auth_api.createAuthMiddleware)((ctx) => runAfter(binding, ctx, scope(), (error) => {
|
|
271
|
+
afterMatcherErrors.set(ctx.context, error);
|
|
272
|
+
}))
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
matcher: (ctx) => {
|
|
276
|
+
if (afterMatcherErrors.has(ctx.context)) {
|
|
277
|
+
const error = afterMatcherErrors.get(ctx.context);
|
|
278
|
+
afterMatcherErrors.delete(ctx.context);
|
|
279
|
+
throw error;
|
|
280
|
+
}
|
|
281
|
+
return binding !== null && !isRouter(ctx);
|
|
282
|
+
},
|
|
283
|
+
handler: (0, better_auth_api.createAuthMiddleware)(async (ctx) => {
|
|
284
|
+
const value = ctx.context.returned;
|
|
285
|
+
if (typeof value === "object" && value !== null) endpointResults.add(value);
|
|
286
|
+
})
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
matcher: (ctx) => {
|
|
290
|
+
if (isRouter(ctx)) return false;
|
|
291
|
+
const current = scope();
|
|
292
|
+
return !!current?.cookies && current.forward !== "none";
|
|
293
|
+
},
|
|
294
|
+
handler: (0, better_auth_api.createAuthMiddleware)(async (ctx) => {
|
|
295
|
+
const current = scope();
|
|
296
|
+
if (current.forward === "same-credential" && !sameCredential(ctx, current, binding.credentialHeaders)) {
|
|
297
|
+
binding.onDropped(ctx.path);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
const cookies = ctx.context.responseHeaders?.getSetCookie() ?? [];
|
|
301
|
+
if (cookies.length) current.cookies.append(cookies);
|
|
302
|
+
})
|
|
303
|
+
}
|
|
304
|
+
]
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
//#endregion
|
|
309
|
+
exports.NESTJS_PLUGIN_ID = NESTJS_PLUGIN_ID;
|
|
310
|
+
exports.nestjs = nestjs;
|
|
311
|
+
|
|
312
|
+
//# sourceMappingURL=plugin.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.cjs","names":["createDefu","APIError","createAuthMiddleware","isAPIError","parseCookies","createAuthMiddleware","setShouldSkipSessionRefresh"],"sources":["../src/bridge-protocol.ts","../src/database-hook-dispatcher.ts","../src/hook-dispatcher.ts","../src/plugin.ts"],"sourcesContent":["import type { HookEndpointContext } from \"better-auth\";\nimport type { CookieSink, DatabaseHookTarget } from \"./auth-contracts.js\";\nimport type { DatabaseHookMethod } from \"./auth-types.js\";\n\nexport const BRIDGE_HANDLE = Symbol.for(\"nestjs-slightly-better-auth:bridge\");\nexport const EXTENSION_DEFINITION = Symbol.for(\n \"nestjs-slightly-better-auth:extension\",\n);\nexport const UPGRADE_REQUEST = Symbol.for(\n \"nestjs-slightly-better-auth:upgrade-request\",\n);\n\nexport interface BridgeHandle {\n readonly protocol: 4; // checked by core (B04); v5: binding state and instance, the caller-session check\n readonly clientIpHeader: string | null; // single source of truth for the header name (§6.8)\n /** 'unbound' until the first bind(); 'bound' while an application's hooks are registered; 'closed' after its shutdown, hooks still registered. */\n readonly state: \"unbound\" | \"bound\" | \"closed\";\n /** Endpoint dispatches and database-hook dispatches (writes) seen before the first binding, reset by every bind() (B26). */\n readonly unboundDispatches: number;\n /**\n * Registers the application's hooks and returns close(), which the kernel calls in onApplicationShutdown: a closed binding keeps\n * dispatching until another application binds (§10.6). A second bind() from the same owner for the same instance is a no-op that\n * returns the existing registration (NestMicroservice.init() runs lifecycle hooks twice); from the same owner for another instance it\n * throws PLUGIN_SHARED_BETWEEN_INSTANCES (B03). Throws INSTANCE_ALREADY_BOUND if another bootstrapped application is bound; takes over\n * a never-bootstrapped one (reported, B06) and a closed one (silently).\n */\n bind(binding: BridgeBinding): { close(): void; tookOverFrom?: string };\n /** true when an endpoint returned `value` (an object) in a non-router dispatch observed while bound; false for before-hook short-circuits (LEAD-V37). */\n producedByEndpoint(value: unknown): boolean;\n}\nexport interface BridgeBinding {\n /** The application: compared by identity for the same-owner no-op; `description` goes into the B06 message. */\n readonly owner: { readonly description: string };\n /** The instance this plugin object serves; one plugin object serves one instance (B03). */\n readonly instance: string;\n /** 'initialized' at bind; the kernel sets 'bootstrapped' in onApplicationBootstrap; close() sets 'closed'. */\n state: \"initialized\" | \"bootstrapped\" | \"closed\";\n /** View of the kernel's RequestScope; the plugin never owns an AsyncLocalStorage. [C] */\n current(): ScopeView | undefined;\n /** Credential header names declared by the instance's principal sources (credential matching, §7.5). */\n readonly credentialHeaders: readonly string[];\n readonly before: readonly CompiledHook[]; // sorted by order, then discovery order\n readonly after: readonly CompiledHook[];\n readonly database: Readonly<{\n [E in DatabaseHookTarget]: {\n readonly before: readonly DatabaseHookMethod<E, \"before\">[];\n readonly after: readonly DatabaseHookMethod<E, \"after\">[];\n };\n }>;\n /** Debug log when the bridge drops a direct call's cookies because its credential is foreign. */\n onDropped(path: string): void;\n}\nexport interface ScopeView {\n /** Cookie-capable forwarding handlers have already passed the enforcing form check on every method/operation (§7.10). */\n readonly cookies: CookieSink | null;\n readonly forward: \"none\" | \"same-credential\" | \"any\";\n readonly inbound: (() => Headers) | undefined;\n readonly internal: boolean;\n /**\n * Present in EVERY handler scope whose transport exposes a browser leg, unless the plan's origin check is 'off' — enforcing or not,\n * so safe methods and GraphQL queries are covered too (§7.5). Returns when this leg has a passing origin verdict for `instance`, or\n * the single kernel disable predicate (§7.10 item 4) holds; a guard run without a passing verdict is insufficient. Otherwise throws the kernel's\n * BetterAuthConfigurationError PUBLIC_HANDLER_USED_CALLER_SESSION.\n */\n readonly checkCallerSession?: (path: string, instance: string) => void;\n /** The browser leg's OWN headers (TransportCall.browser.headers()), before any transport credential mapping replaced them; undefined\n * when the transport exposes no browser leg. Entry 2 recognizes an ambiently carried session cookie with it. */\n readonly browserHeaders: (() => Headers) | undefined;\n}\nexport interface CompiledHook {\n /**\n * Evaluate the user predicate once and let it throw. The dispatcher logs and\n * converts before-hook matcher failures to APIError 500; after-hook matcher\n * failures cross the next fixed SDK matcher boundary unchanged, so the SDK\n * cannot recover them as handler APIErrors. Never swallow a failure as a\n * non-match or evaluate the predicate again in run().\n */\n matches(ctx: HookEndpointContext, scope: ScopeView | undefined): boolean;\n run(ctx: HookEndpointContext): Promise<unknown>;\n}\n","import type { BetterAuthOptions } from \"better-auth\";\nimport type { DatabaseHookTarget } from \"./auth-contracts.js\";\nimport type { DatabaseHookMethod, DatabaseHookResult } from \"./auth-types.js\";\nimport type { BridgeBinding } from \"./bridge-protocol.js\";\n\n/** Construct all dispatchers once; bindings supply only the late-bound methods. */\nexport function createDatabaseDispatchers(\n getBinding: () => BridgeBinding | null,\n countUnbound: () => void,\n): NonNullable<BetterAuthOptions[\"databaseHooks\"]> {\n function operation<E extends DatabaseHookTarget>(target: E) {\n const before = async (\n ...[data, ctx]: Parameters<DatabaseHookMethod<E, \"before\">>\n ): Promise<DatabaseHookResult<E, \"before\">> => {\n const binding = getBinding();\n if (!binding) {\n countUnbound();\n return undefined as DatabaseHookResult<E, \"before\">;\n }\n const hooks = binding.database[target].before;\n let accumulated: Record<string, unknown> = {};\n let changed = false;\n for (const hook of hooks) {\n const result = await hook(\n target.endsWith(\".create\") ? { ...data, ...accumulated } : data,\n ctx,\n );\n if (result === false) {\n return false as DatabaseHookResult<E, \"before\">;\n }\n if (\n !target.endsWith(\".delete\") &&\n result &&\n typeof result === \"object\" &&\n \"data\" in result\n ) {\n accumulated = { ...accumulated, ...result.data };\n changed = true;\n }\n }\n // A generic target cannot express the runtime delete narrowing. Delete\n // never reaches this branch; the public binding keeps its void/false type.\n return (\n changed ? { data: accumulated } : undefined\n ) as DatabaseHookResult<E, \"before\">;\n };\n const after = async (\n ...[data, ctx]: Parameters<DatabaseHookMethod<E, \"after\">>\n ): Promise<void> => {\n const binding = getBinding();\n if (!binding) {\n countUnbound();\n return;\n }\n for (const hook of binding.database[target].after) {\n await hook(data, ctx);\n }\n };\n return { before, after };\n }\n return {\n user: {\n create: operation(\"user.create\"),\n update: operation(\"user.update\"),\n delete: operation(\"user.delete\"),\n },\n session: {\n create: operation(\"session.create\"),\n update: operation(\"session.update\"),\n delete: operation(\"session.delete\"),\n },\n account: {\n create: operation(\"account.create\"),\n update: operation(\"account.update\"),\n delete: operation(\"account.delete\"),\n },\n verification: {\n create: operation(\"verification.create\"),\n update: operation(\"verification.update\"),\n delete: operation(\"verification.delete\"),\n },\n };\n}\n","import type { HookEndpointContext } from \"better-auth\";\nimport { APIError, createAuthMiddleware, isAPIError } from \"better-auth/api\";\nimport { createDefu } from \"defu\";\nimport type { BridgeBinding, ScopeView } from \"./bridge-protocol.js\";\n\nconst API_ERROR_HEADERS = Symbol.for(\"better-call:api-error-headers\");\nconst mergeContext = createDefu((object, key, value) => {\n if (Array.isArray(object[key]) && Array.isArray(value)) {\n object[key] = value;\n return true;\n }\n});\n\nfunction mergeHeaders(\n target: Headers,\n source: Headers | null | undefined,\n): void {\n source?.forEach((value, key) => {\n if (key === \"set-cookie\") {\n target.append(key, value);\n } else {\n target.set(key, value);\n }\n });\n}\n\nfunction errorHeaders(error: APIError): Headers | undefined {\n const attached = (error as unknown as Record<symbol, Headers | undefined>)[\n API_ERROR_HEADERS\n ];\n if (!attached && !error.headers) {\n return undefined;\n }\n const headers = new Headers(attached);\n if (error.headers && error.headers !== attached) {\n mergeHeaders(headers, new Headers(error.headers));\n }\n return headers;\n}\n\n/** Run each method through the SDK middleware so its cookie/header state is isolated. */\nexport async function runBefore(\n binding: BridgeBinding,\n ctx: HookEndpointContext,\n scope: ScopeView | undefined,\n): Promise<unknown> {\n let accumulated: Record<string, unknown> = {};\n for (const hook of binding.before) {\n let matched: boolean;\n try {\n matched = hook.matches(ctx, scope);\n } catch (error) {\n ctx.context.logger.error(\n \"An error occurred during Nest hook matcher execution:\",\n error,\n );\n throw new APIError(\"INTERNAL_SERVER_ERROR\", {\n message:\n \"An error occurred during hook matcher execution. Check the logs for more details.\",\n });\n }\n if (!matched) {\n continue;\n }\n let result: { response: unknown; headers: Headers };\n try {\n result = (await createAuthMiddleware(hook.run)({\n ...ctx,\n returnHeaders: true,\n })) as { response: unknown; headers: Headers };\n } catch (error) {\n if (isAPIError(error)) {\n // The enclosing SDK middleware reattaches its own header object. Keep\n // the throwing method's headers, including non-enumerable cookie state.\n ctx.responseHeaders =\n (error as unknown as Record<symbol, Headers | undefined>)[\n API_ERROR_HEADERS\n ] ?? new Headers();\n }\n throw error;\n }\n ctx.context.responseHeaders ??= new Headers();\n mergeHeaders(ctx.context.responseHeaders, result.headers);\n const value = result.response;\n if (value && typeof value === \"object\") {\n if (\"context\" in value && typeof value.context === \"object\") {\n const { headers, ...rest } = value.context as Record<string, unknown>;\n if (headers instanceof Headers) {\n const requestHeaders =\n accumulated.headers instanceof Headers\n ? accumulated.headers\n : new Headers();\n headers.forEach((header, key) => {\n requestHeaders.set(key, header);\n });\n accumulated.headers = requestHeaders;\n }\n accumulated = mergeContext(rest, accumulated);\n } else {\n return value;\n }\n }\n }\n return Object.keys(accumulated).length ? { context: accumulated } : undefined;\n}\n\nexport async function runAfter(\n binding: BridgeBinding,\n ctx: HookEndpointContext,\n scope: ScopeView | undefined,\n relayMatcherError?: (error: unknown) => void,\n): Promise<unknown> {\n for (const hook of binding.after) {\n let matched: boolean;\n try {\n matched = hook.matches(ctx, scope);\n } catch (error) {\n if (!relayMatcherError) {\n throw error;\n }\n // A surrounding SDK handler catches APIErrors as recoverable results.\n // Stop here and rethrow from the next fixed SDK matcher instead.\n relayMatcherError(error);\n return undefined;\n }\n if (!matched) {\n continue;\n }\n let result: { response: unknown; headers?: Headers | null };\n try {\n result = (await createAuthMiddleware(hook.run)({\n ...ctx,\n returnHeaders: true,\n })) as { response: unknown; headers: Headers };\n } catch (error) {\n if (!isAPIError(error)) {\n throw error;\n }\n result = { response: error, headers: errorHeaders(error) };\n }\n if (result.headers) {\n ctx.context.responseHeaders ??= new Headers();\n mergeHeaders(ctx.context.responseHeaders, result.headers);\n }\n if (result.response !== undefined) {\n ctx.context.returned = result.response;\n }\n }\n return ctx.context.returned;\n}\n","import type { BetterAuthPlugin, HookEndpointContext } from \"better-auth\";\nimport {\n createAuthMiddleware,\n setShouldSkipSessionRefresh,\n} from \"better-auth/api\";\nimport { parseCookies } from \"better-auth/cookies\";\nimport type { NestjsPluginOptions } from \"./auth-contracts.js\";\nimport {\n BRIDGE_HANDLE,\n type BridgeBinding,\n type BridgeHandle,\n type ScopeView,\n} from \"./bridge-protocol.js\";\nimport { createDatabaseDispatchers } from \"./database-hook-dispatcher.js\";\nimport { runAfter, runBefore } from \"./hook-dispatcher.js\";\n\nexport type { NestjsPluginOptions } from \"./auth-contracts.js\";\nexport const NESTJS_PLUGIN_ID = \"nestjs-slightly-better-auth\";\n\nconst isRouter = (ctx: object): boolean =>\n \"_flag\" in ctx && ctx._flag === \"router\";\nconst separator = \"\\u0000\";\n\nfunction sessionToken(\n headers: Headers | undefined,\n ctx: HookEndpointContext,\n): string {\n return (\n parseCookies(headers?.get(\"cookie\") ?? \"\").get(\n ctx.context.authCookies.sessionToken.name,\n ) ?? \"\"\n );\n}\n\nfunction credential(\n headers: Headers | undefined,\n ctx: HookEndpointContext,\n extra: readonly string[],\n): string {\n return [\n sessionToken(headers, ctx),\n headers?.get(\"authorization\") ?? \"\",\n ...extra.map((name) => headers?.get(name) ?? \"\"),\n ].join(separator);\n}\n\nfunction sameCredential(\n ctx: HookEndpointContext,\n scope: ScopeView,\n extra: readonly string[],\n): boolean {\n const call = credential(ctx.headers, ctx, extra);\n return (\n call === separator.repeat(extra.length + 1) ||\n call === credential(scope.inbound?.(), ctx, extra)\n );\n}\n\n/** Pure construction-time Better Auth plugin; the Nest kernel binds through a global symbol. */\nexport function nestjs(\n options: NestjsPluginOptions = {},\n): BetterAuthPlugin & { id: typeof NESTJS_PLUGIN_ID } {\n let binding: BridgeBinding | null = null;\n let registration: ReturnType<BridgeHandle[\"bind\"]> | undefined;\n let unboundDispatches = 0;\n const endpointResults = new WeakSet<object>();\n const afterMatcherErrors = new WeakMap<object, unknown>();\n const scope = () => binding?.current();\n const clientIpHeader =\n options.clientIpHeader === false\n ? null\n : (options.clientIpHeader ??\n `x-nsba-ip-${globalThis.crypto.randomUUID().replaceAll(\"-\", \"\")}`);\n const handle: BridgeHandle = {\n protocol: 4,\n clientIpHeader,\n get state() {\n return binding === null\n ? \"unbound\"\n : binding.state === \"closed\"\n ? \"closed\"\n : \"bound\";\n },\n get unboundDispatches() {\n return unboundDispatches;\n },\n bind(next) {\n if (binding && binding.instance !== next.instance) {\n throw new Error(\n `PLUGIN_SHARED_BETWEEN_INSTANCES: '${binding.instance}' and '${next.instance}'`,\n );\n }\n if (binding?.owner === next.owner && registration) {\n return registration;\n }\n if (binding?.state === \"bootstrapped\") {\n throw new Error(\n `INSTANCE_ALREADY_BOUND: bound to ${binding.owner.description}`,\n );\n }\n const tookOverFrom =\n binding?.state === \"initialized\"\n ? binding.owner.description\n : undefined;\n binding = next;\n unboundDispatches = 0;\n registration = {\n tookOverFrom,\n close: () => {\n next.state = \"closed\";\n },\n };\n return registration;\n },\n producedByEndpoint(value) {\n return (\n typeof value === \"object\" &&\n value !== null &&\n endpointResults.has(value)\n );\n },\n };\n const plugin = {\n id: NESTJS_PLUGIN_ID,\n [BRIDGE_HANDLE]: handle,\n init: () => ({\n options: {\n databaseHooks: createDatabaseDispatchers(\n () => binding,\n () => {\n unboundDispatches++;\n },\n ),\n ...(clientIpHeader\n ? { advanced: { ipAddress: { ipAddressHeaders: [clientIpHeader] } } }\n : {}),\n },\n }),\n hooks: {\n before: [\n {\n matcher: (ctx) => {\n if (!binding) {\n unboundDispatches++;\n return false;\n }\n return !isRouter(ctx) && scope()?.cookies === null;\n },\n handler: createAuthMiddleware(async () => {\n await setShouldSkipSessionRefresh(true);\n }),\n },\n {\n matcher: (ctx) => {\n if (!binding || isRouter(ctx)) {\n return false;\n }\n const current = scope();\n if (!current || current.internal) {\n return false;\n }\n // Access capabilities before testing credentials: extraction errors\n // must fail even a credential-free direct endpoint call.\n const check = current.checkCallerSession;\n const inbound = current.inbound?.();\n const browser = current.browserHeaders?.();\n const token = sessionToken(ctx.headers, ctx);\n return (\n !!check &&\n token !== \"\" &&\n (token === sessionToken(inbound, ctx) ||\n token === sessionToken(browser, ctx))\n );\n },\n handler: createAuthMiddleware(async (ctx) => {\n scope()?.checkCallerSession?.(ctx.path, binding!.instance);\n }),\n },\n {\n matcher: () => binding !== null && binding.before.length > 0,\n handler: createAuthMiddleware((ctx) =>\n runBefore(binding!, ctx, scope()),\n ),\n },\n ],\n after: [\n {\n matcher: () => binding !== null && binding.after.length > 0,\n handler: createAuthMiddleware((ctx) =>\n runAfter(binding!, ctx, scope(), (error) => {\n afterMatcherErrors.set(ctx.context, error);\n }),\n ),\n },\n {\n matcher: (ctx) => {\n // Each endpoint dispatch owns this shared context, including nested\n // calls. Rethrow outside the SDK's recoverable handler-error catch.\n if (afterMatcherErrors.has(ctx.context)) {\n const error = afterMatcherErrors.get(ctx.context);\n afterMatcherErrors.delete(ctx.context);\n throw error;\n }\n return binding !== null && !isRouter(ctx);\n },\n handler: createAuthMiddleware(async (ctx) => {\n const value = ctx.context.returned;\n if (typeof value === \"object\" && value !== null) {\n endpointResults.add(value);\n }\n }),\n },\n {\n matcher: (ctx) => {\n if (isRouter(ctx)) {\n return false;\n }\n const current = scope();\n return !!current?.cookies && current.forward !== \"none\";\n },\n handler: createAuthMiddleware(async (ctx) => {\n const current = scope()!;\n if (\n current.forward === \"same-credential\" &&\n !sameCredential(ctx, current, binding!.credentialHeaders)\n ) {\n binding!.onDropped(ctx.path);\n return;\n }\n const cookies = ctx.context.responseHeaders?.getSetCookie() ?? [];\n if (cookies.length) {\n current.cookies!.append(cookies);\n }\n }),\n },\n ],\n },\n } satisfies BetterAuthPlugin & { [BRIDGE_HANDLE]: BridgeHandle };\n return plugin;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BetterAuthPlugin } from "better-auth";
|
|
2
|
+
import "@nestjs/common";
|
|
3
|
+
import "@nestjs/core";
|
|
4
|
+
import "@nestjs/core/injector/instance-wrapper.js";
|
|
5
|
+
import "@nestjs/common/exceptions/intrinsic.exception.js";
|
|
6
|
+
import "rxjs";
|
|
7
|
+
//#region src/auth-contracts.d.ts
|
|
8
|
+
interface NestjsPluginOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Header better-auth reads the client IP from, contributed to advanced.ipAddress.ipAddressHeaders as a default
|
|
11
|
+
* (user values win and come first). Default: a random name per plugin instance (per nestjs() call), `x-nsba-ip-<32 hex chars>`, generated with
|
|
12
|
+
* globalThis.crypto.randomUUID(); it never leaves the process and clients cannot guess it. A string pins a fixed name
|
|
13
|
+
* (for a trusted sidecar that calls auth.handler itself); false contributes nothing (configure advanced.ipAddress yourself).
|
|
14
|
+
*/
|
|
15
|
+
clientIpHeader?: string | false;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/plugin.d.ts
|
|
19
|
+
export declare const NESTJS_PLUGIN_ID = "nestjs-slightly-better-auth";
|
|
20
|
+
/** Pure construction-time Better Auth plugin; the Nest kernel binds through a global symbol. */
|
|
21
|
+
export declare function nestjs(options?: NestjsPluginOptions): BetterAuthPlugin & {
|
|
22
|
+
id: typeof NESTJS_PLUGIN_ID;
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
export type { NestjsPluginOptions };
|
|
26
|
+
//# sourceMappingURL=plugin.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.cts","names":[],"sources":["../src/auth-contracts.ts","../src/plugin.ts"],"mappings":";;;;;;;UAgXiB;;;;;;;EAOf;;;;qBCtWW;;wBA0CG,OACd,UAAS,sBACR;EAAqB,WAAW"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BetterAuthPlugin } from "better-auth";
|
|
2
|
+
import "@nestjs/common";
|
|
3
|
+
import "@nestjs/core";
|
|
4
|
+
import "@nestjs/core/injector/instance-wrapper.js";
|
|
5
|
+
import "@nestjs/common/exceptions/intrinsic.exception.js";
|
|
6
|
+
import "rxjs";
|
|
7
|
+
//#region src/auth-contracts.d.ts
|
|
8
|
+
interface NestjsPluginOptions {
|
|
9
|
+
/**
|
|
10
|
+
* Header better-auth reads the client IP from, contributed to advanced.ipAddress.ipAddressHeaders as a default
|
|
11
|
+
* (user values win and come first). Default: a random name per plugin instance (per nestjs() call), `x-nsba-ip-<32 hex chars>`, generated with
|
|
12
|
+
* globalThis.crypto.randomUUID(); it never leaves the process and clients cannot guess it. A string pins a fixed name
|
|
13
|
+
* (for a trusted sidecar that calls auth.handler itself); false contributes nothing (configure advanced.ipAddress yourself).
|
|
14
|
+
*/
|
|
15
|
+
clientIpHeader?: string | false;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/plugin.d.ts
|
|
19
|
+
export declare const NESTJS_PLUGIN_ID = "nestjs-slightly-better-auth";
|
|
20
|
+
/** Pure construction-time Better Auth plugin; the Nest kernel binds through a global symbol. */
|
|
21
|
+
export declare function nestjs(options?: NestjsPluginOptions): BetterAuthPlugin & {
|
|
22
|
+
id: typeof NESTJS_PLUGIN_ID;
|
|
23
|
+
};
|
|
24
|
+
//#endregion
|
|
25
|
+
export type { NestjsPluginOptions };
|
|
26
|
+
//# sourceMappingURL=plugin.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.mts","names":[],"sources":["../src/auth-contracts.ts","../src/plugin.ts"],"mappings":";;;;;;;UAgXiB;;;;;;;EAOf;;;;qBCtWW;;wBA0CG,OACd,UAAS,sBACR;EAAqB,WAAW"}
|