@cauth/core 0.1.0 → 0.1.2

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.ts CHANGED
@@ -248,11 +248,11 @@ declare const LoginSchema: z.ZodUnion<readonly [z.ZodObject<{
248
248
  type LoginSchemaType = z.infer<typeof LoginSchema>;
249
249
  declare const OTPCodeUnion: z.ZodUnion<readonly [z.ZodObject<{
250
250
  email: z.ZodEmail;
251
- phoneNumber: z.ZodNever;
251
+ phoneNumber: z.ZodOptional<z.ZodNever>;
252
252
  code: z.ZodString;
253
253
  }, z.core.$strip>, z.ZodObject<{
254
254
  phoneNumber: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
255
- email: z.ZodNever;
255
+ email: z.ZodOptional<z.ZodNever>;
256
256
  code: z.ZodString;
257
257
  }, z.core.$strip>]>;
258
258
  type OTPLogin = z.infer<typeof OTPCodeUnion>;
@@ -265,7 +265,7 @@ declare const RequestOTPCodeSchema: z.ZodUnion<readonly [z.ZodObject<{
265
265
  usePassword: z.ZodDefault<z.ZodBoolean>;
266
266
  password: z.ZodOptional<z.ZodString>;
267
267
  phoneNumber: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
268
- email: z.ZodNever;
268
+ email: z.ZodOptional<z.ZodNever>;
269
269
  }, z.core.$strip>, z.ZodObject<{
270
270
  otpPurpose: z.ZodEnum<{
271
271
  LOGIN: "LOGIN";
@@ -274,7 +274,7 @@ declare const RequestOTPCodeSchema: z.ZodUnion<readonly [z.ZodObject<{
274
274
  }>;
275
275
  usePassword: z.ZodDefault<z.ZodBoolean>;
276
276
  password: z.ZodOptional<z.ZodString>;
277
- phoneNumber: z.ZodNever;
277
+ phoneNumber: z.ZodOptional<z.ZodNever>;
278
278
  email: z.ZodString;
279
279
  }, z.core.$strip>]>;
280
280
  type RequestOTP = z.infer<typeof RequestOTPCodeSchema>;
package/dist/index.js CHANGED
@@ -1 +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 LoginPurpose=`LOGIN`;static ResetPasswordPurpose=`RESET_PASSWORD`;static ActionPurpose=`ACTION`};const o=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),s=t.enum([`LOGIN`,`RESET_PASSWORD`,`ACTION`]),c=t.object({email:t.email(),phoneNumber:t.never().optional(),password:t.string().min(6).optional()}),l=t.object({phoneNumber:o,email:t.never().optional(),password:t.string().min(6).optional()}),u=t.union([c,l]).superRefine((e,n)=>{e.email&&e.phoneNumber&&n.addIssue({code:t.ZodIssueCode.custom,message:`Provide either email or phoneNumber`,path:[`email`,`phoneNumber`]})}),d=t.object({phoneNumber:o,email:t.never(),code:t.string().min(4).max(8)}),f=t.object({email:t.email(),phoneNumber:t.never(),code:t.string().min(4).max(8)}),p=t.union([f,d]),m=t.object({otpPurpose:s,usePassword:t.boolean().default(!1),password:t.string().optional()}),h=m.extend({phoneNumber:o,email:t.never()}),g=m.extend({phoneNumber:t.never(),email:t.string().email()});t.union([h,g]).refine(e=>e.usePassword?!!e.password:!e.password,{message:`Password required only if usePassword is true`,path:[`password`]});const _=t.object({phoneNumber:o.optional(),email:t.email().optional(),role:t.string(),password:t.string().optional()}).superRefine((e,n)=>{!e.email&&!e.phoneNumber&&n.addIssue({code:t.ZodIssueCode.custom,message:`Provide either email or phoneNumber`,path:[`email`,`phoneNumber`]})}),v=t.object({refreshToken:t.string()}),y=t.object({refreshToken:t.string()}),b=t.object({accountId:t.string(),oldPassword:t.string(),newPassword:t.string()});var x=class{static ValidationError=`validation-error`;static CredentialError=`credential-error`;static UnKnownError=`unknown-error`;static InvalidDataError=`invalid-data-error`},S=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`;static SchemaValidationError=`schema-validation`;static SchemaValidationMessage=`Your database error is not is sync with CAuth Spec`};const C={CredentialMismatchError:{type:x.CredentialError,message:S.CredentialMismatchMessage,code:S.CredentialMismatch,name:`CredentialMismatchError`},InvalidDataError:e=>({type:x.ValidationError,message:S.InvalidDataMessage(e),code:S.InvalidData,name:`InvalidDataError`}),AccountNotFoundError:{type:x.InvalidDataError,message:S.AccountNotFoundMessage,code:S.AccountNotFound,name:`AccountNotFoundError`},InvalidRoleError:e=>({type:x.ValidationError,message:S.InvalidRoleMessage(e),code:S.InvalidRole,name:`InvalidRoleError`}),InvalidRefreshTokenError:{type:x.ValidationError,message:S.InvalidRefreshTokenMessage,code:S.InvalidRefreshToken,name:`InvalidRefreshTokenError`},DuplicateAccountError:{type:x.ValidationError,message:S.DuplicateAccountMessage,code:S.DuplicateAccount,name:`DuplicateAccountError`},InvalidOTPCode:{type:x.ValidationError,message:S.InvalidOtpMessage,code:S.InvalidOtp,name:`InvalidOTPCode`},SchemaInvalidError:{type:x.ValidationError,message:S.SchemaValidationMessage,code:S.SchemaValidationError,name:`SchemaInvalidError`}};function w(e,t){return typeof e==`object`&&!!e&&`name`in e&&e.name===t}function T(e,t){return w(e,t)}function E(e){return`${e?.error?.issues[0].path}: ${e?.error?.issues[0].message}`}function D(e){return{success:!0,value:e}}function O(...e){return{success:!1,errors:e}}async function k({config:e},t){let n=u.safeParse({email:t.email,phoneNumber:t.phoneNumber});if(!n.success)return O({error:C.InvalidDataError(E(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 O({error:C.CredentialMismatchError});let a=await e.dbContractor.createOTP({config:e},{id:i.id,purpose:t.otpPurpose});return D({id:i.id,code:a.code})}async function A({config:e,tokens:t},n){let r=p.safeParse({phoneNumber:n.phoneNumber,email:n.email,code:n.code});if(!r.success)return O({error:C.InvalidDataError(E(r))});let i=await e.dbContractor.findAccountWithCredential({email:n.email,phoneNumber:n.phoneNumber});if(!i)return O({error:C.CredentialMismatchError});if(!(await e.dbContractor.verifyOTP({id:i.id,code:n.code,purpose:a.LoginPurpose})).isValid)return O({error:C.InvalidOTPCode});let o=await t.GenerateTokenPairs({id:i.id,role:i.role});return await e.dbContractor.updateAccountLogin({id:i.id,refreshToken:o.refreshToken}),delete i.passwordHash,delete i.refreshTokens,D({account:i,tokens:o})}async function j({config:e},t){return D({isValid:(await e.dbContractor.verifyOTP({id:t.id,code:t.code,purpose:t.otpPurpose})).isValid})}async function M({config:e},{...t}){let n=b.safeParse(t);if(!n.success)return O({error:C.InvalidDataError(E(n))});let i=await e.dbContractor.findAccountById({id:t.accountId});if(!i||!r.compare(t.oldPassword,String(i.passwordHash)))return O({error:C.CredentialMismatchError});let a=await r.hash(t.newPassword,10);return await e.dbContractor.updateAccount({id:i.id,data:{passwordHash:a}}),D({})}async function N({config:e,tokens:t},{...n}){let i=u.safeParse(n);if(!i.success)return O({error:C.InvalidDataError(E(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 O({error:C.CredentialMismatchError});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,D({account:a,tokens:o})}async function P(e){try{return{data:await e,error:null}}catch(e){return{data:null,error:e}}}async function F({config:e,tokens:t},{...n}){let r=y.safeParse(n);if(!r.success)return O({error:C.InvalidDataError(E(r))});let i=await P(t.VerifyRefreshToken(n.refreshToken));return i.error||!i?O({error:C.InvalidRefreshTokenError}):(await e.dbContractor.removeAndAddRefreshToken({id:String(i.data?.id),refreshToken:n.refreshToken}),D({}))}async function I({config:e,tokens:t},{...n}){let r=v.safeParse(n);if(!r.success)return O({error:C.InvalidDataError(E(r))});let i=await P(t.VerifyRefreshToken(n.refreshToken));if(i.error)return O({error:C.InvalidRefreshTokenError});let a=await e.dbContractor.findAccountById({id:String(i.data?.id)});if(!a)return O({error:C.AccountNotFoundError});if(!a?.refreshTokens?.includes(n.refreshToken))return O({error:C.InvalidRefreshTokenError});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,D({account:a,tokens:o})}async function L({config:e,tokens:t},{...n}){let i=_.safeParse(n);if(!i.success)return O({error:C.InvalidDataError(E(i))});if(!e.roles?.includes(n.role))return O({error:C.InvalidRoleError(e.roles)});if(await e.dbContractor.findAccountWithCredential({email:n.email,phoneNumber:n.phoneNumber}))return O({error:C.DuplicateAccountError});let a=await r.hash(String(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}),D({account:o,tokens:s})}async function R({...e}){return i.sign(e.payload,e.config.jwtConfig.accessTokenSecret,{expiresIn:e.config.jwtConfig?.accessTokenLifeSpan??`15m`})}async function z({...e}){return i.sign(e.payload,e.config.jwtConfig.refreshTokenSecret,{expiresIn:e.config.jwtConfig?.refreshTokenLifeSpan??`30d`})}async function B({...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 V({...e}){let t=i.verify(e.token,e.config.jwtConfig.refreshTokenSecret);return t instanceof String?null:t}async function H({...e}){let t=i.verify(e.token,e.config.jwtConfig.accessTokenSecret);return t instanceof String?null:t}const U=e.custom(()=>!0,{message:`Invalid dbContractor: must implement Database Contract interface`}),W=e.custom(()=>!0,{message:`Invalid routeContractor: must implement RoutesContract interface`}),G=e.custom(),K=e.object({dbContractor:U,routeContractor:W,roles:e.array(e.string()).min(1),jwtConfig:e.object({refreshTokenSecret:e.string(),accessTokenSecret:e.string(),accessTokenLifeSpan:G.optional(),refreshTokenLifeSpan:G.optional()}),otpConfig:e.object({expiresIn:e.number().optional(),length:e.number().min(4).max(8).optional()})});var q=class{#config;constructor(e){if(!K.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})=>N({config:this.#config,tokens:this.Tokens},e),Register:({...e})=>L({config:this.#config,tokens:this.Tokens},e),Logout:({...e})=>F({config:this.#config,tokens:this.Tokens},e),Refresh:({...e})=>I({config:this.#config,tokens:this.Tokens},e),ChangePassword:({...e})=>M({config:this.#config,tokens:this.Tokens},e),RequestOTPCode:({...e})=>k({config:this.#config,tokens:this.Tokens},e),LoginWithOTP:e=>A({config:this.#config,tokens:this.Tokens},e),VerifyOTP:e=>j({config:this.#config,tokens:this.Tokens},e)};Tokens={GenerateRefreshToken:e=>z({payload:e,config:this.#config}),GenerateAccessToken:e=>R({payload:e,config:this.#config}),GenerateTokenPairs:e=>B({payload:e,config:this.#config}),VerifyRefreshToken:e=>V({token:e,config:this.#config}),VerifyAccessToken:e=>H({token:e,config:this.#config})}};function J(e){return new q(e)}export{J as CAuth,C as CAuthErrors,T as is,w as isCAuthError};
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 LoginPurpose=`LOGIN`;static ResetPasswordPurpose=`RESET_PASSWORD`;static ActionPurpose=`ACTION`};const o=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),s=t.enum([`LOGIN`,`RESET_PASSWORD`,`ACTION`]),c=t.object({email:t.email(),phoneNumber:t.never().optional(),password:t.string().min(6).optional()}),l=t.object({phoneNumber:o,email:t.never().optional(),password:t.string().min(6).optional()}),u=t.union([c,l]).superRefine((e,n)=>{e.email&&e.phoneNumber&&n.addIssue({code:t.ZodIssueCode.custom,message:`Provide either email or phoneNumber`,path:[`email`,`phoneNumber`]})}),d=t.object({phoneNumber:o,email:t.never().optional(),code:t.string().min(4).max(8)}),f=t.object({email:t.email(),phoneNumber:t.never().optional(),code:t.string().min(4).max(8)}),p=t.union([f,d]),m=t.object({otpPurpose:s,usePassword:t.boolean().default(!1),password:t.string().optional()}),h=m.extend({phoneNumber:o,email:t.never().optional()}),g=m.extend({phoneNumber:t.never().optional(),email:t.string().email()});t.union([h,g]).refine(e=>e.usePassword?!!e.password:!e.password,{message:`Password required only if usePassword is true`,path:[`password`]});const _=t.object({phoneNumber:o.optional(),email:t.email().optional(),role:t.string(),password:t.string().optional()}).superRefine((e,n)=>{!e.email&&!e.phoneNumber&&n.addIssue({code:t.ZodIssueCode.custom,message:`Provide either email or phoneNumber`,path:[`email`,`phoneNumber`]})}),v=t.object({refreshToken:t.string()}),y=t.object({refreshToken:t.string()}),b=t.object({accountId:t.string(),oldPassword:t.string(),newPassword:t.string()});var x=class{static ValidationError=`validation-error`;static CredentialError=`credential-error`;static UnKnownError=`unknown-error`;static InvalidDataError=`invalid-data-error`},S=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`;static SchemaValidationError=`schema-validation`;static SchemaValidationMessage=`Your database error is not is sync with CAuth Spec`};const C={CredentialMismatchError:{type:x.CredentialError,message:S.CredentialMismatchMessage,code:S.CredentialMismatch,name:`CredentialMismatchError`},InvalidDataError:e=>({type:x.ValidationError,message:S.InvalidDataMessage(e),code:S.InvalidData,name:`InvalidDataError`}),AccountNotFoundError:{type:x.InvalidDataError,message:S.AccountNotFoundMessage,code:S.AccountNotFound,name:`AccountNotFoundError`},InvalidRoleError:e=>({type:x.ValidationError,message:S.InvalidRoleMessage(e),code:S.InvalidRole,name:`InvalidRoleError`}),InvalidRefreshTokenError:{type:x.ValidationError,message:S.InvalidRefreshTokenMessage,code:S.InvalidRefreshToken,name:`InvalidRefreshTokenError`},DuplicateAccountError:{type:x.ValidationError,message:S.DuplicateAccountMessage,code:S.DuplicateAccount,name:`DuplicateAccountError`},InvalidOTPCode:{type:x.ValidationError,message:S.InvalidOtpMessage,code:S.InvalidOtp,name:`InvalidOTPCode`},SchemaInvalidError:{type:x.ValidationError,message:S.SchemaValidationMessage,code:S.SchemaValidationError,name:`SchemaInvalidError`}};function w(e,t){return typeof e==`object`&&!!e&&`name`in e&&e.name===t}function T(e,t){return w(e,t)}function E(e){return`${e?.error?.issues[0].path}: ${e?.error?.issues[0].message}`}function D(e){return{success:!0,value:e}}function O(...e){return{success:!1,errors:e}}async function k({config:e},t){let n=u.safeParse({email:t.email,phoneNumber:t.phoneNumber});if(!n.success)return O({error:C.InvalidDataError(E(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 O({error:C.CredentialMismatchError});let a=await e.dbContractor.createOTP({config:e},{id:i.id,purpose:t.otpPurpose});return D({id:i.id,code:a.code})}async function A({config:e,tokens:t},n){let r=p.safeParse({phoneNumber:n.phoneNumber,email:n.email,code:n.code});if(!r.success)return O({error:C.InvalidDataError(E(r))});let i=await e.dbContractor.findAccountWithCredential({email:n.email,phoneNumber:n.phoneNumber});if(!i)return O({error:C.CredentialMismatchError});if(!(await e.dbContractor.verifyOTP({id:i.id,code:n.code,purpose:a.LoginPurpose})).isValid)return O({error:C.InvalidOTPCode});let o=await t.GenerateTokenPairs({id:i.id,role:i.role});return await e.dbContractor.updateAccountLogin({id:i.id,refreshToken:o.refreshToken}),delete i.passwordHash,delete i.refreshTokens,D({account:i,tokens:o})}async function j({config:e},t){return D({isValid:(await e.dbContractor.verifyOTP({id:t.id,code:t.code,purpose:t.otpPurpose})).isValid})}async function M({config:e},{...t}){let n=b.safeParse(t);if(!n.success)return O({error:C.InvalidDataError(E(n))});let i=await e.dbContractor.findAccountById({id:t.accountId});if(!i||!r.compare(t.oldPassword,String(i.passwordHash)))return O({error:C.CredentialMismatchError});let a=await r.hash(t.newPassword,10);return await e.dbContractor.updateAccount({id:i.id,data:{passwordHash:a}}),D({})}async function N({config:e,tokens:t},{...n}){let i=u.safeParse(n);if(!i.success)return O({error:C.InvalidDataError(E(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 O({error:C.CredentialMismatchError});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,D({account:a,tokens:o})}async function P(e){try{return{data:await e,error:null}}catch(e){return{data:null,error:e}}}async function F({config:e,tokens:t},{...n}){let r=y.safeParse(n);if(!r.success)return O({error:C.InvalidDataError(E(r))});let i=await P(t.VerifyRefreshToken(n.refreshToken));return i.error||!i?O({error:C.InvalidRefreshTokenError}):(await e.dbContractor.removeAndAddRefreshToken({id:String(i.data?.id),refreshToken:n.refreshToken}),D({}))}async function I({config:e,tokens:t},{...n}){let r=v.safeParse(n);if(!r.success)return O({error:C.InvalidDataError(E(r))});let i=await P(t.VerifyRefreshToken(n.refreshToken));if(i.error)return O({error:C.InvalidRefreshTokenError});let a=await e.dbContractor.findAccountById({id:String(i.data?.id)});if(!a)return O({error:C.AccountNotFoundError});if(!a?.refreshTokens?.includes(n.refreshToken))return O({error:C.InvalidRefreshTokenError});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,D({account:a,tokens:o})}async function L({config:e,tokens:t},{...n}){let i=_.safeParse(n);if(!i.success)return O({error:C.InvalidDataError(E(i))});if(!e.roles?.includes(n.role))return O({error:C.InvalidRoleError(e.roles)});if(await e.dbContractor.findAccountWithCredential({email:n.email,phoneNumber:n.phoneNumber}))return O({error:C.DuplicateAccountError});let a=await r.hash(String(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}),D({account:o,tokens:s})}async function R({...e}){return i.sign(e.payload,e.config.jwtConfig.accessTokenSecret,{expiresIn:e.config.jwtConfig?.accessTokenLifeSpan??`15m`})}async function z({...e}){return i.sign(e.payload,e.config.jwtConfig.refreshTokenSecret,{expiresIn:e.config.jwtConfig?.refreshTokenLifeSpan??`30d`})}async function B({...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 V({...e}){let t=i.verify(e.token,e.config.jwtConfig.refreshTokenSecret);return t instanceof String?null:t}async function H({...e}){let t=i.verify(e.token,e.config.jwtConfig.accessTokenSecret);return t instanceof String?null:t}const U=e.custom(()=>!0,{message:`Invalid dbContractor: must implement Database Contract interface`}),W=e.custom(()=>!0,{message:`Invalid routeContractor: must implement RoutesContract interface`}),G=e.custom(),K=e.object({dbContractor:U,routeContractor:W,roles:e.array(e.string()).min(1),jwtConfig:e.object({refreshTokenSecret:e.string(),accessTokenSecret:e.string(),accessTokenLifeSpan:G.optional(),refreshTokenLifeSpan:G.optional()}),otpConfig:e.object({expiresIn:e.number().optional(),length:e.number().min(4).max(8).optional()})});var q=class{#config;constructor(e){if(!K.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})=>N({config:this.#config,tokens:this.Tokens},e),Register:({...e})=>L({config:this.#config,tokens:this.Tokens},e),Logout:({...e})=>F({config:this.#config,tokens:this.Tokens},e),Refresh:({...e})=>I({config:this.#config,tokens:this.Tokens},e),ChangePassword:({...e})=>M({config:this.#config,tokens:this.Tokens},e),RequestOTPCode:({...e})=>k({config:this.#config,tokens:this.Tokens},e),LoginWithOTP:e=>A({config:this.#config,tokens:this.Tokens},e),VerifyOTP:e=>j({config:this.#config,tokens:this.Tokens},e)};Tokens={GenerateRefreshToken:e=>z({payload:e,config:this.#config}),GenerateAccessToken:e=>R({payload:e,config:this.#config}),GenerateTokenPairs:e=>B({payload:e,config:this.#config}),VerifyRefreshToken:e=>V({token:e,config:this.#config}),VerifyAccessToken:e=>H({token:e,config:this.#config})}};function J(e){return new q(e)}export{J as CAuth,C as CAuthErrors,T as is,w as isCAuthError};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cauth/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",