@cauth/core 0.0.1 → 0.0.3

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.
@@ -194,33 +194,37 @@ type AuthGuardDeps = {
194
194
  tokens: _CAuth<any>['Tokens'];
195
195
  roles?: Array<string>;
196
196
  };
197
- interface RoutesContract {
197
+ /**
198
+ * Generic RoutesContract
199
+ * THandler is generic, defaults to any function
200
+ */
201
+ interface RoutesContract<THandler extends (...args: any[]) => any = (...args: any[]) => any> {
198
202
  Login({
199
203
  ...config
200
- }: RouteDeps): any;
204
+ }: RouteDeps): THandler;
201
205
  Register({
202
206
  ...config
203
- }: RouteDeps): any;
207
+ }: RouteDeps): THandler;
204
208
  Logout({
205
209
  ...config
206
- }: RouteDeps): any;
210
+ }: RouteDeps): THandler;
207
211
  Guard({
208
212
  ...config
209
- }: AuthGuardDeps): any;
213
+ }: AuthGuardDeps): THandler;
210
214
  Refresh({
211
215
  ...config
212
- }: AuthGuardDeps): any;
216
+ }: AuthGuardDeps): THandler;
213
217
  ChangePassword({
214
218
  ...config
215
219
  }: RouteDeps & {
216
220
  userId: string;
217
- }): any;
221
+ }): THandler;
218
222
  }
219
223
  //#endregion
220
224
  //#region src/types/config.t.d.ts
