@fougere/auth-better 0.1.0-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/LICENSE +21 -0
- package/README.md +16 -0
- package/dist/adapter.d.ts +15 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +157 -0
- package/dist/adapter.js.map +1 -0
- package/dist/entities.d.ts +39 -0
- package/dist/entities.d.ts.map +1 -0
- package/dist/entities.js +71 -0
- package/dist/entities.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +68 -0
- package/dist/index.js.map +1 -0
- package/dist/translate.d.ts +67 -0
- package/dist/translate.d.ts.map +1 -0
- package/dist/translate.js +45 -0
- package/dist/translate.js.map +1 -0
- package/package.json +42 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Fougere contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# @fougere/auth-better
|
|
2
|
+
> Fougere's auth
|
|
3
|
+
A translation layer onto [better-auth](https://better-auth.com): its writes go through
|
|
4
|
+
Fougere's ORM, and the application's `User` stays its own — Session and Account are
|
|
5
|
+
built against it.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
```bash
|
|
9
|
+
pnpm add @fougere/auth-better
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
Part of [Fougere](https://github.com/chok/fougere) — one schema, a gradient from
|
|
15
|
+
monolith to distributed, the same user code.
|
|
16
|
+
Reference documentation: [the site](https://chok.github.io/fougere/) (en/fr).
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EntityOrm } from '@fougere/core';
|
|
2
|
+
/**
|
|
3
|
+
* Map of better-auth model names ('user', 'session', 'account', ...)
|
|
4
|
+
* to Fougere EntityOrm instances. Built once at boot by create() in index.ts.
|
|
5
|
+
*/
|
|
6
|
+
export type OrmMap = Map<string, EntityOrm>;
|
|
7
|
+
/**
|
|
8
|
+
* Better-auth adapter that routes every operation through Fougere EntityOrm.
|
|
9
|
+
*
|
|
10
|
+
* This closes the loop: the same `db` resolved by Fougere's bootstrap is the
|
|
11
|
+
* one EntityOrm writes to, and better-auth never touches the storage directly.
|
|
12
|
+
* If Fougere swaps Kysely for another backend, this adapter follows for free.
|
|
13
|
+
*/
|
|
14
|
+
export declare function fougereAdapter(ormMap: OrmMap): import("better-auth/adapters").AdapterFactory<import("better-auth").BetterAuthOptions>;
|
|
15
|
+
//# sourceMappingURL=adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C;;;GAGG;AACH,MAAM,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAqC5C;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,0FAyG5C"}
|
package/dist/adapter.js
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { createAdapterFactory } from 'better-auth/adapters';
|
|
2
|
+
/**
|
|
3
|
+
* Where[] supported subset:
|
|
4
|
+
* - All clauses use 'eq' operator
|
|
5
|
+
* - Implicit AND between clauses (no OR connector)
|
|
6
|
+
* Anything else throws — extend EntityOrm or add an engine-level fallback when needed.
|
|
7
|
+
*/
|
|
8
|
+
function whereToCriteria(where) {
|
|
9
|
+
const criteria = {};
|
|
10
|
+
for (const clause of where) {
|
|
11
|
+
if (clause.operator !== 'eq') {
|
|
12
|
+
throw new Error(`[fougereAdapter] Operator '${clause.operator}' not yet supported on field '${clause.field}'. ` +
|
|
13
|
+
`Only 'eq' with implicit AND is implemented.`);
|
|
14
|
+
}
|
|
15
|
+
if (clause.connector === 'OR') {
|
|
16
|
+
throw new Error(`[fougereAdapter] OR connector not yet supported (field '${clause.field}').`);
|
|
17
|
+
}
|
|
18
|
+
criteria[clause.field] = clause.value;
|
|
19
|
+
}
|
|
20
|
+
return criteria;
|
|
21
|
+
}
|
|
22
|
+
function getOrm(ormMap, model) {
|
|
23
|
+
const orm = ormMap.get(model);
|
|
24
|
+
if (!orm) {
|
|
25
|
+
throw new Error(`[fougereAdapter] Unknown model '${model}'. ` +
|
|
26
|
+
`Known models: ${[...ormMap.keys()].join(', ')}. ` +
|
|
27
|
+
`Plugins that ship their own schema need entities registered explicitly.`);
|
|
28
|
+
}
|
|
29
|
+
return orm;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Better-auth adapter that routes every operation through Fougere EntityOrm.
|
|
33
|
+
*
|
|
34
|
+
* This closes the loop: the same `db` resolved by Fougere's bootstrap is the
|
|
35
|
+
* one EntityOrm writes to, and better-auth never touches the storage directly.
|
|
36
|
+
* If Fougere swaps Kysely for another backend, this adapter follows for free.
|
|
37
|
+
*/
|
|
38
|
+
export function fougereAdapter(ormMap) {
|
|
39
|
+
return createAdapterFactory({
|
|
40
|
+
config: {
|
|
41
|
+
adapterId: 'fougere',
|
|
42
|
+
adapterName: 'Fougere Adapter',
|
|
43
|
+
usePlural: false,
|
|
44
|
+
supportsArrays: false,
|
|
45
|
+
supportsJSON: false,
|
|
46
|
+
// The ORM converts both ways now (`schema-sql/src/values.ts`), so better-auth
|
|
47
|
+
// can hand over the Dates and booleans its own types declare.
|
|
48
|
+
supportsDates: true,
|
|
49
|
+
supportsBooleans: true,
|
|
50
|
+
},
|
|
51
|
+
adapter: () => ({
|
|
52
|
+
create: async ({ model, data }) => {
|
|
53
|
+
const orm = getOrm(ormMap, model);
|
|
54
|
+
return (await orm.create(data));
|
|
55
|
+
},
|
|
56
|
+
findOne: async ({ model, where }) => {
|
|
57
|
+
const orm = getOrm(ormMap, model);
|
|
58
|
+
const criteria = whereToCriteria(where);
|
|
59
|
+
if (Object.keys(criteria).length === 1 && 'id' in criteria) {
|
|
60
|
+
const found = await orm.findById(criteria.id);
|
|
61
|
+
return (found ?? null);
|
|
62
|
+
}
|
|
63
|
+
const found = await orm.findBy(criteria);
|
|
64
|
+
return (found ?? null);
|
|
65
|
+
},
|
|
66
|
+
findMany: async ({ model, where, limit, offset, sortBy, }) => {
|
|
67
|
+
const orm = getOrm(ormMap, model);
|
|
68
|
+
if (where && where.length > 0) {
|
|
69
|
+
const criteria = whereToCriteria(where);
|
|
70
|
+
const rows = await orm.findAllBy(criteria);
|
|
71
|
+
return applyClientSidePagination(rows, sortBy, offset, limit);
|
|
72
|
+
}
|
|
73
|
+
const rows = await orm.list({
|
|
74
|
+
limit,
|
|
75
|
+
offset,
|
|
76
|
+
orderBy: sortBy?.field,
|
|
77
|
+
order: sortBy?.direction,
|
|
78
|
+
});
|
|
79
|
+
return rows;
|
|
80
|
+
},
|
|
81
|
+
count: async ({ model, where }) => {
|
|
82
|
+
const orm = getOrm(ormMap, model);
|
|
83
|
+
if (where && where.length > 0) {
|
|
84
|
+
const criteria = whereToCriteria(where);
|
|
85
|
+
const rows = await orm.findAllBy(criteria);
|
|
86
|
+
return rows.length;
|
|
87
|
+
}
|
|
88
|
+
const rows = await orm.list({ count: true });
|
|
89
|
+
return rows.total ?? rows.length;
|
|
90
|
+
},
|
|
91
|
+
update: async ({ model, where, update }) => {
|
|
92
|
+
const orm = getOrm(ormMap, model);
|
|
93
|
+
const criteria = whereToCriteria(where);
|
|
94
|
+
const target = 'id' in criteria
|
|
95
|
+
? await orm.findById(criteria.id)
|
|
96
|
+
: await orm.findBy(criteria);
|
|
97
|
+
if (!target)
|
|
98
|
+
return null;
|
|
99
|
+
return (await orm.update(target.id, update));
|
|
100
|
+
},
|
|
101
|
+
updateMany: async ({ model, where, update }) => {
|
|
102
|
+
const orm = getOrm(ormMap, model);
|
|
103
|
+
const criteria = whereToCriteria(where);
|
|
104
|
+
const targets = await orm.findAllBy(criteria);
|
|
105
|
+
await Promise.all(targets.map((t) => orm.update(t.id, update)));
|
|
106
|
+
return targets.length;
|
|
107
|
+
},
|
|
108
|
+
delete: async ({ model, where }) => {
|
|
109
|
+
const orm = getOrm(ormMap, model);
|
|
110
|
+
const criteria = whereToCriteria(where);
|
|
111
|
+
const target = 'id' in criteria
|
|
112
|
+
? await orm.findById(criteria.id)
|
|
113
|
+
: await orm.findBy(criteria);
|
|
114
|
+
if (target)
|
|
115
|
+
await orm.delete(target.id);
|
|
116
|
+
},
|
|
117
|
+
deleteMany: async ({ model, where }) => {
|
|
118
|
+
const orm = getOrm(ormMap, model);
|
|
119
|
+
const criteria = whereToCriteria(where);
|
|
120
|
+
const targets = await orm.findAllBy(criteria);
|
|
121
|
+
await Promise.all(targets.map((t) => orm.delete(t.id)));
|
|
122
|
+
return targets.length;
|
|
123
|
+
},
|
|
124
|
+
}),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Augmented EntityOrm shape — the core interface doesn't expose findBy/findAllBy
|
|
129
|
+
* but SqlEntityOrm (the only impl today) does. Cast locally to use them.
|
|
130
|
+
*/
|
|
131
|
+
/**
|
|
132
|
+
* EntityOrm.findAllBy doesn't expose pagination/sort, so we apply them in JS
|
|
133
|
+
* after fetching the eq-filtered rows. Fine for auth volumes (orgs/sessions/accounts).
|
|
134
|
+
*/
|
|
135
|
+
function applyClientSidePagination(rows, sortBy, offset, limit) {
|
|
136
|
+
let result = rows;
|
|
137
|
+
if (sortBy) {
|
|
138
|
+
const { field, direction } = sortBy;
|
|
139
|
+
result = [...result].sort((a, b) => {
|
|
140
|
+
const av = a[field], bv = b[field];
|
|
141
|
+
if (av == null && bv == null)
|
|
142
|
+
return 0;
|
|
143
|
+
if (av == null)
|
|
144
|
+
return -1;
|
|
145
|
+
if (bv == null)
|
|
146
|
+
return 1;
|
|
147
|
+
const cmp = av < bv ? -1 : av > bv ? 1 : 0;
|
|
148
|
+
return direction === 'desc' ? -cmp : cmp;
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
if (offset !== undefined)
|
|
152
|
+
result = result.slice(offset);
|
|
153
|
+
if (limit !== undefined)
|
|
154
|
+
result = result.slice(0, limit);
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type SchemaLike } from '@fougere/schema';
|
|
2
|
+
declare const AuthUser_base: import("@fougere/schema").SchemaConstructor<{
|
|
3
|
+
id: import("@fougere/schema").Field<string, true>;
|
|
4
|
+
name: import("@fougere/schema").Field<string, false>;
|
|
5
|
+
email: import("@fougere/schema").Field<string, false>;
|
|
6
|
+
emailVerified: import("@fougere/schema").Field<boolean, false>;
|
|
7
|
+
image: import("@fougere/schema").Field<string | null, true>;
|
|
8
|
+
createdAt: import("@fougere/schema").Field<Date, true>;
|
|
9
|
+
updatedAt: import("@fougere/schema").Field<Date, true>;
|
|
10
|
+
}>;
|
|
11
|
+
/**
|
|
12
|
+
* Default User entity — shipped as a fallback. Apps should declare their own
|
|
13
|
+
* User entity in a frond and pass it via `auth.user` (with extra fields like roles).
|
|
14
|
+
*
|
|
15
|
+
* Field shape matches better-auth's expectations: name/email/emailVerified/image
|
|
16
|
+
* + standard timestamps.
|
|
17
|
+
*/
|
|
18
|
+
export declare class AuthUser extends AuthUser_base {
|
|
19
|
+
}
|
|
20
|
+
export declare function authEntities(User: SchemaLike): {
|
|
21
|
+
AuthSession: SchemaLike;
|
|
22
|
+
AuthAccount: SchemaLike;
|
|
23
|
+
};
|
|
24
|
+
declare const AuthVerification_base: import("@fougere/schema").SchemaConstructor<{
|
|
25
|
+
id: import("@fougere/schema").Field<string, true>;
|
|
26
|
+
identifier: import("@fougere/schema").Field<string, false>;
|
|
27
|
+
value: import("@fougere/schema").Field<string, false>;
|
|
28
|
+
expiresAt: import("@fougere/schema").Field<Date, false>;
|
|
29
|
+
createdAt: import("@fougere/schema").Field<Date, true>;
|
|
30
|
+
updatedAt: import("@fougere/schema").Field<Date, true>;
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* Default Verification entity — better-auth shape.
|
|
34
|
+
* Used for email verification, password reset, magic links, etc.
|
|
35
|
+
*/
|
|
36
|
+
export declare class AuthVerification extends AuthVerification_base {
|
|
37
|
+
}
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=entities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entities.d.ts","sourceRoot":"","sources":["../src/entities.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0D,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;;;;;;;;;;AAE1G;;;;;;GAMG;AACH,qBAAa,QAAS,SAAQ,aAQ5B;CAAG;AAqBL,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG;IAC9C,WAAW,EAAE,UAAU,CAAC;IACxB,WAAW,EAAE,UAAU,CAAC;CACzB,CAuCA;;;;;;;;;AAED;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,qBAOpC;CAAG"}
|
package/dist/entities.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { entity, primary, text, bool, date, auto, ref, optional } from '@fougere/schema';
|
|
2
|
+
/**
|
|
3
|
+
* Default User entity — shipped as a fallback. Apps should declare their own
|
|
4
|
+
* User entity in a frond and pass it via `auth.user` (with extra fields like roles).
|
|
5
|
+
*
|
|
6
|
+
* Field shape matches better-auth's expectations: name/email/emailVerified/image
|
|
7
|
+
* + standard timestamps.
|
|
8
|
+
*/
|
|
9
|
+
export class AuthUser extends entity({
|
|
10
|
+
id: primary(),
|
|
11
|
+
name: text(),
|
|
12
|
+
email: text(),
|
|
13
|
+
emailVerified: bool(),
|
|
14
|
+
image: optional(text()),
|
|
15
|
+
createdAt: auto(),
|
|
16
|
+
updatedAt: auto(),
|
|
17
|
+
}) {
|
|
18
|
+
}
|
|
19
|
+
export function authEntities(User) {
|
|
20
|
+
const target = User;
|
|
21
|
+
/**
|
|
22
|
+
* Session entity — better-auth shape.
|
|
23
|
+
* `token` carries the opaque session secret (cookie value).
|
|
24
|
+
*/
|
|
25
|
+
class AuthSession extends entity({
|
|
26
|
+
id: primary(),
|
|
27
|
+
userId: ref(target),
|
|
28
|
+
token: text(),
|
|
29
|
+
expiresAt: date(),
|
|
30
|
+
ipAddress: optional(text()),
|
|
31
|
+
userAgent: optional(text()),
|
|
32
|
+
createdAt: auto(),
|
|
33
|
+
updatedAt: auto(),
|
|
34
|
+
}) {
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Account entity — better-auth shape (single PK, accountId/providerId pair,
|
|
38
|
+
* separate token columns instead of a JSON blob).
|
|
39
|
+
*/
|
|
40
|
+
class AuthAccount extends entity({
|
|
41
|
+
id: primary(),
|
|
42
|
+
accountId: text(),
|
|
43
|
+
providerId: text(),
|
|
44
|
+
userId: ref(target),
|
|
45
|
+
accessToken: optional(text()),
|
|
46
|
+
refreshToken: optional(text()),
|
|
47
|
+
idToken: optional(text()),
|
|
48
|
+
accessTokenExpiresAt: optional(date()),
|
|
49
|
+
refreshTokenExpiresAt: optional(date()),
|
|
50
|
+
scope: optional(text()),
|
|
51
|
+
password: optional(text()),
|
|
52
|
+
createdAt: auto(),
|
|
53
|
+
updatedAt: auto(),
|
|
54
|
+
}) {
|
|
55
|
+
}
|
|
56
|
+
return { AuthSession, AuthAccount };
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Default Verification entity — better-auth shape.
|
|
60
|
+
* Used for email verification, password reset, magic links, etc.
|
|
61
|
+
*/
|
|
62
|
+
export class AuthVerification extends entity({
|
|
63
|
+
id: primary(),
|
|
64
|
+
identifier: text(),
|
|
65
|
+
value: text(),
|
|
66
|
+
expiresAt: date(),
|
|
67
|
+
createdAt: auto(),
|
|
68
|
+
updatedAt: auto(),
|
|
69
|
+
}) {
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=entities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entities.js","sourceRoot":"","sources":["../src/entities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAmB,MAAM,iBAAiB,CAAC;AAE1G;;;;;;GAMG;AACH,MAAM,OAAO,QAAS,SAAQ,MAAM,CAAC;IACnC,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,IAAI,EAAE;IACjB,SAAS,EAAE,IAAI,EAAE;CAClB,CAAC;CAAG;AAqBL,MAAM,UAAU,YAAY,CAAC,IAAgB;IAI3C,MAAM,MAAM,GAAG,IAA6B,CAAC;IAE7C;;;OAGG;IACH,MAAM,WAAY,SAAQ,MAAM,CAAC;QAC/B,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,IAAI,EAAE;QACjB,SAAS,EAAE,IAAI,EAAE;KAClB,CAAC;KAAG;IAEL;;;OAGG;IACH,MAAM,WAAY,SAAQ,MAAM,CAAC;QAC/B,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,IAAI,EAAE;QACjB,SAAS,EAAE,IAAI,EAAE;KAClB,CAAC;KAAG;IAEL,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC;AACtC,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,gBAAiB,SAAQ,MAAM,CAAC;IAC3C,EAAE,EAAE,OAAO,EAAE;IACb,UAAU,EAAE,IAAI,EAAE;IAClB,KAAK,EAAE,IAAI,EAAE;IACb,SAAS,EAAE,IAAI,EAAE;IACjB,SAAS,EAAE,IAAI,EAAE;IACjB,SAAS,EAAE,IAAI,EAAE;CAClB,CAAC;CAAG"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { AuthConfig } from '@fougere/core';
|
|
2
|
+
import type { SchemaLike } from '@fougere/schema';
|
|
3
|
+
import { type FougereProviders } from './translate.js';
|
|
4
|
+
export { AuthUser, AuthVerification, authEntities } from './entities.js';
|
|
5
|
+
export type { FougereProviders, OIDCProviderConfig } from './translate.js';
|
|
6
|
+
/**
|
|
7
|
+
* Options accepted by the betterAuth() factory in fougere.config.ts.
|
|
8
|
+
*
|
|
9
|
+
* `user` should come from the app's own frond (roles, extra columns, its own
|
|
10
|
+
* table — Session/Account are built against it, see `authEntities`). Omitting
|
|
11
|
+
* it falls back to the package's `AuthUser`. Other entities default to the
|
|
12
|
+
* shapes shipped by this package and can be overridden too.
|
|
13
|
+
*/
|
|
14
|
+
export interface BetterAuthOptions {
|
|
15
|
+
user?: SchemaLike;
|
|
16
|
+
secret: string;
|
|
17
|
+
baseUrl?: string;
|
|
18
|
+
basePath?: string;
|
|
19
|
+
providers?: FougereProviders;
|
|
20
|
+
trustedOrigins?: string[];
|
|
21
|
+
sessionTtl?: number;
|
|
22
|
+
session?: SchemaLike;
|
|
23
|
+
account?: SchemaLike;
|
|
24
|
+
verification?: SchemaLike;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Factory used in fougere.config.ts:
|
|
28
|
+
*
|
|
29
|
+
* ```ts
|
|
30
|
+
* export default defineFougere({
|
|
31
|
+
* auth: betterAuth({ user: User, secret, providers: {...} }),
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* Returns a lazy AuthConfig — the better-auth engine is only constructed when
|
|
36
|
+
* the core calls `create(ctx)` at boot, with the resolved db + ormFactory.
|
|
37
|
+
*/
|
|
38
|
+
export declare function betterAuth(opts: BetterAuthOptions): AuthConfig;
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAA4B,MAAM,eAAe,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGlD,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACzE,YAAY,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAE3E;;;;;;;GAOG;AACH,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;;;;;;;;;;;GAWG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,UAAU,CAmD9D"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { betterAuth as betterAuthLib } from 'better-auth';
|
|
2
|
+
import { createId } from '@paralleldrive/cuid2';
|
|
3
|
+
import { AuthVerification, AuthUser, authEntities } from './entities.js';
|
|
4
|
+
import { fougereAdapter } from './adapter.js';
|
|
5
|
+
import { translateCredential, translateSocial, translatePlugins, } from './translate.js';
|
|
6
|
+
export { AuthUser, AuthVerification, authEntities } from './entities.js';
|
|
7
|
+
/**
|
|
8
|
+
* Factory used in fougere.config.ts:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* export default defineFougere({
|
|
12
|
+
* auth: betterAuth({ user: User, secret, providers: {...} }),
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Returns a lazy AuthConfig — the better-auth engine is only constructed when
|
|
17
|
+
* the core calls `create(ctx)` at boot, with the resolved db + ormFactory.
|
|
18
|
+
*/
|
|
19
|
+
export function betterAuth(opts) {
|
|
20
|
+
const userSchema = opts.user ?? AuthUser;
|
|
21
|
+
const { AuthSession, AuthAccount } = authEntities(userSchema);
|
|
22
|
+
const sessionSchema = opts.session ?? AuthSession;
|
|
23
|
+
const accountSchema = opts.account ?? AuthAccount;
|
|
24
|
+
const verificationSchema = opts.verification ?? AuthVerification;
|
|
25
|
+
const providers = opts.providers ?? {};
|
|
26
|
+
const basePath = opts.basePath ?? '/auth';
|
|
27
|
+
return {
|
|
28
|
+
entities: {
|
|
29
|
+
user: userSchema,
|
|
30
|
+
session: sessionSchema,
|
|
31
|
+
account: accountSchema,
|
|
32
|
+
verification: verificationSchema,
|
|
33
|
+
},
|
|
34
|
+
create({ ormFactory }) {
|
|
35
|
+
const ormMap = new Map([
|
|
36
|
+
['user', ormFactory(userSchema, 'user')],
|
|
37
|
+
['session', ormFactory(sessionSchema, 'session')],
|
|
38
|
+
['account', ormFactory(accountSchema, 'account')],
|
|
39
|
+
['verification', ormFactory(verificationSchema, 'verification')],
|
|
40
|
+
]);
|
|
41
|
+
const engine = betterAuthLib({
|
|
42
|
+
database: fougereAdapter(ormMap),
|
|
43
|
+
secret: opts.secret,
|
|
44
|
+
baseURL: opts.baseUrl,
|
|
45
|
+
basePath,
|
|
46
|
+
trustedOrigins: opts.trustedOrigins,
|
|
47
|
+
advanced: { database: { generateId: () => createId() } },
|
|
48
|
+
session: opts.sessionTtl ? { expiresIn: opts.sessionTtl / 1000 } : undefined,
|
|
49
|
+
emailAndPassword: translateCredential(providers),
|
|
50
|
+
socialProviders: translateSocial(providers),
|
|
51
|
+
plugins: translatePlugins(providers),
|
|
52
|
+
});
|
|
53
|
+
return {
|
|
54
|
+
entities: {
|
|
55
|
+
user: userSchema,
|
|
56
|
+
session: sessionSchema,
|
|
57
|
+
account: accountSchema,
|
|
58
|
+
verification: verificationSchema,
|
|
59
|
+
},
|
|
60
|
+
orms: Object.fromEntries(ormMap),
|
|
61
|
+
handler: engine.handler,
|
|
62
|
+
api: engine.api,
|
|
63
|
+
basePath,
|
|
64
|
+
};
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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;AAGhD,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,EAAE,cAAc,EAAe,MAAM,cAAc,CAAC;AAC3D,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,gBAAgB,GAEjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAwBzE;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,UAAU,CAAC,IAAuB;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,IAAI,QAAQ,CAAC;IACzC,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;IAC9D,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,IAAI,WAAW,CAAC;IAClD,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,IAAI,WAAW,CAAC;IAClD,MAAM,kBAAkB,GAAG,IAAI,CAAC,YAAY,IAAI,gBAAgB,CAAC;IACjE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,OAAO,CAAC;IAE1C,OAAO;QACL,QAAQ,EAAE;YACR,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,aAAa;YACtB,OAAO,EAAE,aAAa;YACtB,YAAY,EAAE,kBAAkB;SACjC;QACD,MAAM,CAAC,EAAE,UAAU,EAAe;YAChC,MAAM,MAAM,GAAW,IAAI,GAAG,CAAC;gBAC7B,CAAC,MAAM,EAAE,UAAU,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;gBACxC,CAAC,SAAS,EAAE,UAAU,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;gBACjD,CAAC,SAAS,EAAE,UAAU,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;gBACjD,CAAC,cAAc,EAAE,UAAU,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAC;aACjE,CAAC,CAAC;YAEH,MAAM,MAAM,GAAG,aAAa,CAAC;gBAC3B,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC;gBAChC,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,QAAQ;gBACR,cAAc,EAAE,IAAI,CAAC,cAAc;gBACnC,QAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,EAAE;gBACxD,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,UAAU,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;gBAC5E,gBAAgB,EAAE,mBAAmB,CAAC,SAAS,CAAC;gBAChD,eAAe,EAAE,eAAe,CAAC,SAAS,CAAC;gBAC3C,OAAO,EAAE,gBAAgB,CAAC,SAAS,CAAC;aACrC,CAAC,CAAC;YAEH,OAAO;gBACL,QAAQ,EAAE;oBACR,IAAI,EAAE,UAAU;oBAChB,OAAO,EAAE,aAAa;oBACtB,OAAO,EAAE,aAAa;oBACtB,YAAY,EAAE,kBAAkB;iBACjC;gBACD,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC;gBAChC,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,GAAG,EAAE,MAAM,CAAC,GAA8B;gBAC1C,QAAQ;aACT,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { BetterAuthOptions, BetterAuthPlugin } from 'better-auth';
|
|
2
|
+
/**
|
|
3
|
+
* Fougere-side provider declaration. Mirrors what users write in fougere.config.ts.
|
|
4
|
+
*
|
|
5
|
+
* - `credential`: email + password (better-auth's emailAndPassword)
|
|
6
|
+
* - Standard OAuth keys (google, github, ...): become socialProviders
|
|
7
|
+
* - `oidc`: dictionary of OIDC providers, become genericOAuth plugin entries
|
|
8
|
+
*/
|
|
9
|
+
export interface FougereProviders {
|
|
10
|
+
credential?: {
|
|
11
|
+
minPasswordLength?: number;
|
|
12
|
+
maxPasswordLength?: number;
|
|
13
|
+
autoSignIn?: boolean;
|
|
14
|
+
};
|
|
15
|
+
google?: {
|
|
16
|
+
clientId: string;
|
|
17
|
+
clientSecret: string;
|
|
18
|
+
scope?: string[];
|
|
19
|
+
};
|
|
20
|
+
github?: {
|
|
21
|
+
clientId: string;
|
|
22
|
+
clientSecret: string;
|
|
23
|
+
scope?: string[];
|
|
24
|
+
};
|
|
25
|
+
facebook?: {
|
|
26
|
+
clientId: string;
|
|
27
|
+
clientSecret: string;
|
|
28
|
+
scope?: string[];
|
|
29
|
+
};
|
|
30
|
+
apple?: {
|
|
31
|
+
clientId: string;
|
|
32
|
+
clientSecret: string;
|
|
33
|
+
scope?: string[];
|
|
34
|
+
};
|
|
35
|
+
discord?: {
|
|
36
|
+
clientId: string;
|
|
37
|
+
clientSecret: string;
|
|
38
|
+
scope?: string[];
|
|
39
|
+
};
|
|
40
|
+
microsoft?: {
|
|
41
|
+
clientId: string;
|
|
42
|
+
clientSecret: string;
|
|
43
|
+
scope?: string[];
|
|
44
|
+
};
|
|
45
|
+
oidc?: Record<string, OIDCProviderConfig>;
|
|
46
|
+
}
|
|
47
|
+
export interface OIDCProviderConfig {
|
|
48
|
+
/** Provider id used in the URL (e.g. /auth/oauth2/{id}/callback). Defaults to the dict key. */
|
|
49
|
+
id?: string;
|
|
50
|
+
/** OIDC issuer URL — used to derive the discovery URL. */
|
|
51
|
+
issuer: string;
|
|
52
|
+
clientId: string;
|
|
53
|
+
clientSecret: string;
|
|
54
|
+
scopes?: string[];
|
|
55
|
+
/** Pass-through for better-auth's genericOAuth provider config. */
|
|
56
|
+
redirectURI?: string;
|
|
57
|
+
responseType?: string;
|
|
58
|
+
}
|
|
59
|
+
export declare function translateCredential(providers?: FougereProviders): BetterAuthOptions['emailAndPassword'];
|
|
60
|
+
export declare function translateSocial(providers?: FougereProviders): BetterAuthOptions['socialProviders'];
|
|
61
|
+
/**
|
|
62
|
+
* Build the plugin list from Fougere provider config.
|
|
63
|
+
* Currently produces:
|
|
64
|
+
* - `genericOAuth` plugin when `providers.oidc` is set (one entry per declared OIDC provider).
|
|
65
|
+
*/
|
|
66
|
+
export declare function translatePlugins(providers?: FougereProviders): BetterAuthPlugin[];
|
|
67
|
+
//# sourceMappingURL=translate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translate.d.ts","sourceRoot":"","sources":["../src/translate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEvE;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE;QACX,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,MAAM,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACtE,MAAM,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACtE,QAAQ,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACxE,KAAK,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACrE,OAAO,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACvE,SAAS,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,kBAAkB;IACjC,+FAA+F;IAC/F,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAID,wBAAgB,mBAAmB,CAAC,SAAS,CAAC,EAAE,gBAAgB,GAAG,iBAAiB,CAAC,kBAAkB,CAAC,CASvG;AAED,wBAAgB,eAAe,CAAC,SAAS,CAAC,EAAE,gBAAgB,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,CAOlG;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,CAAC,EAAE,gBAAgB,GAAG,gBAAgB,EAAE,CAejF"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { genericOAuth } from 'better-auth/plugins';
|
|
2
|
+
const SOCIAL_KEYS = new Set(['google', 'github', 'facebook', 'apple', 'discord', 'microsoft']);
|
|
3
|
+
export function translateCredential(providers) {
|
|
4
|
+
const cred = providers?.credential;
|
|
5
|
+
if (!cred)
|
|
6
|
+
return { enabled: false };
|
|
7
|
+
return {
|
|
8
|
+
enabled: true,
|
|
9
|
+
minPasswordLength: cred.minPasswordLength,
|
|
10
|
+
maxPasswordLength: cred.maxPasswordLength,
|
|
11
|
+
autoSignIn: cred.autoSignIn,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function translateSocial(providers) {
|
|
15
|
+
if (!providers)
|
|
16
|
+
return {};
|
|
17
|
+
const social = {};
|
|
18
|
+
for (const [key, value] of Object.entries(providers)) {
|
|
19
|
+
if (SOCIAL_KEYS.has(key))
|
|
20
|
+
social[key] = value;
|
|
21
|
+
}
|
|
22
|
+
return social;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Build the plugin list from Fougere provider config.
|
|
26
|
+
* Currently produces:
|
|
27
|
+
* - `genericOAuth` plugin when `providers.oidc` is set (one entry per declared OIDC provider).
|
|
28
|
+
*/
|
|
29
|
+
export function translatePlugins(providers) {
|
|
30
|
+
const plugins = [];
|
|
31
|
+
if (providers?.oidc) {
|
|
32
|
+
const config = Object.entries(providers.oidc).map(([key, oidc]) => ({
|
|
33
|
+
providerId: oidc.id ?? key,
|
|
34
|
+
discoveryUrl: oidc.issuer.replace(/\/$/, '') + '/.well-known/openid-configuration',
|
|
35
|
+
clientId: oidc.clientId,
|
|
36
|
+
clientSecret: oidc.clientSecret,
|
|
37
|
+
scopes: oidc.scopes ?? ['openid', 'email', 'profile'],
|
|
38
|
+
redirectURI: oidc.redirectURI,
|
|
39
|
+
responseType: oidc.responseType,
|
|
40
|
+
}));
|
|
41
|
+
plugins.push(genericOAuth({ config }));
|
|
42
|
+
}
|
|
43
|
+
return plugins;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=translate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../src/translate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAsCnD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;AAE/F,MAAM,UAAU,mBAAmB,CAAC,SAA4B;IAC9D,MAAM,IAAI,GAAG,SAAS,EAAE,UAAU,CAAC;IACnC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IACrC,OAAO;QACL,OAAO,EAAE,IAAI;QACb,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;QACzC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;QACzC,UAAU,EAAE,IAAI,CAAC,UAAU;KAC5B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,SAA4B;IAC1D,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,CAAC;IAC1B,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QACrD,IAAI,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAChD,CAAC;IACD,OAAO,MAA8C,CAAC;AACxD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,SAA4B;IAC3D,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,IAAI,SAAS,EAAE,IAAI,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YAClE,UAAU,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;YAC1B,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,mCAAmC;YAClF,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,MAAM,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC;YACrD,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,YAAY,EAAE,IAAI,CAAC,YAAY;SAChC,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fougere/auth-better",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "Fougere's auth — a translation layer onto better-auth.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/chok/fougere.git",
|
|
9
|
+
"directory": "packages/auth-better"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "dist/index.js",
|
|
13
|
+
"types": "dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@paralleldrive/cuid2": "^3.3.0",
|
|
25
|
+
"better-auth": "^1.6.11",
|
|
26
|
+
"@fougere/core": "0.1.0-alpha.0",
|
|
27
|
+
"@fougere/schema": "0.1.0-alpha.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"vitest": "^4.1.0",
|
|
31
|
+
"@fougere/schema-sql": "0.1.0-alpha.0"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "rm -rf dist && tsc",
|
|
38
|
+
"test": "vitest run",
|
|
39
|
+
"test:watch": "vitest",
|
|
40
|
+
"typecheck": "tsc --noEmit -p tsconfig.test.json"
|
|
41
|
+
}
|
|
42
|
+
}
|