@lunora/auth 1.0.0-alpha.164 → 1.0.0-alpha.166

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/dist/index.d.mts CHANGED
@@ -845,6 +845,48 @@ declare const authDoSchemaStatements: (options: LunoraAuthOptions) => string[];
845
845
  * @experimental
846
846
  */
847
847
  declare const authDoColumnAdditions: (options: LunoraAuthOptions, existingColumns: (table: string) => Iterable<string>) => string[];
848
+ /** What one table looked like after a copy call. */
849
+ interface AuthMoveTableReport {
850
+ /** Rows that collided with a row the pinned object holds on its own, kept as they are (only under `force`). */
851
+ conflicts: number;
852
+ /** Rows this call inserted into the target. */
853
+ copied: number;
854
+ /** Rows this call deleted from the target because the source deleted them since they were copied. */
855
+ deleted: number;
856
+ /** Rows in the source object. */
857
+ sourceRows: number;
858
+ table: string;
859
+ /** Rows in the target object after this call. */
860
+ targetRows: number;
861
+ /** Rows this call read that the target already held exactly. */
862
+ unchanged: number;
863
+ /** Rows this call updated in the target because the source changed them since they were copied. */
864
+ updated: number;
865
+ }
866
+ /** The answer to one copy call. */
867
+ interface AuthMoveResult {
868
+ /** `true` once every table is copied and matches the source's fingerprint; otherwise call again. */
869
+ done: boolean;
870
+ tables: AuthMoveTableReport[];
871
+ }
872
+ /** The worker-side move between the un-pinned and the pinned auth object. */
873
+ interface AuthJurisdictionMove {
874
+ /**
875
+ * Copy every table from the un-pinned object into the pinned one. Refuses, unless
876
+ * `force` is set, a pinned object holding users the copy did not write, and a row
877
+ * that collides with one.
878
+ */
879
+ copy: (options?: {
880
+ force?: boolean;
881
+ }) => Promise<AuthMoveResult>;
882
+ /**
883
+ * Drop every table in the un-pinned object. Refused unless every table was copied
884
+ * and still matches what was copied.
885
+ */
886
+ purge: () => Promise<{
887
+ dropped: string[];
888
+ }>;
889
+ }
848
890
  /** The slice of a Durable Object namespace this needs — structural, so tests need no runtime. */