221
225
  declare const CAuthOptionsSchema: z$1.ZodObject<{
222
226
  dbContractor: z$1.ZodCustom<DatabaseContract, DatabaseContract>;
223
- routeContractor: z$1.ZodCustom<RoutesContract, RoutesContract>;
227
+ routeContractor: z$1.ZodCustom<RoutesContract<(...args: any[]) => any>, RoutesContract<(...args: any[]) => any>>;
224
228
  roles: z$1.ZodArray<z$1.ZodString>;
225
229
  jwtConfig: z$1.ZodObject<{
226
230
  refreshTokenSecret: z$1.ZodString;
@@ -282,13 +286,13 @@ declare class _CAuth<T extends string[]> {
282
286
  *
283
287
  * @default undefined
284
288
  */
285
- Guard: (roles?: Array<T[number]>) => any;
289
+ Guard: (roles?: Array<T[number]>) => (...args: any[]) => any;
286
290
  Routes: {
287
- Register: () => any;
288
- Login: () => any;
289
- Logout: () => any;
290
- Refresh: () => any;
291
- ChangePassword: (userId: string) => any;
291
+ Register: () => (...args: any[]) => any;
292
+ Login: () => (...args: any[]) => any;
293
+ Logout: () => (...args: any[]) => any;
294
+ Refresh: () => (...args: any[]) => any;
295
+ ChangePassword: (userId: string) => (...args: any[]) => any;
292
296
  };
293
297
  FN: {
294
298
  Login: ({
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import e,{z as t}from"zod";import{parsePhoneNumberFromString as n}from"libphonenumber-js";import r from"bcrypt";import i from"jsonwebtoken";var a=class{static ValidationError=`validation-error`;static CredentialError=`credential-error`;static UnKnownError=`unknown-error`;static InvalidDataError=`invalid-data-error`},o=class{static ServerError=`internal-server-error`;static ServerErrorMessage=`Internal server error. We are working to fix this, please try again later`;static InvalidToken=`invalid-token`;static InvalidTokenMessage=`Invalid Token`;static ForbiddenResource=`forbidden-resource`;static ForbiddenResourceMessage=`You don't have sufficient permission for this action`;static InvalidOtp=`invalid-otp`;static InvalidOtpMessage=`Invalid Otp. Please check and try again`;static CredentialMismatch=`credential-mismatch`;static CredentialMismatchMessage=`Credential mismatch. Please check your credentials and try again.`;static InvalidData=`invalid-data`;static InvalidDataMessage=e=>`Invalid Body: ${e}`;static AccountNotFound=`account-not-found`;static AccountNotFoundMessage=`Account not found`;static InvalidRole=`invalid-role`;static InvalidRoleMessage=e=>`Role is invalid, please use one of the following roles: ${e.join(`, `)}`;static InvalidRefreshToken=`invalid-refresh-token`;static InvalidRefreshTokenMessage=`Invalid refresh token`;static DuplicateAccount=`account-already-exists`;static DuplicateAccountMessage=`Account with this credentials already exists`},s=class extends Error{code;static type=a.CredentialError;constructor(){super(o.CredentialMismatchMessage),this.code=o.CredentialMismatch,this.name=`CredentialMismatch`}},c=class extends Error{code;static type=a.ValidationError;constructor(e){super(o.InvalidDataMessage(e)),this.code=o.InvalidData,this.name=`InvalidDataError`}},l=class extends Error{code;static type=a.InvalidDataError;constructor(){super(o.AccountNotFoundMessage),this.code=o.AccountNotFound,this.name=`AccountNotFoundError`}},u=class extends Error{code;static type=a.ValidationError;constructor(e){super(o.InvalidRoleMessage(e)),this.code=o.InvalidRole,this.name=`InvalidRoleError`}},d=class extends Error{code;static type=a.ValidationError;constructor(){super(o.InvalidRefreshTokenMessage),this.code=o.InvalidRefreshToken,this.name=`InvalidRefreshTokenError`}},f=class extends Error{code;static type=a.ValidationError;constructor(){super(o.DuplicateAccountMessage),this.code=o.DuplicateAccount,this.name=`DuplicateAccountError`}},p=class extends Error{code;static type=a.ValidationError;constructor(){super(o.InvalidOtpMessage),this.code=o.InvalidOtp,this.name=`InvalidOTPCode`}},m=class{static LoginPurpose=`LOGIN`;static ResetPasswordPurpose=`RESET_PASSWORD`;static ActionPurpose=`ACTION`};const h=t.string().trim().refine(e=>{let t=n(e);return!!t&&t.isValid()},{message:`Invalid phone number`}).transform(e=>n(e)?.format(`E.164`)??e),g=t.object({email:t.email(),phoneNumber:t.never().optional(),password:t.string().min(6)}),_=t.object({phoneNumber:h,email:t.never().optional(),password:t.string().min(6)}),v=t.union([g,_]).superRefine((e,n)=>{e.email&&e.phoneNumber&&n.addIssue({code:t.ZodIssueCode.custom,message:`Provide either email or phoneNumber`,path:[`email`,`phoneNumber`]})}),y=t.object({phoneNumber:h.optional(),email:t.email().optional(),role:t.string(),password:t.string()}).superRefine((e,n)=>{!e.email&&!e.phoneNumber&&n.addIssue({code:t.ZodIssueCode.custom,message:`Provide either email or phoneNumber`,path:[`email`,`phoneNumber`]})}),b=t.object({refreshToken:t.string()}),x=t.object({refreshToken:t.string()}),S=t.object({accountId:t.string(),oldPassword:t.string(),newPassword:t.string()});function C(e){return`${e?.error?.issues[0].path}: ${e?.error?.issues[0].message}`}function w(e){return{success:!0,value:e}}function T(...e){return{success:!1,errors:e}}async function E({config:e},{...t}){let n=v.safeParse({email:t.email,phoneNumber:t.phoneNumber,password:``});if(!n.success)return T({type:c.type,error:new c(C(n))});let i=await e.dbContractor.findAccountWithCredential({phoneNumber:t.phoneNumber,email:t.email});if(!i||t.usePassword&&!await r.compare(String(t.password),String(i?.passwordHash)))return T({type:s.type,error:new s});let a=await e.dbContractor.createOTP({config:e},{id:i.id,purpose:t.otpPurpose});return w({id:i.id,code:a.code})}async function D({config:e,tokens:t},{...n}){let r=v.safeParse({email:n.email,phoneNumber:n.phoneNumber,password:``});if(!r.success)return T({type:c.type,error:new c(C(r))});let i=await e.dbContractor.findAccountWithCredential({email:n.email,phoneNumber:n.phoneNumber});if(!i)return T({type:s.type,error:new s});if(!(await e.dbContractor.verifyOTP({id:i.id,code:n.code,purpose:m.LoginPurpose})).isValid)return T({type:p.type,error:new p});let a=await t.GenerateTokenPairs({id:i.id,role:i.role});return await e.dbContractor.updateAccountLogin({id:i.id,refreshToken:a.refreshToken}),delete i.passwordHash,delete i.refreshTokens,w({account:i,tokens:a})}async function O({config:e},{...t}){return await e.dbContractor.verifyOTP({id:t.id,code:t.code,purpose:t.otpPurpose})}async function k({config:e},{...t}){let n=S.safeParse(t);if(!n.success)return T({type:c.type,error:new c(C(n))});let i=await e.dbContractor.findAccountById({id:t.accountId});if(!i)return T({type:l.type,error:new l});if(!r.compare(t.oldPassword,String(i.passwordHash)))return T({type:s.type,error:new s});let a=await r.hash(t.newPassword,10);return await e.dbContractor.updateAccount({id:i.id,data:{passwordHash:a}}),w({})}async function A({config:e,tokens:t},{...n}){let i=v.safeParse(n);if(!i.success)return T({type:c.type,error:new c(C(i))});let a=await e.dbContractor.findAccountWithCredential({email:n.email,phoneNumber:n.phoneNumber});if(!a||!await r.compare(String(n.password),String(a?.passwordHash)))return T({type:s.type,error:new s});let o=await t.GenerateTokenPairs({id:a.id,role:a.role});return await e.dbContractor.updateAccountLogin({id:a.id,refreshToken:o.refreshToken}),delete a.passwordHash,delete a.refreshTokens,w({account:a,tokens:o})}async function j(e){try{return{data:await e,error:null}}catch(e){return{data:null,error:e}}}async function M({config:e,tokens:t},{...n}){let r=x.safeParse(n);if(!r.success)return T({type:c.type,error:new c(C(r))});let i=await j(t.VerifyRefreshToken(n.refreshToken));return i.error||!i?T({type:d.type,error:new d}):(await e.dbContractor.removeAndAddRefreshToken({id:String(i.data?.id),refreshToken:n.refreshToken}),w({}))}async function N({config:e,tokens:t},{...n}){let r=b.safeParse(n);if(!r.success)return T({type:c.type,error:new c(C(r))});let i=await j(t.VerifyRefreshToken(n.refreshToken));if(i.error)return T({type:d.type,error:new d});let a=await e.dbContractor.findAccountById({id:String(i.data?.id)});if(!a)return T({type:l.type,error:new l});if(!a?.refreshTokens?.includes(n.refreshToken))return T({type:d.type,error:new d});let o=await t.GenerateTokenPairs({id:a.id,role:a.role});return await e.dbContractor.removeAndAddRefreshToken({id:a.id,refreshToken:n.refreshToken,newRefreshToken:o.refreshToken}),delete a.refreshTokens,delete a.passwordHash,w({account:a,tokens:o})}async function P({config:e,tokens:t},{...n}){let i=y.safeParse(n);if(!i.success)return T({type:c.type,error:new c(C(i))});if(!e.roles?.includes(n.role))return T({type:u.type,error:new u(e.roles)});if(await e.dbContractor.findAccountWithCredential({email:n.email,phoneNumber:n.phoneNumber}))return T({type:f.type,error:new f});let a=await r.hash(n.password,10),o=await e.dbContractor.createAccount({data:{email:n.email,phoneNumber:n.phoneNumber,passwordHash:a,role:n.role,lastLogin:new Date}}),s=await t.GenerateTokenPairs({id:o.id,role:o.role});return await e.dbContractor.updateAccountLogin({id:o.id,refreshToken:s.refreshToken}),w({account:o,tokens:s})}async function F({...e}){return i.sign(e.payload,e.config.jwtConfig.accessTokenSecret,{expiresIn:e.config.jwtConfig?.accessTokenLifeSpan??`15m`})}async function I({...e}){return i.sign(e.payload,e.config.jwtConfig.refreshTokenSecret,{expiresIn:e.config.jwtConfig?.refreshTokenLifeSpan??`30d`})}async function L({...e}){return{accessToken:i.sign(e.payload,e.config.jwtConfig.accessTokenSecret,{expiresIn:e.config.jwtConfig?.accessTokenLifeSpan??`15m`}),refreshToken:i.sign(e.payload,e.config.jwtConfig.refreshTokenSecret,{expiresIn:e.config.jwtConfig?.refreshTokenLifeSpan??`30d`})}}async function R({...e}){let t=i.verify(e.token,e.config.jwtConfig.refreshTokenSecret);return t instanceof String?null:t}async function z({...e}){let t=i.verify(e.token,e.config.jwtConfig.accessTokenSecret);return t instanceof String?null:t}const B=e.custom(()=>!0,{message:`Invalid dbContractor: must implement Database Contract interface`}),V=e.custom(()=>!0,{message:`Invalid routeContractor: must implement RoutesContract interface`}),H=e.custom(),U=e.object({dbContractor:B,routeContractor:V,roles:e.array(e.string()).min(1),jwtConfig:e.object({refreshTokenSecret:e.string(),accessTokenSecret:e.string(),accessTokenLifeSpan:H.optional(),refreshTokenLifeSpan:H.optional()}),otpConfig:e.object({expiresIn:e.number().optional(),length:e.number().min(4).max(8).optional()})});var W=class{#config;constructor(e){if(!U.safeParse(e).success)throw Error(`❌ Failed to initiate CAuth. You provided an invalid config!`);this.#config=e}get RoleType(){return null}Guard=e=>this.#config.routeContractor.Guard({config:this.#config,tokens:this.Tokens,roles:e});Routes={Register:()=>this.#config.routeContractor.Register({config:this.#config,tokens:this.Tokens}),Login:()=>this.#config.routeContractor.Login({config:this.#config,tokens:this.Tokens}),Logout:()=>this.#config.routeContractor.Logout({config:this.#config,tokens:this.Tokens}),Refresh:()=>this.#config.routeContractor.Refresh({config:this.#config,tokens:this.Tokens}),ChangePassword:e=>this.#config.routeContractor.ChangePassword({config:this.#config,tokens:this.Tokens,userId:e})};FN={Login:({...e})=>A({config:this.#config,tokens:this.Tokens},e),Register:({...e})=>P({config:this.#config,tokens:this.Tokens},e),Logout:({...e})=>M({config:this.#config,tokens:this.Tokens},e),Refresh:({...e})=>N({config:this.#config,tokens:this.Tokens},e),ChangePassword:({...e})=>k({config:this.#config,tokens:this.Tokens},e),RequestOTPCode:({...e})=>E({config:this.#config,tokens:this.Tokens},e),LoginWithOTP:({...e})=>D({config:this.#config,tokens:this.Tokens},{...e}),VerifyOTP:({...e})=>O({config:this.#config,tokens:this.Tokens},e)};Tokens={GenerateRefreshToken:e=>I({payload:e,config:this.#config}),GenerateAccessToken:e=>F({payload:e,config:this.#config}),GenerateTokenPairs:e=>L({payload:e,config:this.#config}),VerifyRefreshToken:e=>R({token:e,config:this.#config}),VerifyAccessToken:e=>z({token:e,config:this.#config})}};function G(e){return new W(e)}export{l as AccountNotFoundError,G as CAuth,s as CredentialMismatchError,f as DuplicateAccountError,c as InvalidDataError,p as InvalidOTPCode,d as InvalidRefreshTokenError,u as InvalidRoleError};
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@cauth/core",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "",
5
- "main": "./dist/index.cjs",
6
- "types": "./dist/index.d.cts",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
7
  "type": "module",
8
8
  "scripts": {
9
9
  "build": "tsdown",
package/dist/index.cjs DELETED
@@ -1 +0,0 @@
1
- var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let c=require(`zod`);c=s(c);let l=require(`libphonenumber-js`);l=s(l);let u=require(`bcrypt`);u=s(u);let d=require(`jsonwebtoken`);d=s(d);var f=class{static ValidationError=`validation-error`;static CredentialError=`credential-error`;static UnKnownError=`unknown-error`;static InvalidDataError=`invalid-data-error`},p=class{static ServerError=`internal-server-error`;static ServerErrorMessage=`Internal server error. We are working to fix this, please try again later`;static InvalidToken=`invalid-token`;static InvalidTokenMessage=`Invalid Token`;static ForbiddenResource=`forbidden-resource`;static ForbiddenResourceMessage=`You don't have sufficient permission for this action`;static InvalidOtp=`invalid-otp`;static InvalidOtpMessage=`Invalid Otp. Please check and try again`;static CredentialMismatch=`credential-mismatch`;static CredentialMismatchMessage=`Credential mismatch. Please check your credentials and try again.`;static InvalidData=`invalid-data`;static InvalidDataMessage=e=>`Invalid Body: ${e}`;static AccountNotFound=`account-not-found`;static AccountNotFoundMessage=`Account not found`;static InvalidRole=`invalid-role`;static InvalidRoleMessage=e=>`Role is invalid, please use one of the following roles: ${e.join(`, `)}`;static InvalidRefreshToken=`invalid-refresh-token`;static InvalidRefreshTokenMessage=`Invalid refresh token`;static DuplicateAccount=`account-already-exists`;static DuplicateAccountMessage=`Account with this credentials already exists`},m=class extends Error{code;static type=f.CredentialError;constructor(){super(p.CredentialMismatchMessage),this.code=p.CredentialMismatch,this.name=`CredentialMismatch`}},h=class extends Error{code;static type=f.ValidationError;constructor(e){super(p.InvalidDataMessage(e)),this.code=p.InvalidData,this.name=`InvalidDataError`}},g=class extends Error{code;static type=f.InvalidDataError;constructor(){super(p.AccountNotFoundMessage),this.code=p.AccountNotFound,this.name=`AccountNotFoundError`}},_=class extends Error{code;static type=f.ValidationError;constructor(e){super(p.InvalidRoleMessage(e)),this.code=p.InvalidRole,this.name=`InvalidRoleError`}},v=class extends Error{code;static type=f.ValidationError;constructor(){super(p.InvalidRefreshTokenMessage),this.code=p.InvalidRefreshToken,this.name=`InvalidRefreshTokenError`}},y=class extends Error{code;static type=f.ValidationError;constructor(){super(p.DuplicateAccountMessage),this.code=p.DuplicateAccount,this.name=`DuplicateAccountError`}},b=class extends Error{code;static type=f.ValidationError;constructor(){super(p.InvalidOtpMessage),this.code=p.InvalidOtp,this.name=`InvalidOTPCode`}},x=class{static LoginPurpose=`LOGIN`;static ResetPasswordPurpose=`RESET_PASSWORD`;static ActionPurpose=`ACTION`};const S=c.z.string().trim().refine(e=>{let t=(0,l.parsePhoneNumberFromString)(e);return!!t&&t.isValid()},{message:`Invalid phone number`}).transform(e=>(0,l.parsePhoneNumberFromString)(e)?.format(`E.164`)??e),C=c.z.object({email:c.z.email(),phoneNumber:c.z.never().optional(),password:c.z.string().min(6)}),w=c.z.object({phoneNumber:S,email:c.z.never().optional(),password:c.z.string().min(6)}),T=c.z.union([C,w]).superRefine((e,t)=>{e.email&&e.phoneNumber&&t.addIssue({code:c.z.ZodIssueCode.custom,message:`Provide either email or phoneNumber`,path:[`email`,`phoneNumber`]})}),E=c.z.object({phoneNumber:S.optional(),email:c.z.email().optional(),role:c.z.string(),password:c.z.string()}),D=E.superRefine((e,t)=>{!e.email&&!e.phoneNumber&&t.addIssue({code:c.z.ZodIssueCode.custom,message:`Provide either email or phoneNumber`,path:[`email`,`phoneNumber`]})}),O=c.z.object({refreshToken:c.z.string()}),k=c.z.object({refreshToken:c.z.string()}),A=c.z.object({accountId:c.z.string(),oldPassword:c.z.string(),newPassword:c.z.string()});function j(e){return`${e?.error?.issues[0].path}: ${e?.error?.issues[0].message}`}function M(e){return{success:!0,value:e}}function N(...e){return{success:!1,errors:e}}async function P({config:e},{...t}){let n=T.safeParse({email:t.email,phoneNumber:t.phoneNumber,password:``});if(!n.success)return N({type:h.type,error:new h(j(n))});let r=await e.dbContractor.findAccountWithCredential({phoneNumber:t.phoneNumber,email:t.email});if(!r||t.usePassword&&!await u.default.compare(String(t.password),String(r?.passwordHash)))return N({type:m.type,error:new m});let i=await e.dbContractor.createOTP({config:e},{id:r.id,purpose:t.otpPurpose});return M({id:r.id,code:i.code})}async function F({config:e,tokens:t},{...n}){let r=T.safeParse({email:n.email,phoneNumber:n.phoneNumber,password:``});if(!r.success)return N({type:h.type,error:new h(j(r))});let i=await e.dbContractor.findAccountWithCredential({email:n.email,phoneNumber:n.phoneNumber});if(!i)return N({type:m.type,error:new m});if(!(await e.dbContractor.verifyOTP({id:i.id,code:n.code,purpose:x.LoginPurpose})).isValid)return N({type:b.type,error:new b});let a=await t.GenerateTokenPairs({id:i.id,role:i.role});return await e.dbContractor.updateAccountLogin({id:i.id,refreshToken:a.refreshToken}),delete i.passwordHash,delete i.refreshTokens,M({account:i,tokens:a})}async function I({config:e},{...t}){return await e.dbContractor.verifyOTP({id:t.id,code:t.code,purpose:t.otpPurpose})}async function L({config:e},{...t}){let n=A.safeParse(t);if(!n.success)return N({type:h.type,error:new h(j(n))});let r=await e.dbContractor.findAccountById({id:t.accountId});if(!r)return N({type:g.type,error:new g});if(!u.default.compare(t.oldPassword,String(r.passwordHash)))return N({type:m.type,error:new m});let i=await u.default.hash(t.newPassword,10);return await e.dbContractor.updateAccount({id:r.id,data:{passwordHash:i}}),M({})}async function R({config:e,tokens:t},{...n}){let r=T.safeParse(n);if(!r.success)return N({type:h.type,error:new h(j(r))});let i=await e.dbContractor.findAccountWithCredential({email:n.email,phoneNumber:n.phoneNumber});if(!i||!await u.default.compare(String(n.password),String(i?.passwordHash)))return N({type:m.type,error:new m});let a=await t.GenerateTokenPairs({id:i.id,role:i.role});return await e.dbContractor.updateAccountLogin({id:i.id,refreshToken:a.refreshToken}),delete i.passwordHash,delete i.refreshTokens,M({account:i,tokens:a})}async function z(e){try{return{data:await e,error:null}}catch(e){return{data:null,error:e}}}async function B({config:e,tokens:t},{...n}){let r=k.safeParse(n);if(!r.success)return N({type:h.type,error:new h(j(r))});let i=await z(t.VerifyRefreshToken(n.refreshToken));return i.error||!i?N({type:v.type,error:new v}):(await e.dbContractor.removeAndAddRefreshToken({id:String(i.data?.id),refreshToken:n.refreshToken}),M({}))}async function V({config:e,tokens:t},{...n}){let r=O.safeParse(n);if(!r.success)return N({type:h.type,error:new h(j(r))});let i=await z(t.VerifyRefreshToken(n.refreshToken));if(i.error)return N({type:v.type,error:new v});let a=await e.dbContractor.findAccountById({id:String(i.data?.id)});if(!a)return N({type:g.type,error:new g});if(!a?.refreshTokens?.includes(n.refreshToken))return N({type:v.type,error:new v});let o=await t.GenerateTokenPairs({id:a.id,role:a.role});return await e.dbContractor.removeAndAddRefreshToken({id:a.id,refreshToken:n.refreshToken,newRefreshToken:o.refreshToken}),delete a.refreshTokens,delete a.passwordHash,M({account:a,tokens:o})}async function H({config:e,tokens:t},{...n}){let r=D.safeParse(n);if(!r.success)return N({type:h.type,error:new h(j(r))});if(!e.roles?.includes(n.role))return N({type:_.type,error:new _(e.roles)});if(await e.dbContractor.findAccountWithCredential({email:n.email,phoneNumber:n.phoneNumber}))return N({type:y.type,error:new y});let i=await u.default.hash(n.password,10),a=await e.dbContractor.createAccount({data:{email:n.email,phoneNumber:n.phoneNumber,passwordHash:i,role:n.role,lastLogin:new Date}}),o=await t.GenerateTokenPairs({id:a.id,role:a.role});return await e.dbContractor.updateAccountLogin({id:a.id,refreshToken:o.refreshToken}),M({account:a,tokens:o})}async function U({...e}){return d.default.sign(e.payload,e.config.jwtConfig.accessTokenSecret,{expiresIn:e.config.jwtConfig?.accessTokenLifeSpan??`15m`})}async function W({...e}){return d.default.sign(e.payload,e.config.jwtConfig.refreshTokenSecret,{expiresIn:e.config.jwtConfig?.refreshTokenLifeSpan??`30d`})}async function G({...e}){return{accessToken:d.default.sign(e.payload,e.config.jwtConfig.accessTokenSecret,{expiresIn:e.config.jwtConfig?.accessTokenLifeSpan??`15m`}),refreshToken:d.default.sign(e.payload,e.config.jwtConfig.refreshTokenSecret,{expiresIn:e.config.jwtConfig?.refreshTokenLifeSpan??`30d`})}}async function K({...e}){let t=d.default.verify(e.token,e.config.jwtConfig.refreshTokenSecret);return t instanceof String?null:t}async function q({...e}){let t=d.default.verify(e.token,e.config.jwtConfig.accessTokenSecret);return t instanceof String?null:t}const J=c.default.custom(()=>!0,{message:`Invalid dbContractor: must implement Database Contract interface`}),Y=c.default.custom(()=>!0,{message:`Invalid routeContractor: must implement RoutesContract interface`}),X=c.default.custom(),Z=c.default.object({dbContractor:J,routeContractor:Y,roles:c.default.array(c.default.string()).min(1),jwtConfig:c.default.object({refreshTokenSecret:c.default.string(),accessTokenSecret:c.default.string(),accessTokenLifeSpan:X.optional(),refreshTokenLifeSpan:X.optional()}),otpConfig:c.default.object({expiresIn:c.default.number().optional(),length:c.default.number().min(4).max(8).optional()})});var Q=class{#config;constructor(e){if(!Z.safeParse(e).success)throw Error(`❌ Failed to initiate CAuth. You provided an invalid config!`);this.#config=e}get RoleType(){return null}Guard=e=>this.#config.routeContractor.Guard({config:this.#config,tokens:this.Tokens,roles:e});Routes={Register:()=>this.#config.routeContractor.Register({config:this.#config,tokens:this.Tokens}),Login:()=>this.#config.routeContractor.Login({config:this.#config,tokens:this.Tokens}),Logout:()=>this.#config.routeContractor.Logout({config:this.#config,tokens:this.Tokens}),Refresh:()=>this.#config.routeContractor.Refresh({config:this.#config,tokens:this.Tokens}),ChangePassword:e=>this.#config.routeContractor.ChangePassword({config:this.#config,tokens:this.Tokens,userId:e})};FN={Login:({...e})=>R({config:this.#config,tokens:this.Tokens},e),Register:({...e})=>H({config:this.#config,tokens:this.Tokens},e),Logout:({...e})=>B({config:this.#config,tokens:this.Tokens},e),Refresh:({...e})=>V({config:this.#config,tokens:this.Tokens},e),ChangePassword:({...e})=>L({config:this.#config,tokens:this.Tokens},e),RequestOTPCode:({...e})=>P({config:this.#config,tokens:this.Tokens},e),LoginWithOTP:({...e})=>F({config:this.#config,tokens:this.Tokens},{...e}),VerifyOTP:({...e})=>I({config:this.#config,tokens:this.Tokens},e)};Tokens={GenerateRefreshToken:e=>W({payload:e,config:this.#config}),GenerateAccessToken:e=>U({payload:e,config:this.#config}),GenerateTokenPairs:e=>G({payload:e,config:this.#config}),VerifyRefreshToken:e=>K({token:e,config:this.#config}),VerifyAccessToken:e=>q({token:e,config:this.#config})}};function $(e){return new Q(e)}exports.AccountNotFoundError=g,exports.CAuth=$,exports.CredentialMismatchError=m,exports.DuplicateAccountError=y,exports.InvalidDataError=h,exports.InvalidOTPCode=b,exports.InvalidRefreshTokenError=v,exports.InvalidRoleError=_;