@savant-realms/federated-auth-realm-sdk-ts-js 0.4.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 ADDED
@@ -0,0 +1,120 @@
1
+ # Federated Auth Realm TS/JS SDK
2
+
3
+ A comprehensive TypeScript/JavaScript SDK for the Federated Auth Realm, enabling easy integration of multi-app authentication and authorization.
4
+
5
+ ## Features
6
+
7
+ - **Built-in Session Management**: Handles `accessToken` and `refreshToken` automatically.
8
+ - **Axios Interceptors**: Automatically injects Bearer tokens and handles token refresh logic (401 response).
9
+ - **Universal Storage**: Support for `LocalStorage` (browser) and `MemoryStorage` (server-side).
10
+ - **Full API Coverage**: Methods for registration, login (email/Google/Facebook), profile management, and more.
11
+ - **SRWP Support**: Savant Realms Workspace Protocol discovery for realm-to-realm communication.
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install federated-auth-realm-sdk-ts-js
17
+ ```
18
+
19
+ ## Basic Usage
20
+
21
+ ### Initialization
22
+
23
+ ```typescript
24
+ import {
25
+ FederatedAuthClient,
26
+ LocalStorageProvider,
27
+ } from 'federated-auth-realm-sdk-ts-js';
28
+
29
+ const client = new FederatedAuthClient({
30
+ baseURL: 'https://api.federatedauthrealm.com/v1',
31
+ appKey: 'your-app-key',
32
+ storage: new LocalStorageProvider(), // Optional, defaults to LocalStorageProvider
33
+ onSessionExpired: () => {
34
+ // Redirect to login page
35
+ window.location.href = '/login';
36
+ },
37
+ });
38
+ ```
39
+
40
+ ### Authentication
41
+
42
+ ```typescript
43
+ // Login
44
+ const auth = await client.login({
45
+ email: 'user@example.com',
46
+ password: 'password',
47
+ });
48
+
49
+ // Check if authenticated
50
+ const isAuthenticated = await client.isAuthenticated();
51
+
52
+ // Get current user
53
+ const user = await client.getUser();
54
+
55
+ // Logout
56
+ await client.logout();
57
+ ```
58
+
59
+ ### Profile Management
60
+
61
+ ```typescript
62
+ const profile = await client.getProfile();
63
+
64
+ await client.updateProfile({
65
+ name: 'Updated Name',
66
+ metadata: { theme: 'dark' },
67
+ });
68
+ ```
69
+
70
+ ### Token Verification (Server-side)
71
+
72
+ Back-end services can verify tokens without knowing the `JWT_SECRET` by using the realm's verification endpoint:
73
+
74
+ ```typescript
75
+ const result = await client.verifyToken('user-access-token');
76
+
77
+ if (result.valid) {
78
+ console.log('Token is valid for user:', result.user);
79
+ } else {
80
+ console.log('Token is invalid');
81
+ }
82
+ ```
83
+
84
+ ### SRWP Discovery
85
+
86
+ ```typescript
87
+ import { SRWPDiscoveryClient } from 'federated-auth-realm-sdk-ts-js';
88
+
89
+ const discovery = new SRWPDiscoveryClient(
90
+ 'https://api.federatedauthrealm.com/v1'
91
+ );
92
+
93
+ const knownRealms = await discovery.getKnownRealms();
94
+ ```
95
+
96
+ ## Advanced Storage
97
+
98
+ For server-side usage (Node.js), use `MemoryStorageProvider` or implement your own `StorageProvider`:
99
+
100
+ ```typescript
101
+ import { MemoryStorageProvider } from 'federated-auth-realm-sdk-ts-js';
102
+
103
+ const client = new FederatedAuthClient({
104
+ baseURL: '...',
105
+ appKey: '...',
106
+ storage: new MemoryStorageProvider(),
107
+ });
108
+ ```
109
+
110
+ ## Development
111
+
112
+ ```bash
113
+ npm install
114
+ npm run build
115
+ npm test
116
+ ```
117
+
118
+ ## License
119
+
120
+ MIT
@@ -0,0 +1,45 @@
1
+ import { AuthResponse, LoginRequest, RegisterRequest, GoogleAuthRequest, FacebookAuthRequest, ForgotPasswordRequest, ResetPasswordRequest, ChangePasswordRequest, RefreshTokenRequest, UpdateProfileRequest, VerifyTokenResponse, User } from './types';
2
+ import { StorageProvider } from './storage';
3
+ export interface FederatedAuthClientConfig {
4
+ baseURL: string;
5
+ appKey: string;
6
+ storage?: StorageProvider;
7
+ onSessionExpired?: () => void;
8
+ }
9
+ export declare class FederatedAuthClient {
10
+ private client;
11
+ private storage;
12
+ private appKey;
13
+ private onSessionExpired?;
14
+ private isRefreshing;
15
+ private refreshSubscribers;
16
+ constructor(config: FederatedAuthClientConfig);
17
+ private setupInterceptors;
18
+ private onRefreshed;
19
+ register(data: RegisterRequest): Promise<AuthResponse>;
20
+ login(data: LoginRequest): Promise<AuthResponse>;
21
+ loginWithGoogle(data: GoogleAuthRequest): Promise<AuthResponse>;
22
+ loginWithFacebook(data: FacebookAuthRequest): Promise<AuthResponse>;
23
+ forgotPassword(data: ForgotPasswordRequest): Promise<{
24
+ message: string;
25
+ }>;
26
+ resetPassword(data: ResetPasswordRequest): Promise<{
27
+ message: string;
28
+ }>;
29
+ changePassword(data: ChangePasswordRequest): Promise<{
30
+ message: string;
31
+ }>;
32
+ refreshToken(data: RefreshTokenRequest): Promise<AuthResponse>;
33
+ logout(): Promise<{
34
+ message: string;
35
+ }>;
36
+ logoutLocal(): Promise<void>;
37
+ getProfile(): Promise<User>;
38
+ updateProfile(data: UpdateProfileRequest): Promise<{
39
+ message: string;
40
+ }>;
41
+ verifyToken(token: string): Promise<VerifyTokenResponse>;
42
+ private setSession;
43
+ getUser(): Promise<User | null>;
44
+ isAuthenticated(): Promise<boolean>;
45
+ }
package/dist/client.js ADDED
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FederatedAuthClient = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ const storage_1 = require("./storage");
9
+ const jwt_1 = require("./utils/jwt");
10
+ class FederatedAuthClient {
11
+ constructor(config) {
12
+ this.isRefreshing = false;
13
+ this.refreshSubscribers = [];
14
+ this.appKey = config.appKey;
15
+ this.storage = config.storage || new storage_1.LocalStorageProvider();
16
+ this.onSessionExpired = config.onSessionExpired;
17
+ this.client = axios_1.default.create({
18
+ baseURL: config.baseURL,
19
+ headers: {
20
+ 'Content-Type': 'application/json',
21
+ },
22
+ });
23
+ this.setupInterceptors();
24
+ }
25
+ setupInterceptors() {
26
+ this.client.interceptors.request.use(async (config) => {
27
+ const token = await this.storage.getItem('accessToken');
28
+ if (token) {
29
+ config.headers.Authorization = `Bearer ${token}`;
30
+ }
31
+ return config;
32
+ }, error => Promise.reject(error));
33
+ this.client.interceptors.response.use(response => response, async (error) => {
34
+ const originalRequest = error.config;
35
+ if (error.response?.status === 401 && !originalRequest._retry) {
36
+ if (originalRequest.url?.includes('/auth/login') ||
37
+ originalRequest.url?.includes('/auth/register') ||
38
+ originalRequest.url?.includes('/auth/refresh')) {
39
+ return Promise.reject(error);
40
+ }
41
+ if (this.isRefreshing) {
42
+ return new Promise(resolve => {
43
+ this.refreshSubscribers.push((token) => {
44
+ originalRequest.headers.Authorization = `Bearer ${token}`;
45
+ resolve(this.client(originalRequest));
46
+ });
47
+ });
48
+ }
49
+ originalRequest._retry = true;
50
+ this.isRefreshing = true;
51
+ try {
52
+ const refreshToken = await this.storage.getItem('refreshToken');
53
+ if (!refreshToken) {
54
+ throw new Error('No refresh token available');
55
+ }
56
+ const response = await this.refreshToken({ refreshToken });
57
+ const { accessToken, refreshToken: newRefreshToken } = response;
58
+ await this.storage.setItem('accessToken', accessToken);
59
+ await this.storage.setItem('refreshToken', newRefreshToken);
60
+ this.onRefreshed(accessToken);
61
+ originalRequest.headers.Authorization = `Bearer ${accessToken}`;
62
+ return this.client(originalRequest);
63
+ }
64
+ catch (refreshError) {
65
+ await this.logoutLocal();
66
+ if (this.onSessionExpired) {
67
+ this.onSessionExpired();
68
+ }
69
+ return Promise.reject(refreshError);
70
+ }
71
+ finally {
72
+ this.isRefreshing = false;
73
+ }
74
+ }
75
+ return Promise.reject(error);
76
+ });
77
+ }
78
+ onRefreshed(token) {
79
+ this.refreshSubscribers.forEach(callback => callback(token));
80
+ this.refreshSubscribers = [];
81
+ }
82
+ // Auth Methods
83
+ async register(data) {
84
+ const response = await this.client.post('/auth/register', {
85
+ ...data,
86
+ appKey: this.appKey,
87
+ });
88
+ await this.setSession(response.data);
89
+ return response.data;
90
+ }
91
+ async login(data) {
92
+ const response = await this.client.post('/auth/login', {
93
+ ...data,
94
+ appKey: this.appKey,
95
+ });
96
+ await this.setSession(response.data);
97
+ return response.data;
98
+ }
99
+ async loginWithGoogle(data) {
100
+ const response = await this.client.post('/auth/google', {
101
+ ...data,
102
+ appKey: this.appKey,
103
+ });
104
+ await this.setSession(response.data);
105
+ return response.data;
106
+ }
107
+ async loginWithFacebook(data) {
108
+ const response = await this.client.post('/auth/facebook', {
109
+ ...data,
110
+ appKey: this.appKey,
111
+ });
112
+ await this.setSession(response.data);
113
+ return response.data;
114
+ }
115
+ async forgotPassword(data) {
116
+ const response = await this.client.post('/auth/forgot-password', {
117
+ ...data,
118
+ appKey: this.appKey,
119
+ });
120
+ return response.data;
121
+ }
122
+ async resetPassword(data) {
123
+ const response = await this.client.post('/auth/reset-password', data);
124
+ return response.data;
125
+ }
126
+ async changePassword(data) {
127
+ const response = await this.client.post('/auth/change-password', data);
128
+ return response.data;
129
+ }
130
+ async refreshToken(data) {
131
+ const response = await this.client.post('/auth/refresh', data);
132
+ return response.data;
133
+ }
134
+ async logout() {
135
+ try {
136
+ const response = await this.client.post('/auth/logout');
137
+ return response.data;
138
+ }
139
+ finally {
140
+ await this.logoutLocal();
141
+ }
142
+ }
143
+ async logoutLocal() {
144
+ await this.storage.removeItem('accessToken');
145
+ await this.storage.removeItem('refreshToken');
146
+ await this.storage.removeItem('user');
147
+ }
148
+ async getProfile() {
149
+ const response = await this.client.get('/auth/profile');
150
+ return response.data;
151
+ }
152
+ async updateProfile(data) {
153
+ const response = await this.client.put('/auth/profile', data);
154
+ return response.data;
155
+ }
156
+ async verifyToken(token) {
157
+ const response = await this.client.post('/auth/verify', { token });
158
+ return response.data;
159
+ }
160
+ // Session management
161
+ async setSession(auth) {
162
+ if (auth.accessToken) {
163
+ await this.storage.setItem('accessToken', auth.accessToken);
164
+ }
165
+ if (auth.refreshToken) {
166
+ await this.storage.setItem('refreshToken', auth.refreshToken);
167
+ }
168
+ if (auth.user) {
169
+ await this.storage.setItem('user', JSON.stringify(auth.user));
170
+ }
171
+ }
172
+ async getUser() {
173
+ const userStr = await this.storage.getItem('user');
174
+ if (userStr) {
175
+ try {
176
+ return JSON.parse(userStr);
177
+ }
178
+ catch {
179
+ return null;
180
+ }
181
+ }
182
+ return null;
183
+ }
184
+ async isAuthenticated() {
185
+ const token = await this.storage.getItem('accessToken');
186
+ if (!token)
187
+ return false;
188
+ return !jwt_1.JwtUtils.isExpired(token);
189
+ }
190
+ }
191
+ exports.FederatedAuthClient = FederatedAuthClient;
@@ -0,0 +1,23 @@
1
+ export interface RealmInfo {
2
+ id: string;
3
+ url: string;
4
+ status: string;
5
+ lastSeen: number;
6
+ }
7
+ export interface SRWPWhisperRequest {
8
+ sourceRealm: string;
9
+ sourceUrl: string;
10
+ timestamp: number;
11
+ knownRealms: RealmInfo[];
12
+ }
13
+ export declare class SRWPDiscoveryClient {
14
+ private client;
15
+ constructor(baseURL: string);
16
+ whisper(data: SRWPWhisperRequest): Promise<{
17
+ message: string;
18
+ }>;
19
+ getKnownRealms(): Promise<RealmInfo[]>;
20
+ bootstrap(peerUrl: string): Promise<{
21
+ message: string;
22
+ }>;
23
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SRWPDiscoveryClient = void 0;
7
+ const axios_1 = __importDefault(require("axios"));
8
+ class SRWPDiscoveryClient {
9
+ constructor(baseURL) {
10
+ this.client = axios_1.default.create({
11
+ baseURL,
12
+ headers: {
13
+ 'Content-Type': 'application/json',
14
+ },
15
+ });
16
+ }
17
+ async whisper(data) {
18
+ const response = await this.client.post('/whisper', data);
19
+ return response.data;
20
+ }
21
+ async getKnownRealms() {
22
+ const response = await this.client.get('/known');
23
+ return response.data;
24
+ }
25
+ async bootstrap(peerUrl) {
26
+ const response = await this.client.post('/bootstrap', {
27
+ peerUrl,
28
+ });
29
+ return response.data;
30
+ }
31
+ }
32
+ exports.SRWPDiscoveryClient = SRWPDiscoveryClient;
@@ -0,0 +1,5 @@
1
+ export * from './types';
2
+ export * from './storage';
3
+ export * from './client';
4
+ export * from './discovery';
5
+ export * from './utils/jwt';
package/dist/index.js ADDED
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./storage"), exports);
19
+ __exportStar(require("./client"), exports);
20
+ __exportStar(require("./discovery"), exports);
21
+ __exportStar(require("./utils/jwt"), exports);
@@ -0,0 +1,16 @@
1
+ export interface StorageProvider {
2
+ getItem(key: string): string | null | Promise<string | null>;
3
+ setItem(key: string, value: string): void | Promise<void>;
4
+ removeItem(key: string): void | Promise<void>;
5
+ }
6
+ export declare class LocalStorageProvider implements StorageProvider {
7
+ getItem(key: string): string | null;
8
+ setItem(key: string, value: string): void;
9
+ removeItem(key: string): void;
10
+ }
11
+ export declare class MemoryStorageProvider implements StorageProvider {
12
+ private storage;
13
+ getItem(key: string): string | null;
14
+ setItem(key: string, value: string): void;
15
+ removeItem(key: string): void;
16
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MemoryStorageProvider = exports.LocalStorageProvider = void 0;
4
+ class LocalStorageProvider {
5
+ getItem(key) {
6
+ if (typeof window !== 'undefined' && window.localStorage) {
7
+ return localStorage.getItem(key);
8
+ }
9
+ return null;
10
+ }
11
+ setItem(key, value) {
12
+ if (typeof window !== 'undefined' && window.localStorage) {
13
+ localStorage.setItem(key, value);
14
+ }
15
+ }
16
+ removeItem(key) {
17
+ if (typeof window !== 'undefined' && window.localStorage) {
18
+ localStorage.removeItem(key);
19
+ }
20
+ }
21
+ }
22
+ exports.LocalStorageProvider = LocalStorageProvider;
23
+ class MemoryStorageProvider {
24
+ constructor() {
25
+ this.storage = new Map();
26
+ }
27
+ getItem(key) {
28
+ return this.storage.get(key) || null;
29
+ }
30
+ setItem(key, value) {
31
+ this.storage.set(key, value);
32
+ }
33
+ removeItem(key) {
34
+ this.storage.delete(key);
35
+ }
36
+ }
37
+ exports.MemoryStorageProvider = MemoryStorageProvider;
@@ -0,0 +1,272 @@
1
+ export declare enum UserType {
2
+ SUPERADMIN = "SUPERADMIN",
3
+ MANAGER = "MANAGER",
4
+ EMPLOYEE = "EMPLOYEE",
5
+ CLIENT_USER = "CLIENT_USER",
6
+ GUEST_USER = "GUEST_USER"
7
+ }
8
+ export declare enum Gender {
9
+ MALE = "MALE",
10
+ FEMALE = "FEMALE",
11
+ OTHER = "OTHER"
12
+ }
13
+ export interface PhoneNumber {
14
+ internationalPrefix: string;
15
+ number: string;
16
+ fullNumber: string;
17
+ type?: 'MOBILE' | 'WORK_PHONE' | 'HOME_PHONE';
18
+ isPrimary: boolean;
19
+ isActive: boolean;
20
+ }
21
+ export interface Address {
22
+ inline: string;
23
+ structured: {
24
+ street: string | null;
25
+ secondaryStreet?: string | null;
26
+ civicNumber: string | null;
27
+ townCity: string;
28
+ provinceState: string;
29
+ provinceStateShortForm?: string;
30
+ postalCode: string;
31
+ country: string;
32
+ countryISO: string;
33
+ notes?: string;
34
+ };
35
+ type?: 'HOME' | 'WORK' | 'OTHER';
36
+ isPrimary: boolean | null;
37
+ isActive: boolean | null;
38
+ }
39
+ export interface Link {
40
+ url: string;
41
+ isPrimary: boolean;
42
+ isActive: boolean;
43
+ }
44
+ export interface ProfilePhoto {
45
+ url: string;
46
+ uploadDate: string;
47
+ exifData?: Record<string, unknown>;
48
+ isAvatar: boolean;
49
+ }
50
+ export interface EmergencyContact {
51
+ name: string;
52
+ surname: string;
53
+ email: string;
54
+ phone: PhoneNumber;
55
+ address?: Address;
56
+ relation: 'Legally Married Spouse' | 'Partner' | 'Child' | 'Parent' | 'Sibling' | 'Relative' | 'Friend' | 'Coworker' | 'Other';
57
+ isPrimary: boolean;
58
+ }
59
+ export interface PartialDateWithYear {
60
+ year: string;
61
+ month?: string;
62
+ day?: string;
63
+ }
64
+ export interface Salary {
65
+ value: number;
66
+ currency: string;
67
+ dateFrom: PartialDateWithYear;
68
+ dateTo?: PartialDateWithYear;
69
+ }
70
+ export interface WorkFlexibleBenefit {
71
+ benefit: {
72
+ name: string;
73
+ notes?: string;
74
+ isActive: boolean;
75
+ };
76
+ benefitingFrom?: PartialDateWithYear;
77
+ benefitingTo?: PartialDateWithYear;
78
+ value?: string;
79
+ }
80
+ export interface Company {
81
+ id: string;
82
+ name: string;
83
+ headquarters?: Address;
84
+ yearOfFoundation: number;
85
+ typeOfCompany: 'Corporation' | 'LLC' | 'Partnership' | 'Sole Proprietorship' | 'Non-Profit' | 'Government' | 'Other';
86
+ industry: string;
87
+ rangeOfNumberOfEmployees: string;
88
+ website: Link;
89
+ email: string;
90
+ phoneNumber: PhoneNumber;
91
+ }
92
+ export interface Occupation {
93
+ title: string;
94
+ company?: Company;
95
+ startDate?: PartialDateWithYear;
96
+ endDate?: PartialDateWithYear;
97
+ role?: string;
98
+ workLocationType: 'Onsite' | 'Hybrid' | 'Remote';
99
+ workLocation?: Address;
100
+ contract?: 'Internal Hire' | 'Contractor/Freelancer';
101
+ timeEffort?: 'Full Time' | 'Part Time';
102
+ experienceLevel?: 'Junior' | 'Middle' | 'Senior';
103
+ managementLevel?: 'Simple Employee' | 'Middle Manager' | 'Senior Manager' | 'Officer' | 'Chief Officer' | 'CEO';
104
+ salaries?: Salary[];
105
+ benefits?: WorkFlexibleBenefit[];
106
+ }
107
+ export interface User {
108
+ id: string;
109
+ email?: string;
110
+ name?: string;
111
+ surname?: string;
112
+ userType: UserType;
113
+ gender?: Gender;
114
+ dateOfBirth?: string;
115
+ isEmailVerified: boolean;
116
+ isActive: boolean;
117
+ enabledApps: Application[];
118
+ permissions?: string[];
119
+ accessRequests?: unknown[];
120
+ phoneNumbers?: PhoneNumber[];
121
+ addresses?: Address[];
122
+ bio?: string;
123
+ profileLinks?: Link[];
124
+ occupations?: Occupation[];
125
+ profilePhotos?: ProfilePhoto[];
126
+ emergencyContacts?: EmergencyContact[];
127
+ metadata?: Record<string, unknown>;
128
+ createdAt?: string;
129
+ updatedAt?: string;
130
+ lastLoginAt?: string;
131
+ }
132
+ export declare enum ApplicationStatus {
133
+ ACTIVE = "ACTIVE",
134
+ TEMPORARILY_INACTIVE = "TEMPORARILY_INACTIVE",
135
+ SHADOW_DELETED = "SHADOW_DELETED"
136
+ }
137
+ export declare enum PlatformType {
138
+ API = "API",
139
+ UI = "UI",
140
+ DB = "DB",
141
+ SERVICE = "SERVICE",
142
+ OTHER = "OTHER"
143
+ }
144
+ export declare enum UIPlatformSubtype {
145
+ UI_WEB = "UI_WEB",
146
+ UI_MOBILE_ANDROID = "UI_MOBILE_ANDROID",
147
+ UI_MOBILE_IOS = "UI_MOBILE_IOS",
148
+ UI_OTHER = "UI_OTHER"
149
+ }
150
+ export interface PlatformUrl {
151
+ id: string;
152
+ value: string;
153
+ name: string;
154
+ description?: string;
155
+ isPrimary: boolean;
156
+ isRedirect: boolean;
157
+ isActive: boolean;
158
+ createdAt: string;
159
+ updatedAt: string;
160
+ }
161
+ export interface Platform {
162
+ id: string;
163
+ type: PlatformType;
164
+ name: string;
165
+ environment: 'development' | 'staging' | 'production';
166
+ subtype?: UIPlatformSubtype;
167
+ urls: PlatformUrl[];
168
+ isActive: boolean;
169
+ createdAt: string;
170
+ updatedAt: string;
171
+ }
172
+ export interface Application {
173
+ id: string;
174
+ appKey: string;
175
+ slug?: string;
176
+ name: string;
177
+ logo?: string;
178
+ description?: string;
179
+ status?: ApplicationStatus;
180
+ managerId?: string;
181
+ isPublic?: boolean;
182
+ platforms?: Platform[];
183
+ config?: Record<string, unknown>;
184
+ createdAt?: string;
185
+ updatedAt?: string;
186
+ }
187
+ export interface AuthResponse {
188
+ accessToken: string;
189
+ refreshToken: string;
190
+ expiresIn: number;
191
+ user?: User;
192
+ action?: 'account_created' | 'guest_user_transformed' | 'access_granted' | 'access_requested' | 'already_has_access' | 'account_exists';
193
+ message?: string;
194
+ }
195
+ export interface LoginRequest {
196
+ email?: string;
197
+ id?: string;
198
+ password?: string;
199
+ appKey: string;
200
+ rememberMe?: boolean;
201
+ }
202
+ export interface RegisterRequest {
203
+ email?: string;
204
+ password?: string;
205
+ name?: string;
206
+ surname?: string;
207
+ appKey: string;
208
+ gender?: Gender;
209
+ dateOfBirth?: string;
210
+ phoneNumbers?: PhoneNumber[];
211
+ addresses?: Address[];
212
+ bio?: string;
213
+ profileLinks?: Link[];
214
+ occupations?: Occupation[];
215
+ profilePhotos?: ProfilePhoto[];
216
+ emergencyContacts?: EmergencyContact[];
217
+ metadata?: Record<string, unknown>;
218
+ }
219
+ export interface GoogleAuthRequest {
220
+ googleToken: string;
221
+ appKey: string;
222
+ }
223
+ export interface FacebookAuthRequest {
224
+ facebookToken: string;
225
+ appKey: string;
226
+ }
227
+ export interface ForgotPasswordRequest {
228
+ email: string;
229
+ appKey?: string;
230
+ }
231
+ export interface ResetPasswordRequest {
232
+ token: string;
233
+ password?: string;
234
+ confirmPassword?: string;
235
+ }
236
+ export interface ChangePasswordRequest {
237
+ currentPassword?: string;
238
+ newPassword?: string;
239
+ confirmPassword?: string;
240
+ }
241
+ export interface RefreshTokenRequest {
242
+ refreshToken: string;
243
+ }
244
+ export interface UpdateProfileRequest {
245
+ name?: string;
246
+ surname?: string;
247
+ gender?: Gender;
248
+ dateOfBirth?: string;
249
+ phoneNumbers?: PhoneNumber[];
250
+ addresses?: Address[];
251
+ bio?: string;
252
+ profileLinks?: Link[];
253
+ occupations?: Occupation[];
254
+ profilePhotos?: ProfilePhoto[];
255
+ emergencyContacts?: EmergencyContact[];
256
+ metadata?: Record<string, unknown>;
257
+ }
258
+ export interface VerifyTokenRequest {
259
+ token: string;
260
+ }
261
+ export interface VerifyTokenResponse {
262
+ valid: boolean;
263
+ user: User | null;
264
+ }
265
+ export interface TokenPayload {
266
+ sub: string;
267
+ email: string;
268
+ userType: UserType;
269
+ appKey?: string;
270
+ iat: number;
271
+ exp: number;
272
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UIPlatformSubtype = exports.PlatformType = exports.ApplicationStatus = exports.Gender = exports.UserType = void 0;
4
+ var UserType;
5
+ (function (UserType) {
6
+ UserType["SUPERADMIN"] = "SUPERADMIN";
7
+ UserType["MANAGER"] = "MANAGER";
8
+ UserType["EMPLOYEE"] = "EMPLOYEE";
9
+ UserType["CLIENT_USER"] = "CLIENT_USER";
10
+ UserType["GUEST_USER"] = "GUEST_USER";
11
+ })(UserType || (exports.UserType = UserType = {}));
12
+ var Gender;
13
+ (function (Gender) {
14
+ Gender["MALE"] = "MALE";
15
+ Gender["FEMALE"] = "FEMALE";
16
+ Gender["OTHER"] = "OTHER";
17
+ })(Gender || (exports.Gender = Gender = {}));
18
+ var ApplicationStatus;
19
+ (function (ApplicationStatus) {
20
+ ApplicationStatus["ACTIVE"] = "ACTIVE";
21
+ ApplicationStatus["TEMPORARILY_INACTIVE"] = "TEMPORARILY_INACTIVE";
22
+ ApplicationStatus["SHADOW_DELETED"] = "SHADOW_DELETED";
23
+ })(ApplicationStatus || (exports.ApplicationStatus = ApplicationStatus = {}));
24
+ var PlatformType;
25
+ (function (PlatformType) {
26
+ PlatformType["API"] = "API";
27
+ PlatformType["UI"] = "UI";
28
+ PlatformType["DB"] = "DB";
29
+ PlatformType["SERVICE"] = "SERVICE";
30
+ PlatformType["OTHER"] = "OTHER";
31
+ })(PlatformType || (exports.PlatformType = PlatformType = {}));
32
+ var UIPlatformSubtype;
33
+ (function (UIPlatformSubtype) {
34
+ UIPlatformSubtype["UI_WEB"] = "UI_WEB";
35
+ UIPlatformSubtype["UI_MOBILE_ANDROID"] = "UI_MOBILE_ANDROID";
36
+ UIPlatformSubtype["UI_MOBILE_IOS"] = "UI_MOBILE_IOS";
37
+ UIPlatformSubtype["UI_OTHER"] = "UI_OTHER";
38
+ })(UIPlatformSubtype || (exports.UIPlatformSubtype = UIPlatformSubtype = {}));
@@ -0,0 +1,5 @@
1
+ import { TokenPayload } from '../types';
2
+ export declare class JwtUtils {
3
+ static decode(token: string): TokenPayload | null;
4
+ static isExpired(token: string): boolean;
5
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.JwtUtils = void 0;
4
+ class JwtUtils {
5
+ static decode(token) {
6
+ try {
7
+ const base64Url = token.split('.')[1];
8
+ const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
9
+ const jsonPayload = decodeURIComponent(atob(base64)
10
+ .split('')
11
+ .map(function (c) {
12
+ return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
13
+ })
14
+ .join(''));
15
+ return JSON.parse(jsonPayload);
16
+ }
17
+ catch {
18
+ return null;
19
+ }
20
+ }
21
+ static isExpired(token) {
22
+ const payload = this.decode(token);
23
+ if (!payload || !payload.exp)
24
+ return true;
25
+ const currentTime = Math.floor(Date.now() / 1000);
26
+ return payload.exp < currentTime;
27
+ }
28
+ }
29
+ exports.JwtUtils = JwtUtils;
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "@savant-realms/federated-auth-realm-sdk-ts-js",
3
+ "version": "0.4.1",
4
+ "description": "Federated Auth Realm - SDK Ts/Js",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "test": "jest",
16
+ "test:watch": "jest --watch",
17
+ "prepublishOnly": "npm run build",
18
+ "deploy": "./scripts/deploy.sh",
19
+ "lint": "eslint src/**/*.ts",
20
+ "lint:fix": "eslint src/**/*.ts --fix",
21
+ "format": "prettier --write src/**/*.ts",
22
+ "format:check": "prettier --check src/**/*.ts",
23
+ "type-check": "tsc --noEmit",
24
+ "check-all": "npm run type-check && npm run lint && npm run format:check && npm run test",
25
+ "lint-staged": "lint-staged",
26
+ "prepare": "husky install"
27
+ },
28
+ "lint-staged": {
29
+ "*.ts": [
30
+ "eslint --fix",
31
+ "prettier --write"
32
+ ],
33
+ "*.{json,md}": [
34
+ "prettier --write"
35
+ ]
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "git+https://github.com/savant-realms/federated-auth-realm-sdk-ts-js.git"
40
+ },
41
+ "keywords": [],
42
+ "author": "",
43
+ "license": "ISC",
44
+ "bugs": {
45
+ "url": "https://github.com/savant-realms/federated-auth-realm-sdk-ts-js/issues"
46
+ },
47
+ "homepage": "https://github.com/savant-realms/federated-auth-realm-sdk-ts-js#readme",
48
+ "dependencies": {
49
+ "axios": "^1.13.2",
50
+ "jsonwebtoken": "^9.0.3",
51
+ "zod": "^4.3.5"
52
+ },
53
+ "devDependencies": {
54
+ "@eslint/js": "^9.39.2",
55
+ "@types/jest": "^30.0.0",
56
+ "@types/jsonwebtoken": "^9.0.10",
57
+ "@types/node": "^25.0.3",
58
+ "@typescript-eslint/eslint-plugin": "^8.52.0",
59
+ "@typescript-eslint/parser": "^8.52.0",
60
+ "eslint": "^9.39.2",
61
+ "eslint-config-prettier": "^10.1.8",
62
+ "eslint-plugin-prettier": "^5.5.4",
63
+ "globals": "^17.0.0",
64
+ "husky": "^9.1.7",
65
+ "jest": "^30.2.0",
66
+ "lint-staged": "^16.2.7",
67
+ "prettier": "^3.7.4",
68
+ "ts-jest": "^29.4.6",
69
+ "tsx": "^4.21.0",
70
+ "typescript": "^5.9.3"
71
+ }
72
+ }