@lenan-soft/auth 1.0.1
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 +591 -0
- package/dist/index.cjs +45 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +129 -0
- package/dist/index.d.ts +129 -0
- package/dist/index.js +17 -0
- package/dist/index.js.map +1 -0
- package/dist/nestjs/index.cjs +738 -0
- package/dist/nestjs/index.cjs.map +1 -0
- package/dist/nestjs/index.d.cts +510 -0
- package/dist/nestjs/index.d.ts +510 -0
- package/dist/nestjs/index.js +709 -0
- package/dist/nestjs/index.js.map +1 -0
- package/dist/react/index.cjs +560 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +285 -0
- package/dist/react/index.d.ts +285 -0
- package/dist/react/index.js +531 -0
- package/dist/react/index.js.map +1 -0
- package/dist/react/native/index.cjs +60 -0
- package/dist/react/native/index.cjs.map +1 -0
- package/dist/react/native/index.d.cts +50 -0
- package/dist/react/native/index.d.ts +50 -0
- package/dist/react/native/index.js +41 -0
- package/dist/react/native/index.js.map +1 -0
- package/dist/shared/index.cjs +45 -0
- package/dist/shared/index.cjs.map +1 -0
- package/dist/shared/index.d.cts +129 -0
- package/dist/shared/index.d.ts +129 -0
- package/dist/shared/index.js +17 -0
- package/dist/shared/index.js.map +1 -0
- package/package.json +151 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token storage interface for frontend applications
|
|
3
|
+
* Implement this to use different storage backends (localStorage, SecureStore, etc.)
|
|
4
|
+
*/
|
|
5
|
+
interface TokenStorage {
|
|
6
|
+
getItem(key: string): Promise<string | null> | string | null;
|
|
7
|
+
setItem(key: string, value: string): Promise<void> | void;
|
|
8
|
+
removeItem(key: string): Promise<void> | void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
type SecureStoreModule = {
|
|
12
|
+
getItemAsync: (key: string) => Promise<string | null>;
|
|
13
|
+
setItemAsync: (key: string, value: string) => Promise<void>;
|
|
14
|
+
deleteItemAsync: (key: string) => Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Expo SecureStore adapter for React Native
|
|
18
|
+
* Provides secure token storage using expo-secure-store
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* import { SecureStoreAdapter } from '@lenan-soft/auth/react/native';
|
|
23
|
+
* import { AuthProvider } from '@lenan-soft/auth/react';
|
|
24
|
+
*
|
|
25
|
+
* export default function App() {
|
|
26
|
+
* return (
|
|
27
|
+
* <AuthProvider
|
|
28
|
+
* baseUrl="https://api.example.com"
|
|
29
|
+
* tokenStorage={new SecureStoreAdapter()}
|
|
30
|
+
* >
|
|
31
|
+
* <RootNavigator />
|
|
32
|
+
* </AuthProvider>
|
|
33
|
+
* );
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
declare class SecureStoreAdapter implements TokenStorage {
|
|
38
|
+
private secureStore;
|
|
39
|
+
constructor(secureStoreModule?: SecureStoreModule);
|
|
40
|
+
getItem(key: string): Promise<string | null>;
|
|
41
|
+
setItem(key: string, value: string): Promise<void>;
|
|
42
|
+
removeItem(key: string): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a SecureStore adapter with an injected module
|
|
46
|
+
* Useful for when you want to pass the module reference explicitly
|
|
47
|
+
*/
|
|
48
|
+
declare function createSecureStoreAdapter(secureStoreModule: SecureStoreModule): SecureStoreAdapter;
|
|
49
|
+
|
|
50
|
+
export { SecureStoreAdapter, createSecureStoreAdapter };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token storage interface for frontend applications
|
|
3
|
+
* Implement this to use different storage backends (localStorage, SecureStore, etc.)
|
|
4
|
+
*/
|
|
5
|
+
interface TokenStorage {
|
|
6
|
+
getItem(key: string): Promise<string | null> | string | null;
|
|
7
|
+
setItem(key: string, value: string): Promise<void> | void;
|
|
8
|
+
removeItem(key: string): Promise<void> | void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
type SecureStoreModule = {
|
|
12
|
+
getItemAsync: (key: string) => Promise<string | null>;
|
|
13
|
+
setItemAsync: (key: string, value: string) => Promise<void>;
|
|
14
|
+
deleteItemAsync: (key: string) => Promise<void>;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Expo SecureStore adapter for React Native
|
|
18
|
+
* Provides secure token storage using expo-secure-store
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```tsx
|
|
22
|
+
* import { SecureStoreAdapter } from '@lenan-soft/auth/react/native';
|
|
23
|
+
* import { AuthProvider } from '@lenan-soft/auth/react';
|
|
24
|
+
*
|
|
25
|
+
* export default function App() {
|
|
26
|
+
* return (
|
|
27
|
+
* <AuthProvider
|
|
28
|
+
* baseUrl="https://api.example.com"
|
|
29
|
+
* tokenStorage={new SecureStoreAdapter()}
|
|
30
|
+
* >
|
|
31
|
+
* <RootNavigator />
|
|
32
|
+
* </AuthProvider>
|
|
33
|
+
* );
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
declare class SecureStoreAdapter implements TokenStorage {
|
|
38
|
+
private secureStore;
|
|
39
|
+
constructor(secureStoreModule?: SecureStoreModule);
|
|
40
|
+
getItem(key: string): Promise<string | null>;
|
|
41
|
+
setItem(key: string, value: string): Promise<void>;
|
|
42
|
+
removeItem(key: string): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create a SecureStore adapter with an injected module
|
|
46
|
+
* Useful for when you want to pass the module reference explicitly
|
|
47
|
+
*/
|
|
48
|
+
declare function createSecureStoreAdapter(secureStoreModule: SecureStoreModule): SecureStoreAdapter;
|
|
49
|
+
|
|
50
|
+
export { SecureStoreAdapter, createSecureStoreAdapter };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/react/native/index.ts
|
|
9
|
+
var SecureStoreAdapter = class {
|
|
10
|
+
secureStore;
|
|
11
|
+
constructor(secureStoreModule) {
|
|
12
|
+
if (secureStoreModule) {
|
|
13
|
+
this.secureStore = secureStoreModule;
|
|
14
|
+
} else {
|
|
15
|
+
try {
|
|
16
|
+
this.secureStore = __require("expo-secure-store");
|
|
17
|
+
} catch {
|
|
18
|
+
throw new Error(
|
|
19
|
+
"expo-secure-store is not installed. Please install it with: npx expo install expo-secure-store"
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async getItem(key) {
|
|
25
|
+
return this.secureStore.getItemAsync(key);
|
|
26
|
+
}
|
|
27
|
+
async setItem(key, value) {
|
|
28
|
+
return this.secureStore.setItemAsync(key, value);
|
|
29
|
+
}
|
|
30
|
+
async removeItem(key) {
|
|
31
|
+
return this.secureStore.deleteItemAsync(key);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
function createSecureStoreAdapter(secureStoreModule) {
|
|
35
|
+
return new SecureStoreAdapter(secureStoreModule);
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
SecureStoreAdapter,
|
|
39
|
+
createSecureStoreAdapter
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/react/native/index.ts"],"sourcesContent":["import type { TokenStorage } from \"../../shared\";\n\n// Type declaration for expo-secure-store\n// This allows the adapter to work without bundling the actual dependency\ntype SecureStoreModule = {\n getItemAsync: (key: string) => Promise<string | null>;\n setItemAsync: (key: string, value: string) => Promise<void>;\n deleteItemAsync: (key: string) => Promise<void>;\n};\n\n/**\n * Expo SecureStore adapter for React Native\n * Provides secure token storage using expo-secure-store\n *\n * @example\n * ```tsx\n * import { SecureStoreAdapter } from '@lenan-soft/auth/react/native';\n * import { AuthProvider } from '@lenan-soft/auth/react';\n *\n * export default function App() {\n * return (\n * <AuthProvider\n * baseUrl=\"https://api.example.com\"\n * tokenStorage={new SecureStoreAdapter()}\n * >\n * <RootNavigator />\n * </AuthProvider>\n * );\n * }\n * ```\n */\nexport class SecureStoreAdapter implements TokenStorage {\n private secureStore: SecureStoreModule;\n\n constructor(secureStoreModule?: SecureStoreModule) {\n if (secureStoreModule) {\n this.secureStore = secureStoreModule;\n } else {\n // Dynamic import to avoid bundling expo-secure-store\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n try {\n this.secureStore = require(\"expo-secure-store\") as SecureStoreModule;\n } catch {\n throw new Error(\n \"expo-secure-store is not installed. Please install it with: npx expo install expo-secure-store\",\n );\n }\n }\n }\n\n async getItem(key: string): Promise<string | null> {\n return this.secureStore.getItemAsync(key);\n }\n\n async setItem(key: string, value: string): Promise<void> {\n return this.secureStore.setItemAsync(key, value);\n }\n\n async removeItem(key: string): Promise<void> {\n return this.secureStore.deleteItemAsync(key);\n }\n}\n\n/**\n * Create a SecureStore adapter with an injected module\n * Useful for when you want to pass the module reference explicitly\n */\nexport function createSecureStoreAdapter(\n secureStoreModule: SecureStoreModule,\n): SecureStoreAdapter {\n return new SecureStoreAdapter(secureStoreModule);\n}\n"],"mappings":";;;;;;;;AA+BO,IAAM,qBAAN,MAAiD;AAAA,EAC9C;AAAA,EAER,YAAY,mBAAuC;AACjD,QAAI,mBAAmB;AACrB,WAAK,cAAc;AAAA,IACrB,OAAO;AAGL,UAAI;AACF,aAAK,cAAc,UAAQ,mBAAmB;AAAA,MAChD,QAAQ;AACN,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,QAAQ,KAAqC;AACjD,WAAO,KAAK,YAAY,aAAa,GAAG;AAAA,EAC1C;AAAA,EAEA,MAAM,QAAQ,KAAa,OAA8B;AACvD,WAAO,KAAK,YAAY,aAAa,KAAK,KAAK;AAAA,EACjD;AAAA,EAEA,MAAM,WAAW,KAA4B;AAC3C,WAAO,KAAK,YAAY,gBAAgB,GAAG;AAAA,EAC7C;AACF;AAMO,SAAS,yBACd,mBACoB;AACpB,SAAO,IAAI,mBAAmB,iBAAiB;AACjD;","names":[]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/shared/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
DEFAULT_AUTH_ENDPOINTS: () => DEFAULT_AUTH_ENDPOINTS,
|
|
24
|
+
TOKEN_STORAGE_KEYS: () => TOKEN_STORAGE_KEYS
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
|
|
28
|
+
// src/shared/types.ts
|
|
29
|
+
var DEFAULT_AUTH_ENDPOINTS = {
|
|
30
|
+
login: "/auth/login",
|
|
31
|
+
register: "/auth/register",
|
|
32
|
+
refresh: "/auth/refresh",
|
|
33
|
+
logout: "/auth/logout",
|
|
34
|
+
me: "/auth/me"
|
|
35
|
+
};
|
|
36
|
+
var TOKEN_STORAGE_KEYS = {
|
|
37
|
+
ACCESS_TOKEN: "lenan_access_token",
|
|
38
|
+
REFRESH_TOKEN: "lenan_refresh_token"
|
|
39
|
+
};
|
|
40
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
41
|
+
0 && (module.exports = {
|
|
42
|
+
DEFAULT_AUTH_ENDPOINTS,
|
|
43
|
+
TOKEN_STORAGE_KEYS
|
|
44
|
+
});
|
|
45
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/shared/index.ts","../../src/shared/types.ts"],"sourcesContent":["export * from \"./types\";\n","/**\n * JWT payload structure\n */\nexport interface JwtPayload {\n /** User ID (subject) */\n sub: string;\n /** User email */\n email: string;\n /** Issued at timestamp */\n iat?: number;\n /** Expiration timestamp */\n exp?: number;\n}\n\n/**\n * Token response containing access and refresh tokens\n */\nexport interface AuthTokens {\n /** Short-lived access token */\n accessToken: string;\n /** Long-lived refresh token */\n refreshToken: string;\n}\n\n/**\n * Base user interface - minimal fields required by the auth system\n * Consumers should extend this with their own user properties\n */\nexport interface BaseUser {\n /** Unique user identifier */\n id: string;\n /** User email address */\n email: string;\n}\n\n/**\n * User with password hash - used internally for authentication\n */\nexport interface UserWithPassword extends BaseUser {\n /** Bcrypt hashed password */\n passwordHash: string;\n}\n\n/**\n * User with refresh token - used for token refresh operations\n */\nexport interface UserWithRefreshToken extends BaseUser {\n /** Hashed refresh token (nullable when logged out) */\n hashedRefreshToken: string | null;\n}\n\n/**\n * Full auth user interface combining all auth-related fields\n */\nexport interface AuthUser extends BaseUser {\n passwordHash: string;\n hashedRefreshToken: string | null;\n}\n\n/**\n * Login credentials\n */\nexport interface LoginCredentials {\n email: string;\n password: string;\n}\n\n/**\n * Registration data\n */\nexport interface RegisterData {\n email: string;\n password: string;\n}\n\n/**\n * Auth state for frontend applications\n */\nexport interface AuthState<TUser extends BaseUser = BaseUser> {\n /** Current authenticated user or null */\n user: TUser | null;\n /** Current tokens or null */\n tokens: AuthTokens | null;\n /** Whether auth state is being loaded/validated */\n isLoading: boolean;\n /** Whether user is authenticated */\n isAuthenticated: boolean;\n /** Auth error if any */\n error: string | null;\n}\n\n/**\n * Token storage interface for frontend applications\n * Implement this to use different storage backends (localStorage, SecureStore, etc.)\n */\nexport interface TokenStorage {\n getItem(key: string): Promise<string | null> | string | null;\n setItem(key: string, value: string): Promise<void> | void;\n removeItem(key: string): Promise<void> | void;\n}\n\n/**\n * Auth client configuration for frontend HTTP client\n */\nexport interface AuthClientConfig {\n /** Base URL for auth API endpoints */\n baseUrl: string;\n /** Token storage implementation */\n tokenStorage: TokenStorage;\n /** Custom headers to include in requests */\n headers?: Record<string, string>;\n /** Access token storage key (default: 'lenan_access_token') */\n accessTokenKey?: string;\n /** Refresh token storage key (default: 'lenan_refresh_token') */\n refreshTokenKey?: string;\n}\n\n/**\n * Auth API endpoints configuration\n */\nexport interface AuthEndpoints {\n login: string;\n register: string;\n refresh: string;\n logout: string;\n me: string;\n}\n\n/**\n * Default auth endpoints\n */\nexport const DEFAULT_AUTH_ENDPOINTS: AuthEndpoints = {\n login: \"/auth/login\",\n register: \"/auth/register\",\n refresh: \"/auth/refresh\",\n logout: \"/auth/logout\",\n me: \"/auth/me\",\n};\n\n/**\n * Default token storage keys\n */\nexport const TOKEN_STORAGE_KEYS = {\n ACCESS_TOKEN: \"lenan_access_token\",\n REFRESH_TOKEN: \"lenan_refresh_token\",\n} as const;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACmIO,IAAM,yBAAwC;AAAA,EACnD,OAAO;AAAA,EACP,UAAU;AAAA,EACV,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,IAAI;AACN;AAKO,IAAM,qBAAqB;AAAA,EAChC,cAAc;AAAA,EACd,eAAe;AACjB;","names":[]}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT payload structure
|
|
3
|
+
*/
|
|
4
|
+
interface JwtPayload {
|
|
5
|
+
/** User ID (subject) */
|
|
6
|
+
sub: string;
|
|
7
|
+
/** User email */
|
|
8
|
+
email: string;
|
|
9
|
+
/** Issued at timestamp */
|
|
10
|
+
iat?: number;
|
|
11
|
+
/** Expiration timestamp */
|
|
12
|
+
exp?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Token response containing access and refresh tokens
|
|
16
|
+
*/
|
|
17
|
+
interface AuthTokens {
|
|
18
|
+
/** Short-lived access token */
|
|
19
|
+
accessToken: string;
|
|
20
|
+
/** Long-lived refresh token */
|
|
21
|
+
refreshToken: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Base user interface - minimal fields required by the auth system
|
|
25
|
+
* Consumers should extend this with their own user properties
|
|
26
|
+
*/
|
|
27
|
+
interface BaseUser {
|
|
28
|
+
/** Unique user identifier */
|
|
29
|
+
id: string;
|
|
30
|
+
/** User email address */
|
|
31
|
+
email: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* User with password hash - used internally for authentication
|
|
35
|
+
*/
|
|
36
|
+
interface UserWithPassword extends BaseUser {
|
|
37
|
+
/** Bcrypt hashed password */
|
|
38
|
+
passwordHash: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* User with refresh token - used for token refresh operations
|
|
42
|
+
*/
|
|
43
|
+
interface UserWithRefreshToken extends BaseUser {
|
|
44
|
+
/** Hashed refresh token (nullable when logged out) */
|
|
45
|
+
hashedRefreshToken: string | null;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Full auth user interface combining all auth-related fields
|
|
49
|
+
*/
|
|
50
|
+
interface AuthUser extends BaseUser {
|
|
51
|
+
passwordHash: string;
|
|
52
|
+
hashedRefreshToken: string | null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Login credentials
|
|
56
|
+
*/
|
|
57
|
+
interface LoginCredentials {
|
|
58
|
+
email: string;
|
|
59
|
+
password: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Registration data
|
|
63
|
+
*/
|
|
64
|
+
interface RegisterData {
|
|
65
|
+
email: string;
|
|
66
|
+
password: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Auth state for frontend applications
|
|
70
|
+
*/
|
|
71
|
+
interface AuthState<TUser extends BaseUser = BaseUser> {
|
|
72
|
+
/** Current authenticated user or null */
|
|
73
|
+
user: TUser | null;
|
|
74
|
+
/** Current tokens or null */
|
|
75
|
+
tokens: AuthTokens | null;
|
|
76
|
+
/** Whether auth state is being loaded/validated */
|
|
77
|
+
isLoading: boolean;
|
|
78
|
+
/** Whether user is authenticated */
|
|
79
|
+
isAuthenticated: boolean;
|
|
80
|
+
/** Auth error if any */
|
|
81
|
+
error: string | null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Token storage interface for frontend applications
|
|
85
|
+
* Implement this to use different storage backends (localStorage, SecureStore, etc.)
|
|
86
|
+
*/
|
|
87
|
+
interface TokenStorage {
|
|
88
|
+
getItem(key: string): Promise<string | null> | string | null;
|
|
89
|
+
setItem(key: string, value: string): Promise<void> | void;
|
|
90
|
+
removeItem(key: string): Promise<void> | void;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Auth client configuration for frontend HTTP client
|
|
94
|
+
*/
|
|
95
|
+
interface AuthClientConfig {
|
|
96
|
+
/** Base URL for auth API endpoints */
|
|
97
|
+
baseUrl: string;
|
|
98
|
+
/** Token storage implementation */
|
|
99
|
+
tokenStorage: TokenStorage;
|
|
100
|
+
/** Custom headers to include in requests */
|
|
101
|
+
headers?: Record<string, string>;
|
|
102
|
+
/** Access token storage key (default: 'lenan_access_token') */
|
|
103
|
+
accessTokenKey?: string;
|
|
104
|
+
/** Refresh token storage key (default: 'lenan_refresh_token') */
|
|
105
|
+
refreshTokenKey?: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Auth API endpoints configuration
|
|
109
|
+
*/
|
|
110
|
+
interface AuthEndpoints {
|
|
111
|
+
login: string;
|
|
112
|
+
register: string;
|
|
113
|
+
refresh: string;
|
|
114
|
+
logout: string;
|
|
115
|
+
me: string;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Default auth endpoints
|
|
119
|
+
*/
|
|
120
|
+
declare const DEFAULT_AUTH_ENDPOINTS: AuthEndpoints;
|
|
121
|
+
/**
|
|
122
|
+
* Default token storage keys
|
|
123
|
+
*/
|
|
124
|
+
declare const TOKEN_STORAGE_KEYS: {
|
|
125
|
+
readonly ACCESS_TOKEN: "lenan_access_token";
|
|
126
|
+
readonly REFRESH_TOKEN: "lenan_refresh_token";
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export { type AuthClientConfig, type AuthEndpoints, type AuthState, type AuthTokens, type AuthUser, type BaseUser, DEFAULT_AUTH_ENDPOINTS, type JwtPayload, type LoginCredentials, type RegisterData, TOKEN_STORAGE_KEYS, type TokenStorage, type UserWithPassword, type UserWithRefreshToken };
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT payload structure
|
|
3
|
+
*/
|
|
4
|
+
interface JwtPayload {
|
|
5
|
+
/** User ID (subject) */
|
|
6
|
+
sub: string;
|
|
7
|
+
/** User email */
|
|
8
|
+
email: string;
|
|
9
|
+
/** Issued at timestamp */
|
|
10
|
+
iat?: number;
|
|
11
|
+
/** Expiration timestamp */
|
|
12
|
+
exp?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Token response containing access and refresh tokens
|
|
16
|
+
*/
|
|
17
|
+
interface AuthTokens {
|
|
18
|
+
/** Short-lived access token */
|
|
19
|
+
accessToken: string;
|
|
20
|
+
/** Long-lived refresh token */
|
|
21
|
+
refreshToken: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Base user interface - minimal fields required by the auth system
|
|
25
|
+
* Consumers should extend this with their own user properties
|
|
26
|
+
*/
|
|
27
|
+
interface BaseUser {
|
|
28
|
+
/** Unique user identifier */
|
|
29
|
+
id: string;
|
|
30
|
+
/** User email address */
|
|
31
|
+
email: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* User with password hash - used internally for authentication
|
|
35
|
+
*/
|
|
36
|
+
interface UserWithPassword extends BaseUser {
|
|
37
|
+
/** Bcrypt hashed password */
|
|
38
|
+
passwordHash: string;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* User with refresh token - used for token refresh operations
|
|
42
|
+
*/
|
|
43
|
+
interface UserWithRefreshToken extends BaseUser {
|
|
44
|
+
/** Hashed refresh token (nullable when logged out) */
|
|
45
|
+
hashedRefreshToken: string | null;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Full auth user interface combining all auth-related fields
|
|
49
|
+
*/
|
|
50
|
+
interface AuthUser extends BaseUser {
|
|
51
|
+
passwordHash: string;
|
|
52
|
+
hashedRefreshToken: string | null;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Login credentials
|
|
56
|
+
*/
|
|
57
|
+
interface LoginCredentials {
|
|
58
|
+
email: string;
|
|
59
|
+
password: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Registration data
|
|
63
|
+
*/
|
|
64
|
+
interface RegisterData {
|
|
65
|
+
email: string;
|
|
66
|
+
password: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Auth state for frontend applications
|
|
70
|
+
*/
|
|
71
|
+
interface AuthState<TUser extends BaseUser = BaseUser> {
|
|
72
|
+
/** Current authenticated user or null */
|
|
73
|
+
user: TUser | null;
|
|
74
|
+
/** Current tokens or null */
|
|
75
|
+
tokens: AuthTokens | null;
|
|
76
|
+
/** Whether auth state is being loaded/validated */
|
|
77
|
+
isLoading: boolean;
|
|
78
|
+
/** Whether user is authenticated */
|
|
79
|
+
isAuthenticated: boolean;
|
|
80
|
+
/** Auth error if any */
|
|
81
|
+
error: string | null;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Token storage interface for frontend applications
|
|
85
|
+
* Implement this to use different storage backends (localStorage, SecureStore, etc.)
|
|
86
|
+
*/
|
|
87
|
+
interface TokenStorage {
|
|
88
|
+
getItem(key: string): Promise<string | null> | string | null;
|
|
89
|
+
setItem(key: string, value: string): Promise<void> | void;
|
|
90
|
+
removeItem(key: string): Promise<void> | void;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Auth client configuration for frontend HTTP client
|
|
94
|
+
*/
|
|
95
|
+
interface AuthClientConfig {
|
|
96
|
+
/** Base URL for auth API endpoints */
|
|
97
|
+
baseUrl: string;
|
|
98
|
+
/** Token storage implementation */
|
|
99
|
+
tokenStorage: TokenStorage;
|
|
100
|
+
/** Custom headers to include in requests */
|
|
101
|
+
headers?: Record<string, string>;
|
|
102
|
+
/** Access token storage key (default: 'lenan_access_token') */
|
|
103
|
+
accessTokenKey?: string;
|
|
104
|
+
/** Refresh token storage key (default: 'lenan_refresh_token') */
|
|
105
|
+
refreshTokenKey?: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Auth API endpoints configuration
|
|
109
|
+
*/
|
|
110
|
+
interface AuthEndpoints {
|
|
111
|
+
login: string;
|
|
112
|
+
register: string;
|
|
113
|
+
refresh: string;
|
|
114
|
+
logout: string;
|
|
115
|
+
me: string;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Default auth endpoints
|
|
119
|
+
*/
|
|
120
|
+
declare const DEFAULT_AUTH_ENDPOINTS: AuthEndpoints;
|
|
121
|
+
/**
|
|
122
|
+
* Default token storage keys
|
|
123
|
+
*/
|
|
124
|
+
declare const TOKEN_STORAGE_KEYS: {
|
|
125
|
+
readonly ACCESS_TOKEN: "lenan_access_token";
|
|
126
|
+
readonly REFRESH_TOKEN: "lenan_refresh_token";
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export { type AuthClientConfig, type AuthEndpoints, type AuthState, type AuthTokens, type AuthUser, type BaseUser, DEFAULT_AUTH_ENDPOINTS, type JwtPayload, type LoginCredentials, type RegisterData, TOKEN_STORAGE_KEYS, type TokenStorage, type UserWithPassword, type UserWithRefreshToken };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// src/shared/types.ts
|
|
2
|
+
var DEFAULT_AUTH_ENDPOINTS = {
|
|
3
|
+
login: "/auth/login",
|
|
4
|
+
register: "/auth/register",
|
|
5
|
+
refresh: "/auth/refresh",
|
|
6
|
+
logout: "/auth/logout",
|
|
7
|
+
me: "/auth/me"
|
|
8
|
+
};
|
|
9
|
+
var TOKEN_STORAGE_KEYS = {
|
|
10
|
+
ACCESS_TOKEN: "lenan_access_token",
|
|
11
|
+
REFRESH_TOKEN: "lenan_refresh_token"
|
|
12
|
+
};
|
|
13
|
+
export {
|
|
14
|
+
DEFAULT_AUTH_ENDPOINTS,
|
|
15
|
+
TOKEN_STORAGE_KEYS
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/shared/types.ts"],"sourcesContent":["/**\n * JWT payload structure\n */\nexport interface JwtPayload {\n /** User ID (subject) */\n sub: string;\n /** User email */\n email: string;\n /** Issued at timestamp */\n iat?: number;\n /** Expiration timestamp */\n exp?: number;\n}\n\n/**\n * Token response containing access and refresh tokens\n */\nexport interface AuthTokens {\n /** Short-lived access token */\n accessToken: string;\n /** Long-lived refresh token */\n refreshToken: string;\n}\n\n/**\n * Base user interface - minimal fields required by the auth system\n * Consumers should extend this with their own user properties\n */\nexport interface BaseUser {\n /** Unique user identifier */\n id: string;\n /** User email address */\n email: string;\n}\n\n/**\n * User with password hash - used internally for authentication\n */\nexport interface UserWithPassword extends BaseUser {\n /** Bcrypt hashed password */\n passwordHash: string;\n}\n\n/**\n * User with refresh token - used for token refresh operations\n */\nexport interface UserWithRefreshToken extends BaseUser {\n /** Hashed refresh token (nullable when logged out) */\n hashedRefreshToken: string | null;\n}\n\n/**\n * Full auth user interface combining all auth-related fields\n */\nexport interface AuthUser extends BaseUser {\n passwordHash: string;\n hashedRefreshToken: string | null;\n}\n\n/**\n * Login credentials\n */\nexport interface LoginCredentials {\n email: string;\n password: string;\n}\n\n/**\n * Registration data\n */\nexport interface RegisterData {\n email: string;\n password: string;\n}\n\n/**\n * Auth state for frontend applications\n */\nexport interface AuthState<TUser extends BaseUser = BaseUser> {\n /** Current authenticated user or null */\n user: TUser | null;\n /** Current tokens or null */\n tokens: AuthTokens | null;\n /** Whether auth state is being loaded/validated */\n isLoading: boolean;\n /** Whether user is authenticated */\n isAuthenticated: boolean;\n /** Auth error if any */\n error: string | null;\n}\n\n/**\n * Token storage interface for frontend applications\n * Implement this to use different storage backends (localStorage, SecureStore, etc.)\n */\nexport interface TokenStorage {\n getItem(key: string): Promise<string | null> | string | null;\n setItem(key: string, value: string): Promise<void> | void;\n removeItem(key: string): Promise<void> | void;\n}\n\n/**\n * Auth client configuration for frontend HTTP client\n */\nexport interface AuthClientConfig {\n /** Base URL for auth API endpoints */\n baseUrl: string;\n /** Token storage implementation */\n tokenStorage: TokenStorage;\n /** Custom headers to include in requests */\n headers?: Record<string, string>;\n /** Access token storage key (default: 'lenan_access_token') */\n accessTokenKey?: string;\n /** Refresh token storage key (default: 'lenan_refresh_token') */\n refreshTokenKey?: string;\n}\n\n/**\n * Auth API endpoints configuration\n */\nexport interface AuthEndpoints {\n login: string;\n register: string;\n refresh: string;\n logout: string;\n me: string;\n}\n\n/**\n * Default auth endpoints\n */\nexport const DEFAULT_AUTH_ENDPOINTS: AuthEndpoints = {\n login: \"/auth/login\",\n register: \"/auth/register\",\n refresh: \"/auth/refresh\",\n logout: \"/auth/logout\",\n me: \"/auth/me\",\n};\n\n/**\n * Default token storage keys\n */\nexport const TOKEN_STORAGE_KEYS = {\n ACCESS_TOKEN: \"lenan_access_token\",\n REFRESH_TOKEN: \"lenan_refresh_token\",\n} as const;\n"],"mappings":";AAmIO,IAAM,yBAAwC;AAAA,EACnD,OAAO;AAAA,EACP,UAAU;AAAA,EACV,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,IAAI;AACN;AAKO,IAAM,qBAAqB;AAAA,EAChC,cAAc;AAAA,EACd,eAAe;AACjB;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@lenan-soft/auth",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Reusable JWT authentication library for NestJS and React/React Native",
|
|
5
|
+
"author": "Simon Gatenby",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.cjs"
|
|
16
|
+
},
|
|
17
|
+
"./nestjs": {
|
|
18
|
+
"types": "./dist/nestjs/index.d.ts",
|
|
19
|
+
"import": "./dist/nestjs/index.js",
|
|
20
|
+
"require": "./dist/nestjs/index.cjs"
|
|
21
|
+
},
|
|
22
|
+
"./react": {
|
|
23
|
+
"types": "./dist/react/index.d.ts",
|
|
24
|
+
"import": "./dist/react/index.js",
|
|
25
|
+
"require": "./dist/react/index.cjs"
|
|
26
|
+
},
|
|
27
|
+
"./react/native": {
|
|
28
|
+
"types": "./dist/react/native/index.d.ts",
|
|
29
|
+
"import": "./dist/react/native/index.js",
|
|
30
|
+
"require": "./dist/react/native/index.cjs"
|
|
31
|
+
},
|
|
32
|
+
"./shared": {
|
|
33
|
+
"types": "./dist/shared/index.d.ts",
|
|
34
|
+
"import": "./dist/shared/index.js",
|
|
35
|
+
"require": "./dist/shared/index.cjs"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"README.md"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsup",
|
|
44
|
+
"dev": "tsup --watch",
|
|
45
|
+
"test": "jest",
|
|
46
|
+
"test:watch": "jest --watch",
|
|
47
|
+
"test:coverage": "jest --coverage",
|
|
48
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
49
|
+
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
|
50
|
+
"clean": "rm -rf dist",
|
|
51
|
+
"prepublishOnly": "npm run clean && npm run build && npm run test"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"bcryptjs": "^2.4.3",
|
|
55
|
+
"tslib": "^2.6.2"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@nestjs/common": "^11.0.0",
|
|
59
|
+
"@nestjs/core": "^11.0.0",
|
|
60
|
+
"@nestjs/jwt": "^11.0.0",
|
|
61
|
+
"@nestjs/passport": "^11.0.0",
|
|
62
|
+
"@nestjs/testing": "^11.0.0",
|
|
63
|
+
"@testing-library/react": "^14.0.0",
|
|
64
|
+
"@types/bcryptjs": "^2.4.6",
|
|
65
|
+
"@types/jest": "^29.5.12",
|
|
66
|
+
"@types/node": "^22.0.0",
|
|
67
|
+
"@types/passport-jwt": "^4.0.1",
|
|
68
|
+
"@types/react": "^18.3.0",
|
|
69
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
70
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
71
|
+
"class-transformer": "^0.5.1",
|
|
72
|
+
"class-validator": "^0.14.1",
|
|
73
|
+
"eslint": "^9.0.0",
|
|
74
|
+
"expo-secure-store": "^14.0.0",
|
|
75
|
+
"jest": "^29.7.0",
|
|
76
|
+
"passport": "^0.7.0",
|
|
77
|
+
"passport-jwt": "^4.0.1",
|
|
78
|
+
"react": "^18.3.0",
|
|
79
|
+
"reflect-metadata": "^0.2.2",
|
|
80
|
+
"rxjs": "^7.8.1",
|
|
81
|
+
"ts-jest": "^29.1.2",
|
|
82
|
+
"ts-node": "^10.9.2",
|
|
83
|
+
"tsup": "^8.0.2",
|
|
84
|
+
"typescript": "^5.4.0"
|
|
85
|
+
},
|
|
86
|
+
"peerDependencies": {
|
|
87
|
+
"@nestjs/common": ">=10.0.0",
|
|
88
|
+
"@nestjs/core": ">=10.0.0",
|
|
89
|
+
"@nestjs/jwt": ">=10.0.0",
|
|
90
|
+
"@nestjs/passport": ">=10.0.0",
|
|
91
|
+
"class-transformer": ">=0.5.0",
|
|
92
|
+
"class-validator": ">=0.14.0",
|
|
93
|
+
"expo-secure-store": ">=13.0.0",
|
|
94
|
+
"passport": ">=0.6.0",
|
|
95
|
+
"passport-jwt": ">=4.0.0",
|
|
96
|
+
"react": ">=17.0.0",
|
|
97
|
+
"reflect-metadata": ">=0.1.0"
|
|
98
|
+
},
|
|
99
|
+
"peerDependenciesMeta": {
|
|
100
|
+
"@nestjs/common": {
|
|
101
|
+
"optional": true
|
|
102
|
+
},
|
|
103
|
+
"@nestjs/core": {
|
|
104
|
+
"optional": true
|
|
105
|
+
},
|
|
106
|
+
"@nestjs/jwt": {
|
|
107
|
+
"optional": true
|
|
108
|
+
},
|
|
109
|
+
"@nestjs/passport": {
|
|
110
|
+
"optional": true
|
|
111
|
+
},
|
|
112
|
+
"class-transformer": {
|
|
113
|
+
"optional": true
|
|
114
|
+
},
|
|
115
|
+
"class-validator": {
|
|
116
|
+
"optional": true
|
|
117
|
+
},
|
|
118
|
+
"expo-secure-store": {
|
|
119
|
+
"optional": true
|
|
120
|
+
},
|
|
121
|
+
"passport": {
|
|
122
|
+
"optional": true
|
|
123
|
+
},
|
|
124
|
+
"passport-jwt": {
|
|
125
|
+
"optional": true
|
|
126
|
+
},
|
|
127
|
+
"react": {
|
|
128
|
+
"optional": true
|
|
129
|
+
},
|
|
130
|
+
"reflect-metadata": {
|
|
131
|
+
"optional": true
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"keywords": [
|
|
135
|
+
"auth",
|
|
136
|
+
"authentication",
|
|
137
|
+
"jwt",
|
|
138
|
+
"nestjs",
|
|
139
|
+
"react",
|
|
140
|
+
"react-native",
|
|
141
|
+
"expo",
|
|
142
|
+
"refresh-token"
|
|
143
|
+
],
|
|
144
|
+
"repository": {
|
|
145
|
+
"type": "git",
|
|
146
|
+
"url": "https://github.com/simongatenby/lenan-auth.git"
|
|
147
|
+
},
|
|
148
|
+
"publishConfig": {
|
|
149
|
+
"access": "public"
|
|
150
|
+
}
|
|
151
|
+
}
|