@velajs/better-auth 0.6.0 → 0.6.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/CHANGELOG.md +6 -1
- package/dist/better-auth.service-BMkyFX-w.js +63 -0
- package/dist/better-auth.service-BMkyFX-w.js.map +1 -0
- package/dist/index.d.ts +270 -12
- package/dist/index.js +364 -15
- package/dist/index.js.map +1 -0
- package/dist/testing/index.d.ts +50 -2
- package/dist/testing/index.js +60 -3
- package/dist/testing/index.js.map +1 -0
- package/package.json +58 -41
- package/dist/better-auth.controller.d.ts +0 -21
- package/dist/better-auth.controller.js +0 -68
- package/dist/better-auth.module.d.ts +0 -52
- package/dist/better-auth.module.js +0 -138
- package/dist/better-auth.service.d.ts +0 -42
- package/dist/better-auth.service.js +0 -51
- package/dist/better-auth.tokens.d.ts +0 -5
- package/dist/better-auth.tokens.js +0 -4
- package/dist/better-auth.types.d.ts +0 -11
- package/dist/better-auth.types.js +0 -1
- package/dist/decorators/current-session.decorator.d.ts +0 -1
- package/dist/decorators/current-session.decorator.js +0 -7
- package/dist/decorators/current-user.decorator.d.ts +0 -1
- package/dist/decorators/current-user.decorator.js +0 -7
- package/dist/decorators/optional-auth.decorator.d.ts +0 -2
- package/dist/decorators/optional-auth.decorator.js +0 -5
- package/dist/decorators/public.decorator.d.ts +0 -2
- package/dist/decorators/public.decorator.js +0 -5
- package/dist/decorators/roles.decorator.d.ts +0 -2
- package/dist/decorators/roles.decorator.js +0 -5
- package/dist/guards/auth.guard.d.ts +0 -10
- package/dist/guards/auth.guard.js +0 -68
- package/dist/guards/roles.guard.d.ts +0 -5
- package/dist/guards/roles.guard.js +0 -36
- package/dist/testing/acting-as.d.ts +0 -46
- package/dist/testing/acting-as.js +0 -70
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 89f5473: Modernize the package build, validation, and release toolchain.
|
|
8
|
+
|
|
3
9
|
## 0.4.0 (2026-07-04)
|
|
4
10
|
|
|
5
11
|
- Rebuilt on vela 1.11 `defineModule` + `lazyProvider` + `provideGlobal` (lazy auth-builder deferral preserved; public API unchanged). Requires `@velajs/vela >=1.11.0`.
|
|
6
12
|
|
|
7
|
-
|
|
8
13
|
All notable changes to `@velajs/better-auth` are documented here. The format
|
|
9
14
|
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
10
15
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Inject, Injectable, InjectionToken } from "@velajs/vela";
|
|
2
|
+
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/decorateMetadata.js
|
|
3
|
+
function __decorateMetadata(k, v) {
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
5
|
+
}
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/decorateParam.js
|
|
8
|
+
function __decorateParam(paramIndex, decorator) {
|
|
9
|
+
return function(target, key) {
|
|
10
|
+
decorator(target, key, paramIndex);
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/decorate.js
|
|
15
|
+
function __decorate(decorators, target, key, desc) {
|
|
16
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
17
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
18
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
19
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
20
|
+
}
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/better-auth.service.ts
|
|
23
|
+
/**
|
|
24
|
+
* Internal token holding the auth-construction closure with its inject deps
|
|
25
|
+
* closed over. Resolves cheaply at module load (just captures references);
|
|
26
|
+
* the inner call happens lazily on first auth use (see `BetterAuthService`).
|
|
27
|
+
*
|
|
28
|
+
* Not exported from the public surface — only the service consumes it.
|
|
29
|
+
*/
|
|
30
|
+
const BETTER_AUTH_BUILDER = new InjectionToken("vela.better-auth.Builder");
|
|
31
|
+
let BetterAuthService = class BetterAuthService {
|
|
32
|
+
build;
|
|
33
|
+
cached;
|
|
34
|
+
constructor(build) {
|
|
35
|
+
this.build = build;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The underlying better-auth instance. Constructed once on first access.
|
|
39
|
+
* Safe to call from any request-time code path (guards, controllers,
|
|
40
|
+
* services invoked from handlers).
|
|
41
|
+
*/
|
|
42
|
+
get auth() {
|
|
43
|
+
if (!this.cached) this.cached = this.build();
|
|
44
|
+
return this.cached;
|
|
45
|
+
}
|
|
46
|
+
/** Convenience accessor — equivalent to `service.auth.api`. */
|
|
47
|
+
get api() {
|
|
48
|
+
return this.auth.api;
|
|
49
|
+
}
|
|
50
|
+
/** Convenience accessor — equivalent to `service.auth.handler`. */
|
|
51
|
+
get handler() {
|
|
52
|
+
return this.auth.handler;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
BetterAuthService = __decorate([
|
|
56
|
+
Injectable(),
|
|
57
|
+
__decorateParam(0, Inject(BETTER_AUTH_BUILDER)),
|
|
58
|
+
__decorateMetadata("design:paramtypes", [Function])
|
|
59
|
+
], BetterAuthService);
|
|
60
|
+
//#endregion
|
|
61
|
+
export { __decorateMetadata as a, __decorateParam as i, BetterAuthService as n, __decorate as r, BETTER_AUTH_BUILDER as t };
|
|
62
|
+
|
|
63
|
+
//# sourceMappingURL=better-auth.service-BMkyFX-w.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"better-auth.service-BMkyFX-w.js","names":[],"sources":["../src/better-auth.service.ts"],"sourcesContent":["import { Inject, Injectable, InjectionToken } from '@velajs/vela';\nimport type { BetterAuthInstance } from './better-auth.types';\n\n/**\n * Internal token holding the auth-construction closure with its inject deps\n * closed over. Resolves cheaply at module load (just captures references);\n * the inner call happens lazily on first auth use (see `BetterAuthService`).\n *\n * Not exported from the public surface — only the service consumes it.\n */\nexport const BETTER_AUTH_BUILDER = new InjectionToken<() => BetterAuthInstance>(\n 'vela.better-auth.Builder',\n);\n\n/**\n * The single injectable consumers reach for to interact with better-auth.\n * Wraps the underlying `betterAuth({...})` instance with lazy construction:\n *\n * - `forRoot({ auth })` — the builder returns the eagerly-provided instance,\n * so the first `.auth` / `.api` / `.handler` access is effectively a\n * read-and-cache.\n * - `forRootAsync({ inject, useFactory })` — the builder wraps the user's\n * factory + inject deps. First access triggers `useFactory(...deps)`. This\n * is what makes Cloudflare D1/KV bindings work: at module load the factory\n * doesn't run; on first request (when AuthGuard or the catch-all calls\n * `service.api` / `service.handler`), the bindings are populated and the\n * factory can read them safely.\n *\n * Used directly by AuthGuard and the catch-all controller. Consumers in\n * application code inject the same way: `@Inject(BetterAuthService)`.\n */\n@Injectable()\nexport class BetterAuthService {\n private cached: BetterAuthInstance | undefined;\n\n constructor(@Inject(BETTER_AUTH_BUILDER) private readonly build: () => BetterAuthInstance) {}\n\n /**\n * The underlying better-auth instance. Constructed once on first access.\n * Safe to call from any request-time code path (guards, controllers,\n * services invoked from handlers).\n */\n get auth(): BetterAuthInstance {\n if (!this.cached) this.cached = this.build();\n return this.cached;\n }\n\n /** Convenience accessor — equivalent to `service.auth.api`. */\n get api(): BetterAuthInstance['api'] {\n return this.auth.api;\n }\n\n /** Convenience accessor — equivalent to `service.auth.handler`. */\n get handler(): BetterAuthInstance['handler'] {\n return this.auth.handler;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,MAAa,sBAAsB,IAAI,eACrC,0BACF;AAoBO,IAAA,oBAAA,MAAM,kBAAkB;CAG6B;CAF1D;CAEA,YAAY,OAA+E;EAAjC,KAAA,QAAA;CAAkC;;;;;;CAO5F,IAAI,OAA2B;EAC7B,IAAI,CAAC,KAAK,QAAQ,KAAK,SAAS,KAAK,MAAM;EAC3C,OAAO,KAAK;CACd;;CAGA,IAAI,MAAiC;EACnC,OAAO,KAAK,KAAK;CACnB;;CAGA,IAAI,UAAyC;EAC3C,OAAO,KAAK,KAAK;CACnB;AACF;;CAzBC,WAAW;oBAIG,OAAO,mBAAmB,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,270 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { CanActivate, DynamicModule, ExecutionContext, InferTokens, InjectionToken, Token, Type } from "@velajs/vela";
|
|
2
|
+
import { Auth, Session as Session$1, User as User$1 } from "better-auth";
|
|
3
|
+
import { Identity, PermissionResolver } from "@velajs/authz";
|
|
4
|
+
//#region src/better-auth.types.d.ts
|
|
5
|
+
type BetterAuthInstance = Auth<any>;
|
|
6
|
+
interface BetterAuthModuleOptions {
|
|
7
|
+
auth: BetterAuthInstance;
|
|
8
|
+
basePath?: string;
|
|
9
|
+
isGlobal?: boolean;
|
|
10
|
+
defaultPolicy?: 'deny' | 'allow';
|
|
11
|
+
mountHandler?: boolean;
|
|
12
|
+
}
|
|
13
|
+
type User = User$1;
|
|
14
|
+
type Session = Session$1;
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/better-auth.module.d.ts
|
|
17
|
+
/**
|
|
18
|
+
* Options for {@link BetterAuthModule.forRootAsync}.
|
|
19
|
+
*
|
|
20
|
+
* The `Inject` type parameter captures the literal `inject` tuple at the call
|
|
21
|
+
* site (via `const` inference) so `useFactory` parameters are typed from the
|
|
22
|
+
* inject array, position-by-position — no `as const`, no `(...deps: any[])`:
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
25
|
+
* BetterAuthModule.forRootAsync({
|
|
26
|
+
* inject: [D1Service, ConfigService], // captured as readonly tuple
|
|
27
|
+
* useFactory: (d1, config) => // d1: D1Service, config: ConfigService
|
|
28
|
+
* betterAuth({ database: drizzleAdapter(drizzle(d1.database), ...) }),
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
interface ForRootAsyncOptions<Inject extends readonly Token<unknown>[] = readonly Token<unknown>[]> {
|
|
33
|
+
inject?: Inject;
|
|
34
|
+
imports?: DynamicModule['imports'];
|
|
35
|
+
useFactory: (...deps: InferTokens<Inject>) => BetterAuthInstance;
|
|
36
|
+
isGlobal?: boolean;
|
|
37
|
+
mountHandler?: boolean;
|
|
38
|
+
basePath?: string;
|
|
39
|
+
defaultPolicy?: 'deny' | 'allow';
|
|
40
|
+
key?: string;
|
|
41
|
+
}
|
|
42
|
+
declare class BetterAuthModule {
|
|
43
|
+
/**
|
|
44
|
+
* Synchronous registration. The auth instance is constructed by the consumer
|
|
45
|
+
* at module-load time and passed in directly. Use this when the inputs to
|
|
46
|
+
* `betterAuth({...})` are available at startup (Node apps with a static DB
|
|
47
|
+
* connection, in-memory adapters, etc.).
|
|
48
|
+
*/
|
|
49
|
+
static forRoot(options: BetterAuthModuleOptions & {
|
|
50
|
+
isGlobal?: boolean;
|
|
51
|
+
key?: string;
|
|
52
|
+
}): DynamicModule;
|
|
53
|
+
/**
|
|
54
|
+
* Deferred / DI-driven registration. The user factory runs **lazily**, on the
|
|
55
|
+
* first time anything reads `BetterAuthService.auth` (or `.api` / `.handler`).
|
|
56
|
+
* In normal request handling that's `AuthGuard.canActivate` or the catch-all
|
|
57
|
+
* controller's `.handle`. At module load the factory does NOT run — it's only
|
|
58
|
+
* captured behind {@link lazyProvider}'s memoized thunk. This is what makes
|
|
59
|
+
* Cloudflare bindings (D1, KV, R2) work: the binding isn't ready at boot, but
|
|
60
|
+
* it IS by the time a request flows through and the guard / catch-all reads
|
|
61
|
+
* the service. Inject deps resolve at module load (cheap BindingRef wrappers);
|
|
62
|
+
* their *values* are read at first auth use, inside your factory body.
|
|
63
|
+
*/
|
|
64
|
+
static forRootAsync<const Inject extends readonly Token<unknown>[] = readonly Token<unknown>[]>(options: ForRootAsyncOptions<Inject>): DynamicModule;
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/better-auth.service.d.ts
|
|
68
|
+
/**
|
|
69
|
+
* The single injectable consumers reach for to interact with better-auth.
|
|
70
|
+
* Wraps the underlying `betterAuth({...})` instance with lazy construction:
|
|
71
|
+
*
|
|
72
|
+
* - `forRoot({ auth })` — the builder returns the eagerly-provided instance,
|
|
73
|
+
* so the first `.auth` / `.api` / `.handler` access is effectively a
|
|
74
|
+
* read-and-cache.
|
|
75
|
+
* - `forRootAsync({ inject, useFactory })` — the builder wraps the user's
|
|
76
|
+
* factory + inject deps. First access triggers `useFactory(...deps)`. This
|
|
77
|
+
* is what makes Cloudflare D1/KV bindings work: at module load the factory
|
|
78
|
+
* doesn't run; on first request (when AuthGuard or the catch-all calls
|
|
79
|
+
* `service.api` / `service.handler`), the bindings are populated and the
|
|
80
|
+
* factory can read them safely.
|
|
81
|
+
*
|
|
82
|
+
* Used directly by AuthGuard and the catch-all controller. Consumers in
|
|
83
|
+
* application code inject the same way: `@Inject(BetterAuthService)`.
|
|
84
|
+
*/
|
|
85
|
+
declare class BetterAuthService {
|
|
86
|
+
private readonly build;
|
|
87
|
+
private cached;
|
|
88
|
+
constructor(build: () => BetterAuthInstance);
|
|
89
|
+
/**
|
|
90
|
+
* The underlying better-auth instance. Constructed once on first access.
|
|
91
|
+
* Safe to call from any request-time code path (guards, controllers,
|
|
92
|
+
* services invoked from handlers).
|
|
93
|
+
*/
|
|
94
|
+
get auth(): BetterAuthInstance;
|
|
95
|
+
/** Convenience accessor — equivalent to `service.auth.api`. */
|
|
96
|
+
get api(): BetterAuthInstance['api'];
|
|
97
|
+
/** Convenience accessor — equivalent to `service.auth.handler`. */
|
|
98
|
+
get handler(): BetterAuthInstance['handler'];
|
|
99
|
+
}
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/better-auth.controller.d.ts
|
|
102
|
+
/**
|
|
103
|
+
* Build a catch-all controller that mounts better-auth's handler at `basePath`
|
|
104
|
+
* (default `/api/auth`). This is a factory because vela reads a controller's
|
|
105
|
+
* route off the class at decoration time, so a custom base path needs its own
|
|
106
|
+
* decorated class — the path can't be parametrized on a single shared class.
|
|
107
|
+
*
|
|
108
|
+
* Two base paths to keep consistent:
|
|
109
|
+
* - this `basePath` is RELATIVE to vela's `globalPrefix` (always prepended);
|
|
110
|
+
* - better-auth routes against its OWN absolute `basePath` (the one you pass to
|
|
111
|
+
* `betterAuth({ basePath })`), which must equal `globalPrefix + basePath`.
|
|
112
|
+
*
|
|
113
|
+
* Both default to `/api/auth`, so the no-prefix / no-config case just works.
|
|
114
|
+
*/
|
|
115
|
+
declare function createBetterAuthCatchallController(basePath?: string): Type;
|
|
116
|
+
/**
|
|
117
|
+
* Default-path (`/api/auth`) catch-all controller. Retained for back-compat;
|
|
118
|
+
* `BetterAuthModule` now mounts {@link createBetterAuthCatchallController} with
|
|
119
|
+
* the configured `basePath`. Prefer the factory for a custom base path.
|
|
120
|
+
*/
|
|
121
|
+
declare const BetterAuthCatchallController: Type;
|
|
122
|
+
//#endregion
|
|
123
|
+
//#region src/better-auth.tokens.d.ts
|
|
124
|
+
declare const BETTER_AUTH_OPTIONS: InjectionToken<BetterAuthModuleOptions>;
|
|
125
|
+
declare const AUTH_USER_KEY: unique symbol;
|
|
126
|
+
declare const AUTH_SESSION_KEY: unique symbol;
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region src/guards/auth.guard.d.ts
|
|
129
|
+
declare class AuthGuard implements CanActivate {
|
|
130
|
+
private readonly auth;
|
|
131
|
+
private readonly opts;
|
|
132
|
+
private readonly reflector;
|
|
133
|
+
constructor(auth: BetterAuthService, opts: BetterAuthModuleOptions);
|
|
134
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
135
|
+
}
|
|
136
|
+
//#endregion
|
|
137
|
+
//#region src/guards/roles.guard.d.ts
|
|
138
|
+
declare class RolesGuard implements CanActivate {
|
|
139
|
+
private readonly reflector;
|
|
140
|
+
canActivate(context: ExecutionContext): boolean;
|
|
141
|
+
}
|
|
142
|
+
//#endregion
|
|
143
|
+
//#region src/guards/permission.guard.d.ts
|
|
144
|
+
/**
|
|
145
|
+
* Enforces the `@RequirePermission(...)` metadata against the `@velajs/authz`
|
|
146
|
+
* engine. For each required permission it calls `authz.can(identity, perm)`,
|
|
147
|
+
* requiring **all** of them (AND semantics — contrast {@link RolesGuard}, which
|
|
148
|
+
* is OR over roles). The caller's `Identity` is derived from the better-auth
|
|
149
|
+
* user that {@link AuthGuard} placed in the request context, so this guard must
|
|
150
|
+
* run *after* `AuthGuard` (e.g. `@UseGuards(AuthGuard, PermissionGuard)`).
|
|
151
|
+
*
|
|
152
|
+
* `AUTHZ` is resolved at **request time** from the per-request container (the
|
|
153
|
+
* same container `REQUEST_CONTEXT` is resolved from), not constructor-injected.
|
|
154
|
+
* This deliberately avoids DI visibility coupling: the guard works whether or
|
|
155
|
+
* not `AuthzModule` is registered as global — a present-but-non-global
|
|
156
|
+
* `AuthzModule` resolves fine and, crucially, never crashes bootstrap. If
|
|
157
|
+
* `AuthzModule` is not registered at all the resolve fails and the guard fails
|
|
158
|
+
* closed (403) rather than granting access.
|
|
159
|
+
*
|
|
160
|
+
* Fail-closed on every abnormal path — no branch grants access on missing
|
|
161
|
+
* wiring or a missing caller:
|
|
162
|
+
* - no required permissions → allow (nothing to enforce);
|
|
163
|
+
* - `AUTHZ` unresolvable (`AuthzModule` not registered) → deny (`ForbiddenException`);
|
|
164
|
+
* - no authenticated user in the request context → deny;
|
|
165
|
+
* - any single required permission not granted → deny.
|
|
166
|
+
*
|
|
167
|
+
* The guard is stateless (no injected dependencies), so it is safe to register
|
|
168
|
+
* as a plain provided guard.
|
|
169
|
+
*/
|
|
170
|
+
declare class PermissionGuard implements CanActivate {
|
|
171
|
+
private readonly reflector;
|
|
172
|
+
canActivate(context: ExecutionContext): Promise<boolean>;
|
|
173
|
+
}
|
|
174
|
+
//#endregion
|
|
175
|
+
//#region src/decorators/current-user.decorator.d.ts
|
|
176
|
+
declare const CurrentUser: (data?: unknown, ...pipes: import("@velajs/vela").PipeType[]) => ParameterDecorator;
|
|
177
|
+
//#endregion
|
|
178
|
+
//#region src/decorators/current-session.decorator.d.ts
|
|
179
|
+
declare const CurrentSession: (data?: unknown, ...pipes: import("@velajs/vela").PipeType[]) => ParameterDecorator;
|
|
180
|
+
//#endregion
|
|
181
|
+
//#region src/decorators/public.decorator.d.ts
|
|
182
|
+
declare const Public: import("@velajs/vela").ReflectableDecorator<boolean>;
|
|
183
|
+
declare const PUBLIC_KEY: string;
|
|
184
|
+
//#endregion
|
|
185
|
+
//#region src/decorators/optional-auth.decorator.d.ts
|
|
186
|
+
declare const OptionalAuth: import("@velajs/vela").ReflectableDecorator<boolean>;
|
|
187
|
+
declare const OPTIONAL_AUTH_KEY: string;
|
|
188
|
+
//#endregion
|
|
189
|
+
//#region src/decorators/roles.decorator.d.ts
|
|
190
|
+
declare const Roles: import("@velajs/vela").ReflectableDecorator<string[]>;
|
|
191
|
+
declare const ROLES_KEY: string;
|
|
192
|
+
//#endregion
|
|
193
|
+
//#region src/decorators/require-permission.decorator.d.ts
|
|
194
|
+
/**
|
|
195
|
+
* Declares the `@velajs/authz` permission(s) required to reach a controller or
|
|
196
|
+
* route handler. Read via `Reflector` in an authorization guard, then checked
|
|
197
|
+
* against the caller's `Identity` with `authz.can(...)`.
|
|
198
|
+
*
|
|
199
|
+
* ```ts
|
|
200
|
+
* @RequirePermission(['posts:write'])
|
|
201
|
+
* @Post()
|
|
202
|
+
* create() { ... }
|
|
203
|
+
* ```
|
|
204
|
+
*
|
|
205
|
+
* The metadata is a plain `string[]` of permission strings in the granted-side
|
|
206
|
+
* format `@velajs/authz` matches (`resource:action`, or wildcards like
|
|
207
|
+
* `posts:*`). Handler-level metadata overrides class-level (standard
|
|
208
|
+
* `Reflector.getAllAndOverride` precedence).
|
|
209
|
+
*
|
|
210
|
+
* Semantics are **require-ALL** (AND): every listed permission must be granted
|
|
211
|
+
* for access — the `PermissionGuard` denies if any one is missing. This
|
|
212
|
+
* contrasts with `@Roles`, which is **OR** (any one of the listed roles
|
|
213
|
+
* suffices).
|
|
214
|
+
*/
|
|
215
|
+
declare const RequirePermission: import("@velajs/vela").ReflectableDecorator<string[]>;
|
|
216
|
+
declare const REQUIRE_PERMISSION_KEY: string;
|
|
217
|
+
//#endregion
|
|
218
|
+
//#region src/authz-bridge.d.ts
|
|
219
|
+
/**
|
|
220
|
+
* A better-auth user carrying the optional `role` field contributed by the
|
|
221
|
+
* admin plugin. `role` may be a single role, a comma-separated list, or an
|
|
222
|
+
* array — {@link identityFromUser} normalizes all three.
|
|
223
|
+
*/
|
|
224
|
+
type AuthUser = User & {
|
|
225
|
+
role?: string | string[] | null;
|
|
226
|
+
};
|
|
227
|
+
/**
|
|
228
|
+
* Adapts a better-auth user into a `@velajs/authz` {@link Identity}. Maps
|
|
229
|
+
* `user.id` → `userId` and the admin-plugin `role` field → `roles`.
|
|
230
|
+
*
|
|
231
|
+
* Fail-closed: a missing user (`null`/`undefined`, i.e. an unauthenticated
|
|
232
|
+
* request) maps to the zero-privilege identity `{ roles: [] }`, so downstream
|
|
233
|
+
* `can()` checks grant nothing.
|
|
234
|
+
*/
|
|
235
|
+
declare const identityFromUser: (user: AuthUser | null | undefined) => Identity;
|
|
236
|
+
/**
|
|
237
|
+
* The minimal slice of a better-auth access-control role consumed here. Both
|
|
238
|
+
* `createAccessControl(...).newRole(...)` and the standalone `role(...)` return
|
|
239
|
+
* `{ authorize, statements }`; `statements` is the `{ resource: actions[] }`
|
|
240
|
+
* grant map for that role — the only accessor {@link betterAuthAcResolver}
|
|
241
|
+
* reads.
|
|
242
|
+
*/
|
|
243
|
+
interface BetterAuthAcRole {
|
|
244
|
+
readonly statements: Readonly<Record<string, readonly string[]>>;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Flattens a better-auth AC role's `statements` into `resource:action`
|
|
248
|
+
* permission strings — the granted-side format `@velajs/authz` matches
|
|
249
|
+
* (wildcards included).
|
|
250
|
+
*/
|
|
251
|
+
declare const permissionsFromAcRole: (role: BetterAuthAcRole) => string[];
|
|
252
|
+
/**
|
|
253
|
+
* Builds a fail-closed `@velajs/authz` {@link PermissionResolver} from a
|
|
254
|
+
* better-auth access-control role table (`{ roleName: acRole }` — the same map
|
|
255
|
+
* shape passed to better-auth's admin/organization plugins). An identity's
|
|
256
|
+
* `roles` are unioned into their granted permission strings; unknown roles
|
|
257
|
+
* contribute nothing.
|
|
258
|
+
*
|
|
259
|
+
* ```ts
|
|
260
|
+
* const ac = createAccessControl({ posts: ['read', 'write'] });
|
|
261
|
+
* const authz = createAuthz({
|
|
262
|
+
* resolver: betterAuthAcResolver({ editor: ac.newRole({ posts: ['write'] }) }),
|
|
263
|
+
* });
|
|
264
|
+
* await authz.can(identityFromUser(user), 'posts:write');
|
|
265
|
+
* ```
|
|
266
|
+
*/
|
|
267
|
+
declare const betterAuthAcResolver: (roles: Readonly<Record<string, BetterAuthAcRole>>) => PermissionResolver;
|
|
268
|
+
//#endregion
|
|
269
|
+
export { AUTH_SESSION_KEY, AUTH_USER_KEY, AuthGuard, type AuthUser, BETTER_AUTH_OPTIONS, type BetterAuthAcRole, BetterAuthCatchallController, type BetterAuthInstance, BetterAuthModule, type BetterAuthModuleOptions, BetterAuthService, CurrentSession, CurrentUser, OPTIONAL_AUTH_KEY, OptionalAuth, PUBLIC_KEY, PermissionGuard, Public, REQUIRE_PERMISSION_KEY, ROLES_KEY, RequirePermission, Roles, RolesGuard, type Session, type User, betterAuthAcResolver, createBetterAuthCatchallController, identityFromUser, permissionsFromAcRole };
|
|
270
|
+
//# sourceMappingURL=index.d.ts.map
|