849
891
  interface AuthNamespaceLike {
850
892
  get(this: void, id: unknown): {
@@ -903,6 +945,12 @@ interface DoAuthWiring {
903
945
  * subclass that set its own served nothing.
904
946
  */
905
947
  authHandler: (request: Request) => Promise<Response | undefined>;
948
+ /**
949
+ * Copy the auth tables from the un-pinned object into the pinned one, and later
950
+ * purge the un-pinned copy. Present only when a `jurisdiction` is set. Backs the
951
+ * worker's `copyAuthToJurisdiction` and `purgeUnpinnedAuth` admin ops.
952
+ */
953
+ jurisdictionMove?: AuthJurisdictionMove;
906
954
  /**
907
955
  * Resolves a request's identity by asking the object. `null` when anonymous,
908
956
  * unreachable, or ungated.
@@ -1092,4 +1140,4 @@ declare const validateSessionPolicy: (policy: SessionPolicy) => SessionPolicy;
1092
1140
  * with the same 60s cookie cache as `rolling`.
1093
1141
  */
1094
1142
  declare const sessionPresets: Record<"longLived" | "rolling" | "strict", SessionPolicy>;
1095
- export { READ_AUDIT_PATH as AUTH_DO_AUDIT_PATH, INTERNAL_SECRET_HEADER as AUTH_DO_SECRET_HEADER, RESOLVE_SESSION_PATH as AUTH_DO_SESSION_PATH, type AppendAuthAuditEntry, type AppendAuthAuditOptions, type AuthAccount, type AuthAdmin, type AuthAdminSession, type AuthAdminUser, type AuthAuditEvent, type AuthAuditHookConfig, type AuthAuditReader, type AuthCapabilities, type AuthConfigInfo, type AuthDoOptions, type AuthDoState, type AuthInvitation, type AuthJurisdiction, type AuthMember, type AuthNamespaceLike, type AuthOrgRole, type AuthOrganization, type AuthPage, type AuthPasskey, type AuthSignUpInvitation, type AuthTeam, type AuthTeamMember, type AuthTimestamp, type AuthUserFieldSpec, type CreateAuthAdminOptions, DEFAULT_AUTH_BASE_PATH, type DoAuthWiring, type DoAuthWiringOptions, type EmailClassification, type EmailGateConfig, type EmailGateHookConfig, type ImpersonationResult, type ListUsersOptions, type LunoraAuth, LunoraAuthAdminError, LunoraAuthDO, type LunoraAuthOptions, type SessionPolicy, type SqlExecutor, authAuditHook, authDoColumnAdditions, authDoSchemaStatements, buildAuditEntry, compileMigrationsSql, createAuthAdmin, createDoAuthWiring, emailGateDatabaseHooks, ensureMigrated, eventForPath, handleAuthRequest, legacyIssuerCleanupStatements, sessionPresets, validateSessionPolicy, withAuthAudit, withEmailGate };
1143
+ export { READ_AUDIT_PATH as AUTH_DO_AUDIT_PATH, INTERNAL_SECRET_HEADER as AUTH_DO_SECRET_HEADER, RESOLVE_SESSION_PATH as AUTH_DO_SESSION_PATH, type AppendAuthAuditEntry, type AppendAuthAuditOptions, type AuthAccount, type AuthAdmin, type AuthAdminSession, type AuthAdminUser, type AuthAuditEvent, type AuthAuditHookConfig, type AuthAuditReader, type AuthCapabilities, type AuthConfigInfo, type AuthDoOptions, type AuthDoState, type AuthInvitation, type AuthJurisdiction, type AuthJurisdictionMove, type AuthMember, type AuthMoveResult, type AuthMoveTableReport, type AuthNamespaceLike, type AuthOrgRole, type AuthOrganization, type AuthPage, type AuthPasskey, type AuthSignUpInvitation, type AuthTeam, type AuthTeamMember, type AuthTimestamp, type AuthUserFieldSpec, type CreateAuthAdminOptions, DEFAULT_AUTH_BASE_PATH, type DoAuthWiring, type DoAuthWiringOptions, type EmailClassification, type EmailGateConfig, type EmailGateHookConfig, type ImpersonationResult, type ListUsersOptions, type LunoraAuth, LunoraAuthAdminError, LunoraAuthDO, type LunoraAuthOptions, type SessionPolicy, type SqlExecutor, authAuditHook, authDoColumnAdditions, authDoSchemaStatements, buildAuditEntry, compileMigrationsSql, createAuthAdmin, createDoAuthWiring, emailGateDatabaseHooks, ensureMigrated, eventForPath, handleAuthRequest, legacyIssuerCleanupStatements, sessionPresets, validateSessionPolicy, withAuthAudit, withEmailGate };
package/dist/index.d.ts CHANGED
@@ -845,6 +845,48 @@ declare const authDoSchemaStatements: (options: LunoraAuthOptions) => string[];
845
845
  * @experimental
846
846
  */
847
847
  declare const authDoColumnAdditions: (options: LunoraAuthOptions, existingColumns: (table: string) => Iterable<string>) => string[];
848
+ /** What one table looked like after a copy call. */
849
+ interface AuthMoveTableReport {
850
+ /** Rows that collided with a row the pinned object holds on its own, kept as they are (only under `force`). */
851
+ conflicts: number;
852
+ /** Rows this call inserted into the target. */
853
+ copied: number;
854
+ /** Rows this call deleted from the target because the source deleted them since they were copied. */
855
+ deleted: number;
856
+ /** Rows in the source object. */
857
+ sourceRows: number;
858
+ table: string;
859
+ /** Rows in the target object after this call. */
860
+ targetRows: number;
861
+ /** Rows this call read that the target already held exactly. */
862
+ unchanged: number;
863
+ /** Rows this call updated in the target because the source changed them since they were copied. */
864
+ updated: number;
865
+ }
866
+ /** The answer to one copy call. */
867
+ interface AuthMoveResult {
868
+ /** `true` once every table is copied and matches the source's fingerprint; otherwise call again. */
869
+ done: boolean;
870
+ tables: AuthMoveTableReport[];
871
+ }
872
+ /** The worker-side move between the un-pinned and the pinned auth object. */
873
+ interface AuthJurisdictionMove {
874
+ /**
875
+ * Copy every table from the un-pinned object into the pinned one. Refuses, unless
876
+ * `force` is set, a pinned object holding users the copy did not write, and a row
877
+ * that collides with one.
878
+ */
879
+ copy: (options?: {
880
+ force?: boolean;
881
+ }) => Promise<AuthMoveResult>;
882
+ /**
883
+ * Drop every table in the un-pinned object. Refused unless every table was copied
884
+ * and still matches what was copied.
885
+ */
886
+ purge: () => Promise<{
887
+ dropped: string[];
888
+ }>;
889
+ }
848
890
  /** The slice of a Durable Object namespace this needs — structural, so tests need no runtime. */
849
891
  interface AuthNamespaceLike {
850
892
  get(this: void, id: unknown): {
@@ -903,6 +945,12 @@ interface DoAuthWiring {
903
945
  * subclass that set its own served nothing.
904
946
  */
905
947
  authHandler: (request: Request) => Promise<Response | undefined>;
948
+ /**
949
+ * Copy the auth tables from the un-pinned object into the pinned one, and later
950
+ * purge the un-pinned copy. Present only when a `jurisdiction` is set. Backs the
951
+ * worker's `copyAuthToJurisdiction` and `purgeUnpinnedAuth` admin ops.
952
+ */
953
+ jurisdictionMove?: AuthJurisdictionMove;
906
954
  /**
907
955
  * Resolves a request's identity by asking the object. `null` when anonymous,
908
956
  * unreachable, or ungated.
@@ -1092,4 +1140,4 @@ declare const validateSessionPolicy: (policy: SessionPolicy) => SessionPolicy;
1092
1140
  * with the same 60s cookie cache as `rolling`.
1093
1141
  */
1094
1142
  declare const sessionPresets: Record<"longLived" | "rolling" | "strict", SessionPolicy>;
1095
- export { READ_AUDIT_PATH as AUTH_DO_AUDIT_PATH, INTERNAL_SECRET_HEADER as AUTH_DO_SECRET_HEADER, RESOLVE_SESSION_PATH as AUTH_DO_SESSION_PATH, type AppendAuthAuditEntry, type AppendAuthAuditOptions, type AuthAccount, type AuthAdmin, type AuthAdminSession, type AuthAdminUser, type AuthAuditEvent, type AuthAuditHookConfig, type AuthAuditReader, type AuthCapabilities, type AuthConfigInfo, type AuthDoOptions, type AuthDoState, type AuthInvitation, type AuthJurisdiction, type AuthMember, type AuthNamespaceLike, type AuthOrgRole, type AuthOrganization, type AuthPage, type AuthPasskey, type AuthSignUpInvitation, type AuthTeam, type AuthTeamMember, type AuthTimestamp, type AuthUserFieldSpec, type CreateAuthAdminOptions, DEFAULT_AUTH_BASE_PATH, type DoAuthWiring, type DoAuthWiringOptions, type EmailClassification, type EmailGateConfig, type EmailGateHookConfig, type ImpersonationResult, type ListUsersOptions, type LunoraAuth, LunoraAuthAdminError, LunoraAuthDO, type LunoraAuthOptions, type SessionPolicy, type SqlExecutor, authAuditHook, authDoColumnAdditions, authDoSchemaStatements, buildAuditEntry, compileMigrationsSql, createAuthAdmin, createDoAuthWiring, emailGateDatabaseHooks, ensureMigrated, eventForPath, handleAuthRequest, legacyIssuerCleanupStatements, sessionPresets, validateSessionPolicy, withAuthAudit, withEmailGate };
1143
+ export { READ_AUDIT_PATH as AUTH_DO_AUDIT_PATH, INTERNAL_SECRET_HEADER as AUTH_DO_SECRET_HEADER, RESOLVE_SESSION_PATH as AUTH_DO_SESSION_PATH, type AppendAuthAuditEntry, type AppendAuthAuditOptions, type AuthAccount, type AuthAdmin, type AuthAdminSession, type AuthAdminUser, type AuthAuditEvent, type AuthAuditHookConfig, type AuthAuditReader, type AuthCapabilities, type AuthConfigInfo, type AuthDoOptions, type AuthDoState, type AuthInvitation, type AuthJurisdiction, type AuthJurisdictionMove, type AuthMember, type AuthMoveResult, type AuthMoveTableReport, type AuthNamespaceLike, type AuthOrgRole, type AuthOrganization, type AuthPage, type AuthPasskey, type AuthSignUpInvitation, type AuthTeam, type AuthTeamMember, type AuthTimestamp, type AuthUserFieldSpec, type CreateAuthAdminOptions, DEFAULT_AUTH_BASE_PATH, type DoAuthWiring, type DoAuthWiringOptions, type EmailClassification, type EmailGateConfig, type EmailGateHookConfig, type ImpersonationResult, type ListUsersOptions, type LunoraAuth, LunoraAuthAdminError, LunoraAuthDO, type LunoraAuthOptions, type SessionPolicy, type SqlExecutor, authAuditHook, authDoColumnAdditions, authDoSchemaStatements, buildAuditEntry, compileMigrationsSql, createAuthAdmin, createDoAuthWiring, emailGateDatabaseHooks, ensureMigrated, eventForPath, handleAuthRequest, legacyIssuerCleanupStatements, sessionPresets, validateSessionPolicy, withAuthAudit, withEmailGate };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{l as r,a as o,b as a}from"./packem_shared/adapter-CG0Yv85f.mjs";import{LunoraAuthAdminError as A,createAuthAdmin as u}from"./packem_shared/LunoraAuthAdminError-uhKG1MgQ.mjs";import{AUTH_AUDIT_TABLE as n,appendAuthAuditEntry as m,createAuthAuditReader as l,ensureAuthAuditTable as p,readAuthAuditLog as d}from"./audit.mjs";import{authAuditHook as E,buildAuditEntry as f,eventForPath as T,withAuthAudit as S}from"./packem_shared/authAuditHook-DPTKdjBe.mjs";import{READ_AUDIT_PATH as _,INTERNAL_SECRET_HEADER as D,RESOLVE_SESSION_PATH as c,LunoraAuthDO as H}from"./packem_shared/AUTH_DO_AUDIT_PATH-u9QgGb_v.mjs";import{createAuth as U,resolveAuthOptions as R}from"./packem_shared/createAuth-8aUw8v8D.mjs";import{authDoColumnAdditions as v,authDoSchemaStatements as L}from"./packem_shared/authDoColumnAdditions-UwF3Rl41.mjs";import{createDoAuthWiring as O}from"./packem_shared/createDoAuthWiring-zfQiAS75.mjs";import{emailGateDatabaseHooks as N,withEmailGate as w}from"./packem_shared/emailGateDatabaseHooks-CAygR3iq.mjs";import{assertEmailAllowed as M,classifyEmail as C,emailGateMiddleware as k,loadEmailDomainLists as q}from"./email-guard.mjs";import{DEFAULT_AUTH_BASE_PATH as G,handleAuthRequest as B}from"./packem_shared/DEFAULT_AUTH_BASE_PATH-DneiLGpv.mjs";import{createSignUpInvitation as W,listSignUpInvitations as Y,pruneSignUpInvitations as j,revokeSignUpInvitation as z}from"./packem_shared/createSignUpInvitation-DHZL9fNl.mjs";import{legacyIssuerCleanupStatements as K}from"./packem_shared/legacyIssuerCleanupStatements-D9Kf8OD1.mjs";import{LunoraAuthHeadersError as X,withAuthPlugins as Z}from"./middleware.mjs";import{compileMigrationsSql as tt,ensureMigrated as et}from"./packem_shared/compileMigrationsSql-DKGrw7Lf.mjs";import{default as ot}from"./schema.mjs";import{sessionPresets as it,validateSessionPolicy as At}from"./packem_shared/sessionPresets-C867Mlo4.mjs";import{c as st,d as nt}from"./packem_shared/sql-store-CYa4HJsO.mjs";import{createMemoryAuthStore as lt,matchesWhere as pt}from"./store.mjs";import{TURNSTILE_VERIFY_ENDPOINT as ht,verifyTurnstile as Et}from"./turnstile.mjs";import{verifyTurnstileMiddleware as Tt}from"./turnstile-middleware.mjs";export{n as AUTH_AUDIT_TABLE,_ as AUTH_DO_AUDIT_PATH,D as AUTH_DO_SECRET_HEADER,c as AUTH_DO_SESSION_PATH,G as DEFAULT_AUTH_BASE_PATH,A as LunoraAuthAdminError,H as LunoraAuthDO,X as LunoraAuthHeadersError,ht as TURNSTILE_VERIFY_ENDPOINT,m as appendAuthAuditEntry,M as assertEmailAllowed,E as authAuditHook,v as authDoColumnAdditions,L as authDoSchemaStatements,ot as authTables,f as buildAuditEntry,C as classifyEmail,tt as compileMigrationsSql,U as createAuth,u as createAuthAdmin,l as createAuthAuditReader,O as createDoAuthWiring,lt as createMemoryAuthStore,W as createSignUpInvitation,st as createSqlAuthStore,nt as d1Executor,N as emailGateDatabaseHooks,k as emailGateMiddleware,p as ensureAuthAuditTable,et as ensureMigrated,T as eventForPath,B as handleAuthRequest,K as legacyIssuerCleanupStatements,Y as listSignUpInvitations,q as loadEmailDomainLists,r as lunoraAuthAdapter,o as lunoraD1Adapter,a as lunoraDoAdapter,pt as matchesWhere,j as pruneSignUpInvitations,d as readAuthAuditLog,R as resolveAuthOptions,z as revokeSignUpInvitation,it as sessionPresets,At as validateSessionPolicy,Et as verifyTurnstile,Tt as verifyTurnstileMiddleware,S as withAuthAudit,Z as withAuthPlugins,w as withEmailGate};
1
+ import{l as r,a as o,b as a}from"./packem_shared/adapter-CG0Yv85f.mjs";import{LunoraAuthAdminError as u,createAuthAdmin as s}from"./packem_shared/LunoraAuthAdminError-uhKG1MgQ.mjs";import{AUTH_AUDIT_TABLE as n,appendAuthAuditEntry as m,createAuthAuditReader as l,ensureAuthAuditTable as p,readAuthAuditLog as d}from"./audit.mjs";import{authAuditHook as f,buildAuditEntry as x,eventForPath as E,withAuthAudit as T}from"./packem_shared/authAuditHook-DPTKdjBe.mjs";import{R as D,I as _,a as c,L as U}from"./packem_shared/auth-do-DoiVT_x7.mjs";import{createAuth as I,resolveAuthOptions as g}from"./packem_shared/createAuth-8aUw8v8D.mjs";import{authDoColumnAdditions as L,authDoSchemaStatements as y}from"./packem_shared/authDoColumnAdditions-UwF3Rl41.mjs";import{createDoAuthWiring as O}from"./packem_shared/createDoAuthWiring-5upQbv-P.mjs";import{emailGateDatabaseHooks as w,withEmailGate as b}from"./packem_shared/emailGateDatabaseHooks-CAygR3iq.mjs";import{assertEmailAllowed as N,classifyEmail as k,emailGateMiddleware as q,loadEmailDomainLists as C}from"./email-guard.mjs";import{DEFAULT_AUTH_BASE_PATH as G,handleAuthRequest as B}from"./packem_shared/DEFAULT_AUTH_BASE_PATH-DneiLGpv.mjs";import{createSignUpInvitation as V,listSignUpInvitations as Y,pruneSignUpInvitations as j,revokeSignUpInvitation as z}from"./packem_shared/createSignUpInvitation-DHZL9fNl.mjs";import{legacyIssuerCleanupStatements as K}from"./packem_shared/legacyIssuerCleanupStatements-D9Kf8OD1.mjs";import{LunoraAuthHeadersError as X,withAuthPlugins as Z}from"./middleware.mjs";import{compileMigrationsSql as tt,ensureMigrated as et}from"./packem_shared/compileMigrationsSql-DKGrw7Lf.mjs";import{default as ot}from"./schema.mjs";import{sessionPresets as it,validateSessionPolicy as ut}from"./packem_shared/sessionPresets-C867Mlo4.mjs";import{c as At,d as nt}from"./packem_shared/sql-store-CYa4HJsO.mjs";import{createMemoryAuthStore as lt,matchesWhere as pt}from"./store.mjs";import{TURNSTILE_VERIFY_ENDPOINT as ht,verifyTurnstile as ft}from"./turnstile.mjs";import{verifyTurnstileMiddleware as Et}from"./turnstile-middleware.mjs";export{n as AUTH_AUDIT_TABLE,D as AUTH_DO_AUDIT_PATH,_ as AUTH_DO_SECRET_HEADER,c as AUTH_DO_SESSION_PATH,G as DEFAULT_AUTH_BASE_PATH,u as LunoraAuthAdminError,U as LunoraAuthDO,X as LunoraAuthHeadersError,ht as TURNSTILE_VERIFY_ENDPOINT,m as appendAuthAuditEntry,N as assertEmailAllowed,f as authAuditHook,L as authDoColumnAdditions,y as authDoSchemaStatements,ot as authTables,x as buildAuditEntry,k as classifyEmail,tt as compileMigrationsSql,I as createAuth,s as createAuthAdmin,l as createAuthAuditReader,O as createDoAuthWiring,lt as createMemoryAuthStore,V as createSignUpInvitation,At as createSqlAuthStore,nt as d1Executor,w as emailGateDatabaseHooks,q as emailGateMiddleware,p as ensureAuthAuditTable,et as ensureMigrated,E as eventForPath,B as handleAuthRequest,K as legacyIssuerCleanupStatements,Y as listSignUpInvitations,C as loadEmailDomainLists,r as lunoraAuthAdapter,o as lunoraD1Adapter,a as lunoraDoAdapter,pt as matchesWhere,j as pruneSignUpInvitations,d as readAuthAuditLog,g as resolveAuthOptions,z as revokeSignUpInvitation,it as sessionPresets,ut as validateSessionPolicy,ft as verifyTurnstile,Et as verifyTurnstileMiddleware,T as withAuthAudit,Z as withAuthPlugins,b as withEmailGate};
@@ -0,0 +1 @@
1
+ import{I as i,L as R,R as _,a as S}from"./auth-do-DoiVT_x7.mjs";import"./adapter-CG0Yv85f.mjs";import"../audit.mjs";import"./createAuth-8aUw8v8D.mjs";import"./authDoColumnAdditions-UwF3Rl41.mjs";import"./DEFAULT_AUTH_BASE_PATH-DneiLGpv.mjs";import"./legacyIssuerCleanupStatements-D9Kf8OD1.mjs";export{i as INTERNAL_SECRET_HEADER,R as LunoraAuthDO,_ as READ_AUDIT_PATH,S as RESOLVE_SESSION_PATH};
@@ -0,0 +1 @@
1
+ import{getAuthTablesWithResolvedIndexes as x}from"@better-auth/core/db/internal";import{LunoraError as b,toErrorBody as re}from"@lunora/errors";import{d as P,b as ne}from"./adapter-CG0Yv85f.mjs";import{AUTH_AUDIT_TABLE as oe,ensureAuthAuditTable as se,createAuthAuditReader as ie}from"../audit.mjs";import{resolveAuthOptions as ae,createAuth as ce}from"./createAuth-8aUw8v8D.mjs";import{authDoSchemaStatements as ue,authDoColumnAdditions as fe}from"./authDoColumnAdditions-UwF3Rl41.mjs";import{handleAuthRequest as le}from"./DEFAULT_AUTH_BASE_PATH-DneiLGpv.mjs";import{q as c}from"./quote-identifier-CGiYFBvY.mjs";import{schemaDeclaresIssuer as me,legacyIssuerCleanupStatements as de,indexesReferencingIssuer as pe}from"./legacyIssuerCleanupStatements-D9Kf8OD1.mjs";const Ee=(t,e)=>{const r=Math.max(t.length,e.length);let n=t.length^e.length;for(let s=0;s<r;s+=1){const o=s<t.length?t.charCodeAt(s):0,i=s<e.length?e.charCodeAt(s):0;n|=o^i}return n===0},W=2166136261,V=16777619,F=(t,e=W)=>{let r=e;for(let n=0;n<t.length;n+=1)r^=t.charCodeAt(n),r=Math.imul(r,V);return(r>>>0).toString(16).padStart(8,"0")},he=t=>`${F(t,W)}${F(t,V)}`,$=t=>{let e="";for(let n=0;n<t.length;n+=32768)e+=String.fromCharCode(...t.subarray(n,n+32768));return btoa(e)},we=t=>{const e=atob(t),r=new Uint8Array(e.length);for(let n=0;n<e.length;n+=1)r[n]=e.codePointAt(n)??0;return r},d="$lunora.wire$",j=64,H=1024,U="__proto__",B={BigInt64Array,BigUint64Array,Float32Array,Float64Array,Int8Array,Int16Array,Int32Array,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array},q={Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError},ye=t=>{if(t===null||typeof t!="object")return!1;const e=Object.getPrototypeOf(t);return e===null||e===Object.prototype},T=(t,e=0)=>{if(e>j)throw new RangeError(`wire-codec: value nesting exceeds the ${j}-level limit`);if(t===void 0)return[d,"undefined"];if(t===null)return null;const r=typeof t;if(r==="bigint")return[d,"bigint",t.toString()];if(r==="number"){const o=t;return Number.isNaN(o)?[d,"nan"]:o===1/0?[d,"inf"]:o===-1/0?[d,"-inf"]:o}if(r!=="object")return t;if(t instanceof Date)return[d,"date",T(t.getTime(),e+1)];if(t instanceof Error){const o=t,i={};for(const u of Object.keys(o)){if(o[u]===void 0)continue;const f=T(o[u],e+1);u===U?Object.defineProperty(i,u,{configurable:!0,enumerable:!0,value:f,writable:!0}):i[u]=f}const a=[d,"error",String(o.name),String(o.message),i];return o.cause!==void 0&&a.push(T(o.cause,e+1)),a}if(t instanceof URL)return[d,"url",t.href];if(t instanceof Map)return[d,"map",[...t.entries()].map(([o,i])=>[T(o,e+1),T(i,e+1)])];if(t instanceof Set)return[d,"set",[...t].map(o=>T(o,e+1))];if(t instanceof ArrayBuffer)return[d,"bytes",$(new Uint8Array(t)),"ArrayBuffer"];if(ArrayBuffer.isView(t)){const o=t,i=o.constructor.name,a=new Uint8Array(o.buffer,o.byteOffset,o.byteLength);return i==="Uint8Array"?[d,"bytes",$(a)]:[d,"bytes",$(a),i]}if(Array.isArray(t)){const o=t.map(i=>T(i,e+1));return o.length>0&&o[0]===d?[d,"arr",o]:o}if(!ye(t)){const o=t.constructor?.name??"value";throw new TypeError(`wire-codec: cannot encode a ${o} over the Lunora wire — only plain objects, arrays, and the supported built-ins (Date, Error, URL, Map, Set, ArrayBuffer/typed arrays, bigint) round-trip`)}const n=t,s={};for(const o of Object.keys(n)){const i=n[o];if(i===void 0)continue;const a=T(i,e+1);o===U?Object.defineProperty(s,o,{configurable:!0,enumerable:!0,value:a,writable:!0}):s[o]=a}return s},E=(t,e=0)=>{if(e>j)throw new RangeError(`wire-codec: value nesting exceeds the ${j}-level limit`);if(t===null||typeof t!="object")return t;if(Array.isArray(t)){if(t[0]===d)switch(t[1]){case"-inf":return-1/0;case"arr":return t[2].map(o=>E(o,e+1));case"bigint":{const o=t[2];if(typeof o!="string"||o.length>H||!/^-?\d+$/.test(o))throw new RangeError(`wire-codec: invalid or over-long bigint (max ${H} digits)`);return BigInt(o)}case"date":{const o=E(t[2],e+1);if(typeof o!="number")throw new TypeError("wire-codec: malformed date — epoch must be a number");return new Date(o)}case"map":{const o=t[2];return new Map(o.map(i=>{if(!Array.isArray(i)||i.length!==2)throw new TypeError("wire-codec: malformed map entry — expected a [key, value] pair");return[E(i[0],e+1),E(i[1],e+1)]}))}case"set":return new Set(t[2].map(o=>E(o,e+1)));case"url":{const o=t[2];if(typeof o!="string")throw new TypeError("wire-codec: malformed url — href must be a string");return new URL(o)}case"error":{const o=t[2],i=t[3];if(typeof o!="string"||typeof i!="string")throw new TypeError("wire-codec: malformed error — name and message must be strings");const a=(Object.hasOwn(q,o)?q[o]:void 0)??Error,u=new a(i);u.name!==o&&Object.defineProperty(u,"name",{configurable:!0,value:o,writable:!0});const f=E(t[4],e+1);if(f===null||typeof f!="object"||Array.isArray(f))throw new TypeError("wire-codec: malformed error — props must be an object");for(const m of Object.keys(f))m===U?Object.defineProperty(u,m,{configurable:!0,enumerable:!0,value:f[m],writable:!0}):u[m]=f[m];return t.length>5&&Object.defineProperty(u,"cause",{configurable:!0,value:E(t[5],e+1),writable:!0}),u}case"bytes":{const o=t[2];if(typeof o!="string")throw new TypeError("wire-codec: malformed bytes — payload must be a base64 string");const i=we(o);if($(i)!==o)throw new TypeError("wire-codec: malformed bytes — payload must be canonical padded base64");const a=t[3]??"Uint8Array";if(a==="ArrayBuffer")return i.buffer.byteLength===i.byteLength?i.buffer:i.slice().buffer;const u=Object.hasOwn(B,a)?B[a]:void 0;return u?new u(i.slice().buffer):i}case"inf":return 1/0;case"nan":return Number.NaN;case"undefined":return;default:return t.map(o=>E(o,e+1))}return t.map(s=>E(s,e+1))}const r=t,n={};for(const s of Object.keys(r)){const o=E(r[s],e+1);s===U?Object.defineProperty(n,s,{configurable:!0,enumerable:!0,value:o,writable:!0}):n[s]=o}return n},Te="/__lunora/auth/move",g="__lunora_auth_move__",S="__lunora_auth_move_rows__",D="__lunora_auth_purged__",G=100,ge=16,Ae=100,be=2n**64n,X=t=>t.startsWith("sqlite_")||t.startsWith("_cf_")||t===g||t===S||t===D,Y=async(t,e)=>t.transaction(async()=>Promise.resolve().then(e)),h=(t,e,...r)=>[...t.sql.exec(e,...r)],l=(t,e,...r)=>{[...t.sql.exec(e,...r)]},N=t=>h(t,"SELECT name FROM sqlite_master WHERE type = 'table' ORDER BY name").map(e=>String(e.name)).filter(e=>!X(e)),J=(t,e)=>h(t,"SELECT name, pk FROM pragma_table_info(?)",e).map(r=>({name:String(r.name),pk:Number(r.pk)})),L=(t,e)=>J(t,e).map(({name:r})=>r),K=(t,e)=>{const r=J(t,e),n=r.filter(({pk:s})=>s>0).toSorted((s,o)=>s.pk-o.pk).map(({name:s})=>s);return n.length>0?n:r.map(({name:s})=>s)},Q=(t,e)=>Number(h(t,`SELECT count(*) AS n FROM ${c(e)}`)[0]?.n??0),z=t=>JSON.stringify(T(t)),C=(t,e)=>BigInt(`0x${he(z(e.map(r=>t[r]??null)))}`),Z=(t,e)=>{let r=0,n=0n;for(const s of t)r+=1,n=(n+e(s))%be;return`${String(r)}:${n.toString(16)}`},ee=(t,e)=>{const r=L(t,e).toSorted((n,s)=>n.localeCompare(s));return Z(t.sql.exec(`SELECT * FROM ${c(e)}`),n=>C(n,r))},Se=t=>N(t).map(e=>{const r=h(t,"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?",e)[0]?.sql,n=h(t,"SELECT name, sql FROM sqlite_master WHERE type = 'index' AND tbl_name = ? AND sql IS NOT NULL",e).map(s=>({name:String(s.name),sql:String(s.sql)}));return{columns:L(t,e),indexes:n,name:e,rows:Q(t,e),sql:typeof r=="string"?r:""}}),v=(t,e)=>{if(typeof e!="string"||!N(t).includes(e))throw new TypeError(`unknown table ${JSON.stringify(e)}`);return e},Re=(t,e,r)=>{const n=h(t,`SELECT rowid AS "__lunora_rowid__", * FROM ${c(e)} WHERE rowid > ? ORDER BY rowid LIMIT ?`,r,G),s=n.at(-1)?.__lunora_rowid__;return{last:typeof s=="number"?s:void 0,rows:n.map(({__lunora_rowid__:o,...i})=>i)}},Oe=t=>L(t,g).length>0,_=t=>Oe(t)?Object.fromEntries(h(t,`SELECT tbl, after, done, pass, cols, watermark FROM ${c(g)}`).map(e=>[String(e.tbl),{after:Number(e.after),columns:JSON.parse(String(e.cols)),done:e.done===1,pass:Number(e.pass),watermark:Number(e.watermark)}])):{},Ne=(t,e,r)=>Z(t.sql.exec(`SELECT h FROM ${c(S)} WHERE tbl = ? AND pass = ?`,e,r),n=>BigInt(`0x${String(n.h)}`)),_e=t=>{l(t,`CREATE TABLE IF NOT EXISTS ${c(g)} (tbl TEXT NOT NULL PRIMARY KEY, after INTEGER NOT NULL, done INTEGER NOT NULL, pass INTEGER NOT NULL, cols TEXT NOT NULL, watermark INTEGER NOT NULL DEFAULT 0)`),l(t,`CREATE TABLE IF NOT EXISTS ${c(S)} (tbl TEXT NOT NULL, k TEXT NOT NULL, h TEXT NOT NULL, pass INTEGER NOT NULL, PRIMARY KEY (tbl, k))`)},Le=(t,e,r)=>{if(!N(t).includes(e))return 0;const n=K(t,e).map(s=>`u.${c(s)}`).join(", ");return Number(h(t,`SELECT count(*) AS n FROM ${c(e)} u WHERE u.rowid > ? AND NOT EXISTS (SELECT 1 FROM ${c(S)} c WHERE c.tbl = ? AND c.k = json_array(${n}))`,r,e)[0]?.n??0)},Ie=/^CREATE TABLE /iu,$e=/^CREATE (?:UNIQUE )?INDEX /iu,je=(t,e,r)=>{if(X(e.name))throw new TypeError(`refusing reserved table ${JSON.stringify(e.name)}`);if(!Ie.test(e.sql)||e.indexes.some(({sql:s})=>!$e.test(s)))throw new TypeError(`refusing unexpected DDL for ${JSON.stringify(e.name)}`);if(r.has(e.name)){const s=new Set(L(t,e.name));for(const o of e.columns.filter(i=>!s.has(i)))l(t,`ALTER TABLE ${c(e.name)} ADD COLUMN ${c(o)}`)}else l(t,e.sql);const n=new Set(h(t,"SELECT name FROM sqlite_master WHERE type = 'index'").map(s=>String(s.name)));for(const s of e.indexes.filter(({name:o})=>!n.has(o)))l(t,s.sql)},Ue=(t,e,r)=>{_e(t);const n=Le(t,r.userTable,_(t)[r.userTable]?.watermark??0);if(n>0&&!r.force)throw new b("AUTH_MOVE_TARGET_NOT_EMPTY",`the pinned auth object has ${String(n)} user(s) the copy did not write; copying into it would merge two user bases — pass force to copy anyway`,{data:{users:n}});const s=new Set(N(t)),o=_(t);for(const a of e){je(t,a,s);const u=o[a.name],f=JSON.stringify(a.columns.toSorted((m,w)=>m.localeCompare(w)));u===void 0?l(t,`INSERT INTO ${c(g)} (tbl, after, done, pass, cols) VALUES (?, 0, 0, 1, ?)`,a.name,f):l(t,`UPDATE ${c(g)} SET cols = ? WHERE tbl = ?`,f,a.name)}l(t,`UPDATE ${c(g)} SET watermark = (SELECT coalesce(max(rowid), 0) FROM ${c(r.userTable)}) WHERE tbl = ?`,r.userTable);const i=_(t);return{cursors:Object.fromEntries(e.map(({name:a})=>[a,i[a]?.after??0])),done:Object.fromEntries(e.map(({name:a})=>[a,i[a]?.done??!1])),targetRows:Object.fromEntries(e.map(({name:a})=>[a,Q(t,a)]))}},te=(t,e,r,n,s)=>h(t,`SELECT ${s.map(o=>c(o)).join(", ")} FROM ${c(e)} WHERE ${r.map(o=>`${c(o)} IS ?`).join(" AND ")} LIMIT 1`,...n)[0],k=(t,e)=>{if(!e)throw new b("AUTH_MOVE_CONFLICT",`a row copied into ${t} collides with a row the pinned auth object holds on its own — nothing from this page was written; pass force to keep the pinned object's rows`,{data:{table:t}});return"conflicts"},De=t=>t instanceof Error&&t.message.includes("UNIQUE constraint failed"),ke=(t,e)=>{if(e.prior!==void 0)return k(e.table,e.force);try{l(t,`INSERT INTO ${c(e.table)} (${e.columns.map(r=>c(r)).join(", ")}) VALUES (${e.columns.map(()=>"?").join(", ")})`,...e.columns.map(r=>e.row[r]))}catch(r){if(!De(r))throw r;return k(e.table,e.force)}return"copied"},Ce=(t,e,r)=>{const n=C(r,e.columns).toString(16);return n===e.h?"unchanged":e.prior===void 0||n!==e.prior?k(e.table,e.force):(l(t,`UPDATE ${c(e.table)} SET ${e.columns.map(s=>`${c(s)} = ?`).join(", ")} WHERE ${e.keys.map(s=>`${c(s)} IS ?`).join(" AND ")}`,...e.columns.map(s=>e.row[s]),...e.key),"updated")},Me=(t,e,r,n)=>{const{force:s,keys:o,pass:i}=n,a=Object.keys(r).toSorted((A,I)=>A.localeCompare(I));if(a.length+o.length>Ae)throw new TypeError(`${e} has too many columns to copy`);const u=o.map(A=>r[A]??null),f=z(u),m=C(r,a).toString(16),w=h(t,`SELECT h FROM ${c(S)} WHERE tbl = ? AND k = ?`,e,f)[0]?.h,p={columns:a,force:s,h:m,key:u,keys:o,prior:typeof w=="string"?w:void 0,row:r,table:e},y=p.prior===m?void 0:te(t,e,o,u,a);let R="unchanged";return p.prior!==m&&(R=y===void 0?ke(t,p):Ce(t,p,y)),l(t,`INSERT INTO ${c(S)} (tbl, k, h, pass) VALUES (?, ?, ?, ?) ON CONFLICT (tbl, k) DO UPDATE SET h = excluded.h, pass = excluded.pass`,e,f,m,i),R},xe=(t,e,r)=>{const{counts:n,force:s,keys:o,marker:i}=r,a=h(t,`SELECT k, h FROM ${c(S)} WHERE tbl = ? AND pass < ?`,e,i.pass);for(const u of a){const f=E(JSON.parse(String(u.k))),m=te(t,e,o,f,i.columns);m!==void 0&&(C(m,i.columns).toString(16)===String(u.h)?(l(t,`DELETE FROM ${c(e)} WHERE ${o.map(w=>`${c(w)} IS ?`).join(" AND ")}`,...f),n.deleted+=1):n[k(e,s)]+=1),l(t,`DELETE FROM ${c(S)} WHERE tbl = ? AND k = ?`,e,String(u.k))}},Pe=async(t,e,r)=>{const n=_(t)[e];if(n===void 0)throw new TypeError(`table ${JSON.stringify(e)} was not part of this move`);return Y(t,()=>{const s={conflicts:0,copied:0,deleted:0,unchanged:0,updated:0},o=K(t,e);for(const i of r.rows)s[Me(t,e,i,{force:r.force,keys:o,pass:n.pass})]+=1;return r.final&&xe(t,e,{counts:s,force:r.force,keys:o,marker:n}),l(t,`UPDATE ${c(g)} SET after = ?, done = ? WHERE tbl = ?`,r.last,r.final?1:0,e),s})},Fe=async(t,e)=>{const r=N(t);return await Y(t,()=>{const n=r.filter(o=>e[o]===void 0);if(n.length>0)throw new b("AUTH_MOVE_INCOMPLETE",`refusing to purge the un-pinned auth object: ${n.join(", ")} not fully copied — run the copy to done: true first`,{data:{unfinished:n}});const s=r.filter(o=>ee(t,o)!==e[o]);if(s.length>0)throw new b("AUTH_MOVE_SOURCE_CHANGED",`refusing to purge the un-pinned auth object: ${s.join(", ")} changed since it was copied — run the copy again to carry the changes, then purge`,{data:{changed:s}});for(const o of r)l(t,`DROP TABLE ${c(o)}`);l(t,`CREATE TABLE IF NOT EXISTS ${c(D)} (at INTEGER NOT NULL)`),l(t,`INSERT INTO ${c(D)} (at) VALUES (?)`,Date.now())}),{dropped:r}},He=t=>{if(L(t,D).length>0)throw new b("AUTH_MOVE_SOURCE_PURGED","the un-pinned auth object was purged after its tables were copied; anything in it now is new, and copying it would delete the pinned object's users")},Be=new Set(["fingerprints","manifest","page","purge"]),qe=(t,e,r)=>{e.prepare();const n=_(t);return{copied:r?Object.fromEntries(Object.entries(n).map(([s,o])=>[s,Ne(t,s,o.pass)])):{},markers:n,order:e.order()}},ve=(t,e)=>{for(const r of e)l(t,`UPDATE ${c(g)} SET after = 0, done = 0, pass = pass + 1 WHERE tbl = ?`,r);return{}},We=[/(?:UNIQUE|NOT NULL|CHECK|FOREIGN KEY|PRIMARY KEY) constraint failed/u,/no such (?:table|column)/u,/datatype mismatch/u,/SQLITE_[A-Z_]+/u],Ve=t=>{const e=t instanceof Error?t.message:String(t);for(const r of We){const n=r.exec(e);if(n)return n[0]}return t instanceof Error?t.name:"unknown"},Ge=async(t,e,r)=>{switch(Be.has(String(e.op))&&He(t),e.op){case"begin":return r.prepare(),Ue(t,e.tables,{force:e.force===!0,userTable:r.userTable()});case"fingerprints":return{fingerprints:Object.fromEntries(N(t).map(n=>[n,ee(t,n)]))};case"manifest":return{tables:Se(t)};case"page":{const n=Re(t,v(t,e.table),Number(e.after??0));return{last:n.last,rows:T(n.rows)}}case"purge":{const n=await Fe(t,e.expected??{});return r.onPurge(),n}case"rescan":return ve(t,e.tables??[]);case"status":return qe(t,r,e.fingerprints===!0);case"write":return Pe(t,v(t,e.table),{final:e.final===!0,force:e.force===!0,last:Number(e.last),rows:E(e.rows)});default:throw new TypeError(`unknown move op ${JSON.stringify(e.op)}`)}},Xe=async(t,e,r)=>{try{return await Ge(t,e,r)}catch(n){if(n instanceof b)throw n;console.error("@lunora/auth: auth move step failed",n);const s=String(e.op),o=typeof e.table=="string"?e.table:void 0,i=Ve(n);throw new b("AUTH_MOVE_FAILED",`auth move ${s}${o===void 0?"":` on ${o}`} failed: ${i}`,{data:{cause:i,op:s,...o===void 0?{}:{table:o}}})}},Ye=(t,e)=>{const r=n=>{const s=e.first.indexOf(n);if(s!==-1)return s;const o=e.last.indexOf(n);return o===-1?e.first.length:e.first.length+1+o};return t.toSorted((n,s)=>r(n.name)-r(s.name)||n.name.localeCompare(s.name))},Je=(t,e)=>({conflicts:0,copied:0,deleted:0,sourceRows:t.rows,table:t.name,targetRows:e,unchanged:0,updated:0}),ut=t=>{const e=async(r,n)=>{const s=await t(r,n);if(!s.ok){let o={};try{const i=await s.json();typeof i.error=="object"&&i.error!==null&&(o=i.error)}catch{}throw new b(o.code??"AUTH_MOVE_FAILED",o.message??`auth move ${String(n.op)} on the ${r} object failed (${String(s.status)})`,{data:o.data,status:s.status})}return s.json()};return{copy:async(r={})=>{const n=r.force===!0,s=await e("target",{op:"status"}),{tables:o}=await e("source",{op:"manifest"}),i=await e("target",{force:n,op:"begin",tables:o}),a=[];let u=0;for(const p of Ye(o,s.order)){const y=Je(p,i.targetRows[p.name]??0);let R=i.cursors[p.name]??0;for(a.push(y);;){if(u>=ge)return{done:!1,tables:a};u+=1;const A=await e("source",{after:R,op:"page",table:p.name}),I=E(A.rows),M=I.length<G;if(I.length===0&&i.done[p.name]===!0)break;const O=await e("target",{final:M,force:n,last:A.last??R,op:"write",rows:A.rows,table:p.name});if(y.conflicts+=O.conflicts,y.copied+=O.copied,y.deleted+=O.deleted,y.unchanged+=O.unchanged,y.updated+=O.updated,y.targetRows+=O.copied-O.deleted,R=A.last??R,M)break}}const{fingerprints:f}=await e("source",{op:"fingerprints"}),m=await e("target",{fingerprints:!0,op:"status"}),w=Object.keys(f).filter(p=>m.copied[p]!==f[p]);return w.length>0&&await e("target",{op:"rescan",tables:w}),{done:w.length===0,tables:a}},purge:async()=>{const{copied:r,markers:n}=await e("target",{fingerprints:!0,op:"status"}),s=Object.fromEntries(Object.entries(n).filter(([,o])=>o.done).map(([o])=>[o,r[o]]));return e("source",{expected:s,op:"purge"})}}},Ke="/__lunora/auth/session",Qe="/__lunora/auth/audit",ze="x-lunora-auth-do-secret",Ze=t=>{if(t===null||typeof t!="object"||Array.isArray(t))return{error:"body must be a JSON object"};const e={};for(const[r,n]of Object.entries(t))if(r==="limit"||r==="sinceSeq"){if(typeof n!="number"||!Number.isFinite(n))return{error:`"${r}" must be a finite number`};e[r]=n}else if(r==="actorId"||r==="event"){if(typeof n!="string")return{error:`"${r}" must be a string`};e[r]=n}else return{error:`unknown audit read option "${r}"`};return{options:e}};class ft{#r;#a;#c;#e;#t;#n=!1;#o={first:["user"],last:[]};constructor(e,r,n={}){this.#e=e.storage,this.#r=P(e.storage),this.#c=r,this.#a=n}#s(){if(this.#t!==void 0)return this.#t;const e=this.#c(),r=ae(e),{tables:n}=x(r);if(this.#o={first:[n.user?.modelName??"user",n.account?.modelName??"account",n.session?.modelName??"session"],last:[oe,n.rateLimit?.modelName??"rateLimit"]},!this.#n){for(const s of ue(r))[...this.#e.sql.exec(s)];for(const s of fe(r,o=>this.#u(o)))[...this.#e.sql.exec(s)];this.#f(r),this.#n=!0}return this.#t=ce({...e,database:ne(this.#e)}),this.#t}#u(e){return[...this.#e.sql.exec("SELECT name FROM pragma_table_info(?)",e)].map(n=>String(n.name))}#f(e){const{tables:r}=x(e),{account:n}=r;if(n===void 0)return;const s=Object.entries(n.fields).map(([o,i])=>i.fieldName??o);if(!(me(s)||!this.#u(n.modelName).includes("issuer")))try{const o=[...this.#e.sql.exec("SELECT name, sql FROM sqlite_master WHERE type = 'index' AND tbl_name = ?",n.modelName)].map(i=>({name:String(i.name),sql:typeof i.sql=="string"?i.sql:void 0}));for(const i of de(n.modelName,pe(o)))[...this.#e.sql.exec(i)]}catch(o){console.error("@lunora/auth: could not drop the reverted `account.issuer` column; if it is still present, sign-ups will fail until it is removed.",o)}}async#l(e){if(!this.#i(e))return Response.json({error:"unauthorized"},{status:401});let r;try{r=await e.json()}catch{return Response.json({error:"invalid body"},{status:400})}const n=Ze(r??{});if("error"in n)return Response.json({error:n.error},{status:400});await se(this.#r);const s=await ie(this.#r).read(n.options);return Response.json({entries:s})}async#m(e){if(e.method!=="POST"||!this.#i(e))return Response.json({error:"unauthorized"},{status:401});try{const r=await e.json(),n=await Xe(this.#e,r,{onPurge:()=>{this.#n=!1,this.#t=void 0,this.#r=P(this.#e)},order:()=>this.#o,prepare:()=>{this.#s()},userTable:()=>this.#o.first[0]??"user"});return Response.json(n)}catch(r){const{body:n,redacted:s,status:o}=re(r,{encodeData:i=>i,fallbackCode:"AUTH_MOVE_FAILED",redactedMessage:"auth move failed"});return s&&console.error("@lunora/auth: auth move failed",r),Response.json({error:n},{status:o})}}#i(e){const{internalSecret:r}=this.#a;if(r===void 0||r==="")return!1;const n=e.headers.get(ze);return n!==null&&Ee(n,r)}async#d(e){if(!this.#i(e))return Response.json({error:"unauthorized"},{status:401});const n=await this.#s().api.getSession({headers:e.headers}),s=n?.user.id;if(s===void 0)return Response.json({});const o=n?.session.expiresAt,i=n?.user,a=i?.role;return Response.json({...typeof i?.email=="string"&&i.email.length>0?{email:i.email}:{},...o instanceof Date?{expiresAtMs:o.getTime()}:{},...typeof i?.name=="string"&&i.name.length>0?{name:i.name}:{},...typeof a=="string"&&a.length>0?{role:a}:{},userId:s})}async fetch(e){const r=new URL(e.url);if(r.pathname===Ke)return this.#d(e);if(r.pathname===Qe)return this.#l(e);if(r.pathname===Te)return this.#m(e);const n=this.#s();return await le(n,e)??Response.json({error:"not an auth route"},{status:404})}}export{ze as I,ft as L,Te as M,Qe as R,Ke as a,ut as c};
@@ -0,0 +1 @@
1
+ import{LunoraError as y}from"@lunora/errors";import{I as d,a as A,c as w,R as E,M as R}from"./auth-do-DoiVT_x7.mjs";import{isAuthRoutePath as v,DEFAULT_AUTH_BASE_PATH as g}from"./DEFAULT_AUTH_BASE_PATH-DneiLGpv.mjs";const _=u=>{const{internalSecret:i,jurisdiction:a,objectName:l="auth"}=u,p=u.namespace;let{namespace:r}=u;if(r&&a!==void 0){if(typeof r.jurisdiction!="function")throw new TypeError(`@lunora/auth: Durable Object namespace does not support jurisdiction("${a}") — update @cloudflare/workers-types or remove the jurisdiction option`);r=r.jurisdiction(a)}const c=()=>{if(r)return r.get(r.idFromName(l))},m=async(t,n,o)=>{if(!i)return;const s=c();if(!s)return;const e=await s.fetch(new Request(new URL(t,n),{body:JSON.stringify(o),headers:{"content-type":"application/json",[d]:i},method:"POST"}));return e.ok?e:void 0},h=r,f=p&&h&&a!==void 0?w(async(t,n)=>{if(!i)throw new y("AUTH_MOVE_NOT_CONFIGURED","copying the auth object needs its internal secret; set the auth object's `internalSecret`");const o=t==="source"?p:h;return o.get(o.idFromName(l)).fetch(new Request(new URL(R,"https://auth-do.invalid"),{body:JSON.stringify(n),headers:{"content-type":"application/json",[d]:i},method:"POST"}))}):void 0;return{...f===void 0?{}:{jurisdictionMove:f},auditReader:{read:async t=>{const n=await m(E,"https://auth-do.invalid",t);return n?(await n.json())?.entries??[]:[]}},authHandler:async t=>{if(v(new URL(t.url).pathname,g))return c()?.fetch(t)},resolveIdentity:async t=>{if(!i)return null;const n=c();if(!n)return null;const o=new Headers(t.headers);o.set(d,i);const s=await n.fetch(new Request(new URL(A,t.url),{headers:o}));if(!s.ok)return null;const e=await s.json();return e?.userId?{...typeof e.email=="string"&&e.email.length>0?{email:e.email}:{},...typeof e.expiresAtMs=="number"&&Number.isFinite(e.expiresAtMs)?{expiresAtMs:e.expiresAtMs}:{},...typeof e.name=="string"&&e.name.length>0?{name:e.name}:{},...typeof e.role=="string"&&e.role.length>0?{role:e.role}:{},userId:e.userId}:null}}};export{_ as createDoAuthWiring};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/auth",
3
- "version": "1.0.0-alpha.164",
3
+ "version": "1.0.0-alpha.166",
4
4
  "description": "Auth for Lunora — a thin better-auth wrapper: email/password, OAuth, plugins, D1-backed",
5
5
  "keywords": [
6
6
  "auth",
@@ -103,8 +103,8 @@
103
103
  "@better-auth/oauth-provider": "1.7.3",
104
104
  "@better-auth/passkey": "1.7.3",
105
105
  "@better-auth/scim": "1.7.3",
106
- "@lunora/errors": "1.0.0-alpha.43",
107
- "@lunora/values": "1.0.0-alpha.54",
106
+ "@lunora/errors": "1.0.0-alpha.44",
107
+ "@lunora/values": "1.0.0-alpha.55",
108
108
  "@visulima/disposable-email-domains": "1.1.1",
109
109
  "@visulima/email-verifier": "1.0.9",
110
110
  "@visulima/free-email-domains": "1.0.1",
@@ -1 +0,0 @@
1
- import{getAuthTablesWithResolvedIndexes as u}from"@better-auth/core/db/internal";import{d as c,b as l}from"./adapter-CG0Yv85f.mjs";import{ensureAuthAuditTable as h,createAuthAuditReader as m}from"../audit.mjs";import{resolveAuthOptions as d,createAuth as p}from"./createAuth-8aUw8v8D.mjs";import{authDoSchemaStatements as f,authDoColumnAdditions as g}from"./authDoColumnAdditions-UwF3Rl41.mjs";import{handleAuthRequest as A}from"./DEFAULT_AUTH_BASE_PATH-DneiLGpv.mjs";import{schemaDeclaresIssuer as y,legacyIssuerCleanupStatements as R,indexesReferencingIssuer as x}from"./legacyIssuerCleanupStatements-D9Kf8OD1.mjs";const E=(o,t)=>{const s=Math.max(o.length,t.length);let e=o.length^t.length;for(let n=0;n<s;n+=1){const i=n<o.length?o.charCodeAt(n):0,r=n<t.length?t.charCodeAt(n):0;e|=i^r}return e===0},S="/__lunora/auth/session",b="/__lunora/auth/audit",v="x-lunora-auth-do-secret",_=o=>{if(o===null||typeof o!="object"||Array.isArray(o))return{error:"body must be a JSON object"};const t={};for(const[s,e]of Object.entries(o))if(s==="limit"||s==="sinceSeq"){if(typeof e!="number"||!Number.isFinite(e))return{error:`"${s}" must be a finite number`};t[s]=e}else if(s==="actorId"||s==="event"){if(typeof e!="string")return{error:`"${s}" must be a string`};t[s]=e}else return{error:`unknown audit read option "${s}"`};return{options:t}};class q{#s;#r;#n;#e;#t;#o=!1;constructor(t,s,e={}){this.#e=t.storage,this.#s=c(t.storage),this.#n=s,this.#r=e}#i(){if(this.#t!==void 0)return this.#t;const t=this.#n();if(!this.#o){const s=d(t);for(const e of f(s))[...this.#e.sql.exec(e)];for(const e of g(s,n=>this.#a(n)))[...this.#e.sql.exec(e)];this.#c(s),this.#o=!0}return this.#t=p({...t,database:l(this.#e)}),this.#t}#a(t){return[...this.#e.sql.exec("SELECT name FROM pragma_table_info(?)",t)].map(e=>String(e.name))}#c(t){const{tables:s}=u(t),{account:e}=s;if(e===void 0)return;const n=Object.entries(e.fields).map(([i,r])=>r.fieldName??i);if(!(y(n)||!this.#a(e.modelName).includes("issuer")))try{const i=[...this.#e.sql.exec("SELECT name, sql FROM sqlite_master WHERE type = 'index' AND tbl_name = ?",e.modelName)].map(r=>({name:String(r.name),sql:typeof r.sql=="string"?r.sql:void 0}));for(const r of R(e.modelName,x(i)))[...this.#e.sql.exec(r)]}catch(i){console.error("@lunora/auth: could not drop the reverted `account.issuer` column; if it is still present, sign-ups will fail until it is removed.",i)}}async#l(t){if(!this.#u(t))return Response.json({error:"unauthorized"},{status:401});let s;try{s=await t.json()}catch{return Response.json({error:"invalid body"},{status:400})}const e=_(s??{});if("error"in e)return Response.json({error:e.error},{status:400});await h(this.#s);const n=await m(this.#s).read(e.options);return Response.json({entries:n})}#u(t){const{internalSecret:s}=this.#r;if(s===void 0||s==="")return!1;const e=t.headers.get(v);return e!==null&&E(e,s)}async#h(t){if(!this.#u(t))return Response.json({error:"unauthorized"},{status:401});const e=await this.#i().api.getSession({headers:t.headers}),n=e?.user.id;if(n===void 0)return Response.json({});const i=e?.session.expiresAt,r=e?.user,a=r?.role;return Response.json({...typeof r?.email=="string"&&r.email.length>0?{email:r.email}:{},...i instanceof Date?{expiresAtMs:i.getTime()}:{},...typeof r?.name=="string"&&r.name.length>0?{name:r.name}:{},...typeof a=="string"&&a.length>0?{role:a}:{},userId:n})}async fetch(t){const s=new URL(t.url);if(s.pathname===S)return this.#h(t);if(s.pathname===b)return this.#l(t);const e=this.#i();return await A(e,t)??Response.json({error:"not an auth route"},{status:404})}}export{v as INTERNAL_SECRET_HEADER,q as LunoraAuthDO,b as READ_AUDIT_PATH,S as RESOLVE_SESSION_PATH};
@@ -1 +0,0 @@
1
- import{INTERNAL_SECRET_HEADER as d,RESOLVE_SESSION_PATH as f,READ_AUDIT_PATH as m}from"./AUTH_DO_AUDIT_PATH-u9QgGb_v.mjs";import{isAuthRoutePath as h,DEFAULT_AUTH_BASE_PATH as y}from"./DEFAULT_AUTH_BASE_PATH-DneiLGpv.mjs";const E=c=>{const{internalSecret:s,jurisdiction:a,objectName:l="auth"}=c;let{namespace:r}=c;if(r&&a!==void 0){if(typeof r.jurisdiction!="function")throw new TypeError(`@lunora/auth: Durable Object namespace does not support jurisdiction("${a}") — update @cloudflare/workers-types or remove the jurisdiction option`);r=r.jurisdiction(a)}const u=()=>{if(r)return r.get(r.idFromName(l))},p=async(t,n,o)=>{if(!s)return;const i=u();if(!i)return;const e=await i.fetch(new Request(new URL(t,n),{body:JSON.stringify(o),headers:{"content-type":"application/json",[d]:s},method:"POST"}));return e.ok?e:void 0};return{auditReader:{read:async t=>{const n=await p(m,"https://auth-do.invalid",t);return n?(await n.json())?.entries??[]:[]}},authHandler:async t=>{if(h(new URL(t.url).pathname,y))return u()?.fetch(t)},resolveIdentity:async t=>{if(!s)return null;const n=u();if(!n)return null;const o=new Headers(t.headers);o.set(d,s);const i=await n.fetch(new Request(new URL(f,t.url),{headers:o}));if(!i.ok)return null;const e=await i.json();return e?.userId?{...typeof e.email=="string"&&e.email.length>0?{email:e.email}:{},...typeof e.expiresAtMs=="number"&&Number.isFinite(e.expiresAtMs)?{expiresAtMs:e.expiresAtMs}:{},...typeof e.name=="string"&&e.name.length>0?{name:e.name}:{},...typeof e.role=="string"&&e.role.length>0?{role:e.role}:{},userId:e.userId}:null}}};export{E as createDoAuthWiring};