@flexbe/sdk 0.1.1 → 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.
@@ -1,19 +1,19 @@
1
1
  export class Pages {
2
- constructor(client) {
3
- this.client = client;
2
+ constructor(api) {
3
+ this.api = api;
4
4
  }
5
5
  /**
6
6
  * Get list of pages for a site
7
7
  */
8
8
  async getPages(params) {
9
- const response = await this.client.sitesGet('/pages', { params });
9
+ const response = await this.api.get('/sites/:siteId:/pages', { params });
10
10
  return response.data;
11
11
  }
12
12
  /**
13
13
  * Get a single page by ID
14
14
  */
15
15
  async getPage(pageId) {
16
- const response = await this.client.sitesGet(`/pages/${pageId}`);
16
+ const response = await this.api.get(`/sites/:siteId:/pages/${pageId}`);
17
17
  return response.data;
18
18
  }
19
19
  }
@@ -0,0 +1,132 @@
1
+ const TOKEN_STORAGE_KEY = 'flexbe_jwt_token';
2
+ const REFRESH_THRESHOLD = 0.8; // Refresh when 80% of token lifetime has passed
3
+ export class TokenManager {
4
+ constructor() {
5
+ this.token = null;
6
+ this.refreshInterval = null;
7
+ this.initializeFromStorage();
8
+ this.setupStorageListener();
9
+ }
10
+ static getInstance() {
11
+ if (!TokenManager.instance) {
12
+ TokenManager.instance = new TokenManager();
13
+ }
14
+ return TokenManager.instance;
15
+ }
16
+ initializeFromStorage() {
17
+ if (typeof window !== 'undefined') {
18
+ const storedToken = localStorage.getItem(TOKEN_STORAGE_KEY);
19
+ if (storedToken) {
20
+ try {
21
+ this.token = JSON.parse(storedToken);
22
+ if (this.token.expiresAt > Date.now()) {
23
+ console.log('Reusing stored token:', {
24
+ expiresIn: `${Math.round((this.token.expiresAt - Date.now()) / 1000)} seconds`,
25
+ expiresAt: new Date(this.token.expiresAt).toISOString(),
26
+ });
27
+ this.startRefreshInterval();
28
+ }
29
+ else {
30
+ this.clearToken();
31
+ }
32
+ }
33
+ catch (error) {
34
+ console.error('Failed to parse stored token:', error);
35
+ this.clearToken();
36
+ }
37
+ }
38
+ }
39
+ }
40
+ setupStorageListener() {
41
+ if (typeof window !== 'undefined') {
42
+ window.addEventListener('storage', (event) => {
43
+ if (event.key === TOKEN_STORAGE_KEY) {
44
+ if (event.newValue) {
45
+ try {
46
+ const newToken = JSON.parse(event.newValue);
47
+ if (newToken.expiresAt > Date.now()) {
48
+ this.token = newToken;
49
+ console.log('Token updated from storage:', {
50
+ expiresIn: `${Math.round((newToken.expiresAt - Date.now()) / 1000)} seconds`,
51
+ expiresAt: new Date(newToken.expiresAt).toISOString(),
52
+ });
53
+ this.startRefreshInterval();
54
+ }
55
+ else {
56
+ this.clearToken();
57
+ }
58
+ }
59
+ catch (error) {
60
+ console.error('Failed to parse token from storage event:', error);
61
+ this.clearToken();
62
+ }
63
+ }
64
+ else {
65
+ this.clearToken();
66
+ }
67
+ }
68
+ });
69
+ }
70
+ }
71
+ getExpirationFromToken(token) {
72
+ try {
73
+ const [, payload] = token.split('.');
74
+ const decodedPayload = JSON.parse(atob(payload));
75
+ return decodedPayload.exp * 1000; // Convert to milliseconds
76
+ }
77
+ catch (error) {
78
+ console.error('Failed to parse token expiration:', error);
79
+ return Date.now() + (4 * 60 * 1000); // Default to 4 minutes if parsing fails
80
+ }
81
+ }
82
+ startRefreshInterval() {
83
+ if (this.refreshInterval) {
84
+ clearInterval(this.refreshInterval);
85
+ }
86
+ if (this.token) {
87
+ const tokenLifetime = this.token.expiresAt - (this.token.expiresAt - 4 * 60 * 1000); // 4 minutes in milliseconds
88
+ const refreshTime = Math.round(tokenLifetime * REFRESH_THRESHOLD);
89
+ console.log('Setting up token refresh:', {
90
+ tokenLifetime: `${Math.round(tokenLifetime / 1000)} seconds`,
91
+ refreshIn: `${Math.round(refreshTime / 1000)} seconds`,
92
+ refreshAt: new Date(Date.now() + refreshTime).toISOString(),
93
+ });
94
+ this.refreshInterval = window.setInterval(() => {
95
+ this.clearToken();
96
+ }, refreshTime);
97
+ }
98
+ }
99
+ setToken(tokenResponse) {
100
+ const expiresAt = this.getExpirationFromToken(tokenResponse.accessToken);
101
+ this.token = {
102
+ accessToken: tokenResponse.accessToken,
103
+ expiresAt,
104
+ };
105
+ const expiresIn = Math.round((expiresAt - Date.now()) / 1000);
106
+ console.log('New access token obtained:', {
107
+ expiresIn: `${expiresIn} seconds`,
108
+ expiresAt: new Date(expiresAt).toISOString(),
109
+ });
110
+ if (typeof window !== 'undefined') {
111
+ localStorage.setItem(TOKEN_STORAGE_KEY, JSON.stringify(this.token));
112
+ }
113
+ this.startRefreshInterval();
114
+ }
115
+ getToken() {
116
+ if (this.token && this.token.expiresAt > Date.now()) {
117
+ return this.token.accessToken;
118
+ }
119
+ this.clearToken();
120
+ return null;
121
+ }
122
+ clearToken() {
123
+ this.token = null;
124
+ if (this.refreshInterval) {
125
+ clearInterval(this.refreshInterval);
126
+ this.refreshInterval = null;
127
+ }
128
+ if (typeof window !== 'undefined') {
129
+ localStorage.removeItem(TOKEN_STORAGE_KEY);
130
+ }
131
+ }
132
+ }
@@ -0,0 +1,21 @@
1
+ import { FlexbeConfig, FlexbeResponse } from '../types';
2
+ export declare class ApiClient {
3
+ private readonly config;
4
+ private readonly auth;
5
+ constructor(config: FlexbeConfig);
6
+ private replaceSiteId;
7
+ private buildUrl;
8
+ private request;
9
+ get<T>(url: string, config?: RequestInit & {
10
+ params?: Record<string, unknown>;
11
+ }): Promise<FlexbeResponse<T>>;
12
+ post<T>(url: string, data?: unknown, config?: RequestInit & {
13
+ params?: Record<string, unknown>;
14
+ }): Promise<FlexbeResponse<T>>;
15
+ put<T>(url: string, data?: unknown, config?: RequestInit & {
16
+ params?: Record<string, unknown>;
17
+ }): Promise<FlexbeResponse<T>>;
18
+ delete<T>(url: string, config?: RequestInit & {
19
+ params?: Record<string, unknown>;
20
+ }): Promise<FlexbeResponse<T>>;
21
+ }
@@ -0,0 +1,12 @@
1
+ import { FlexbeConfig } from '../types';
2
+ export declare class FlexbeAuth {
3
+ private readonly config;
4
+ private readonly tokenManager;
5
+ private initialized;
6
+ private initializing;
7
+ constructor(config: FlexbeConfig);
8
+ private initializeBearerAuth;
9
+ ensureInitialized(): Promise<void>;
10
+ getAuthHeaders(): Promise<Record<string, string>>;
11
+ isInitialized(): boolean;
12
+ }
@@ -1,26 +1,9 @@
1
- import { FlexbeConfig, FlexbeResponse } from '../types';
1
+ import { FlexbeConfig } from '../types';
2
2
  import { Pages } from './pages';
3
+ import { ApiClient } from './api-client';
3
4
  export declare class FlexbeClient {
4
5
  private readonly config;
5
6
  readonly pages: Pages;
7
+ readonly api: ApiClient;
6
8
  constructor(config?: Partial<FlexbeConfig>);
7
- private buildUrl;
8
- private request;
9
- private get;
10
- private post;
11
- private put;
12
- private delete;
13
- private getSiteUrl;
14
- sitesGet<T>(path: string, config?: RequestInit & {
15
- params?: Record<string, unknown>;
16
- }): Promise<FlexbeResponse<T>>;
17
- sitesPost<T>(path: string, data?: unknown, config?: RequestInit & {
18
- params?: Record<string, unknown>;
19
- }): Promise<FlexbeResponse<T>>;
20
- sitesPut<T>(path: string, data?: unknown, config?: RequestInit & {
21
- params?: Record<string, unknown>;
22
- }): Promise<FlexbeResponse<T>>;
23
- sitesDelete<T>(path: string, config?: RequestInit & {
24
- params?: Record<string, unknown>;
25
- }): Promise<FlexbeResponse<T>>;
26
9
  }
@@ -1,8 +1,8 @@
1
1
  import { Page, GetPagesParams, PageListResponse } from '../types/pages';
2
- import { FlexbeClient } from './client';
2
+ import { ApiClient } from './api-client';
3
3
  export declare class Pages {
4
- private readonly client;
5
- constructor(client: FlexbeClient);
4
+ private readonly api;
5
+ constructor(api: ApiClient);
6
6
  /**
7
7
  * Get list of pages for a site
8
8
  */
@@ -0,0 +1,15 @@
1
+ import { TokenResponse } from '../types';
2
+ export declare class TokenManager {
3
+ private static instance;
4
+ private token;
5
+ private refreshInterval;
6
+ private constructor();
7
+ static getInstance(): TokenManager;
8
+ private initializeFromStorage;
9
+ private setupStorageListener;
10
+ private getExpirationFromToken;
11
+ private startRefreshInterval;
12
+ setToken(tokenResponse: TokenResponse): void;
13
+ getToken(): string | null;
14
+ clearToken(): void;
15
+ }
@@ -3,6 +3,7 @@ export interface FlexbeConfig {
3
3
  baseUrl?: string;
4
4
  timeout?: number;
5
5
  siteId?: string;
6
+ authType?: FlexbeAuthType;
6
7
  }
7
8
  export interface FlexbeResponse<T> {
8
9
  data: T;
@@ -20,4 +21,11 @@ export interface FlexbeError {
20
21
  status?: number;
21
22
  details?: unknown;
22
23
  }
23
- export type FlexbeAuthType = 'apiKey' | 'bearer' | 'oauth2';
24
+ export type FlexbeAuthType = 'apiKey' | 'bearer';
25
+ export interface JwtToken {
26
+ accessToken: string;
27
+ expiresAt: number;
28
+ }
29
+ export interface TokenResponse {
30
+ accessToken: string;
31
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flexbe/sdk",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "TypeScript SDK for Flexbe API",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -18,6 +18,7 @@
18
18
  "build:esm": "tsc -p tsconfig.esm.json",
19
19
  "build:cjs": "tsc -p tsconfig.cjs.json",
20
20
  "build:browser": "tsc -p tsconfig.browser.json",
21
+ "dev": "tsc -p tsconfig.esm.json --watch",
21
22
  "test": "dotenv -e test/.env.test jest",
22
23
  "lint": "eslint src --ext .ts",
23
24
  "format": "prettier --write \"src/**/*.ts\"",