@lunora/auth 1.0.0-alpha.5 → 1.0.0-alpha.50
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.md +38 -0
- package/README.md +56 -1
- package/dist/adapter.d.mts +35 -35
- package/dist/adapter.d.ts +35 -35
- package/dist/adapter.mjs +1 -47
- package/dist/audit.d.mts +114 -0
- package/dist/audit.d.ts +114 -0
- package/dist/audit.mjs +11 -0
- package/dist/email-guard.d.mts +122 -0
- package/dist/email-guard.d.ts +122 -0
- package/dist/email-guard.mjs +1 -0
- package/dist/index.d.mts +460 -146
- package/dist/index.d.ts +460 -146
- package/dist/index.mjs +1 -12
- package/dist/middleware.d.mts +156 -155
- package/dist/middleware.d.ts +156 -155
- package/dist/middleware.mjs +1 -53
- package/dist/packem_shared/DEFAULT_AUTH_BASE_PATH-kIwlEt8i.mjs +1 -0
- package/dist/packem_shared/LunoraAuthAdminError-CiHsF1qZ.mjs +1 -0
- package/dist/packem_shared/authAuditHook-Dx3sqf3G.mjs +1 -0
- package/dist/packem_shared/compileMigrationsSql-C-2ALo6c.mjs +1 -0
- package/dist/packem_shared/create-auth.d-De6IOirt.d.mts +128 -0
- package/dist/packem_shared/create-auth.d-De6IOirt.d.ts +128 -0
- package/dist/packem_shared/createAuth-DS6PL8Mb.mjs +1 -0
- package/dist/packem_shared/emailGateDatabaseHooks-DzBD1Qoq.mjs +1 -0
- package/dist/packem_shared/sessionPresets-DpEFjXKV.mjs +1 -0
- package/dist/plugins-client.d.mts +2 -1
- package/dist/plugins-client.d.ts +2 -1
- package/dist/plugins-client.mjs +1 -2
- package/dist/plugins-enterprise-client.d.mts +9 -0
- package/dist/plugins-enterprise-client.d.ts +9 -0
- package/dist/plugins-enterprise-client.mjs +1 -0
- package/dist/plugins-enterprise.d.mts +1576 -0
- package/dist/plugins-enterprise.d.ts +1576 -0
- package/dist/plugins-enterprise.mjs +1 -0
- package/dist/plugins.d.mts +4 -2
- package/dist/plugins.d.ts +4 -2
- package/dist/plugins.mjs +1 -22
- package/dist/schema.d.mts +39 -39
- package/dist/schema.d.ts +39 -39
- package/dist/schema.mjs +1 -62
- package/dist/sql-store.d.mts +28 -28
- package/dist/sql-store.d.ts +28 -28
- package/dist/sql-store.mjs +1 -162
- package/dist/store.d.mts +49 -31
- package/dist/store.d.ts +49 -31
- package/dist/store.mjs +1 -170
- package/dist/turnstile-middleware.d.mts +55 -55
- package/dist/turnstile-middleware.d.ts +55 -55
- package/dist/turnstile-middleware.mjs +1 -45
- package/dist/turnstile.d.mts +42 -59
- package/dist/turnstile.d.ts +42 -59
- package/dist/turnstile.mjs +1 -61
- package/package.json +39 -6
- package/dist/packem_shared/DEFAULT_AUTH_BASE_PATH-DjcUWEQl.mjs +0 -11
- package/dist/packem_shared/LunoraAuthAdminError-BxrfEeA_.mjs +0 -249
- package/dist/packem_shared/compileMigrationsSql-wZH3oXDu.mjs +0 -28
- package/dist/packem_shared/create-auth.d-M36jwG_Y.d.mts +0 -58
- package/dist/packem_shared/create-auth.d-M36jwG_Y.d.ts +0 -58
- package/dist/packem_shared/createAuth-B-tvsvQU.mjs +0 -56
- package/dist/packem_shared/sessionPresets-B95rXrd8.mjs +0 -35
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{sso as s}from"@better-auth/sso";export{s as sso};
|
package/dist/plugins.d.mts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
export { mcp, mcpHandler, requireMcpAuth } from '@better-auth/mcp';
|
|
2
|
+
export { oauthProvider } from '@better-auth/oauth-provider';
|
|
1
3
|
export { passkey } from '@better-auth/passkey';
|
|
2
|
-
export {
|
|
4
|
+
export { scim } from '@better-auth/scim';
|
|
5
|
+
export { captcha } from 'better-auth/plugins';
|
|
3
6
|
export { createAccessControl } from 'better-auth/plugins/access';
|
|
4
7
|
export { admin } from 'better-auth/plugins/admin';
|
|
5
8
|
export { anonymous } from 'better-auth/plugins/anonymous';
|
|
@@ -13,7 +16,6 @@ export { jwt } from 'better-auth/plugins/jwt';
|
|
|
13
16
|
export { magicLink } from 'better-auth/plugins/magic-link';
|
|
14
17
|
export { multiSession } from 'better-auth/plugins/multi-session';
|
|
15
18
|
export { oAuthProxy } from 'better-auth/plugins/oauth-proxy';
|
|
16
|
-
export { oidcProvider } from 'better-auth/plugins/oidc-provider';
|
|
17
19
|
export { oneTimeToken } from 'better-auth/plugins/one-time-token';
|
|
18
20
|
export { organization } from 'better-auth/plugins/organization';
|
|
19
21
|
export { phoneNumber } from 'better-auth/plugins/phone-number';
|
package/dist/plugins.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
export { mcp, mcpHandler, requireMcpAuth } from '@better-auth/mcp';
|
|
2
|
+
export { oauthProvider } from '@better-auth/oauth-provider';
|
|
1
3
|
export { passkey } from '@better-auth/passkey';
|
|
2
|
-
export {
|
|
4
|
+
export { scim } from '@better-auth/scim';
|
|
5
|
+
export { captcha } from 'better-auth/plugins';
|
|
3
6
|
export { createAccessControl } from 'better-auth/plugins/access';
|
|
4
7
|
export { admin } from 'better-auth/plugins/admin';
|
|
5
8
|
export { anonymous } from 'better-auth/plugins/anonymous';
|
|
@@ -13,7 +16,6 @@ export { jwt } from 'better-auth/plugins/jwt';
|
|
|
13
16
|
export { magicLink } from 'better-auth/plugins/magic-link';
|
|
14
17
|
export { multiSession } from 'better-auth/plugins/multi-session';
|
|
15
18
|
export { oAuthProxy } from 'better-auth/plugins/oauth-proxy';
|
|
16
|
-
export { oidcProvider } from 'better-auth/plugins/oidc-provider';
|
|
17
19
|
export { oneTimeToken } from 'better-auth/plugins/one-time-token';
|
|
18
20
|
export { organization } from 'better-auth/plugins/organization';
|
|
19
21
|
export { phoneNumber } from 'better-auth/plugins/phone-number';
|
package/dist/plugins.mjs
CHANGED
|
@@ -1,22 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { captcha, mcp, withMcpAuth } from 'better-auth/plugins';
|
|
3
|
-
export { createAccessControl } from 'better-auth/plugins/access';
|
|
4
|
-
export { admin } from 'better-auth/plugins/admin';
|
|
5
|
-
export { anonymous } from 'better-auth/plugins/anonymous';
|
|
6
|
-
export { bearer } from 'better-auth/plugins/bearer';
|
|
7
|
-
export { customSession } from 'better-auth/plugins/custom-session';
|
|
8
|
-
export { deviceAuthorization } from 'better-auth/plugins/device-authorization';
|
|
9
|
-
export { emailOTP } from 'better-auth/plugins/email-otp';
|
|
10
|
-
export { genericOAuth } from 'better-auth/plugins/generic-oauth';
|
|
11
|
-
export { haveIBeenPwned } from 'better-auth/plugins/haveibeenpwned';
|
|
12
|
-
export { jwt } from 'better-auth/plugins/jwt';
|
|
13
|
-
export { magicLink } from 'better-auth/plugins/magic-link';
|
|
14
|
-
export { multiSession } from 'better-auth/plugins/multi-session';
|
|
15
|
-
export { oAuthProxy } from 'better-auth/plugins/oauth-proxy';
|
|
16
|
-
export { oidcProvider } from 'better-auth/plugins/oidc-provider';
|
|
17
|
-
export { oneTimeToken } from 'better-auth/plugins/one-time-token';
|
|
18
|
-
export { organization } from 'better-auth/plugins/organization';
|
|
19
|
-
export { phoneNumber } from 'better-auth/plugins/phone-number';
|
|
20
|
-
export { siwe } from 'better-auth/plugins/siwe';
|
|
21
|
-
export { twoFactor } from 'better-auth/plugins/two-factor';
|
|
22
|
-
export { username } from 'better-auth/plugins/username';
|
|
1
|
+
import{mcp as e,mcpHandler as t,requireMcpAuth as m}from"@better-auth/mcp";import{oauthProvider as x}from"@better-auth/oauth-provider";import{passkey as i}from"@better-auth/passkey";import{scim as a}from"@better-auth/scim";import{captcha as s}from"better-auth/plugins";import{createAccessControl as h}from"better-auth/plugins/access";import{admin as A}from"better-auth/plugins/admin";import{anonymous as w}from"better-auth/plugins/anonymous";import{bearer as g}from"better-auth/plugins/bearer";import{customSession as v}from"better-auth/plugins/custom-session";import{deviceAuthorization as T}from"better-auth/plugins/device-authorization";import{emailOTP as z}from"better-auth/plugins/email-otp";import{genericOAuth as S}from"better-auth/plugins/generic-oauth";import{haveIBeenPwned as q}from"better-auth/plugins/haveibeenpwned";import{jwt as C}from"better-auth/plugins/jwt";import{magicLink as H}from"better-auth/plugins/magic-link";import{multiSession as L}from"better-auth/plugins/multi-session";import{oAuthProxy as N}from"better-auth/plugins/oauth-proxy";import{oneTimeToken as E}from"better-auth/plugins/one-time-token";import{organization as J}from"better-auth/plugins/organization";import{phoneNumber as Q}from"better-auth/plugins/phone-number";import{siwe as U}from"better-auth/plugins/siwe";import{twoFactor as W}from"better-auth/plugins/two-factor";import{username as Y}from"better-auth/plugins/username";export{A as admin,w as anonymous,g as bearer,s as captcha,h as createAccessControl,v as customSession,T as deviceAuthorization,z as emailOTP,S as genericOAuth,q as haveIBeenPwned,C as jwt,H as magicLink,e as mcp,t as mcpHandler,L as multiSession,N as oAuthProxy,x as oauthProvider,E as oneTimeToken,J as organization,i as passkey,Q as phoneNumber,m as requireMcpAuth,a as scim,U as siwe,W as twoFactor,Y as username};
|
package/dist/schema.d.mts
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
import { TableDefinition } from '@lunora/server';
|
|
2
|
-
import { a as LunoraAuthOptions } from "./packem_shared/create-auth.d-
|
|
2
|
+
import { a as LunoraAuthOptions } from "./packem_shared/create-auth.d-De6IOirt.mjs";
|
|
3
3
|
import 'better-auth';
|
|
4
4
|
/**
|
|
5
|
-
* Derive Lunora table definitions from a better-auth config — the bridge that
|
|
6
|
-
* makes the **full** better-auth plugin ecosystem first-class Lunora data.
|
|
7
|
-
*
|
|
8
|
-
* better-auth's own `getAuthTables(options)` already merges every configured
|
|
9
|
-
* plugin's `schema` into one table map (core `user`/`session`/`account`/
|
|
10
|
-
* `verification`, plus whatever the plugins on `options.plugins` add —
|
|
11
|
-
* `organization`/`member`/`invitation`/`team`/`teamMember` from the
|
|
12
|
-
* organization plugin, `role`/`banned`/… columns from admin, `passkey`,
|
|
13
|
-
* `twoFactor`, `jwks`, …). This walks that map and emits an equivalent
|
|
14
|
-
* `defineTable` for each, so adding a plugin to `options.plugins` automatically
|
|
15
|
-
* surfaces its tables in the Lunora schema — no hand-written table definitions
|
|
16
|
-
* to keep in sync.
|
|
17
|
-
*
|
|
18
|
-
* Spread the result into `defineSchema` alongside your app tables (the keys are
|
|
19
|
-
* better-auth's real table names — `user`, `session`, … — left **unprefixed**
|
|
20
|
-
* because better-auth's adapter addresses them by exactly those names). Because
|
|
21
|
-
* the names are unprefixed, do **not** declare an app table that reuses one of
|
|
22
|
-
* better-auth's reserved names in the same `defineSchema` — JS spread order
|
|
23
|
-
* would let the later key win silently (unlike the plugin-extension path, which
|
|
24
|
-
* throws on collision):
|
|
25
|
-
*
|
|
26
|
-
* ```ts
|
|
27
|
-
* import { authTables } from "@lunora/auth";
|
|
28
|
-
* const authOptions = { emailAndPassword: { enabled: true }, plugins: [organization(), admin()] };
|
|
29
|
-
* export const schema = defineSchema({
|
|
30
|
-
* ...authTables(authOptions),
|
|
31
|
-
* todos: defineTable({ title: v.string() }),
|
|
32
|
-
* });
|
|
33
|
-
* ```
|
|
34
|
-
*
|
|
35
|
-
* Scope: this emits the table **shapes** (columns + types + nullability +
|
|
36
|
-
* uniqueness + FK ids). It deliberately does not carry better-auth's
|
|
37
|
-
* `defaultValue`/`onUpdate` (filled by better-auth's own write layer), `index`
|
|
38
|
-
* hints, or `bigint` precision (`bigint` fields map to `v.number()`). Those only
|
|
39
|
-
* matter once better-auth's writes are routed through Lunora's ORM — a separate
|
|
40
|
-
* adapter follow-up; today the auth rows are still written by better-auth's D1
|
|
41
|
-
* adapter and these tables make them typed + queryable via `ctx.db`.
|
|
42
|
-
*/
|
|
5
|
+
* Derive Lunora table definitions from a better-auth config — the bridge that
|
|
6
|
+
* makes the **full** better-auth plugin ecosystem first-class Lunora data.
|
|
7
|
+
*
|
|
8
|
+
* better-auth's own `getAuthTables(options)` already merges every configured
|
|
9
|
+
* plugin's `schema` into one table map (core `user`/`session`/`account`/
|
|
10
|
+
* `verification`, plus whatever the plugins on `options.plugins` add —
|
|
11
|
+
* `organization`/`member`/`invitation`/`team`/`teamMember` from the
|
|
12
|
+
* organization plugin, `role`/`banned`/… columns from admin, `passkey`,
|
|
13
|
+
* `twoFactor`, `jwks`, …). This walks that map and emits an equivalent
|
|
14
|
+
* `defineTable` for each, so adding a plugin to `options.plugins` automatically
|
|
15
|
+
* surfaces its tables in the Lunora schema — no hand-written table definitions
|
|
16
|
+
* to keep in sync.
|
|
17
|
+
*
|
|
18
|
+
* Spread the result into `defineSchema` alongside your app tables (the keys are
|
|
19
|
+
* better-auth's real table names — `user`, `session`, … — left **unprefixed**
|
|
20
|
+
* because better-auth's adapter addresses them by exactly those names). Because
|
|
21
|
+
* the names are unprefixed, do **not** declare an app table that reuses one of
|
|
22
|
+
* better-auth's reserved names in the same `defineSchema` — JS spread order
|
|
23
|
+
* would let the later key win silently (unlike the plugin-extension path, which
|
|
24
|
+
* throws on collision):
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* import { authTables } from "@lunora/auth";
|
|
28
|
+
* const authOptions = { emailAndPassword: { enabled: true }, plugins: [organization(), admin()] };
|
|
29
|
+
* export const schema = defineSchema({
|
|
30
|
+
* ...authTables(authOptions),
|
|
31
|
+
* todos: defineTable({ title: v.string() }),
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* Scope: this emits the table **shapes** (columns + types + nullability +
|
|
36
|
+
* uniqueness + FK ids). It deliberately does not carry better-auth's
|
|
37
|
+
* `defaultValue`/`onUpdate` (filled by better-auth's own write layer), `index`
|
|
38
|
+
* hints, or `bigint` precision (`bigint` fields map to `v.number()`). Those only
|
|
39
|
+
* matter once better-auth's writes are routed through Lunora's ORM — a separate
|
|
40
|
+
* adapter follow-up; today the auth rows are still written by better-auth's D1
|
|
41
|
+
* adapter and these tables make them typed + queryable via `ctx.db`.
|
|
42
|
+
*/
|
|
43
43
|
declare const authTables: (options: LunoraAuthOptions) => Record<string, TableDefinition>;
|
|
44
44
|
export { authTables as default };
|
package/dist/schema.d.ts
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
import { TableDefinition } from '@lunora/server';
|
|
2
|
-
import { a as LunoraAuthOptions } from "./packem_shared/create-auth.d-
|
|
2
|
+
import { a as LunoraAuthOptions } from "./packem_shared/create-auth.d-De6IOirt.js";
|
|
3
3
|
import 'better-auth';
|
|
4
4
|
/**
|
|
5
|
-
* Derive Lunora table definitions from a better-auth config — the bridge that
|
|
6
|
-
* makes the **full** better-auth plugin ecosystem first-class Lunora data.
|
|
7
|
-
*
|
|
8
|
-
* better-auth's own `getAuthTables(options)` already merges every configured
|
|
9
|
-
* plugin's `schema` into one table map (core `user`/`session`/`account`/
|
|
10
|
-
* `verification`, plus whatever the plugins on `options.plugins` add —
|
|
11
|
-
* `organization`/`member`/`invitation`/`team`/`teamMember` from the
|
|
12
|
-
* organization plugin, `role`/`banned`/… columns from admin, `passkey`,
|
|
13
|
-
* `twoFactor`, `jwks`, …). This walks that map and emits an equivalent
|
|
14
|
-
* `defineTable` for each, so adding a plugin to `options.plugins` automatically
|
|
15
|
-
* surfaces its tables in the Lunora schema — no hand-written table definitions
|
|
16
|
-
* to keep in sync.
|
|
17
|
-
*
|
|
18
|
-
* Spread the result into `defineSchema` alongside your app tables (the keys are
|
|
19
|
-
* better-auth's real table names — `user`, `session`, … — left **unprefixed**
|
|
20
|
-
* because better-auth's adapter addresses them by exactly those names). Because
|
|
21
|
-
* the names are unprefixed, do **not** declare an app table that reuses one of
|
|
22
|
-
* better-auth's reserved names in the same `defineSchema` — JS spread order
|
|
23
|
-
* would let the later key win silently (unlike the plugin-extension path, which
|
|
24
|
-
* throws on collision):
|
|
25
|
-
*
|
|
26
|
-
* ```ts
|
|
27
|
-
* import { authTables } from "@lunora/auth";
|
|
28
|
-
* const authOptions = { emailAndPassword: { enabled: true }, plugins: [organization(), admin()] };
|
|
29
|
-
* export const schema = defineSchema({
|
|
30
|
-
* ...authTables(authOptions),
|
|
31
|
-
* todos: defineTable({ title: v.string() }),
|
|
32
|
-
* });
|
|
33
|
-
* ```
|
|
34
|
-
*
|
|
35
|
-
* Scope: this emits the table **shapes** (columns + types + nullability +
|
|
36
|
-
* uniqueness + FK ids). It deliberately does not carry better-auth's
|
|
37
|
-
* `defaultValue`/`onUpdate` (filled by better-auth's own write layer), `index`
|
|
38
|
-
* hints, or `bigint` precision (`bigint` fields map to `v.number()`). Those only
|
|
39
|
-
* matter once better-auth's writes are routed through Lunora's ORM — a separate
|
|
40
|
-
* adapter follow-up; today the auth rows are still written by better-auth's D1
|
|
41
|
-
* adapter and these tables make them typed + queryable via `ctx.db`.
|
|
42
|
-
*/
|
|
5
|
+
* Derive Lunora table definitions from a better-auth config — the bridge that
|
|
6
|
+
* makes the **full** better-auth plugin ecosystem first-class Lunora data.
|
|
7
|
+
*
|
|
8
|
+
* better-auth's own `getAuthTables(options)` already merges every configured
|
|
9
|
+
* plugin's `schema` into one table map (core `user`/`session`/`account`/
|
|
10
|
+
* `verification`, plus whatever the plugins on `options.plugins` add —
|
|
11
|
+
* `organization`/`member`/`invitation`/`team`/`teamMember` from the
|
|
12
|
+
* organization plugin, `role`/`banned`/… columns from admin, `passkey`,
|
|
13
|
+
* `twoFactor`, `jwks`, …). This walks that map and emits an equivalent
|
|
14
|
+
* `defineTable` for each, so adding a plugin to `options.plugins` automatically
|
|
15
|
+
* surfaces its tables in the Lunora schema — no hand-written table definitions
|
|
16
|
+
* to keep in sync.
|
|
17
|
+
*
|
|
18
|
+
* Spread the result into `defineSchema` alongside your app tables (the keys are
|
|
19
|
+
* better-auth's real table names — `user`, `session`, … — left **unprefixed**
|
|
20
|
+
* because better-auth's adapter addresses them by exactly those names). Because
|
|
21
|
+
* the names are unprefixed, do **not** declare an app table that reuses one of
|
|
22
|
+
* better-auth's reserved names in the same `defineSchema` — JS spread order
|
|
23
|
+
* would let the later key win silently (unlike the plugin-extension path, which
|
|
24
|
+
* throws on collision):
|
|
25
|
+
*
|
|
26
|
+
* ```ts
|
|
27
|
+
* import { authTables } from "@lunora/auth";
|
|
28
|
+
* const authOptions = { emailAndPassword: { enabled: true }, plugins: [organization(), admin()] };
|
|
29
|
+
* export const schema = defineSchema({
|
|
30
|
+
* ...authTables(authOptions),
|
|
31
|
+
* todos: defineTable({ title: v.string() }),
|
|
32
|
+
* });
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* Scope: this emits the table **shapes** (columns + types + nullability +
|
|
36
|
+
* uniqueness + FK ids). It deliberately does not carry better-auth's
|
|
37
|
+
* `defaultValue`/`onUpdate` (filled by better-auth's own write layer), `index`
|
|
38
|
+
* hints, or `bigint` precision (`bigint` fields map to `v.number()`). Those only
|
|
39
|
+
* matter once better-auth's writes are routed through Lunora's ORM — a separate
|
|
40
|
+
* adapter follow-up; today the auth rows are still written by better-auth's D1
|
|
41
|
+
* adapter and these tables make them typed + queryable via `ctx.db`.
|
|
42
|
+
*/
|
|
43
43
|
declare const authTables: (options: LunoraAuthOptions) => Record<string, TableDefinition>;
|
|
44
44
|
export { authTables as default };
|
package/dist/schema.mjs
CHANGED
|
@@ -1,62 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { v } from '@lunora/values';
|
|
3
|
-
import { getAuthTables } from 'better-auth/db';
|
|
4
|
-
|
|
5
|
-
const baseValidator = (attribute) => {
|
|
6
|
-
if (attribute.references) {
|
|
7
|
-
return v.id(attribute.references.model);
|
|
8
|
-
}
|
|
9
|
-
const { type } = attribute;
|
|
10
|
-
if (Array.isArray(type)) {
|
|
11
|
-
return v.string();
|
|
12
|
-
}
|
|
13
|
-
switch (type) {
|
|
14
|
-
case "boolean": {
|
|
15
|
-
return v.boolean();
|
|
16
|
-
}
|
|
17
|
-
case "date": {
|
|
18
|
-
return v.date();
|
|
19
|
-
}
|
|
20
|
-
case "number": {
|
|
21
|
-
return v.number();
|
|
22
|
-
}
|
|
23
|
-
case "number[]": {
|
|
24
|
-
return v.array(v.number());
|
|
25
|
-
}
|
|
26
|
-
case "string": {
|
|
27
|
-
return v.string();
|
|
28
|
-
}
|
|
29
|
-
case "string[]": {
|
|
30
|
-
return v.array(v.string());
|
|
31
|
-
}
|
|
32
|
-
// "json" and anything unrecognised: keep the row shape permissive rather
|
|
33
|
-
// than fail schema generation on a plugin's exotic column type.
|
|
34
|
-
default: {
|
|
35
|
-
return v.any();
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
const fieldValidator = (attribute) => {
|
|
40
|
-
let validator = baseValidator(attribute);
|
|
41
|
-
if (attribute.required === false) {
|
|
42
|
-
validator = validator.nullable();
|
|
43
|
-
}
|
|
44
|
-
if (attribute.unique === true) {
|
|
45
|
-
validator = validator.unique();
|
|
46
|
-
}
|
|
47
|
-
return validator;
|
|
48
|
-
};
|
|
49
|
-
const authTables = (options) => {
|
|
50
|
-
const tables = getAuthTables(options);
|
|
51
|
-
const schema = {};
|
|
52
|
-
for (const table of Object.values(tables)) {
|
|
53
|
-
const shape = {};
|
|
54
|
-
for (const [fieldKey, attribute] of Object.entries(table.fields)) {
|
|
55
|
-
shape[attribute.fieldName ?? fieldKey] = fieldValidator(attribute);
|
|
56
|
-
}
|
|
57
|
-
schema[table.modelName] = defineTable(shape).externallyManaged();
|
|
58
|
-
}
|
|
59
|
-
return schema;
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export { authTables as default };
|
|
1
|
+
import{defineTable as i}from"@lunora/server";import{v as e}from"@lunora/values";import{getAuthTables as c}from"better-auth/db";const f=n=>{if(n.references)return e.id(n.references.model);const{type:r}=n;if(Array.isArray(r))return e.string();switch(r){case"boolean":return e.boolean();case"date":return e.date();case"number":return e.number();case"number[]":return e.array(e.number());case"string":return e.string();case"string[]":return e.array(e.string());default:return e.any()}},l=n=>{let r=f(n);return n.required===!1&&(r=r.nullable()),n.unique===!0&&(r=r.unique()),r},g=n=>{const r=c(n),t={};for(const a of Object.values(r)){const s={};for(const[o,u]of Object.entries(a.fields))s[u.fieldName??o]=l(u);t[a.modelName]=i(s).externallyManaged()}return t};export{g as default};
|
package/dist/sql-store.d.mts
CHANGED
|
@@ -12,40 +12,40 @@ interface D1Like {
|
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* The minimal SQL seam a {@link createSqlAuthStore} runs on — structurally the
|
|
16
|
-
* same `{ all, run }` contract as `@lunora/d1`'s `D1Exec`, so a Lunora D1 binding
|
|
17
|
-
* satisfies it directly (see {@link d1Executor}) and a `node:sqlite` handle does
|
|
18
|
-
* too in tests. `all` runs reads and returns rows; `run` runs writes.
|
|
19
|
-
*/
|
|
15
|
+
* The minimal SQL seam a {@link createSqlAuthStore} runs on — structurally the
|
|
16
|
+
* same `{ all, run }` contract as `@lunora/d1`'s `D1Exec`, so a Lunora D1 binding
|
|
17
|
+
* satisfies it directly (see {@link d1Executor}) and a `node:sqlite` handle does
|
|
18
|
+
* too in tests. `all` runs reads and returns rows; `run` runs writes.
|
|
19
|
+
*/
|
|
20
20
|
interface SqlExecutor {
|
|
21
21
|
all: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<Record<string, unknown>[]>;
|
|
22
22
|
run: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<void>;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
* An {@link AuthStore} backed by a SQL database through the {@link SqlExecutor}
|
|
26
|
-
* seam — the production counterpart to `createMemoryAuthStore`. Point it at the
|
|
27
|
-
* same database that hosts Lunora's global (D1) tables (the ones `authTables(...)`
|
|
28
|
-
* generates) and better-auth's reads/writes land there as ordinary rows Lunora
|
|
29
|
-
* can also query. Assumes the auth tables already exist (Lunora owns the schema /
|
|
30
|
-
* migrations); it never issues DDL.
|
|
31
|
-
*
|
|
32
|
-
* ```ts
|
|
33
|
-
* const store = createSqlAuthStore(d1Executor(env.DB));
|
|
34
|
-
* const auth = createAuth({ secret: env.AUTH_SECRET, database: lunoraAuthAdapter(store) });
|
|
35
|
-
* ```
|
|
36
|
-
*
|
|
37
|
-
* Clause semantics match `createMemoryAuthStore` (operator parity is
|
|
38
|
-
* covered by a cross-store agreement test) with one unavoidable caveat:
|
|
39
|
-
* case-**insensitive** matching uses SQLite's ASCII-only `LOWER()`, whereas the
|
|
40
|
-
* in-memory store uses JS full-Unicode `toLowerCase()`. They agree on ASCII
|
|
41
|
-
* (emails, ids, tokens — the credential path); they can differ only for
|
|
42
|
-
* case-insensitive comparison of non-ASCII text.
|
|
43
|
-
*/
|
|
25
|
+
* An {@link AuthStore} backed by a SQL database through the {@link SqlExecutor}
|
|
26
|
+
* seam — the production counterpart to `createMemoryAuthStore`. Point it at the
|
|
27
|
+
* same database that hosts Lunora's global (D1) tables (the ones `authTables(...)`
|
|
28
|
+
* generates) and better-auth's reads/writes land there as ordinary rows Lunora
|
|
29
|
+
* can also query. Assumes the auth tables already exist (Lunora owns the schema /
|
|
30
|
+
* migrations); it never issues DDL.
|
|
31
|
+
*
|
|
32
|
+
* ```ts
|
|
33
|
+
* const store = createSqlAuthStore(d1Executor(env.DB));
|
|
34
|
+
* const auth = createAuth({ secret: env.AUTH_SECRET, database: lunoraAuthAdapter(store) });
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* Clause semantics match `createMemoryAuthStore` (operator parity is
|
|
38
|
+
* covered by a cross-store agreement test) with one unavoidable caveat:
|
|
39
|
+
* case-**insensitive** matching uses SQLite's ASCII-only `LOWER()`, whereas the
|
|
40
|
+
* in-memory store uses JS full-Unicode `toLowerCase()`. They agree on ASCII
|
|
41
|
+
* (emails, ids, tokens — the credential path); they can differ only for
|
|
42
|
+
* case-insensitive comparison of non-ASCII text.
|
|
43
|
+
*/
|
|
44
44
|
declare const createSqlAuthStore: (executor: SqlExecutor) => AuthStore;
|
|
45
45
|
/**
|
|
46
|
-
* Wrap a Cloudflare D1 binding (`env.DB`) as a {@link SqlExecutor}, so
|
|
47
|
-
* `createSqlAuthStore(d1Executor(env.DB))` routes better-auth onto D1 — the same
|
|
48
|
-
* binding Lunora's `.global()` tables use.
|
|
49
|
-
*/
|
|
46
|
+
* Wrap a Cloudflare D1 binding (`env.DB`) as a {@link SqlExecutor}, so
|
|
47
|
+
* `createSqlAuthStore(d1Executor(env.DB))` routes better-auth onto D1 — the same
|
|
48
|
+
* binding Lunora's `.global()` tables use.
|
|
49
|
+
*/
|
|
50
50
|
declare const d1Executor: (database: D1Like) => SqlExecutor;
|
|
51
51
|
export { SqlExecutor, createSqlAuthStore, d1Executor };
|
package/dist/sql-store.d.ts
CHANGED
|
@@ -12,40 +12,40 @@ interface D1Like {
|
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* The minimal SQL seam a {@link createSqlAuthStore} runs on — structurally the
|
|
16
|
-
* same `{ all, run }` contract as `@lunora/d1`'s `D1Exec`, so a Lunora D1 binding
|
|
17
|
-
* satisfies it directly (see {@link d1Executor}) and a `node:sqlite` handle does
|
|
18
|
-
* too in tests. `all` runs reads and returns rows; `run` runs writes.
|
|
19
|
-
*/
|
|
15
|
+
* The minimal SQL seam a {@link createSqlAuthStore} runs on — structurally the
|
|
16
|
+
* same `{ all, run }` contract as `@lunora/d1`'s `D1Exec`, so a Lunora D1 binding
|
|
17
|
+
* satisfies it directly (see {@link d1Executor}) and a `node:sqlite` handle does
|
|
18
|
+
* too in tests. `all` runs reads and returns rows; `run` runs writes.
|
|
19
|
+
*/
|
|
20
20
|
interface SqlExecutor {
|
|
21
21
|
all: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<Record<string, unknown>[]>;
|
|
22
22
|
run: (sql: string, parameters: ReadonlyArray<unknown>) => Promise<void>;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
* An {@link AuthStore} backed by a SQL database through the {@link SqlExecutor}
|
|
26
|
-
* seam — the production counterpart to `createMemoryAuthStore`. Point it at the
|
|
27
|
-
* same database that hosts Lunora's global (D1) tables (the ones `authTables(...)`
|
|
28
|
-
* generates) and better-auth's reads/writes land there as ordinary rows Lunora
|
|
29
|
-
* can also query. Assumes the auth tables already exist (Lunora owns the schema /
|
|
30
|
-
* migrations); it never issues DDL.
|
|
31
|
-
*
|
|
32
|
-
* ```ts
|
|
33
|
-
* const store = createSqlAuthStore(d1Executor(env.DB));
|
|
34
|
-
* const auth = createAuth({ secret: env.AUTH_SECRET, database: lunoraAuthAdapter(store) });
|
|
35
|
-
* ```
|
|
36
|
-
*
|
|
37
|
-
* Clause semantics match `createMemoryAuthStore` (operator parity is
|
|
38
|
-
* covered by a cross-store agreement test) with one unavoidable caveat:
|
|
39
|
-
* case-**insensitive** matching uses SQLite's ASCII-only `LOWER()`, whereas the
|
|
40
|
-
* in-memory store uses JS full-Unicode `toLowerCase()`. They agree on ASCII
|
|
41
|
-
* (emails, ids, tokens — the credential path); they can differ only for
|
|
42
|
-
* case-insensitive comparison of non-ASCII text.
|
|
43
|
-
*/
|
|
25
|
+
* An {@link AuthStore} backed by a SQL database through the {@link SqlExecutor}
|
|
26
|
+
* seam — the production counterpart to `createMemoryAuthStore`. Point it at the
|
|
27
|
+
* same database that hosts Lunora's global (D1) tables (the ones `authTables(...)`
|
|
28
|
+
* generates) and better-auth's reads/writes land there as ordinary rows Lunora
|
|
29
|
+
* can also query. Assumes the auth tables already exist (Lunora owns the schema /
|
|
30
|
+
* migrations); it never issues DDL.
|
|
31
|
+
*
|
|
32
|
+
* ```ts
|
|
33
|
+
* const store = createSqlAuthStore(d1Executor(env.DB));
|
|
34
|
+
* const auth = createAuth({ secret: env.AUTH_SECRET, database: lunoraAuthAdapter(store) });
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* Clause semantics match `createMemoryAuthStore` (operator parity is
|
|
38
|
+
* covered by a cross-store agreement test) with one unavoidable caveat:
|
|
39
|
+
* case-**insensitive** matching uses SQLite's ASCII-only `LOWER()`, whereas the
|
|
40
|
+
* in-memory store uses JS full-Unicode `toLowerCase()`. They agree on ASCII
|
|
41
|
+
* (emails, ids, tokens — the credential path); they can differ only for
|
|
42
|
+
* case-insensitive comparison of non-ASCII text.
|
|
43
|
+
*/
|
|
44
44
|
declare const createSqlAuthStore: (executor: SqlExecutor) => AuthStore;
|
|
45
45
|
/**
|
|
46
|
-
* Wrap a Cloudflare D1 binding (`env.DB`) as a {@link SqlExecutor}, so
|
|
47
|
-
* `createSqlAuthStore(d1Executor(env.DB))` routes better-auth onto D1 — the same
|
|
48
|
-
* binding Lunora's `.global()` tables use.
|
|
49
|
-
*/
|
|
46
|
+
* Wrap a Cloudflare D1 binding (`env.DB`) as a {@link SqlExecutor}, so
|
|
47
|
+
* `createSqlAuthStore(d1Executor(env.DB))` routes better-auth onto D1 — the same
|
|
48
|
+
* binding Lunora's `.global()` tables use.
|
|
49
|
+
*/
|
|
50
50
|
declare const d1Executor: (database: D1Like) => SqlExecutor;
|
|
51
51
|
export { SqlExecutor, createSqlAuthStore, d1Executor };
|
package/dist/sql-store.mjs
CHANGED
|
@@ -1,162 +1 @@
|
|
|
1
|
-
const
|
|
2
|
-
const NEVER = { params: [], sql: "0" };
|
|
3
|
-
const sided = (column, insensitive) => insensitive ? { column: `LOWER(${column})`, placeholder: "LOWER(?)" } : { column, placeholder: "?" };
|
|
4
|
-
const patternFragment = (column, value, operator, insensitive) => {
|
|
5
|
-
if (typeof value !== "string") {
|
|
6
|
-
return NEVER;
|
|
7
|
-
}
|
|
8
|
-
const side = sided(column, insensitive);
|
|
9
|
-
if (operator === "contains") {
|
|
10
|
-
return { params: [value], sql: `instr(${side.column}, ${side.placeholder}) > 0` };
|
|
11
|
-
}
|
|
12
|
-
if (operator === "starts_with") {
|
|
13
|
-
return { params: [value], sql: `instr(${side.column}, ${side.placeholder}) = 1` };
|
|
14
|
-
}
|
|
15
|
-
return { params: [value, value], sql: `substr(${side.column}, -length(?)) = ${side.placeholder}` };
|
|
16
|
-
};
|
|
17
|
-
const equalityFragment = (column, value, insensitive, negated) => {
|
|
18
|
-
if (value === null) {
|
|
19
|
-
return { params: [], sql: `${column} IS ${negated ? "NOT " : ""}NULL` };
|
|
20
|
-
}
|
|
21
|
-
const side = sided(column, insensitive);
|
|
22
|
-
const symbol = negated ? "<>" : "=";
|
|
23
|
-
return { params: [value], sql: `${side.column} ${symbol} ${side.placeholder}` };
|
|
24
|
-
};
|
|
25
|
-
const inFragment = (column, value, negated, insensitive) => {
|
|
26
|
-
const values = Array.isArray(value) ? value : [];
|
|
27
|
-
if (values.length === 0) {
|
|
28
|
-
return { params: [], sql: negated ? "1" : "0" };
|
|
29
|
-
}
|
|
30
|
-
const side = sided(column, insensitive);
|
|
31
|
-
const placeholders = values.map(() => side.placeholder).join(", ");
|
|
32
|
-
return { params: [...values], sql: `${side.column} ${negated ? "NOT IN" : "IN"} (${placeholders})` };
|
|
33
|
-
};
|
|
34
|
-
const compileClause = (clause) => {
|
|
35
|
-
const column = quoteId(clause.field);
|
|
36
|
-
const { mode, operator, value } = clause;
|
|
37
|
-
const insensitive = mode === "insensitive";
|
|
38
|
-
switch (operator) {
|
|
39
|
-
case "contains":
|
|
40
|
-
case "ends_with":
|
|
41
|
-
case "starts_with": {
|
|
42
|
-
return patternFragment(column, value, operator, insensitive);
|
|
43
|
-
}
|
|
44
|
-
case "gt": {
|
|
45
|
-
return { params: [value], sql: `${column} > ?` };
|
|
46
|
-
}
|
|
47
|
-
case "gte": {
|
|
48
|
-
return { params: [value], sql: `${column} >= ?` };
|
|
49
|
-
}
|
|
50
|
-
case "in": {
|
|
51
|
-
return inFragment(column, value, false, insensitive);
|
|
52
|
-
}
|
|
53
|
-
case "lt": {
|
|
54
|
-
return { params: [value], sql: `${column} < ?` };
|
|
55
|
-
}
|
|
56
|
-
case "lte": {
|
|
57
|
-
return { params: [value], sql: `${column} <= ?` };
|
|
58
|
-
}
|
|
59
|
-
case "ne": {
|
|
60
|
-
return equalityFragment(column, value, insensitive, true);
|
|
61
|
-
}
|
|
62
|
-
case "not_in": {
|
|
63
|
-
return inFragment(column, value, true, insensitive);
|
|
64
|
-
}
|
|
65
|
-
// "eq" and the default: null-aware equality.
|
|
66
|
-
default: {
|
|
67
|
-
return equalityFragment(column, value, insensitive, false);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
};
|
|
71
|
-
const compileWhere = (where) => {
|
|
72
|
-
if (where.length === 0) {
|
|
73
|
-
return { params: [], sql: "" };
|
|
74
|
-
}
|
|
75
|
-
let accumulator = compileClause(where[0]);
|
|
76
|
-
for (const clause of where.slice(1)) {
|
|
77
|
-
const fragment = compileClause(clause);
|
|
78
|
-
const connector = clause.connector === "OR" ? "OR" : "AND";
|
|
79
|
-
accumulator = { params: [...accumulator.params, ...fragment.params], sql: `(${accumulator.sql} ${connector} ${fragment.sql})` };
|
|
80
|
-
}
|
|
81
|
-
return accumulator;
|
|
82
|
-
};
|
|
83
|
-
const whereSuffix = (fragment) => fragment.sql ? ` WHERE ${fragment.sql}` : "";
|
|
84
|
-
const createSqlAuthStore = (executor) => {
|
|
85
|
-
const selectRows = (model, where) => {
|
|
86
|
-
const fragment = compileWhere(where);
|
|
87
|
-
return executor.all(`SELECT * FROM ${quoteId(model)}${whereSuffix(fragment)}`, fragment.params);
|
|
88
|
-
};
|
|
89
|
-
return {
|
|
90
|
-
consumeOne: async (model, where) => {
|
|
91
|
-
const fragment = compileWhere(where);
|
|
92
|
-
const table = quoteId(model);
|
|
93
|
-
const [row] = await executor.all(
|
|
94
|
-
`DELETE FROM ${table} WHERE rowid IN (SELECT rowid FROM ${table}${whereSuffix(fragment)} LIMIT 1) RETURNING *`,
|
|
95
|
-
fragment.params
|
|
96
|
-
);
|
|
97
|
-
return row;
|
|
98
|
-
},
|
|
99
|
-
count: async (model, where) => {
|
|
100
|
-
const fragment = compileWhere(where);
|
|
101
|
-
const [row] = await executor.all(`SELECT COUNT(*) AS __count FROM ${quoteId(model)}${whereSuffix(fragment)}`, fragment.params);
|
|
102
|
-
return Number(row?.["__count"] ?? 0);
|
|
103
|
-
},
|
|
104
|
-
create: async (model, data) => {
|
|
105
|
-
const columns = Object.keys(data);
|
|
106
|
-
const placeholders = columns.map(() => "?").join(", ");
|
|
107
|
-
const sql = `INSERT INTO ${quoteId(model)} (${columns.map((column) => quoteId(column)).join(", ")}) VALUES (${placeholders})`;
|
|
108
|
-
await executor.run(
|
|
109
|
-
sql,
|
|
110
|
-
columns.map((column) => data[column])
|
|
111
|
-
);
|
|
112
|
-
return { ...data };
|
|
113
|
-
},
|
|
114
|
-
read: async (model, query) => {
|
|
115
|
-
const fragment = compileWhere(query.where);
|
|
116
|
-
const parameters = [...fragment.params];
|
|
117
|
-
let sql = `SELECT * FROM ${quoteId(model)}${whereSuffix(fragment)}`;
|
|
118
|
-
if (query.sortBy) {
|
|
119
|
-
sql += ` ORDER BY ${quoteId(query.sortBy.field)} ${query.sortBy.direction === "asc" ? "ASC" : "DESC"}`;
|
|
120
|
-
}
|
|
121
|
-
if (query.limit !== void 0) {
|
|
122
|
-
sql += " LIMIT ?";
|
|
123
|
-
parameters.push(Math.trunc(query.limit));
|
|
124
|
-
}
|
|
125
|
-
if (query.offset) {
|
|
126
|
-
sql += `${query.limit === void 0 ? " LIMIT -1" : ""} OFFSET ?`;
|
|
127
|
-
parameters.push(Math.trunc(query.offset));
|
|
128
|
-
}
|
|
129
|
-
return executor.all(sql, parameters);
|
|
130
|
-
},
|
|
131
|
-
remove: async (model, where) => {
|
|
132
|
-
const fragment = compileWhere(where);
|
|
133
|
-
const deleted = await executor.all(`DELETE FROM ${quoteId(model)}${whereSuffix(fragment)} RETURNING *`, fragment.params);
|
|
134
|
-
return deleted.length;
|
|
135
|
-
},
|
|
136
|
-
update: async (model, where, values) => {
|
|
137
|
-
const columns = Object.keys(values);
|
|
138
|
-
if (columns.length === 0) {
|
|
139
|
-
return selectRows(model, where);
|
|
140
|
-
}
|
|
141
|
-
const assignments = columns.map((column) => `${quoteId(column)} = ?`).join(", ");
|
|
142
|
-
const fragment = compileWhere(where);
|
|
143
|
-
return executor.all(`UPDATE ${quoteId(model)} SET ${assignments}${whereSuffix(fragment)} RETURNING *`, [
|
|
144
|
-
...columns.map((column) => values[column]),
|
|
145
|
-
...fragment.params
|
|
146
|
-
]);
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
};
|
|
150
|
-
const d1Executor = (database) => {
|
|
151
|
-
return {
|
|
152
|
-
all: async (sql, parameters) => {
|
|
153
|
-
const result = await database.prepare(sql).bind(...parameters).all();
|
|
154
|
-
return result.results ?? [];
|
|
155
|
-
},
|
|
156
|
-
run: async (sql, parameters) => {
|
|
157
|
-
await database.prepare(sql).bind(...parameters).run();
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
};
|
|
161
|
-
|
|
162
|
-
export { createSqlAuthStore, d1Executor };
|
|
1
|
+
const c=r=>`"${r.replaceAll('"','""')}"`,I={params:[],sql:"0"},E=(r,e)=>e?{column:`LOWER(${r})`,placeholder:"LOWER(?)"}:{column:r,placeholder:"?"},N=(r,e,s,n)=>{if(typeof e!="string")return I;const a=E(r,n);return s==="contains"?{params:[e],sql:`instr(${a.column}, ${a.placeholder}) > 0`}:s==="starts_with"?{params:[e],sql:`instr(${a.column}, ${a.placeholder}) = 1`}:{params:[e,e],sql:`substr(${a.column}, -length(?)) = ${a.placeholder}`}},R=(r,e,s,n)=>{if(e===null)return{params:[],sql:`${r} IS ${n?"NOT ":""}NULL`};const a=E(r,s),t=n?"<>":"=";return{params:[e],sql:`${a.column} ${t} ${a.placeholder}`}},T=(r,e,s,n)=>{const a=Array.isArray(e)?e:[];if(a.length===0)return{params:[],sql:s?"1":"0"};const t=E(r,n),l=a.map(()=>t.placeholder).join(", ");return{params:[...a],sql:`${t.column} ${s?"NOT IN":"IN"} (${l})`}},d=r=>{const e=c(r.field),{mode:s,operator:n,value:a}=r,t=s==="insensitive";switch(n){case"contains":case"ends_with":case"starts_with":return N(e,a,n,t);case"gt":return{params:[a],sql:`${e} > ?`};case"gte":return{params:[a],sql:`${e} >= ?`};case"in":return T(e,a,!1,t);case"lt":return{params:[a],sql:`${e} < ?`};case"lte":return{params:[a],sql:`${e} <= ?`};case"ne":return R(e,a,t,!0);case"not_in":return T(e,a,!0,t);default:return R(e,a,t,!1)}},p=r=>{if(r.length===0)return{params:[],sql:""};let e=d(r[0]);for(const s of r.slice(1)){const n=d(s),a=s.connector==="OR"?"OR":"AND";e={params:[...e.params,...n.params],sql:`(${e.sql} ${a} ${n.sql})`}}return e},$=r=>r.sql?` WHERE ${r.sql}`:"",f=r=>{const e=(s,n)=>{const a=p(n);return r.all(`SELECT * FROM ${c(s)}${$(a)}`,a.params)};return{consumeOne:async(s,n)=>{const a=p(n),t=c(s),[l]=await r.all(`DELETE FROM ${t} WHERE rowid IN (SELECT rowid FROM ${t}${$(a)} LIMIT 1) RETURNING *`,a.params);return l},count:async(s,n)=>{const a=p(n),[t]=await r.all(`SELECT COUNT(*) AS __count FROM ${c(s)}${$(a)}`,a.params);return Number(t?.__count??0)},create:async(s,n)=>{const a=Object.keys(n),t=a.map(()=>"?").join(", "),l=`INSERT INTO ${c(s)} (${a.map(o=>c(o)).join(", ")}) VALUES (${t})`;return await r.run(l,a.map(o=>n[o])),{...n}},incrementOne:async(s,n,a,t)=>{const l=c(s),o=Object.keys(a),i=t?Object.keys(t):[],m=p(n);if(o.length===0&&i.length===0){const[u]=await r.all(`SELECT * FROM ${l}${$(m)} LIMIT 1`,m.params);return u}const h=[...o.map(u=>`${c(u)} = COALESCE(${c(u)}, 0) + ?`),...i.map(u=>`${c(u)} = ?`)].join(", "),[O]=await r.all(`UPDATE ${l} SET ${h} WHERE rowid IN (SELECT rowid FROM ${l}${$(m)} LIMIT 1) RETURNING *`,[...o.map(u=>a[u]),...i.map(u=>t[u]),...m.params]);return O},read:async(s,n)=>{const a=p(n.where),t=[...a.params];let l=`SELECT * FROM ${c(s)}${$(a)}`;return n.sortBy&&(l+=` ORDER BY ${c(n.sortBy.field)} ${n.sortBy.direction==="asc"?"ASC":"DESC"}`),n.limit!==void 0&&(l+=" LIMIT ?",t.push(Math.trunc(n.limit))),n.offset&&(l+=`${n.limit===void 0?" LIMIT -1":""} OFFSET ?`,t.push(Math.trunc(n.offset))),r.all(l,t)},remove:async(s,n)=>{const a=p(n);return(await r.all(`DELETE FROM ${c(s)}${$(a)} RETURNING *`,a.params)).length},update:async(s,n,a)=>{const t=Object.keys(a);if(t.length===0)return e(s,n);const l=t.map(i=>`${c(i)} = ?`).join(", "),o=p(n);return r.all(`UPDATE ${c(s)} SET ${l}${$(o)} RETURNING *`,[...t.map(i=>a[i]),...o.params])}}},q=r=>({all:async(e,s)=>(await r.prepare(e).bind(...s).all()).results??[],run:async(e,s)=>{await r.prepare(e).bind(...s).run()}});export{f as createSqlAuthStore,q as d1Executor};
|