sentri 4.1.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +462 -211
- package/dist/adapters/elysia/index.cjs +1 -0
- package/dist/adapters/elysia/index.d.cts +149 -0
- package/dist/adapters/elysia/index.d.ts +149 -0
- package/dist/adapters/elysia/index.js +1 -0
- package/dist/adapters/express/index.cjs +1 -0
- package/dist/adapters/express/index.d.cts +308 -0
- package/dist/adapters/express/index.d.ts +308 -0
- package/dist/adapters/express/index.js +1 -0
- package/dist/adapters/fastify/index.cjs +1 -0
- package/dist/adapters/fastify/index.d.cts +98 -0
- package/dist/adapters/fastify/index.d.ts +98 -0
- package/dist/adapters/fastify/index.js +1 -0
- package/dist/adapters/hono/index.cjs +1 -0
- package/dist/adapters/hono/index.d.cts +114 -0
- package/dist/adapters/hono/index.d.ts +114 -0
- package/dist/adapters/hono/index.js +1 -0
- package/dist/adapters/koa/index.cjs +1 -0
- package/dist/adapters/koa/index.d.cts +90 -0
- package/dist/adapters/koa/index.d.ts +90 -0
- package/dist/adapters/koa/index.js +1 -0
- package/dist/cli.cjs +514 -0
- package/dist/cli.d.cts +1 -0
- package/dist/cli.js +434 -50
- package/dist/core/index.cjs +1 -0
- package/dist/core/index.d.cts +340 -0
- package/dist/core/index.d.ts +340 -0
- package/dist/core/index.js +1 -0
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -671
- package/dist/index.js +1 -1
- package/package.json +78 -6
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import je from'bcrypt';import W from'jsonwebtoken';import {randomUUID,generateKeyPairSync,createPublicKey,createPrivateKey}from'crypto';import {Kysely,sql,PostgresDialect}from'kysely';import {Router}from'express';import {Redis}from'ioredis';import {Pool}from'pg';var Fe=Object.assign(Object.create(null),{UNAUTHORIZED:401,TOKEN_EXPIRED:401,TOKEN_INVALID:401,INVALID_CREDENTIALS:401,FORBIDDEN:403,USER_NOT_FOUND:404,IDENTIFIER_NOT_FOUND:404,USER_ALREADY_EXISTS:409,IDENTIFIER_ALREADY_EXISTS:409,INVALID_ROLE:400,VALIDATION_ERROR:400,CONFIGURATION_ERROR:500}),c=class extends Error{code;statusCode;constructor(r,t,s){super(t),this.name="SentriError",this.code=r,this.statusCode=s??Fe[r]??500;}};async function G(e,r=12){return je.hash(e,r)}async function Z(e,r){return je.compare(e,r)}var qe=new Map,$e=new Map,Or=3600*1e3;function Ve(e){let r=qe.get(e);if(!r){let t=createPrivateKey(e),s=createPublicKey(t),n=s.export({format:"jwk"}),i=Buffer.from(e).slice(0,8).toString("base64url"),u={...n,use:"sig",kid:i};r={kid:i,publicKey:s,jwk:u},qe.set(e,r);}return r}function Be(e){let{jwk:r}=Ve(e);return {keys:[r]}}function Xe(e){return Ve(e).publicKey}async function Je(e){let r=Date.now(),t=$e.get(e);if(t&&r-t.fetchedAt<Or)return t.publicKey;let s=await fetch(e);if(!s.ok)throw new c("CONFIGURATION_ERROR",`Failed to fetch public key from ${e}: HTTP ${s.status}`);let n=await s.json();if(!n.keys||n.keys.length===0)throw new c("CONFIGURATION_ERROR",`No keys found in JWKS response from ${e}`);let i=n.keys[0],u=createPublicKey({key:i,format:"jwk"});return $e.set(e,{publicKey:u,fetchedAt:r}),u}var ze=new WeakMap,Ge=32,Ze=10,We=31;function Qe(e){if(e.mode==="client"){if(!e.keyUri||e.keyUri.trim().length===0)throw new c("CONFIGURATION_ERROR","keyUri must not be empty");return}if(!e.secret||e.secret.trim().length===0)throw new c("CONFIGURATION_ERROR","secret must not be empty");if((e.algorithm??"HS256").startsWith("HS")&&e.secret.length<Ge)throw new c("CONFIGURATION_ERROR",`secret must be at least ${Ge} characters for HMAC algorithms`);let s=e.saltRounds??12;if(!Number.isInteger(s)||s<Ze||s>We)throw new c("CONFIGURATION_ERROR",`saltRounds must be an integer between ${Ze} and ${We}`);if(!e.validRoles||e.validRoles.length===0)throw new c("CONFIGURATION_ERROR","validRoles must contain at least one role");if(!e.dialect)throw new c("CONFIGURATION_ERROR","dialect is required in server mode")}function C(e){let r=ze.get(e);if(r)return r;let t={algorithm:e.algorithm??"HS256",accessExpiresIn:e.accessExpiresIn??"15m",refreshExpiresIn:e.refreshExpiresIn??"7d",saltRounds:e.saltRounds??12,validRoles:e.validRoles,validRolesSet:new Set(e.validRoles),cookieName:e.cookie?.name??"refresh_token",accessCookieName:e.accessCookie?.name??"access_token"};return ze.set(e,t),t}var Ur=/^(\d+)([smhdw])$/,Kr={s:1e3,m:6e4,h:36e5,d:864e5,w:6048e5},Ye=new Map;function j(e){if(typeof e=="number")return e*1e3;let r=Ye.get(e);if(r!==void 0)return r;let t=Ur.exec(e);if(!t?.[1]||!t?.[2])throw new Error(`Invalid expiresIn: "${e}". Use e.g. "15m", "7d", "1h".`);let s=Kr[t[2]];if(s===void 0)throw new Error(`Invalid expiresIn: "${e}". Use e.g. "15m", "7d", "1h".`);let n=parseInt(t[1],10)*s;return Ye.set(e,n),n}var er=new Map,rr=new Map,tr=new Map;function sr(e){return e.startsWith("RS")||e.startsWith("PS")}function ir(e){let r=er.get(e);return r||(r={access:`${e}:access`,refresh:`${e}:refresh`},er.set(e,r)),r}function Hr(e){let r=rr.get(e);return r||(r=createPrivateKey(e),rr.set(e,r)),r}function nr(e){let r=C(e);if(sr(r.algorithm)){let n=Hr(e.secret);return {accessKey:n,refreshKey:n}}let{access:t,refresh:s}=ir(e.secret);return {accessKey:t,refreshKey:s}}function or(e,r){let t=C(e);if(sr(t.algorithm))return Xe(e.secret);let{access:s,refresh:n}=ir(e.secret);return r==="access"?s:n}function ar(e,r,t,s){let n=`${t}:${s}`,i=tr.get(n);return i||(i={expiresIn:t,algorithm:s},tr.set(n,i)),W.sign(e,r,i)}function ur(e,r,t){try{let s=W.verify(e,r,{algorithms:[t]});if(typeof s=="string"||s===null)throw new c("TOKEN_INVALID","Token payload is not an object");return s}catch(s){throw s instanceof c?s:s instanceof W.TokenExpiredError?new c("TOKEN_EXPIRED","Token has expired"):new c("TOKEN_INVALID","Token is invalid or malformed")}}function Y(e,r){let t=C(r),{accessKey:s}=nr(r);return ar(e,s,t.accessExpiresIn,t.algorithm)}function Q(e,r){let t=C(r),{refreshKey:s}=nr(r);return ar({sessionId:e},s,t.refreshExpiresIn,t.algorithm)}function de(e,r){let t=C(r),s=or(r,"access");return ur(e,s,t.algorithm)}function ee(e,r){let t=C(r),s=or(r,"refresh");return ur(e,s,t.algorithm)}function dr(e,r){try{let t=W.verify(e,r,{algorithms:["RS256","RS384","RS512","PS256","PS384","PS512"]});if(typeof t=="string"||t===null)throw new c("TOKEN_INVALID","Token payload is not an object");return t}catch(t){throw t instanceof c?t:t instanceof W.TokenExpiredError?new c("TOKEN_EXPIRED","Token has expired"):new c("TOKEN_INVALID","Token is invalid or malformed")}}function F(e){return C(e).cookieName}function q(e,r){if(!e)return;let t=`${r}=`,s=0;for(;s<e.length;){for(;s<e.length&&e[s]===" ";)s++;let n=e.indexOf(";",s),i=n===-1?e.length:n;if(e.startsWith(t,s))return e.slice(s+t.length,i);s=i+1;}}function re(e,r,t){let s=t.cookie??{},n=C(t),i=j(n.refreshExpiresIn);e.cookie(F(t),r,{httpOnly:s.httpOnly??true,secure:s.secure??false,sameSite:s.sameSite??"strict",path:s.path??"/",maxAge:i});}function ce(e,r){let t=r.cookie??{};e.clearCookie(F(r),{path:t.path??"/"});}function Se(e){return C(e).accessCookieName}function te(e,r,t){if(!t.accessCookie)return;let s=t.accessCookie,n=C(t),i=j(n.accessExpiresIn);e.cookie(Se(t),r,{httpOnly:false,secure:s.secure??false,sameSite:s.sameSite??"strict",path:s.path??"/",maxAge:i});}function Ee(e,r){if(!r.accessCookie)return;let t=r.accessCookie;e.clearCookie(Se(r),{path:t.path??"/"});}function se(e,r){let t=e.headers.authorization;return t?.startsWith("Bearer ")?t.slice(7):q(e.headers.cookie,Se(r))}var cr=new Map;function k(e){let r=cr.get(e);return r||(r=new Kysely({dialect:e}),cr.set(e,r)),r}function be(e){try{return JSON.parse(e)}catch{return []}}function jr(e){return JSON.stringify(e)}function fr(e){return {id:e.id,userId:e.user_id,type:e.type,value:e.value,isPrimary:e.is_primary===1,createdAt:new Date(e.created_at)}}async function ie(e,r){let t=await e.selectFrom("sentri_identifiers as i_login").innerJoin("sentri_users as u","u.id","i_login.user_id").innerJoin("sentri_identifiers as i_primary",s=>s.onRef("i_primary.user_id","=","u.id").on("i_primary.is_primary","=",1)).select(["u.id","u.password_hash","u.roles","i_primary.value as primary_value","i_primary.type as primary_type"]).where("i_login.value","=",r).executeTakeFirst();return t?{id:t.id,identifier:t.primary_value,identifierType:t.primary_type,passwordHash:t.password_hash,roles:be(t.roles)}:null}async function le(e,r){let t=await e.selectFrom("sentri_users as u").innerJoin("sentri_identifiers as i",s=>s.onRef("i.user_id","=","u.id").on("i.is_primary","=",1)).select(["u.id","u.password_hash","u.roles","i.value as primary_value","i.type as primary_type"]).where("u.id","=",r).executeTakeFirst();return t?{id:t.id,identifier:t.primary_value,identifierType:t.primary_type,passwordHash:t.password_hash,roles:be(t.roles)}:null}async function pr(e,r,t){let s=t.map(n=>({id:randomUUID(),user_id:r,type:n.type,value:n.value,is_primary:n.isPrimary?1:0}));return await e.insertInto("sentri_identifiers").values(s).execute(),s.map(n=>({id:n.id,userId:n.user_id,type:n.type,value:n.value,isPrimary:n.is_primary===1,createdAt:new Date}))}async function $(e,r){return (await e.selectFrom("sentri_identifiers").selectAll().where("user_id","=",r).orderBy("created_at","asc").execute()).map(fr)}async function fe(e,r,t){let s=await e.selectFrom("sentri_identifiers").selectAll().where("id","=",r).where("user_id","=",t).executeTakeFirst();return s?fr(s):null}async function mr(e,r){let t=await e.selectFrom("sentri_identifiers").select(s=>s.fn.countAll().as("count")).where("user_id","=",r).executeTakeFirst();return Number(t?.count??0)}async function gr(e,r,t,s){await e.updateTable("sentri_identifiers").set({type:s.type,value:s.value}).where("id","=",r).where("user_id","=",t).execute();}async function hr(e,r,t){await e.deleteFrom("sentri_identifiers").where("user_id","=",r).where("id","in",t).execute();}async function yr(e,r,t){await e.transaction().execute(async s=>{await s.updateTable("sentri_identifiers").set({is_primary:0}).where("user_id","=",r).execute(),await s.updateTable("sentri_identifiers").set({is_primary:1}).where("id","=",t).where("user_id","=",r).execute();});}async function Rr(e,r,t){await e.updateTable("sentri_users").set({password_hash:t}).where("id","=",r).execute();}async function wr(e,r,t){await e.updateTable("sentri_users").set({roles:jr(t)}).where("id","=",r).execute();}async function xe(e,r){let t=randomUUID();return await e.insertInto("sentri_sessions").values({id:t,user_id:r.userId,expires_at:r.expiresAt}).execute(),{id:t}}async function Ir(e,r){let t=await e.selectFrom("sentri_sessions as s").innerJoin("sentri_users as u","u.id","s.user_id").innerJoin("sentri_identifiers as i",s=>s.onRef("i.user_id","=","u.id").on("i.is_primary","=",1)).select(["s.id as session_id","s.user_id","s.expires_at","s.created_at as session_created_at","u.id as user_id_col","u.password_hash","u.roles","i.value as primary_identifier","i.type as primary_identifier_type"]).where("s.id","=",r).executeTakeFirst();return t?{id:t.session_id,userId:t.user_id,expiresAt:new Date(t.expires_at),createdAt:new Date(t.session_created_at),user:{id:t.user_id_col,identifier:t.primary_identifier,identifierType:t.primary_identifier_type,passwordHash:t.password_hash,roles:be(t.roles)}}:null}async function pe(e,r){await e.deleteFrom("sentri_sessions").where("id","=",r).execute();}async function De(e,r){await e.deleteFrom("sentri_sessions").where("user_id","=",r).execute();}async function ne(e,r){let t=C(r),s=k(r.dialect),n=e.roles??[],i=n.filter(_=>!t.validRolesSet.has(_));if(i.length>0)return {success:false,error:new c("INVALID_ROLE",`Invalid roles: ${i.join(", ")}`)};if(!e.identifiers||e.identifiers.length===0)return {success:false,error:new c("VALIDATION_ERROR","At least one identifier is required")};let u=e.identifiers.map(_=>({type:_.type.trim(),value:_.value.trim()}));if(new Set(u.map(_=>_.value)).size!==u.length)return {success:false,error:new c("VALIDATION_ERROR","Duplicate identifier values in request")};for(let _ of u)if(await ie(s,_.value))return {success:false,error:new c("IDENTIFIER_ALREADY_EXISTS",`Identifier already taken: ${_.value}`)};let d=await G(e.password,t.saltRounds),{userId:g,identifierRows:y}=await s.transaction().execute(async _=>{let N=randomUUID();await _.insertInto("sentri_users").values({id:N,password_hash:d,roles:JSON.stringify(n)}).execute();let K=u.map((L,ke)=>({id:randomUUID(),user_id:N,type:L.type,value:L.value,is_primary:ke===0?1:0}));return await _.insertInto("sentri_identifiers").values(K).execute(),{userId:N,identifierRows:K}}),x=y.map(_=>({id:_.id,type:_.type,value:_.value,isPrimary:_.is_primary===1})),S=x[0];return {success:true,user:{id:g,identifier:S.value,identifierType:S.type,roles:n,identifiers:x}}}async function me(e,r){let t=C(r),s=k(r.dialect),n=await ie(s,e.identifier.trim());if(!n)return {success:false,error:new c("INVALID_CREDENTIALS","Invalid credentials")};if(!await Z(e.password,n.passwordHash))return {success:false,error:new c("INVALID_CREDENTIALS","Invalid credentials")};let u=new Date(Date.now()+j(t.refreshExpiresIn)),a=await xe(s,{userId:n.id,expiresAt:u}),d={id:n.id,identifier:n.identifier,identifierType:n.identifierType,roles:n.roles},g=Y({id:n.id,identifier:n.identifier,identifierType:n.identifierType,roles:n.roles,sessionId:a.id},r),y=Q(a.id,r);return {success:true,accessToken:g,refreshToken:y,user:d}}async function M(e,r){let t=C(r),s=k(r.dialect),n;try{({sessionId:n}=ee(e,r));}catch(x){return x instanceof c?{success:false,error:x}:{success:false,error:new c("TOKEN_INVALID","Invalid refresh token")}}let i=await Ir(s,n);if(!i)return {success:false,error:new c("UNAUTHORIZED","Session not found or revoked")};if(i.expiresAt.getTime()<Date.now())return await pe(s,n),{success:false,error:new c("TOKEN_EXPIRED","Session has expired")};await pe(s,n);let u=new Date(Date.now()+j(t.refreshExpiresIn)),a=await xe(s,{userId:i.userId,expiresAt:u}),d={id:i.user.id,identifier:i.user.identifier,identifierType:i.user.identifierType,roles:i.user.roles},g=Y({...d,sessionId:a.id},r),y=Q(a.id,r);return {success:true,accessToken:g,refreshToken:y,user:d}}async function ge(e,r){let t=k(r.dialect),s;try{({sessionId:s}=ee(e,r));}catch{return}await pe(t,s);}async function he(e,r){let t=k(r.dialect);await De(t,e);}async function ye(e,r){let t=k(r.dialect),s=await le(t,e);if(!s)return {success:false,error:new c("USER_NOT_FOUND","User not found")};let n=await $(t,e);return {success:true,user:{id:s.id,identifier:s.identifier,identifierType:s.identifierType,roles:s.roles,identifiers:n.map(i=>({id:i.id,type:i.type,value:i.value,isPrimary:i.isPrimary}))}}}async function Re(e,r,t,s){let n=C(s),i=k(s.dialect),u=await le(i,e);if(!u)return {success:false,error:new c("USER_NOT_FOUND","User not found")};if(!await Z(r,u.passwordHash))return {success:false,error:new c("INVALID_CREDENTIALS","Invalid credentials")};let d=await G(t,n.saltRounds);return await Rr(i,e,d),await De(i,e),{success:true}}async function we(e,r,t){let s=C(t),n=k(t.dialect),i=r.filter(g=>!s.validRolesSet.has(g));if(i.length>0)return {success:false,error:new c("INVALID_ROLE",`Invalid roles: ${i.join(", ")}`)};let u=await le(n,e);if(!u)return {success:false,error:new c("USER_NOT_FOUND","User not found")};let a=new Set(u.roles);for(let g of r)a.add(g);let d=Array.from(a);return await wr(n,e,d),{success:true,user:{id:u.id,identifier:u.identifier,identifierType:u.identifierType,roles:d}}}async function Ie(e,r,t){let s=k(t.dialect);if(r.length===0)return {success:false,error:new c("VALIDATION_ERROR","At least one identifier is required")};let n=r.map(d=>({type:d.type.trim(),value:d.value.trim()}));if(new Set(n.map(d=>d.value)).size!==n.length)return {success:false,error:new c("VALIDATION_ERROR","Duplicate identifier values in request")};for(let d of n)if(await ie(s,d.value))return {success:false,error:new c("IDENTIFIER_ALREADY_EXISTS",`Identifier already taken: ${d.value}`)};await pr(s,e,n.map(d=>({...d,isPrimary:false})));return {success:true,identifiers:(await $(s,e)).map(d=>({id:d.id,type:d.type,value:d.value,isPrimary:d.isPrimary}))}}async function Ae(e,r,t){let s=k(t.dialect);if(r.length===0)return {success:false,error:new c("VALIDATION_ERROR","At least one update is required")};let n=r.map(a=>({id:a.id,type:a.type.trim(),value:a.value.trim()}));if(new Set(n.map(a=>a.value)).size!==n.length)return {success:false,error:new c("VALIDATION_ERROR","Duplicate identifier values in request")};for(let a of n){let d=await fe(s,a.id,e);if(!d)return {success:false,error:new c("IDENTIFIER_NOT_FOUND",`Identifier not found: ${a.id}`)};if(d.value!==a.value&&await ie(s,a.value))return {success:false,error:new c("IDENTIFIER_ALREADY_EXISTS",`Identifier already taken: ${a.value}`)}}for(let a of n)await gr(s,a.id,e,{type:a.type,value:a.value});return {success:true,identifiers:(await $(s,e)).map(a=>({id:a.id,type:a.type,value:a.value,isPrimary:a.isPrimary}))}}async function ve(e,r,t){let s=k(t.dialect);if(r.length===0)return {success:false,error:new c("VALIDATION_ERROR","At least one ID is required")};for(let u of r)if(!await fe(s,u,e))return {success:false,error:new c("IDENTIFIER_NOT_FOUND",`Identifier not found: ${u}`)};return await mr(s,e)-r.length<1?{success:false,error:new c("VALIDATION_ERROR","Cannot delete all identifiers \u2014 at least one must remain")}:(await hr(s,e,r),{success:true,identifiers:(await $(s,e)).map(u=>({id:u.id,type:u.type,value:u.value,isPrimary:u.isPrimary}))})}async function _e(e,r,t){let s=k(t.dialect);return await fe(s,r,e)?(await yr(s,e,r),{success:true,identifiers:(await $(s,e)).map(u=>({id:u.id,type:u.type,value:u.value,isPrimary:u.isPrimary}))}):{success:false,error:new c("IDENTIFIER_NOT_FOUND",`Identifier not found: ${r}`)}}var O={info:()=>{},warn:()=>{},error:()=>{}};function m(e,r,t){return {service:e,event:r,...t}}function E(e){let r=e.logger??O,t=e.loggerService??"sentri";return e.mode==="client"?qr(e.keyUri,r,t):$r(e,r,t)}function qr(e,r,t){return async(s,n,i)=>{let u=s.headers.authorization,a=u?.startsWith("Bearer ")?u.slice(7):void 0,d=s.requestId;if(!a)return r.warn(m(t,"auth.protect.failure",{mode:"client",errorCode:"UNAUTHORIZED",...d!==void 0&&{requestId:d}})),i(new c("UNAUTHORIZED","Missing or malformed Authorization header"));try{let g=await Je(e),y=dr(a,g);s.user={id:y.id,identifier:y.identifier,identifierType:y.identifierType,roles:y.roles},r.info(m(t,"auth.protect.success",{mode:"client",userId:y.id,...d!==void 0&&{requestId:d}})),i();}catch(g){let y=g instanceof c?g.code:"TOKEN_INVALID";r.warn(m(t,"auth.protect.failure",{mode:"client",errorCode:y,...d!==void 0&&{requestId:d}})),i(g);}}}function $r(e,r,t){return async(s,n,i)=>{let u=se(s,e),a=s.requestId;if(!u)return r.warn(m(t,"auth.protect.failure",{mode:"server",errorCode:"UNAUTHORIZED",...a!==void 0&&{requestId:a}})),i(new c("UNAUTHORIZED","Missing or malformed Authorization header"));try{let d=de(u,e);if(e.isTokenRevoked&&await e.isTokenRevoked(d.sessionId))return r.warn(m(t,"auth.protect.token_revoked",{mode:"server",userId:d.id,...a!==void 0&&{requestId:a}})),i(new c("UNAUTHORIZED","Token has been revoked"));s.user={id:d.id,identifier:d.identifier,identifierType:d.identifierType,roles:d.roles},r.info(m(t,"auth.protect.success",{mode:"server",userId:d.id,...a!==void 0&&{requestId:a}})),i();}catch(d){if(d instanceof c&&d.code==="TOKEN_EXPIRED"){let g=q(s.headers.cookie,F(e));if(!g)return r.warn(m(t,"auth.protect.failure",{mode:"server",errorCode:"TOKEN_EXPIRED",...a!==void 0&&{requestId:a}})),i(new c("UNAUTHORIZED","Token expired. Please login again."));try{let y=await M(g,e);if(!y.success)return r.warn(m(t,"auth.protect.failure",{mode:"server",errorCode:y.error.code,...a!==void 0&&{requestId:a}})),i(new c("UNAUTHORIZED","Session expired. Please login again."));re(n,y.refreshToken,e),te(n,y.accessToken,e),n.setHeader("X-New-Access-Token",y.accessToken),s.user=y.user,r.info(m(t,"auth.protect.auto_refresh",{mode:"server",userId:y.user.id,...a!==void 0&&{requestId:a}})),i();}catch{r.warn(m(t,"auth.protect.failure",{mode:"server",errorCode:"TOKEN_EXPIRED",...a!==void 0&&{requestId:a}})),i(new c("UNAUTHORIZED","Session expired. Please login again."));}}else {let g=d instanceof c?d.code:"TOKEN_INVALID";r.warn(m(t,"auth.protect.failure",{mode:"server",errorCode:g,...a!==void 0&&{requestId:a}})),i(d);}}}}function vr(e,r,t){let s=`Requires one of roles: ${e.join(", ")}`;return (n,i,u)=>{let a=n.requestId;if(!n.user)return r.warn(m(t,"auth.authorize.unauthenticated",{requiredRoles:e,...a!==void 0&&{requestId:a}})),u(new c("UNAUTHORIZED","Not authenticated"));let d=n.user.roles;if(!e.some(g=>d.includes(g)))return r.warn(m(t,"auth.authorize.denied",{userId:n.user.id,userRoles:[...d],requiredRoles:e,...a!==void 0&&{requestId:a}})),u(new c("FORBIDDEN",s));r.info(m(t,"auth.authorize.passed",{userId:n.user.id,userRoles:[...d],requiredRoles:e,...a!==void 0&&{requestId:a}})),u();}}function oe(e,r){return function(...s){return vr(s,e,r)}}function Pe(...e){return vr(e,O,"sentri")}var Mr=new c("FORBIDDEN","You do not have permission to perform this action");function _r(e,r,t){return async(s,n,i)=>{let u=s.requestId;if(!s.user)return r.warn(m(t,"auth.permit.unauthenticated",{...u!==void 0&&{requestId:u}})),i(new c("UNAUTHORIZED","Not authenticated"));let a=s.user.id;if(e.roles&&e.roles.length>0){let d=s.user.roles;if(e.roles.some(g=>d.includes(g)))return r.info(m(t,"auth.permit.role_bypass",{userId:a,bypassedByRole:true,...u!==void 0&&{requestId:u}})),i()}try{let d=e.check(s);(d instanceof Promise?await d:d)?(r.info(m(t,"auth.permit.passed",{userId:a,...u!==void 0&&{requestId:u}})),i()):(r.warn(m(t,"auth.permit.denied",{userId:a,...u!==void 0&&{requestId:u}})),i(Mr));}catch(d){i(d);}}}function ae(e,r){return function(s){return _r(typeof s=="function"?{check:s}:s,e,r)}}function Ne(e){return _r(typeof e=="function"?{check:e}:e,O,"sentri")}function V(e){return (r,t,s,n)=>{if(r instanceof c){s.status(r.statusCode).json({error:true,statusCode:r.statusCode,code:r.code,message:r.message,data:null});return}e?.onUnhandled?.(r),s.status(500).json({error:true,statusCode:500,code:"INTERNAL_SERVER_ERROR",message:"Internal server error",data:null});}}var Te=8,B=72,Ce=255,Tr=100,X=50;function I(e){return new c("VALIDATION_ERROR",e)}function b(e,r,t,s){e.status(r).json({error:false,statusCode:r,message:t,data:s});}function D(e,r){e.status(r.statusCode).json({error:true,statusCode:r.statusCode,code:r.code,message:r.message,data:null});}function U(e){if(e==null||typeof e!="object"||Array.isArray(e))throw new c("VALIDATION_ERROR","Request body is missing or not a JSON object. Did you apply express.json()?");return e}function Br(e,r){if(!r.apiKey)return;let t=e.headers["x-api-key"];if(typeof t!="string"||t!==r.apiKey)throw new c("UNAUTHORIZED","Invalid or missing API key")}function Oe(e){if(e)try{let r=e();r instanceof Promise&&r.catch(()=>{});}catch{}}function Xr(e){return e.startsWith("RS")||e.startsWith("PS")}function Ue(e,r){if(typeof e!="object"||e===null||Array.isArray(e))throw I(`identifiers[${r}] must be an object`);let t=e;if(typeof t.type!="string"||t.type.trim().length===0)throw I(`identifiers[${r}].type is required and must be a non-empty string`);if(t.type.length>Tr)throw I(`identifiers[${r}].type must not exceed ${Tr} characters`);if(typeof t.value!="string"||t.value.trim().length===0)throw I(`identifiers[${r}].value is required and must be a non-empty string`);if(t.value.length>Ce)throw I(`identifiers[${r}].value must not exceed ${Ce} characters`);return {type:t.type,value:t.value}}function T(e){return e.requestId!==void 0?{requestId:e.requestId}:{}}function Cr(e){let r=Router(),t=e,s=C(t),n=e.logger??O,i=e.loggerService??"sentri",u=oe(n,i),a=ae(n,i),d=e.router?.register??(o=>ne(o,t)),g=e.router?.login??(o=>me(o,t)),y=e.router?.refresh??(o=>M(o,t)),x=e.router?.logout??(o=>o!==void 0?ge(o,t):Promise.resolve()),S=e.router?.logoutAll??(o=>he(o,t)),_=e.router?.getUser??(o=>ye(o,t)),N=e.router?.assignRoles??((o,f)=>we(o,f,t)),K=e.router?.changePassword??((o,f,A)=>Re(o,f,A,t)),L=e.router?.bulkCreateIdentifiers??((o,f)=>Ie(o,f,t)),ke=e.router?.bulkUpdateIdentifiers??((o,f)=>Ae(o,f,t)),xr=e.router?.bulkDeleteIdentifiers??((o,f)=>ve(o,f,t)),Dr=e.router?.changePrimaryIdentifier??((o,f)=>_e(o,f,t));Xr(s.algorithm)&&r.get("/keys",(o,f)=>{f.setHeader("Cache-Control","public, max-age=3600"),f.json(Be(e.secret));}),r.post("/register",async(o,f,A)=>{let h=Date.now();try{Br(o,e);let l=U(o.body),{identifiers:p,password:R,roles:w}=l;if(!Array.isArray(p)||p.length===0)throw I("identifiers is required and must be a non-empty array");if(p.length>X)throw I(`identifiers must not exceed ${X} entries`);let v=p.map((z,Pr)=>Ue(z,Pr));if(typeof R!="string"||R.length<Te)throw I(`password is required and must be at least ${Te} characters`);if(R.length>B)throw I(`password must not exceed ${B} characters`);if(w!==void 0&&!Array.isArray(w))throw I("roles must be an array of strings when provided");if(Array.isArray(w)&&!w.every(z=>typeof z=="string"))throw I("each role must be a string");let P=Array.isArray(w)?w:void 0,H=await d(P!==void 0?{identifiers:v,password:R,roles:P}:{identifiers:v,password:R});if(!H.success){n.warn(m(i,"auth.register.failure",{errorCode:H.error.code,duration_ms:Date.now()-h,...T(o)})),D(f,H.error);return}n.info(m(i,"auth.register.success",{userId:H.user.id,duration_ms:Date.now()-h,...T(o)})),b(f,201,"User registered successfully",{user:H.user});}catch(l){A(l);}}),r.post("/login",async(o,f,A)=>{let h=Date.now();try{let l=U(o.body),{identifier:p,password:R}=l;if(typeof p!="string"||p.trim().length===0)throw I("identifier is required and must be a non-empty string");if(p.length>Ce)throw I(`identifier must not exceed ${Ce} characters`);if(typeof R!="string"||R.length===0)throw I("password is required");if(R.length>B)throw I(`password must not exceed ${B} characters`);let w=p.trim(),v=await g({identifier:w,password:R});if(!v.success){Oe(()=>e.hooks?.onFailedLogin?.(w,v.error)),n.warn(m(i,"auth.login.failure",{errorCode:v.error.code,duration_ms:Date.now()-h,...T(o)})),D(f,v.error);return}Oe(()=>e.hooks?.onLogin?.(v.user)),re(f,v.refreshToken,e),te(f,v.accessToken,e),n.info(m(i,"auth.login.success",{userId:v.user.id,duration_ms:Date.now()-h,...T(o)})),b(f,200,"Login successful",{accessToken:v.accessToken,user:v.user});}catch(l){A(l);}}),r.post("/refresh",async(o,f,A)=>{let h=Date.now();try{let l=q(o.headers.cookie,F(e));if(!l)throw new c("UNAUTHORIZED","Refresh token cookie is missing");let p=await y(l);if(!p.success){ce(f,e),n.warn(m(i,"auth.refresh.failure",{errorCode:p.error.code,duration_ms:Date.now()-h,...T(o)})),D(f,p.error);return}re(f,p.refreshToken,e),te(f,p.accessToken,e),n.info(m(i,"auth.refresh.success",{userId:p.user.id,duration_ms:Date.now()-h,...T(o)})),b(f,200,"Token refreshed",{accessToken:p.accessToken});}catch(l){A(l);}}),r.post("/logout",async(o,f,A)=>{let h=Date.now();try{let l=q(o.headers.cookie,F(e));await x(l),ce(f,e),Ee(f,e),n.info(m(i,"auth.logout",{duration_ms:Date.now()-h,...T(o)})),b(f,200,"Logged out",null);}catch(l){A(l);}}),r.post("/logout-all",E(e),async(o,f,A)=>{let h=Date.now();try{let l=o.user.id;await S(l),Oe(()=>e.hooks?.onLogout?.(l)),ce(f,e),Ee(f,e),n.info(m(i,"auth.logout_all",{userId:l,duration_ms:Date.now()-h,...T(o)})),b(f,200,"All sessions revoked",null);}catch(l){A(l);}}),r.get("/me",E(e),async(o,f,A)=>{let h=Date.now();try{let l=await _(o.user.id);if(!l.success){n.warn(m(i,"auth.me.failure",{userId:o.user.id,errorCode:l.error.code,duration_ms:Date.now()-h,...T(o)})),D(f,l.error);return}n.info(m(i,"auth.me.success",{userId:l.user.id,duration_ms:Date.now()-h,...T(o)})),b(f,200,"OK",l.user);}catch(l){A(l);}}),r.get("/me/identifiers",E(e),async(o,f,A)=>{let h=Date.now();try{let l=await _(o.user.id);if(!l.success){n.warn(m(i,"auth.me.identifiers.failure",{userId:o.user.id,errorCode:l.error.code,duration_ms:Date.now()-h,...T(o)})),D(f,l.error);return}n.info(m(i,"auth.me.identifiers.success",{userId:l.user.id,count:l.user.identifiers?.length??0,duration_ms:Date.now()-h,...T(o)})),b(f,200,"OK",{identifiers:l.user.identifiers??[]});}catch(l){A(l);}});let J=a(o=>!!o.user);return r.post("/me/identifiers",E(e),J,async(o,f,A)=>{let h=Date.now();try{let l=U(o.body),{identifiers:p}=l;if(!Array.isArray(p)||p.length===0)throw I("identifiers is required and must be a non-empty array");if(p.length>X)throw I(`identifiers must not exceed ${X} entries`);let R=p.map((v,P)=>Ue(v,P)),w=await L(o.user.id,R);if(!w.success){n.warn(m(i,"auth.identifiers.create_failure",{userId:o.user.id,errorCode:w.error.code,duration_ms:Date.now()-h,...T(o)})),D(f,w.error);return}n.info(m(i,"auth.identifiers.created",{userId:o.user.id,count:w.identifiers.length,duration_ms:Date.now()-h,...T(o)})),b(f,201,"Identifiers added successfully",{identifiers:w.identifiers});}catch(l){A(l);}}),r.put("/me/identifiers",E(e),J,async(o,f,A)=>{let h=Date.now();try{let l=U(o.body),{identifiers:p}=l;if(!Array.isArray(p)||p.length===0)throw I("identifiers is required and must be a non-empty array");if(p.length>X)throw I(`identifiers must not exceed ${X} entries`);let R=p.map((v,P)=>{if(typeof v!="object"||v===null||Array.isArray(v))throw I(`identifiers[${P}] must be an object`);let ue=v;if(typeof ue.id!="string"||ue.id.trim().length===0)throw I(`identifiers[${P}].id is required and must be a non-empty string`);let{type:H,value:z}=Ue(v,P);return {id:ue.id,type:H,value:z}}),w=await ke(o.user.id,R);if(!w.success){n.warn(m(i,"auth.identifiers.update_failure",{userId:o.user.id,errorCode:w.error.code,duration_ms:Date.now()-h,...T(o)})),D(f,w.error);return}n.info(m(i,"auth.identifiers.updated",{userId:o.user.id,count:w.identifiers.length,duration_ms:Date.now()-h,...T(o)})),b(f,200,"Identifiers updated successfully",{identifiers:w.identifiers});}catch(l){A(l);}}),r.delete("/me/identifiers",E(e),J,async(o,f,A)=>{let h=Date.now();try{let l=U(o.body),{ids:p}=l;if(!Array.isArray(p)||p.length===0)throw I("ids is required and must be a non-empty array of strings");if(!p.every(w=>typeof w=="string"))throw I("each id must be a string");let R=await xr(o.user.id,p);if(!R.success){n.warn(m(i,"auth.identifiers.delete_failure",{userId:o.user.id,errorCode:R.error.code,duration_ms:Date.now()-h,...T(o)})),D(f,R.error);return}n.info(m(i,"auth.identifiers.deleted",{userId:o.user.id,duration_ms:Date.now()-h,...T(o)})),b(f,200,"Identifiers deleted successfully",{identifiers:R.identifiers});}catch(l){A(l);}}),r.patch("/me/identifiers/primary",E(e),J,async(o,f,A)=>{let h=Date.now();try{let l=U(o.body),{id:p}=l;if(typeof p!="string"||p.trim().length===0)throw I("id is required and must be a non-empty string");let R=await Dr(o.user.id,p.trim());if(!R.success){n.warn(m(i,"auth.identifiers.primary_change_failure",{userId:o.user.id,errorCode:R.error.code,duration_ms:Date.now()-h,...T(o)})),D(f,R.error);return}n.info(m(i,"auth.identifiers.primary_changed",{userId:o.user.id,duration_ms:Date.now()-h,...T(o)})),b(f,200,"Primary identifier updated successfully",{identifiers:R.identifiers});}catch(l){A(l);}}),r.patch("/me/password",E(e),J,async(o,f,A)=>{let h=Date.now();try{let l=U(o.body),{currentPassword:p,newPassword:R}=l;if(typeof p!="string"||p.length===0)throw I("currentPassword is required");if(typeof R!="string"||R.length<Te)throw I(`newPassword must be at least ${Te} characters`);if(R.length>B)throw I(`newPassword must not exceed ${B} characters`);if(p===R)throw I("newPassword must be different from currentPassword");let w=await K(o.user.id,p,R);if(!w.success){n.warn(m(i,"auth.password.change_failure",{userId:o.user.id,errorCode:w.error.code,duration_ms:Date.now()-h,...T(o)})),D(f,w.error);return}n.info(m(i,"auth.password.changed",{userId:o.user.id,duration_ms:Date.now()-h,...T(o)})),b(f,200,"Password updated successfully. All sessions have been revoked.",null);}catch(l){A(l);}}),r.post("/users/:userId/roles",E(e),u("admin"),async(o,f,A)=>{let h=Date.now();try{let l=U(o.body),{roles:p}=l,R=o.params.userId,w=typeof R=="string"?R:void 0;if(!w)throw I("userId is required");if(!Array.isArray(p)||p.length===0)throw I("roles must be a non-empty array of strings");if(!p.every(P=>typeof P=="string"))throw I("each role must be a string");let v=await N(w,p);if(!v.success){n.warn(m(i,"auth.roles.assign_failure",{targetUserId:w,errorCode:v.error.code,duration_ms:Date.now()-h,...T(o)})),D(f,v.error);return}n.info(m(i,"auth.roles.assigned",{targetUserId:w,roles:p,duration_ms:Date.now()-h,...T(o)})),b(f,200,"Roles assigned successfully",{user:v.user});}catch(l){A(l);}}),r.use(V()),r}var kr=new Map;function Sr(e){let r=kr.get(e);return r||(r=new Redis(e,{lazyConnect:false,enableOfflineQueue:false}),kr.set(e,r)),r}function Ke(e){let r=e?.ttl??3e5,t=(e?.header??"X-Idempotency-Key").toLowerCase(),s=new Set((e?.methods??["POST","PUT","PATCH"]).map(i=>i.toUpperCase())),n=e?.redisUrl;return n?zr(n,r,t,s):Gr(r,t,s,e?.maxSize??1e4)}function zr(e,r,t,s){let n=Sr(e),i="sentri:idempotency:";return async(u,a,d)=>{let g=u.headers[t];if(!g||typeof g!="string"||!s.has(u.method))return d();u.requestId=g,a.setHeader("X-Request-Id",g);let y=await n.get(`${i}${g}`);if(y){let S=JSON.parse(y);return a.setHeader("X-Idempotent-Replayed","true"),a.status(S.statusCode).json(S.body)}let x=a.json.bind(a);a.json=function(_){if(a.statusCode>=200&&a.statusCode<300){let N={statusCode:a.statusCode,body:_,expiresAt:Date.now()+r};n.set(`${i}${g}`,JSON.stringify(N),"PX",r).catch(()=>{});}return x(_)},d();}}function Gr(e,r,t,s){let n=Math.max(e,5e3),i=new Map,u=setInterval(()=>{let a=Date.now();for(let[d,g]of i)g.expiresAt<=a&&i.delete(d);},n);return typeof u=="object"&&u!==null&&"unref"in u&&u.unref(),(a,d,g)=>{let y=a.headers[r];if(!y||typeof y!="string"||!t.has(a.method))return g();a.requestId=y,d.setHeader("X-Request-Id",y);let x=Date.now(),S=i.get(y);if(S&&S.expiresAt>x)return d.setHeader("X-Idempotent-Replayed","true"),d.status(S.statusCode).json(S.body);let _=d.json.bind(d);d.json=function(K){if(d.statusCode>=200&&d.statusCode<300){if(i.size>=s){let L=i.keys().next().value;L!==void 0&&i.delete(L);}i.set(y,{statusCode:d.statusCode,body:K,expiresAt:Date.now()+e});}return _(K)},g();}}async function Er(e){await e.schema.createTable("sentri_users").ifNotExists().addColumn("id","varchar(36)",r=>r.primaryKey().notNull()).addColumn("password_hash","varchar(255)",r=>r.notNull()).addColumn("roles","text",r=>r.notNull().defaultTo("[]")).addColumn("created_at","timestamp",r=>r.notNull().defaultTo(sql`CURRENT_TIMESTAMP`)).execute(),await e.schema.createTable("sentri_sessions").ifNotExists().addColumn("id","varchar(36)",r=>r.primaryKey().notNull()).addColumn("user_id","varchar(36)",r=>r.notNull().references("sentri_users.id").onDelete("cascade")).addColumn("expires_at","timestamp",r=>r.notNull()).addColumn("created_at","timestamp",r=>r.notNull().defaultTo(sql`CURRENT_TIMESTAMP`)).execute(),await e.schema.createTable("sentri_identifiers").ifNotExists().addColumn("id","varchar(36)",r=>r.primaryKey().notNull()).addColumn("user_id","varchar(36)",r=>r.notNull().references("sentri_users.id").onDelete("cascade")).addColumn("type","varchar(100)",r=>r.notNull()).addColumn("value","varchar(255)",r=>r.notNull().unique()).addColumn("is_primary","integer",r=>r.notNull().defaultTo(0)).addColumn("created_at","timestamp",r=>r.notNull().defaultTo(sql`CURRENT_TIMESTAMP`)).execute();}function He(e){if(Qe(e),e.mode==="client"){let i=e.logger?oe(e.logger,e.loggerService??"sentri"):Pe,u=e.logger?ae(e.logger,e.loggerService??"sentri"):Ne;return {protect:()=>E(e),authorize:(...a)=>i(...a),permit:a=>u(a),errorHandler:a=>V(a)}}let r=e,t=C(r),s=r.logger?oe(r.logger,r.loggerService??"sentri"):Pe,n=r.logger?ae(r.logger,r.loggerService??"sentri"):Ne;return {protect:()=>E(r),authorize:(...i)=>s(...i),permit:i=>n(i),hashPassword:i=>G(i,t.saltRounds),verifyPassword:(i,u)=>Z(i,u),signAccessToken:i=>Y(i,r),signRefreshToken:i=>Q(i,r),verifyAccessToken:i=>de(i,r),verifyRefreshToken:i=>ee(i,r),getCurrentAccessToken:i=>se(i,r),router:()=>Cr(r),migrate:()=>Er(k(r.dialect)),errorHandler:i=>V(i),idempotencyMiddleware:i=>Ke({...i,...r.redisUrl!==void 0&&{redisUrl:r.redisUrl}}),register:i=>ne(i,r),login:i=>me(i,r),refresh:i=>M(i,r),logout:i=>ge(i,r),logoutAll:i=>he(i,r),getUser:i=>ye(i,r),changePassword:(i,u,a)=>Re(i,u,a,r),assignRoles:(i,u)=>we(i,u,r),bulkCreateIdentifiers:(i,u)=>Ie(i,u,r),bulkUpdateIdentifiers:(i,u)=>Ae(i,u,r),bulkDeleteIdentifiers:(i,u)=>ve(i,u,r),changePrimaryIdentifier:(i,u)=>_e(i,u,r)}}function br(e){return new PostgresDialect({pool:new Pool(e)})}function Qr(e){let{privateKey:r}=generateKeyPairSync("rsa",{modulusLength:2048,privateKeyEncoding:{type:"pkcs8",format:"pem"},publicKeyEncoding:{type:"spki",format:"pem"}}),t={mode:"server",dialect:br(e.db),secret:r,algorithm:"RS256",validRoles:e.validRoles,...e.accessExpiresIn!==void 0&&{accessExpiresIn:e.accessExpiresIn},...e.refreshExpiresIn!==void 0&&{refreshExpiresIn:e.refreshExpiresIn},...e.saltRounds!==void 0&&{saltRounds:e.saltRounds},...e.apiKey!==void 0&&{apiKey:e.apiKey},...e.cookie!==void 0&&{cookie:e.cookie},...e.accessCookie!==void 0&&{accessCookie:e.accessCookie},...e.hooks!==void 0&&{hooks:e.hooks},...e.router!==void 0&&{router:e.router},...e.isTokenRevoked!==void 0&&{isTokenRevoked:e.isTokenRevoked},...e.redisUrl!==void 0&&{redisUrl:e.redisUrl},...e.logger!==void 0&&{logger:e.logger},...e.loggerService!==void 0&&{loggerService:e.loggerService}};return He(t)}export{Fe as SENTRI_ERROR_STATUS,c as SentriError,He as createAuth,Qr as createAuthServer,V as createErrorHandler,Ke as createIdempotencyMiddleware,se as getCurrentAccessToken,ne as register};
|
|
1
|
+
var t=Object.defineProperty;var N=(I,E)=>t(I,"name",{value:E,configurable:true});var O=Object.assign(Object.create(null),{UNAUTHORIZED:401,TOKEN_EXPIRED:401,TOKEN_INVALID:401,INVALID_CREDENTIALS:401,FORBIDDEN:403,USER_NOT_FOUND:404,IDENTIFIER_NOT_FOUND:404,USER_ALREADY_EXISTS:409,IDENTIFIER_ALREADY_EXISTS:409,INVALID_ROLE:400,VALIDATION_ERROR:400,CONFIGURATION_ERROR:500,TOKEN_REUSE:401}),R=class extends Error{static{N(this,"SentriError");}code;statusCode;constructor(E,T,_){super(T),this.name="SentriError",this.code=E,this.statusCode=_??O[E]??500;}};export{O as SENTRI_ERROR_STATUS,R as SentriError};
|
package/package.json
CHANGED
|
@@ -1,14 +1,45 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sentri",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
|
+
"description": "Auth/authorization library for Express, Fastify, Hono, and Elysia — PostgreSQL + JWT",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
10
11
|
"import": "./dist/index.js",
|
|
11
|
-
"
|
|
12
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
},
|
|
14
|
+
"./core": {
|
|
15
|
+
"types": "./dist/core/index.d.ts",
|
|
16
|
+
"import": "./dist/core/index.js",
|
|
17
|
+
"require": "./dist/core/index.cjs"
|
|
18
|
+
},
|
|
19
|
+
"./express": {
|
|
20
|
+
"types": "./dist/adapters/express/index.d.ts",
|
|
21
|
+
"import": "./dist/adapters/express/index.js",
|
|
22
|
+
"require": "./dist/adapters/express/index.cjs"
|
|
23
|
+
},
|
|
24
|
+
"./fastify": {
|
|
25
|
+
"types": "./dist/adapters/fastify/index.d.ts",
|
|
26
|
+
"import": "./dist/adapters/fastify/index.js",
|
|
27
|
+
"require": "./dist/adapters/fastify/index.cjs"
|
|
28
|
+
},
|
|
29
|
+
"./hono": {
|
|
30
|
+
"types": "./dist/adapters/hono/index.d.ts",
|
|
31
|
+
"import": "./dist/adapters/hono/index.js",
|
|
32
|
+
"require": "./dist/adapters/hono/index.cjs"
|
|
33
|
+
},
|
|
34
|
+
"./elysia": {
|
|
35
|
+
"types": "./dist/adapters/elysia/index.d.ts",
|
|
36
|
+
"import": "./dist/adapters/elysia/index.js",
|
|
37
|
+
"require": "./dist/adapters/elysia/index.cjs"
|
|
38
|
+
},
|
|
39
|
+
"./koa": {
|
|
40
|
+
"types": "./dist/adapters/koa/index.d.ts",
|
|
41
|
+
"import": "./dist/adapters/koa/index.js",
|
|
42
|
+
"require": "./dist/adapters/koa/index.cjs"
|
|
12
43
|
}
|
|
13
44
|
},
|
|
14
45
|
"bin": {
|
|
@@ -30,12 +61,17 @@
|
|
|
30
61
|
"authentication",
|
|
31
62
|
"authorization",
|
|
32
63
|
"express",
|
|
64
|
+
"fastify",
|
|
65
|
+
"hono",
|
|
66
|
+
"elysia",
|
|
33
67
|
"jwt",
|
|
34
68
|
"bcrypt"
|
|
35
69
|
],
|
|
36
70
|
"author": "rizzzdev",
|
|
37
71
|
"license": "ISC",
|
|
38
72
|
"devDependencies": {
|
|
73
|
+
"@fastify/cookie": "^11.0.2",
|
|
74
|
+
"@swc/core": "^1.3.100",
|
|
39
75
|
"@types/bcrypt": "^6.0.0",
|
|
40
76
|
"@types/express": "^5.0.6",
|
|
41
77
|
"@types/jsonwebtoken": "^9.0.10",
|
|
@@ -43,7 +79,14 @@
|
|
|
43
79
|
"@types/pg": "^8.11.10",
|
|
44
80
|
"@types/supertest": "^7.2.0",
|
|
45
81
|
"@vitest/coverage-v8": "^4.1.9",
|
|
82
|
+
"elysia": "^1.4.29",
|
|
46
83
|
"express": "^5.2.1",
|
|
84
|
+
"fastify": "^5.8.5",
|
|
85
|
+
"hono": "^4.12.27",
|
|
86
|
+
"@types/koa": "^2.15.0",
|
|
87
|
+
"@types/koa__router": "^12.0.4",
|
|
88
|
+
"koa": "^2.15.3",
|
|
89
|
+
"@koa/router": "^12.0.1",
|
|
47
90
|
"supertest": "^7.2.2",
|
|
48
91
|
"tsup": "^8.5.1",
|
|
49
92
|
"tsx": "^4.22.4",
|
|
@@ -54,11 +97,40 @@
|
|
|
54
97
|
"bcrypt": "^6.0.0",
|
|
55
98
|
"ioredis": "^5.11.1",
|
|
56
99
|
"jsonwebtoken": "^9.0.3",
|
|
57
|
-
"kysely": "^0.29.2"
|
|
58
|
-
"pg": "^8.13.1"
|
|
100
|
+
"kysely": "^0.29.2"
|
|
59
101
|
},
|
|
60
102
|
"peerDependencies": {
|
|
61
|
-
"
|
|
103
|
+
"@fastify/cookie": ">=9.0.0",
|
|
104
|
+
"elysia": ">=1.0.0",
|
|
105
|
+
"express": ">=4.0.0",
|
|
106
|
+
"fastify": ">=4.0.0",
|
|
107
|
+
"hono": ">=4.0.0",
|
|
108
|
+
"koa": ">=2.0.0",
|
|
109
|
+
"@koa/router": ">=12.0.0",
|
|
110
|
+
"pg": ">=8.0.0"
|
|
111
|
+
},
|
|
112
|
+
"peerDependenciesMeta": {
|
|
113
|
+
"fastify": {
|
|
114
|
+
"optional": true
|
|
115
|
+
},
|
|
116
|
+
"@fastify/cookie": {
|
|
117
|
+
"optional": true
|
|
118
|
+
},
|
|
119
|
+
"hono": {
|
|
120
|
+
"optional": true
|
|
121
|
+
},
|
|
122
|
+
"elysia": {
|
|
123
|
+
"optional": true
|
|
124
|
+
},
|
|
125
|
+
"koa": {
|
|
126
|
+
"optional": true
|
|
127
|
+
},
|
|
128
|
+
"@koa/router": {
|
|
129
|
+
"optional": true
|
|
130
|
+
},
|
|
131
|
+
"pg": {
|
|
132
|
+
"optional": true
|
|
133
|
+
}
|
|
62
134
|
},
|
|
63
135
|
"overrides": {
|
|
64
136
|
"esbuild": "0.28.1"
|