@fougere/auth-better 0.12.2-alpha.0 → 0.12.5-alpha.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 +3 -1
- package/dist/entity/AuthUser.d.ts +4 -4
- package/dist/entity/AuthUser.d.ts.map +1 -1
- package/dist/entity/AuthUser.js +3 -2
- package/dist/entity/AuthUser.js.map +1 -1
- package/dist/entity/AuthVerification.d.ts +3 -3
- package/dist/entity/AuthVerification.d.ts.map +1 -1
- package/dist/entity/AuthVerification.js +2 -1
- package/dist/entity/AuthVerification.js.map +1 -1
- package/dist/entity/authEntities.js +3 -3
- package/dist/entity/authEntities.js.map +1 -1
- package/dist/index.d.ts +12 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +50 -45
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/entity/AuthUser.ts +4 -2
- package/src/entity/AuthVerification.ts +3 -1
- package/src/entity/authEntities.ts +3 -3
- package/src/index.ts +54 -50
package/README.md
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
> Fougere's auth
|
|
3
3
|
A translation layer onto [better-auth](https://better-auth.com): its writes go through
|
|
4
4
|
Fougere's storage, and the application's `User` stays its own — Session and Account are
|
|
5
|
-
built against it.
|
|
5
|
+
built against it. `betterAuth()` is a frond, `fronds: { auth: betterAuth({ … }) }`: it holds
|
|
6
|
+
those rows, and carries the extension that registers the runtime under `AUTH` wherever the
|
|
7
|
+
frond is served.
|
|
6
8
|
|
|
7
9
|
## Installation
|
|
8
10
|
```bash
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const
|
|
1
|
+
declare const User_base: import("@fougere/schema").SchemaConstructor<{
|
|
2
2
|
id: import("@fougere/schema").Field<string>;
|
|
3
3
|
name: import("@fougere/schema").Field<string>;
|
|
4
4
|
email: import("@fougere/schema").Field<string>;
|
|
@@ -7,8 +7,8 @@ declare const AuthUser_base: import("@fougere/schema").SchemaConstructor<{
|
|
|
7
7
|
createdAt: import("@fougere/schema").Field<Date>;
|
|
8
8
|
updatedAt: import("@fougere/schema").Field<Date>;
|
|
9
9
|
}>;
|
|
10
|
-
/**
|
|
11
|
-
|
|
10
|
+
/** The user better-auth writes when the app names none — `User`, since the model is `user`. */
|
|
11
|
+
declare class User extends User_base {
|
|
12
12
|
}
|
|
13
|
-
export {};
|
|
13
|
+
export { User as AuthUser };
|
|
14
14
|
//# sourceMappingURL=AuthUser.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthUser.d.ts","sourceRoot":"","sources":["../../src/entity/AuthUser.ts"],"names":[],"mappings":";;;;;;;;;AAEA
|
|
1
|
+
{"version":3,"file":"AuthUser.d.ts","sourceRoot":"","sources":["../../src/entity/AuthUser.ts"],"names":[],"mappings":";;;;;;;;;AAEA,+FAA+F;AAC/F,cAAM,IAAK,SAAQ,SAQjB;CAAG;AAEL,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,CAAC"}
|
package/dist/entity/AuthUser.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { entity, primary, text, bool, created, optional } from '@fougere/schema';
|
|
2
|
-
/**
|
|
3
|
-
|
|
2
|
+
/** The user better-auth writes when the app names none — `User`, since the model is `user`. */
|
|
3
|
+
class User extends entity({
|
|
4
4
|
id: primary(),
|
|
5
5
|
name: text(),
|
|
6
6
|
email: text(),
|
|
@@ -10,4 +10,5 @@ export class AuthUser extends entity({
|
|
|
10
10
|
updatedAt: created(),
|
|
11
11
|
}) {
|
|
12
12
|
}
|
|
13
|
+
export { User as AuthUser };
|
|
13
14
|
//# sourceMappingURL=AuthUser.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthUser.js","sourceRoot":"","sources":["../../src/entity/AuthUser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEjF
|
|
1
|
+
{"version":3,"file":"AuthUser.js","sourceRoot":"","sources":["../../src/entity/AuthUser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEjF,+FAA+F;AAC/F,MAAM,IAAK,SAAQ,MAAM,CAAC;IACxB,EAAE,EAAE,OAAO,EAAE;IACb,IAAI,EAAE,IAAI,EAAE;IACZ,KAAK,EAAE,IAAI,EAAE;IACb,aAAa,EAAE,IAAI,EAAE;IACrB,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;IACvB,SAAS,EAAE,OAAO,EAAE;IACpB,SAAS,EAAE,OAAO,EAAE;CACrB,CAAC;CAAG;AAEL,OAAO,EAAE,IAAI,IAAI,QAAQ,EAAE,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const
|
|
1
|
+
declare const Verification_base: import("@fougere/schema").SchemaConstructor<{
|
|
2
2
|
id: import("@fougere/schema").Field<string>;
|
|
3
3
|
identifier: import("@fougere/schema").Field<string>;
|
|
4
4
|
value: import("@fougere/schema").Field<string>;
|
|
@@ -10,7 +10,7 @@ declare const AuthVerification_base: import("@fougere/schema").SchemaConstructor
|
|
|
10
10
|
* Default Verification entity — better-auth shape.
|
|
11
11
|
* Used for email verification, password reset, magic links, etc.
|
|
12
12
|
*/
|
|
13
|
-
|
|
13
|
+
declare class Verification extends Verification_base {
|
|
14
14
|
}
|
|
15
|
-
export {};
|
|
15
|
+
export { Verification as AuthVerification };
|
|
16
16
|
//# sourceMappingURL=AuthVerification.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthVerification.d.ts","sourceRoot":"","sources":["../../src/entity/AuthVerification.ts"],"names":[],"mappings":";;;;;;;;AAEA;;;GAGG;AACH,
|
|
1
|
+
{"version":3,"file":"AuthVerification.d.ts","sourceRoot":"","sources":["../../src/entity/AuthVerification.ts"],"names":[],"mappings":";;;;;;;;AAEA;;;GAGG;AACH,cAAM,YAAa,SAAQ,iBAOzB;CAAG;AAEL,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAAE,CAAC"}
|
|
@@ -3,7 +3,7 @@ import { entity, primary, text, date, created } from '@fougere/schema';
|
|
|
3
3
|
* Default Verification entity — better-auth shape.
|
|
4
4
|
* Used for email verification, password reset, magic links, etc.
|
|
5
5
|
*/
|
|
6
|
-
|
|
6
|
+
class Verification extends entity({
|
|
7
7
|
id: primary(),
|
|
8
8
|
identifier: text(),
|
|
9
9
|
value: text(),
|
|
@@ -12,4 +12,5 @@ export class AuthVerification extends entity({
|
|
|
12
12
|
updatedAt: created(),
|
|
13
13
|
}) {
|
|
14
14
|
}
|
|
15
|
+
export { Verification as AuthVerification };
|
|
15
16
|
//# sourceMappingURL=AuthVerification.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthVerification.js","sourceRoot":"","sources":["../../src/entity/AuthVerification.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAEvE;;;GAGG;AACH,MAAM,
|
|
1
|
+
{"version":3,"file":"AuthVerification.js","sourceRoot":"","sources":["../../src/entity/AuthVerification.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAEvE;;;GAGG;AACH,MAAM,YAAa,SAAQ,MAAM,CAAC;IAChC,EAAE,EAAE,OAAO,EAAE;IACb,UAAU,EAAE,IAAI,EAAE;IAClB,KAAK,EAAE,IAAI,EAAE;IACb,SAAS,EAAE,IAAI,EAAE;IACjB,SAAS,EAAE,OAAO,EAAE;IACpB,SAAS,EAAE,OAAO,EAAE;CACrB,CAAC;CAAG;AAEL,OAAO,EAAE,YAAY,IAAI,gBAAgB,EAAE,CAAC"}
|
|
@@ -5,7 +5,7 @@ export function authEntities(User) {
|
|
|
5
5
|
* Session entity — better-auth shape.
|
|
6
6
|
* `token` carries the opaque session secret (cookie value).
|
|
7
7
|
*/
|
|
8
|
-
class
|
|
8
|
+
class Session extends entity({
|
|
9
9
|
id: primary(),
|
|
10
10
|
userId: ref(target),
|
|
11
11
|
token: text(),
|
|
@@ -20,7 +20,7 @@ export function authEntities(User) {
|
|
|
20
20
|
* Account entity — better-auth shape (single PK, accountId/providerId pair,
|
|
21
21
|
* separate token columns instead of a JSON blob).
|
|
22
22
|
*/
|
|
23
|
-
class
|
|
23
|
+
class Account extends entity({
|
|
24
24
|
id: primary(),
|
|
25
25
|
accountId: text(),
|
|
26
26
|
providerId: text(),
|
|
@@ -36,6 +36,6 @@ export function authEntities(User) {
|
|
|
36
36
|
updatedAt: created(),
|
|
37
37
|
}) {
|
|
38
38
|
}
|
|
39
|
-
return { AuthSession, AuthAccount };
|
|
39
|
+
return { AuthSession: Session, AuthAccount: Account };
|
|
40
40
|
}
|
|
41
41
|
//# sourceMappingURL=authEntities.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authEntities.js","sourceRoot":"","sources":["../../src/entity/authEntities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAmB,MAAM,iBAAiB,CAAC;AAKvG,MAAM,UAAU,YAAY,CAAC,IAAgB;IAI3C,MAAM,MAAM,GAAG,IAA6B,CAAC;IAE7C;;;OAGG;IACH,MAAM,
|
|
1
|
+
{"version":3,"file":"authEntities.js","sourceRoot":"","sources":["../../src/entity/authEntities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAmB,MAAM,iBAAiB,CAAC;AAKvG,MAAM,UAAU,YAAY,CAAC,IAAgB;IAI3C,MAAM,MAAM,GAAG,IAA6B,CAAC;IAE7C;;;OAGG;IACH,MAAM,OAAQ,SAAQ,MAAM,CAAC;QAC3B,EAAE,EAAE,OAAO,EAAE;QACb,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC;QACnB,KAAK,EAAE,IAAI,EAAE;QACb,SAAS,EAAE,IAAI,EAAE;QACjB,SAAS,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC3B,SAAS,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC3B,SAAS,EAAE,OAAO,EAAE;QACpB,SAAS,EAAE,OAAO,EAAE;KACrB,CAAC;KAAG;IAEL;;;OAGG;IACH,MAAM,OAAQ,SAAQ,MAAM,CAAC;QAC3B,EAAE,EAAE,OAAO,EAAE;QACb,SAAS,EAAE,IAAI,EAAE;QACjB,UAAU,EAAE,IAAI,EAAE;QAClB,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC;QACnB,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC7B,YAAY,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC9B,OAAO,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;QACzB,oBAAoB,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtC,qBAAqB,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;QACvC,KAAK,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;QACvB,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC1B,SAAS,EAAE,OAAO,EAAE;QACpB,SAAS,EAAE,OAAO,EAAE;KACrB,CAAC;KAAG;IAEL,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;AACxD,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type
|
|
1
|
+
import { type FrondDescriptor } from '@fougere/core';
|
|
2
|
+
import { type SchemaView } from '@fougere/schema';
|
|
3
3
|
import { type FougereProviders } from './FougereProviders.js';
|
|
4
4
|
export { AuthUser } from './entity/AuthUser.js';
|
|
5
|
-
/**
|
|
5
|
+
/** What `fronds: { '@fougere/auth-better': { … } }` hands the factory in fougere.config.ts. */
|
|
6
6
|
export interface BetterAuthOptions {
|
|
7
7
|
user?: SchemaView;
|
|
8
8
|
secret: string;
|
|
@@ -15,6 +15,13 @@ export interface BetterAuthOptions {
|
|
|
15
15
|
account?: SchemaView;
|
|
16
16
|
verification?: SchemaView;
|
|
17
17
|
}
|
|
18
|
-
/**
|
|
19
|
-
|
|
18
|
+
/**
|
|
19
|
+
* The auth provider, as a frond: its rows — the user too, when the app names none — and the
|
|
20
|
+
* extension that rises where it is served, declaring what a signed-in call carries and
|
|
21
|
+
* registering the runtime under `AUTH`. Placed like any frond: a process whose `only:` leaves it
|
|
22
|
+
* out starts no engine and migrates no session table. The session travels without its
|
|
23
|
+
* `token`: a process trusts the one that called it, never the cookie of whoever is behind it.
|
|
24
|
+
*/
|
|
25
|
+
export declare function betterAuth(opts: BetterAuthOptions): FrondDescriptor;
|
|
26
|
+
export default betterAuth;
|
|
20
27
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAA2C,KAAK,eAAe,EAAgB,MAAM,eAAe,CAAC;AAC5G,OAAO,EAAiC,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAKjF,OAAO,EAA0D,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEtH,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,+FAA+F;AAC/F,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,YAAY,CAAC,EAAE,UAAU,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,eAAe,CAqCnE;eAEc,UAAU"}
|
package/dist/index.js
CHANGED
|
@@ -1,59 +1,64 @@
|
|
|
1
1
|
import { betterAuth as betterAuthLib } from 'better-auth';
|
|
2
2
|
import { createId } from '@paralleldrive/cuid2';
|
|
3
|
+
import { AUTH, frond } from '@fougere/core';
|
|
4
|
+
import { json, lowerFirst } from '@fougere/schema';
|
|
3
5
|
import { AuthUser } from './entity/AuthUser.js';
|
|
4
6
|
import { AuthVerification } from './entity/AuthVerification.js';
|
|
5
7
|
import { authEntities } from './entity/authEntities.js';
|
|
6
8
|
import { fougereAdapter } from './adapter.js';
|
|
7
9
|
import { translateCredential, translatePlugins, translateSocial } from './FougereProviders.js';
|
|
8
10
|
export { AuthUser } from './entity/AuthUser.js';
|
|
9
|
-
/**
|
|
11
|
+
/**
|
|
12
|
+
* The auth provider, as a frond: its rows — the user too, when the app names none — and the
|
|
13
|
+
* extension that rises where it is served, declaring what a signed-in call carries and
|
|
14
|
+
* registering the runtime under `AUTH`. Placed like any frond: a process whose `only:` leaves it
|
|
15
|
+
* out starts no engine and migrates no session table. The session travels without its
|
|
16
|
+
* `token`: a process trusts the one that called it, never the cookie of whoever is behind it.
|
|
17
|
+
*/
|
|
10
18
|
export function betterAuth(opts) {
|
|
11
|
-
const
|
|
12
|
-
const { AuthSession, AuthAccount } = authEntities(
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
19
|
+
const user = opts.user ?? AuthUser;
|
|
20
|
+
const { AuthSession, AuthAccount } = authEntities(user);
|
|
21
|
+
const models = {
|
|
22
|
+
user,
|
|
23
|
+
session: opts.session ?? AuthSession,
|
|
24
|
+
account: opts.account ?? AuthAccount,
|
|
25
|
+
verification: opts.verification ?? AuthVerification,
|
|
26
|
+
};
|
|
27
|
+
const brought = Object.values(models).filter((schema) => schema !== opts.user);
|
|
16
28
|
const providers = opts.providers ?? {};
|
|
17
29
|
const basePath = opts.basePath ?? '/auth';
|
|
18
|
-
return {
|
|
19
|
-
entities:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
advanced: { database: { generateId: () => createId() } },
|
|
39
|
-
session: opts.sessionTtl ? { expiresIn: opts.sessionTtl / 1000 } : undefined,
|
|
40
|
-
emailAndPassword: translateCredential(providers),
|
|
41
|
-
socialProviders: translateSocial(providers),
|
|
42
|
-
plugins: translatePlugins(providers),
|
|
43
|
-
});
|
|
44
|
-
return {
|
|
45
|
-
entities: {
|
|
46
|
-
user: userSchema,
|
|
47
|
-
session: sessionSchema,
|
|
48
|
-
account: accountSchema,
|
|
49
|
-
verification: verificationSchema,
|
|
30
|
+
return frond('auth', {
|
|
31
|
+
entities: brought,
|
|
32
|
+
extensions: [{
|
|
33
|
+
name: 'auth',
|
|
34
|
+
state: { user: json(user), session: json(models.session.omit('token')) },
|
|
35
|
+
up(app) {
|
|
36
|
+
const engine = betterAuthLib({
|
|
37
|
+
database: fougereAdapter(storagesOf(app, models)),
|
|
38
|
+
secret: opts.secret,
|
|
39
|
+
baseURL: opts.baseUrl,
|
|
40
|
+
basePath,
|
|
41
|
+
trustedOrigins: opts.trustedOrigins,
|
|
42
|
+
advanced: { database: { generateId: () => createId() } },
|
|
43
|
+
session: opts.sessionTtl ? { expiresIn: opts.sessionTtl / 1000 } : undefined,
|
|
44
|
+
emailAndPassword: translateCredential(providers),
|
|
45
|
+
socialProviders: translateSocial(providers),
|
|
46
|
+
plugins: translatePlugins(providers),
|
|
47
|
+
});
|
|
48
|
+
const runtime = { handler: engine.handler, api: engine.api, basePath };
|
|
49
|
+
app.container.registerValue(AUTH, runtime);
|
|
50
50
|
},
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
}],
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
export default betterAuth;
|
|
55
|
+
function storagesOf(app, models) {
|
|
56
|
+
return new Map(Object.entries(models).map(([model, schema]) => {
|
|
57
|
+
const entity = lowerFirst(schema.name);
|
|
58
|
+
const storage = app.storageFor(entity);
|
|
59
|
+
if (!storage)
|
|
60
|
+
throw new Error(`[auth] no frond in this process holds '${entity}', the ${model} better-auth writes.`);
|
|
61
|
+
return [model, storage];
|
|
62
|
+
}));
|
|
58
63
|
}
|
|
59
64
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAkE,MAAM,eAAe,CAAC;AAC5G,OAAO,EAAE,IAAI,EAAE,UAAU,EAAgC,MAAM,iBAAiB,CAAC;AACjF,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAmB,MAAM,cAAc,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,eAAe,EAAyB,MAAM,uBAAuB,CAAC;AAEtH,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAgBhD;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,IAAuB;IAChD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC;IACnC,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IACxD,MAAM,MAAM,GAA+B;QACzC,IAAI;QACJ,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,WAAW;QACpC,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,WAAW;QACpC,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,gBAAgB;KACpD,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/E,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC;IAE1C,OAAO,KAAK,CAAC,MAAM,EAAE;QACnB,QAAQ,EAAE,OAAO;QACjB,UAAU,EAAE,CAAC;gBACX,IAAI,EAAE,MAAM;gBACZ,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAqB,CAAC,EAAE,OAAO,EAAE,IAAI,CAAE,MAAM,CAAC,OAAyB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE;gBAC5G,EAAE,CAAC,GAAQ;oBACT,MAAM,MAAM,GAAG,aAAa,CAAC;wBAC3B,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;wBACjD,MAAM,EAAE,IAAI,CAAC,MAAM;wBACnB,OAAO,EAAE,IAAI,CAAC,OAAO;wBACrB,QAAQ;wBACR,cAAc,EAAE,IAAI,CAAC,cAAc;wBACnC,QAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,EAAE;wBACxD,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,UAAU,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;wBAC5E,gBAAgB,EAAE,mBAAmB,CAAC,SAAS,CAAC;wBAChD,eAAe,EAAE,eAAe,CAAC,SAAS,CAAC;wBAC3C,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC;qBACrC,CAAC,CAAC;oBACH,MAAM,OAAO,GAAgB,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,GAA8B,EAAE,QAAQ,EAAE,CAAC;oBAE/G,GAAG,CAAC,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;gBAC7C,CAAC;aACF,CAAC;KACH,CAAC,CAAC;AACL,CAAC;AAED,eAAe,UAAU,CAAC;AAE1B,SAAS,UAAU,CAAC,GAAQ,EAAE,MAAkC;IAC9D,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE;QAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,OAAO,GAAwB,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC5D,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,MAAM,UAAU,KAAK,sBAAsB,CAAC,CAAC;QAErH,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC,CAAC;AACN,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fougere/auth-better",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.5-alpha.0",
|
|
4
4
|
"description": "Fougere's auth — a translation layer onto better-auth.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fougere",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@paralleldrive/cuid2": "^3.3.0",
|
|
33
33
|
"better-auth": "^1.6.11",
|
|
34
|
-
"@fougere/
|
|
35
|
-
"@fougere/
|
|
34
|
+
"@fougere/core": "0.12.5-alpha.0",
|
|
35
|
+
"@fougere/schema": "0.12.5-alpha.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"vitest": "^4.1.0",
|
|
39
|
-
"@fougere/adapter-sql": "0.12.
|
|
39
|
+
"@fougere/adapter-sql": "0.12.5-alpha.0"
|
|
40
40
|
},
|
|
41
41
|
"publishConfig": {
|
|
42
42
|
"access": "public"
|
package/src/entity/AuthUser.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { entity, primary, text, bool, created, optional } from '@fougere/schema';
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
|
|
3
|
+
/** The user better-auth writes when the app names none — `User`, since the model is `user`. */
|
|
4
|
+
class User extends entity({
|
|
5
5
|
id: primary(),
|
|
6
6
|
name: text(),
|
|
7
7
|
email: text(),
|
|
@@ -10,3 +10,5 @@ export class AuthUser extends entity({
|
|
|
10
10
|
createdAt: created(),
|
|
11
11
|
updatedAt: created(),
|
|
12
12
|
}) {}
|
|
13
|
+
|
|
14
|
+
export { User as AuthUser };
|
|
@@ -4,7 +4,7 @@ import { entity, primary, text, date, created } from '@fougere/schema';
|
|
|
4
4
|
* Default Verification entity — better-auth shape.
|
|
5
5
|
* Used for email verification, password reset, magic links, etc.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
class Verification extends entity({
|
|
8
8
|
id: primary(),
|
|
9
9
|
identifier: text(),
|
|
10
10
|
value: text(),
|
|
@@ -12,3 +12,5 @@ export class AuthVerification extends entity({
|
|
|
12
12
|
createdAt: created(),
|
|
13
13
|
updatedAt: created(),
|
|
14
14
|
}) {}
|
|
15
|
+
|
|
16
|
+
export { Verification as AuthVerification };
|
|
@@ -13,7 +13,7 @@ export function authEntities(User: SchemaView): {
|
|
|
13
13
|
* Session entity — better-auth shape.
|
|
14
14
|
* `token` carries the opaque session secret (cookie value).
|
|
15
15
|
*/
|
|
16
|
-
class
|
|
16
|
+
class Session extends entity({
|
|
17
17
|
id: primary(),
|
|
18
18
|
userId: ref(target),
|
|
19
19
|
token: text(),
|
|
@@ -28,7 +28,7 @@ export function authEntities(User: SchemaView): {
|
|
|
28
28
|
* Account entity — better-auth shape (single PK, accountId/providerId pair,
|
|
29
29
|
* separate token columns instead of a JSON blob).
|
|
30
30
|
*/
|
|
31
|
-
class
|
|
31
|
+
class Account extends entity({
|
|
32
32
|
id: primary(),
|
|
33
33
|
accountId: text(),
|
|
34
34
|
providerId: text(),
|
|
@@ -44,5 +44,5 @@ export function authEntities(User: SchemaView): {
|
|
|
44
44
|
updatedAt: created(),
|
|
45
45
|
}) {}
|
|
46
46
|
|
|
47
|
-
return { AuthSession, AuthAccount };
|
|
47
|
+
return { AuthSession: Session, AuthAccount: Account };
|
|
48
48
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { betterAuth as betterAuthLib } from 'better-auth';
|
|
2
2
|
import { createId } from '@paralleldrive/cuid2';
|
|
3
|
-
import
|
|
4
|
-
import type
|
|
3
|
+
import { AUTH, frond, type App, type AuthRuntime, type FrondDescriptor, type Storage } from '@fougere/core';
|
|
4
|
+
import { json, lowerFirst, type Schema, type SchemaView } from '@fougere/schema';
|
|
5
5
|
import { AuthUser } from './entity/AuthUser.js';
|
|
6
6
|
import { AuthVerification } from './entity/AuthVerification.js';
|
|
7
7
|
import { authEntities } from './entity/authEntities.js';
|
|
@@ -10,7 +10,7 @@ import { translateCredential, translatePlugins, translateSocial, type FougerePro
|
|
|
10
10
|
|
|
11
11
|
export { AuthUser } from './entity/AuthUser.js';
|
|
12
12
|
|
|
13
|
-
/**
|
|
13
|
+
/** What `fronds: { '@fougere/auth-better': { … } }` hands the factory in fougere.config.ts. */
|
|
14
14
|
export interface BetterAuthOptions {
|
|
15
15
|
user?: SchemaView;
|
|
16
16
|
secret: string;
|
|
@@ -24,56 +24,60 @@ export interface BetterAuthOptions {
|
|
|
24
24
|
verification?: SchemaView;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
/**
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
27
|
+
/**
|
|
28
|
+
* The auth provider, as a frond: its rows — the user too, when the app names none — and the
|
|
29
|
+
* extension that rises where it is served, declaring what a signed-in call carries and
|
|
30
|
+
* registering the runtime under `AUTH`. Placed like any frond: a process whose `only:` leaves it
|
|
31
|
+
* out starts no engine and migrates no session table. The session travels without its
|
|
32
|
+
* `token`: a process trusts the one that called it, never the cookie of whoever is behind it.
|
|
33
|
+
*/
|
|
34
|
+
export function betterAuth(opts: BetterAuthOptions): FrondDescriptor {
|
|
35
|
+
const user = opts.user ?? AuthUser;
|
|
36
|
+
const { AuthSession, AuthAccount } = authEntities(user);
|
|
37
|
+
const models: Record<string, SchemaView> = {
|
|
38
|
+
user,
|
|
39
|
+
session: opts.session ?? AuthSession,
|
|
40
|
+
account: opts.account ?? AuthAccount,
|
|
41
|
+
verification: opts.verification ?? AuthVerification,
|
|
42
|
+
};
|
|
43
|
+
const brought = Object.values(models).filter((schema) => schema !== opts.user);
|
|
34
44
|
const providers = opts.providers ?? {};
|
|
35
45
|
const basePath = opts.basePath ?? '/auth';
|
|
36
46
|
|
|
37
|
-
return {
|
|
38
|
-
entities:
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
return frond('auth', {
|
|
48
|
+
entities: brought,
|
|
49
|
+
extensions: [{
|
|
50
|
+
name: 'auth',
|
|
51
|
+
state: { user: json(user as typeof Schema), session: json((models.session as typeof Schema).omit('token')) },
|
|
52
|
+
up(app: App) {
|
|
53
|
+
const engine = betterAuthLib({
|
|
54
|
+
database: fougereAdapter(storagesOf(app, models)),
|
|
55
|
+
secret: opts.secret,
|
|
56
|
+
baseURL: opts.baseUrl,
|
|
57
|
+
basePath,
|
|
58
|
+
trustedOrigins: opts.trustedOrigins,
|
|
59
|
+
advanced: { database: { generateId: () => createId() } },
|
|
60
|
+
session: opts.sessionTtl ? { expiresIn: opts.sessionTtl / 1000 } : undefined,
|
|
61
|
+
emailAndPassword: translateCredential(providers),
|
|
62
|
+
socialProviders: translateSocial(providers),
|
|
63
|
+
plugins: translatePlugins(providers),
|
|
64
|
+
});
|
|
65
|
+
const runtime: AuthRuntime = { handler: engine.handler, api: engine.api as Record<string, unknown>, basePath };
|
|
51
66
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
trustedOrigins: opts.trustedOrigins,
|
|
58
|
-
advanced: { database: { generateId: () => createId() } },
|
|
59
|
-
session: opts.sessionTtl ? { expiresIn: opts.sessionTtl / 1000 } : undefined,
|
|
60
|
-
emailAndPassword: translateCredential(providers),
|
|
61
|
-
socialProviders: translateSocial(providers),
|
|
62
|
-
plugins: translatePlugins(providers),
|
|
63
|
-
});
|
|
67
|
+
app.container.registerValue(AUTH, runtime);
|
|
68
|
+
},
|
|
69
|
+
}],
|
|
70
|
+
});
|
|
71
|
+
}
|
|
64
72
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
basePath,
|
|
76
|
-
};
|
|
77
|
-
},
|
|
78
|
-
};
|
|
73
|
+
export default betterAuth;
|
|
74
|
+
|
|
75
|
+
function storagesOf(app: App, models: Record<string, SchemaView>): StorageMap {
|
|
76
|
+
return new Map(Object.entries(models).map(([model, schema]) => {
|
|
77
|
+
const entity = lowerFirst(schema.name);
|
|
78
|
+
const storage: Storage | undefined = app.storageFor(entity);
|
|
79
|
+
if (!storage) throw new Error(`[auth] no frond in this process holds '${entity}', the ${model} better-auth writes.`);
|
|
80
|
+
|
|
81
|
+
return [model, storage];
|
|
82
|
+
}));
|
|
79
83
|
}
|