@23blocks/sdk 0.2.1 → 1.0.0
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/lib/client.js +239 -0
- package/dist/lib/client.js.map +1 -0
- package/dist/lib/sdk.js +6 -1
- package/dist/lib/sdk.js.map +1 -1
- package/dist/lib/token-manager.js +140 -0
- package/dist/lib/token-manager.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
import { createHttpTransport } from '@23blocks/transport-http';
|
|
3
|
+
import { createAuthenticationBlock } from '@23blocks/block-authentication';
|
|
4
|
+
import { createSearchBlock } from '@23blocks/block-search';
|
|
5
|
+
import { createProductsBlock } from '@23blocks/block-products';
|
|
6
|
+
import { createCrmBlock } from '@23blocks/block-crm';
|
|
7
|
+
import { createContentBlock } from '@23blocks/block-content';
|
|
8
|
+
import { createGeolocationBlock } from '@23blocks/block-geolocation';
|
|
9
|
+
import { createConversationsBlock } from '@23blocks/block-conversations';
|
|
10
|
+
import { createFilesBlock } from '@23blocks/block-files';
|
|
11
|
+
import { createFormsBlock } from '@23blocks/block-forms';
|
|
12
|
+
import { createAssetsBlock } from '@23blocks/block-assets';
|
|
13
|
+
import { createCampaignsBlock } from '@23blocks/block-campaigns';
|
|
14
|
+
import { createCompanyBlock } from '@23blocks/block-company';
|
|
15
|
+
import { createRewardsBlock } from '@23blocks/block-rewards';
|
|
16
|
+
import { createSalesBlock } from '@23blocks/block-sales';
|
|
17
|
+
import { createWalletBlock } from '@23blocks/block-wallet';
|
|
18
|
+
import { createJarvisBlock } from '@23blocks/block-jarvis';
|
|
19
|
+
import { createOnboardingBlock } from '@23blocks/block-onboarding';
|
|
20
|
+
import { createUniversityBlock } from '@23blocks/block-university';
|
|
21
|
+
import { createTokenManager } from './token-manager.js';
|
|
22
|
+
/**
|
|
23
|
+
* Detect browser environment
|
|
24
|
+
*/ function isBrowser() {
|
|
25
|
+
return typeof window !== 'undefined' && typeof window.localStorage !== 'undefined';
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Create a 23blocks client instance
|
|
29
|
+
*
|
|
30
|
+
* @param config - Client configuration
|
|
31
|
+
* @returns A configured client with all blocks and automatic auth management
|
|
32
|
+
*
|
|
33
|
+
* @example Token mode (default)
|
|
34
|
+
* ```typescript
|
|
35
|
+
* const client = create23BlocksClient({
|
|
36
|
+
* baseUrl: 'https://api.yourapp.com',
|
|
37
|
+
* appId: 'your-app-id',
|
|
38
|
+
* });
|
|
39
|
+
*
|
|
40
|
+
* // Sign in - tokens are stored automatically
|
|
41
|
+
* await client.auth.signIn({ email: 'user@example.com', password: 'password' });
|
|
42
|
+
*
|
|
43
|
+
* // All subsequent requests include the token automatically
|
|
44
|
+
* const products = await client.products.products.list();
|
|
45
|
+
* const user = await client.auth.getCurrentUser();
|
|
46
|
+
*
|
|
47
|
+
* // Sign out - tokens are cleared automatically
|
|
48
|
+
* await client.auth.signOut();
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @example Cookie mode (recommended for new projects)
|
|
52
|
+
* ```typescript
|
|
53
|
+
* const client = create23BlocksClient({
|
|
54
|
+
* baseUrl: 'https://api.yourapp.com',
|
|
55
|
+
* appId: 'your-app-id',
|
|
56
|
+
* authMode: 'cookie',
|
|
57
|
+
* });
|
|
58
|
+
*
|
|
59
|
+
* // Sign in - backend sets httpOnly cookie
|
|
60
|
+
* await client.auth.signIn({ email: 'user@example.com', password: 'password' });
|
|
61
|
+
*
|
|
62
|
+
* // Requests automatically include cookies
|
|
63
|
+
* const products = await client.products.products.list();
|
|
64
|
+
* ```
|
|
65
|
+
*
|
|
66
|
+
* @example SSR with token forwarding
|
|
67
|
+
* ```typescript
|
|
68
|
+
* // On the server
|
|
69
|
+
* const client = create23BlocksClient({
|
|
70
|
+
* baseUrl: 'https://api.yourapp.com',
|
|
71
|
+
* appId: 'your-app-id',
|
|
72
|
+
* storage: 'memory',
|
|
73
|
+
* headers: {
|
|
74
|
+
* Authorization: `Bearer ${tokenFromRequest}`,
|
|
75
|
+
* },
|
|
76
|
+
* });
|
|
77
|
+
* ```
|
|
78
|
+
*/ export function create23BlocksClient(config) {
|
|
79
|
+
const { baseUrl, appId, tenantId, authMode = 'token', storage = isBrowser() ? 'localStorage' : 'memory', headers: staticHeaders = {}, timeout } = config;
|
|
80
|
+
// Create token manager for token mode
|
|
81
|
+
let tokenManager = null;
|
|
82
|
+
if (authMode === 'token') {
|
|
83
|
+
tokenManager = createTokenManager({
|
|
84
|
+
appId,
|
|
85
|
+
tenantId,
|
|
86
|
+
storage
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
// Create transport with appropriate auth strategy
|
|
90
|
+
const transport = createHttpTransport({
|
|
91
|
+
baseUrl,
|
|
92
|
+
timeout,
|
|
93
|
+
credentials: authMode === 'cookie' ? 'include' : undefined,
|
|
94
|
+
headers: ()=>{
|
|
95
|
+
const headers = _extends({}, staticHeaders, {
|
|
96
|
+
appid: appId
|
|
97
|
+
});
|
|
98
|
+
if (tenantId) {
|
|
99
|
+
headers['tenant-id'] = tenantId;
|
|
100
|
+
}
|
|
101
|
+
// In token mode, add Authorization header if we have a token
|
|
102
|
+
if (authMode === 'token' && tokenManager) {
|
|
103
|
+
const token = tokenManager.getAccessToken();
|
|
104
|
+
if (token) {
|
|
105
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return headers;
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
// Create all blocks
|
|
112
|
+
const blockConfig = {
|
|
113
|
+
appId,
|
|
114
|
+
tenantId
|
|
115
|
+
};
|
|
116
|
+
const authenticationBlock = createAuthenticationBlock(transport, blockConfig);
|
|
117
|
+
const searchBlock = createSearchBlock(transport, blockConfig);
|
|
118
|
+
const productsBlock = createProductsBlock(transport, blockConfig);
|
|
119
|
+
const crmBlock = createCrmBlock(transport, blockConfig);
|
|
120
|
+
const contentBlock = createContentBlock(transport, blockConfig);
|
|
121
|
+
const geolocationBlock = createGeolocationBlock(transport, blockConfig);
|
|
122
|
+
const conversationsBlock = createConversationsBlock(transport, blockConfig);
|
|
123
|
+
const filesBlock = createFilesBlock(transport, blockConfig);
|
|
124
|
+
const formsBlock = createFormsBlock(transport, blockConfig);
|
|
125
|
+
const assetsBlock = createAssetsBlock(transport, blockConfig);
|
|
126
|
+
const campaignsBlock = createCampaignsBlock(transport, blockConfig);
|
|
127
|
+
const companyBlock = createCompanyBlock(transport, blockConfig);
|
|
128
|
+
const rewardsBlock = createRewardsBlock(transport, blockConfig);
|
|
129
|
+
const salesBlock = createSalesBlock(transport, blockConfig);
|
|
130
|
+
const walletBlock = createWalletBlock(transport, blockConfig);
|
|
131
|
+
const jarvisBlock = createJarvisBlock(transport, blockConfig);
|
|
132
|
+
const onboardingBlock = createOnboardingBlock(transport, blockConfig);
|
|
133
|
+
const universityBlock = createUniversityBlock(transport, blockConfig);
|
|
134
|
+
// Create managed auth service with automatic token handling
|
|
135
|
+
const managedAuth = {
|
|
136
|
+
// Wrapped methods that handle tokens
|
|
137
|
+
async signIn (request) {
|
|
138
|
+
const response = await authenticationBlock.auth.signIn(request);
|
|
139
|
+
// In token mode, store the tokens
|
|
140
|
+
if (authMode === 'token' && tokenManager && response.accessToken) {
|
|
141
|
+
tokenManager.setTokens(response.accessToken, response.refreshToken);
|
|
142
|
+
}
|
|
143
|
+
return response;
|
|
144
|
+
},
|
|
145
|
+
async signUp (request) {
|
|
146
|
+
const response = await authenticationBlock.auth.signUp(request);
|
|
147
|
+
// Store token if returned (some flows auto-confirm)
|
|
148
|
+
if (authMode === 'token' && tokenManager && response.accessToken) {
|
|
149
|
+
tokenManager.setTokens(response.accessToken);
|
|
150
|
+
}
|
|
151
|
+
return response;
|
|
152
|
+
},
|
|
153
|
+
async signOut () {
|
|
154
|
+
await authenticationBlock.auth.signOut();
|
|
155
|
+
// Clear tokens in token mode
|
|
156
|
+
if (authMode === 'token' && tokenManager) {
|
|
157
|
+
tokenManager.clearTokens();
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
async verifyMagicLink (request) {
|
|
161
|
+
const response = await authenticationBlock.auth.verifyMagicLink(request);
|
|
162
|
+
if (authMode === 'token' && tokenManager && response.accessToken) {
|
|
163
|
+
tokenManager.setTokens(response.accessToken, response.refreshToken);
|
|
164
|
+
}
|
|
165
|
+
return response;
|
|
166
|
+
},
|
|
167
|
+
async acceptInvitation (request) {
|
|
168
|
+
const response = await authenticationBlock.auth.acceptInvitation(request);
|
|
169
|
+
if (authMode === 'token' && tokenManager && response.accessToken) {
|
|
170
|
+
tokenManager.setTokens(response.accessToken, response.refreshToken);
|
|
171
|
+
}
|
|
172
|
+
return response;
|
|
173
|
+
},
|
|
174
|
+
// Pass-through methods
|
|
175
|
+
validateToken: authenticationBlock.auth.validateToken.bind(authenticationBlock.auth),
|
|
176
|
+
getCurrentUser: authenticationBlock.auth.getCurrentUser.bind(authenticationBlock.auth),
|
|
177
|
+
requestPasswordReset: authenticationBlock.auth.requestPasswordReset.bind(authenticationBlock.auth),
|
|
178
|
+
updatePassword: authenticationBlock.auth.updatePassword.bind(authenticationBlock.auth),
|
|
179
|
+
refreshToken: authenticationBlock.auth.refreshToken.bind(authenticationBlock.auth),
|
|
180
|
+
requestMagicLink: authenticationBlock.auth.requestMagicLink.bind(authenticationBlock.auth),
|
|
181
|
+
sendInvitation: authenticationBlock.auth.sendInvitation.bind(authenticationBlock.auth),
|
|
182
|
+
confirmEmail: authenticationBlock.auth.confirmEmail.bind(authenticationBlock.auth),
|
|
183
|
+
resendConfirmation: authenticationBlock.auth.resendConfirmation.bind(authenticationBlock.auth)
|
|
184
|
+
};
|
|
185
|
+
return {
|
|
186
|
+
// Authentication with managed tokens
|
|
187
|
+
auth: managedAuth,
|
|
188
|
+
users: authenticationBlock.users,
|
|
189
|
+
roles: authenticationBlock.roles,
|
|
190
|
+
apiKeys: authenticationBlock.apiKeys,
|
|
191
|
+
authentication: authenticationBlock,
|
|
192
|
+
// All other blocks
|
|
193
|
+
search: searchBlock,
|
|
194
|
+
products: productsBlock,
|
|
195
|
+
crm: crmBlock,
|
|
196
|
+
content: contentBlock,
|
|
197
|
+
geolocation: geolocationBlock,
|
|
198
|
+
conversations: conversationsBlock,
|
|
199
|
+
files: filesBlock,
|
|
200
|
+
forms: formsBlock,
|
|
201
|
+
assets: assetsBlock,
|
|
202
|
+
campaigns: campaignsBlock,
|
|
203
|
+
company: companyBlock,
|
|
204
|
+
rewards: rewardsBlock,
|
|
205
|
+
sales: salesBlock,
|
|
206
|
+
wallet: walletBlock,
|
|
207
|
+
jarvis: jarvisBlock,
|
|
208
|
+
onboarding: onboardingBlock,
|
|
209
|
+
university: universityBlock,
|
|
210
|
+
// Utilities
|
|
211
|
+
getAccessToken () {
|
|
212
|
+
if (authMode !== 'token' || !tokenManager) return null;
|
|
213
|
+
return tokenManager.getAccessToken();
|
|
214
|
+
},
|
|
215
|
+
getRefreshToken () {
|
|
216
|
+
if (authMode !== 'token' || !tokenManager) return null;
|
|
217
|
+
return tokenManager.getRefreshToken();
|
|
218
|
+
},
|
|
219
|
+
setTokens (accessToken, refreshToken) {
|
|
220
|
+
if (authMode === 'token' && tokenManager) {
|
|
221
|
+
tokenManager.setTokens(accessToken, refreshToken);
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
clearSession () {
|
|
225
|
+
if (authMode === 'token' && tokenManager) {
|
|
226
|
+
tokenManager.clearTokens();
|
|
227
|
+
}
|
|
228
|
+
},
|
|
229
|
+
isAuthenticated () {
|
|
230
|
+
if (authMode === 'cookie') {
|
|
231
|
+
// Can't know without calling validateToken
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
return tokenManager ? !!tokenManager.getAccessToken() : false;
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/client.ts"],"sourcesContent":["import { createHttpTransport } from '@23blocks/transport-http';\nimport {\n createAuthenticationBlock,\n type AuthenticationBlock,\n type SignInRequest,\n type SignInResponse,\n type SignUpRequest,\n type SignUpResponse,\n type MagicLinkVerifyRequest,\n type AcceptInvitationRequest,\n} from '@23blocks/block-authentication';\nimport { createSearchBlock, type SearchBlock } from '@23blocks/block-search';\nimport { createProductsBlock, type ProductsBlock } from '@23blocks/block-products';\nimport { createCrmBlock, type CrmBlock } from '@23blocks/block-crm';\nimport { createContentBlock, type ContentBlock } from '@23blocks/block-content';\nimport { createGeolocationBlock, type GeolocationBlock } from '@23blocks/block-geolocation';\nimport { createConversationsBlock, type ConversationsBlock } from '@23blocks/block-conversations';\nimport { createFilesBlock, type FilesBlock } from '@23blocks/block-files';\nimport { createFormsBlock, type FormsBlock } from '@23blocks/block-forms';\nimport { createAssetsBlock, type AssetsBlock } from '@23blocks/block-assets';\nimport { createCampaignsBlock, type CampaignsBlock } from '@23blocks/block-campaigns';\nimport { createCompanyBlock, type CompanyBlock } from '@23blocks/block-company';\nimport { createRewardsBlock, type RewardsBlock } from '@23blocks/block-rewards';\nimport { createSalesBlock, type SalesBlock } from '@23blocks/block-sales';\nimport { createWalletBlock, type WalletBlock } from '@23blocks/block-wallet';\nimport { createJarvisBlock, type JarvisBlock } from '@23blocks/block-jarvis';\nimport { createOnboardingBlock, type OnboardingBlock } from '@23blocks/block-onboarding';\nimport { createUniversityBlock, type UniversityBlock } from '@23blocks/block-university';\n\nimport { createTokenManager, type StorageType, type TokenManager, type TokenManagerConfig } from './token-manager.js';\n\n/**\n * Authentication mode\n * - 'token': Store tokens in browser storage, attach Authorization header\n * - 'cookie': Use httpOnly cookies set by backend (recommended for new projects)\n */\nexport type AuthMode = 'token' | 'cookie';\n\n/**\n * Client configuration\n */\nexport interface ClientConfig {\n /**\n * Base URL for the 23blocks API\n * @example 'https://api.yourapp.com'\n */\n baseUrl: string;\n\n /**\n * Application ID\n */\n appId: string;\n\n /**\n * Tenant ID (optional, for multi-tenant setups)\n */\n tenantId?: string;\n\n /**\n * Authentication mode\n * - 'token' (default): SDK stores tokens in localStorage/sessionStorage/memory\n * - 'cookie': Backend manages auth via httpOnly cookies\n */\n authMode?: AuthMode;\n\n /**\n * Storage type for token mode\n * Only applicable when authMode is 'token'\n * @default 'localStorage' in browser, 'memory' in SSR\n */\n storage?: StorageType;\n\n /**\n * Additional headers to include with every request\n * Useful for SSR cookie forwarding\n */\n headers?: Record<string, string>;\n\n /**\n * Request timeout in milliseconds\n * @default 30000\n */\n timeout?: number;\n}\n\n/**\n * Auth service wrapper with automatic token management\n */\nexport interface ManagedAuthService extends Omit<AuthenticationBlock['auth'], 'signIn' | 'signUp' | 'signOut' | 'verifyMagicLink' | 'acceptInvitation'> {\n /**\n * Sign in and automatically store tokens (token mode) or let backend set cookies (cookie mode)\n */\n signIn(request: SignInRequest): Promise<SignInResponse>;\n\n /**\n * Sign up and optionally store tokens if returned\n */\n signUp(request: SignUpRequest): Promise<SignUpResponse>;\n\n /**\n * Sign out and clear stored tokens/session\n */\n signOut(): Promise<void>;\n\n /**\n * Verify magic link and store tokens\n */\n verifyMagicLink(request: MagicLinkVerifyRequest): Promise<SignInResponse>;\n\n /**\n * Accept invitation and store tokens\n */\n acceptInvitation(request: AcceptInvitationRequest): Promise<SignInResponse>;\n}\n\n/**\n * 23blocks client interface\n */\nexport interface Blocks23Client {\n // ─────────────────────────────────────────────────────────────────────────────\n // Blocks\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Authentication operations with automatic token management\n */\n auth: ManagedAuthService;\n\n /**\n * User management operations\n */\n users: AuthenticationBlock['users'];\n\n /**\n * Role and permission management\n */\n roles: AuthenticationBlock['roles'];\n\n /**\n * API key management\n */\n apiKeys: AuthenticationBlock['apiKeys'];\n\n /**\n * Full authentication block (advanced access)\n */\n authentication: AuthenticationBlock;\n\n /**\n * Search and favorites\n */\n search: SearchBlock;\n\n /**\n * Products, cart, and catalog\n */\n products: ProductsBlock;\n\n /**\n * CRM - contacts, organizations, deals\n */\n crm: CrmBlock;\n\n /**\n * Content management\n */\n content: ContentBlock;\n\n /**\n * Geolocation - addresses, places\n */\n geolocation: GeolocationBlock;\n\n /**\n * Messaging and conversations\n */\n conversations: ConversationsBlock;\n\n /**\n * File uploads and storage\n */\n files: FilesBlock;\n\n /**\n * Form builder and submissions\n */\n forms: FormsBlock;\n\n /**\n * Asset management\n */\n assets: AssetsBlock;\n\n /**\n * Marketing campaigns\n */\n campaigns: CampaignsBlock;\n\n /**\n * Company settings\n */\n company: CompanyBlock;\n\n /**\n * Rewards and loyalty\n */\n rewards: RewardsBlock;\n\n /**\n * Sales, orders, invoices\n */\n sales: SalesBlock;\n\n /**\n * Digital wallet\n */\n wallet: WalletBlock;\n\n /**\n * AI assistant\n */\n jarvis: JarvisBlock;\n\n /**\n * User onboarding\n */\n onboarding: OnboardingBlock;\n\n /**\n * Learning management\n */\n university: UniversityBlock;\n\n // ─────────────────────────────────────────────────────────────────────────────\n // Utilities\n // ─────────────────────────────────────────────────────────────────────────────\n\n /**\n * Get the current access token (token mode only)\n * Returns null if in cookie mode or no token stored\n */\n getAccessToken(): string | null;\n\n /**\n * Get the current refresh token (token mode only)\n * Returns null if in cookie mode or no token stored\n */\n getRefreshToken(): string | null;\n\n /**\n * Manually set tokens (token mode only)\n * Useful for SSR hydration\n */\n setTokens(accessToken: string, refreshToken?: string): void;\n\n /**\n * Clear the current session (tokens or signal backend to clear cookie)\n */\n clearSession(): void;\n\n /**\n * Check if user is likely authenticated\n * In token mode: checks if token exists\n * In cookie mode: always returns null (check with validateToken instead)\n */\n isAuthenticated(): boolean | null;\n}\n\n/**\n * Detect browser environment\n */\nfunction isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof window.localStorage !== 'undefined';\n}\n\n/**\n * Create a 23blocks client instance\n *\n * @param config - Client configuration\n * @returns A configured client with all blocks and automatic auth management\n *\n * @example Token mode (default)\n * ```typescript\n * const client = create23BlocksClient({\n * baseUrl: 'https://api.yourapp.com',\n * appId: 'your-app-id',\n * });\n *\n * // Sign in - tokens are stored automatically\n * await client.auth.signIn({ email: 'user@example.com', password: 'password' });\n *\n * // All subsequent requests include the token automatically\n * const products = await client.products.products.list();\n * const user = await client.auth.getCurrentUser();\n *\n * // Sign out - tokens are cleared automatically\n * await client.auth.signOut();\n * ```\n *\n * @example Cookie mode (recommended for new projects)\n * ```typescript\n * const client = create23BlocksClient({\n * baseUrl: 'https://api.yourapp.com',\n * appId: 'your-app-id',\n * authMode: 'cookie',\n * });\n *\n * // Sign in - backend sets httpOnly cookie\n * await client.auth.signIn({ email: 'user@example.com', password: 'password' });\n *\n * // Requests automatically include cookies\n * const products = await client.products.products.list();\n * ```\n *\n * @example SSR with token forwarding\n * ```typescript\n * // On the server\n * const client = create23BlocksClient({\n * baseUrl: 'https://api.yourapp.com',\n * appId: 'your-app-id',\n * storage: 'memory',\n * headers: {\n * Authorization: `Bearer ${tokenFromRequest}`,\n * },\n * });\n * ```\n */\nexport function create23BlocksClient(config: ClientConfig): Blocks23Client {\n const {\n baseUrl,\n appId,\n tenantId,\n authMode = 'token',\n storage = isBrowser() ? 'localStorage' : 'memory',\n headers: staticHeaders = {},\n timeout,\n } = config;\n\n // Create token manager for token mode\n let tokenManager: TokenManager | null = null;\n if (authMode === 'token') {\n tokenManager = createTokenManager({\n appId,\n tenantId,\n storage,\n });\n }\n\n // Create transport with appropriate auth strategy\n const transport = createHttpTransport({\n baseUrl,\n timeout,\n credentials: authMode === 'cookie' ? 'include' : undefined,\n headers: () => {\n const headers: Record<string, string> = {\n ...staticHeaders,\n appid: appId,\n };\n\n if (tenantId) {\n headers['tenant-id'] = tenantId;\n }\n\n // In token mode, add Authorization header if we have a token\n if (authMode === 'token' && tokenManager) {\n const token = tokenManager.getAccessToken();\n if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n }\n\n return headers;\n },\n });\n\n // Create all blocks\n const blockConfig = { appId, tenantId };\n\n const authenticationBlock = createAuthenticationBlock(transport, blockConfig);\n const searchBlock = createSearchBlock(transport, blockConfig);\n const productsBlock = createProductsBlock(transport, blockConfig);\n const crmBlock = createCrmBlock(transport, blockConfig);\n const contentBlock = createContentBlock(transport, blockConfig);\n const geolocationBlock = createGeolocationBlock(transport, blockConfig);\n const conversationsBlock = createConversationsBlock(transport, blockConfig);\n const filesBlock = createFilesBlock(transport, blockConfig);\n const formsBlock = createFormsBlock(transport, blockConfig);\n const assetsBlock = createAssetsBlock(transport, blockConfig);\n const campaignsBlock = createCampaignsBlock(transport, blockConfig);\n const companyBlock = createCompanyBlock(transport, blockConfig);\n const rewardsBlock = createRewardsBlock(transport, blockConfig);\n const salesBlock = createSalesBlock(transport, blockConfig);\n const walletBlock = createWalletBlock(transport, blockConfig);\n const jarvisBlock = createJarvisBlock(transport, blockConfig);\n const onboardingBlock = createOnboardingBlock(transport, blockConfig);\n const universityBlock = createUniversityBlock(transport, blockConfig);\n\n // Create managed auth service with automatic token handling\n const managedAuth: ManagedAuthService = {\n // Wrapped methods that handle tokens\n async signIn(request: SignInRequest): Promise<SignInResponse> {\n const response = await authenticationBlock.auth.signIn(request);\n\n // In token mode, store the tokens\n if (authMode === 'token' && tokenManager && response.accessToken) {\n tokenManager.setTokens(response.accessToken, response.refreshToken);\n }\n\n return response;\n },\n\n async signUp(request: SignUpRequest): Promise<SignUpResponse> {\n const response = await authenticationBlock.auth.signUp(request);\n\n // Store token if returned (some flows auto-confirm)\n if (authMode === 'token' && tokenManager && response.accessToken) {\n tokenManager.setTokens(response.accessToken);\n }\n\n return response;\n },\n\n async signOut(): Promise<void> {\n await authenticationBlock.auth.signOut();\n\n // Clear tokens in token mode\n if (authMode === 'token' && tokenManager) {\n tokenManager.clearTokens();\n }\n },\n\n async verifyMagicLink(request: MagicLinkVerifyRequest): Promise<SignInResponse> {\n const response = await authenticationBlock.auth.verifyMagicLink(request);\n\n if (authMode === 'token' && tokenManager && response.accessToken) {\n tokenManager.setTokens(response.accessToken, response.refreshToken);\n }\n\n return response;\n },\n\n async acceptInvitation(request: AcceptInvitationRequest): Promise<SignInResponse> {\n const response = await authenticationBlock.auth.acceptInvitation(request);\n\n if (authMode === 'token' && tokenManager && response.accessToken) {\n tokenManager.setTokens(response.accessToken, response.refreshToken);\n }\n\n return response;\n },\n\n // Pass-through methods\n validateToken: authenticationBlock.auth.validateToken.bind(authenticationBlock.auth),\n getCurrentUser: authenticationBlock.auth.getCurrentUser.bind(authenticationBlock.auth),\n requestPasswordReset: authenticationBlock.auth.requestPasswordReset.bind(authenticationBlock.auth),\n updatePassword: authenticationBlock.auth.updatePassword.bind(authenticationBlock.auth),\n refreshToken: authenticationBlock.auth.refreshToken.bind(authenticationBlock.auth),\n requestMagicLink: authenticationBlock.auth.requestMagicLink.bind(authenticationBlock.auth),\n sendInvitation: authenticationBlock.auth.sendInvitation.bind(authenticationBlock.auth),\n confirmEmail: authenticationBlock.auth.confirmEmail.bind(authenticationBlock.auth),\n resendConfirmation: authenticationBlock.auth.resendConfirmation.bind(authenticationBlock.auth),\n };\n\n return {\n // Authentication with managed tokens\n auth: managedAuth,\n users: authenticationBlock.users,\n roles: authenticationBlock.roles,\n apiKeys: authenticationBlock.apiKeys,\n authentication: authenticationBlock,\n\n // All other blocks\n search: searchBlock,\n products: productsBlock,\n crm: crmBlock,\n content: contentBlock,\n geolocation: geolocationBlock,\n conversations: conversationsBlock,\n files: filesBlock,\n forms: formsBlock,\n assets: assetsBlock,\n campaigns: campaignsBlock,\n company: companyBlock,\n rewards: rewardsBlock,\n sales: salesBlock,\n wallet: walletBlock,\n jarvis: jarvisBlock,\n onboarding: onboardingBlock,\n university: universityBlock,\n\n // Utilities\n getAccessToken(): string | null {\n if (authMode !== 'token' || !tokenManager) return null;\n return tokenManager.getAccessToken();\n },\n\n getRefreshToken(): string | null {\n if (authMode !== 'token' || !tokenManager) return null;\n return tokenManager.getRefreshToken();\n },\n\n setTokens(accessToken: string, refreshToken?: string): void {\n if (authMode === 'token' && tokenManager) {\n tokenManager.setTokens(accessToken, refreshToken);\n }\n },\n\n clearSession(): void {\n if (authMode === 'token' && tokenManager) {\n tokenManager.clearTokens();\n }\n },\n\n isAuthenticated(): boolean | null {\n if (authMode === 'cookie') {\n // Can't know without calling validateToken\n return null;\n }\n return tokenManager ? !!tokenManager.getAccessToken() : false;\n },\n };\n}\n\n// Re-export types\nexport type { StorageType, TokenManager } from './token-manager.js';\n"],"names":["createHttpTransport","createAuthenticationBlock","createSearchBlock","createProductsBlock","createCrmBlock","createContentBlock","createGeolocationBlock","createConversationsBlock","createFilesBlock","createFormsBlock","createAssetsBlock","createCampaignsBlock","createCompanyBlock","createRewardsBlock","createSalesBlock","createWalletBlock","createJarvisBlock","createOnboardingBlock","createUniversityBlock","createTokenManager","isBrowser","window","localStorage","create23BlocksClient","config","baseUrl","appId","tenantId","authMode","storage","headers","staticHeaders","timeout","tokenManager","transport","credentials","undefined","appid","token","getAccessToken","blockConfig","authenticationBlock","searchBlock","productsBlock","crmBlock","contentBlock","geolocationBlock","conversationsBlock","filesBlock","formsBlock","assetsBlock","campaignsBlock","companyBlock","rewardsBlock","salesBlock","walletBlock","jarvisBlock","onboardingBlock","universityBlock","managedAuth","signIn","request","response","auth","accessToken","setTokens","refreshToken","signUp","signOut","clearTokens","verifyMagicLink","acceptInvitation","validateToken","bind","getCurrentUser","requestPasswordReset","updatePassword","requestMagicLink","sendInvitation","confirmEmail","resendConfirmation","users","roles","apiKeys","authentication","search","products","crm","content","geolocation","conversations","files","forms","assets","campaigns","company","rewards","sales","wallet","jarvis","onboarding","university","getRefreshToken","clearSession","isAuthenticated"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":";AAAA,SAASA,mBAAmB,QAAQ,2BAA2B;AAC/D,SACEC,yBAAyB,QAQpB,iCAAiC;AACxC,SAASC,iBAAiB,QAA0B,yBAAyB;AAC7E,SAASC,mBAAmB,QAA4B,2BAA2B;AACnF,SAASC,cAAc,QAAuB,sBAAsB;AACpE,SAASC,kBAAkB,QAA2B,0BAA0B;AAChF,SAASC,sBAAsB,QAA+B,8BAA8B;AAC5F,SAASC,wBAAwB,QAAiC,gCAAgC;AAClG,SAASC,gBAAgB,QAAyB,wBAAwB;AAC1E,SAASC,gBAAgB,QAAyB,wBAAwB;AAC1E,SAASC,iBAAiB,QAA0B,yBAAyB;AAC7E,SAASC,oBAAoB,QAA6B,4BAA4B;AACtF,SAASC,kBAAkB,QAA2B,0BAA0B;AAChF,SAASC,kBAAkB,QAA2B,0BAA0B;AAChF,SAASC,gBAAgB,QAAyB,wBAAwB;AAC1E,SAASC,iBAAiB,QAA0B,yBAAyB;AAC7E,SAASC,iBAAiB,QAA0B,yBAAyB;AAC7E,SAASC,qBAAqB,QAA8B,6BAA6B;AACzF,SAASC,qBAAqB,QAA8B,6BAA6B;AAEzF,SAASC,kBAAkB,QAAsE,qBAAqB;AA+OtH;;CAEC,GACD,SAASC;IACP,OAAO,OAAOC,WAAW,eAAe,OAAOA,OAAOC,YAAY,KAAK;AACzE;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmDC,GACD,OAAO,SAASC,qBAAqBC,MAAoB;IACvD,MAAM,EACJC,OAAO,EACPC,KAAK,EACLC,QAAQ,EACRC,WAAW,OAAO,EAClBC,UAAUT,cAAc,iBAAiB,QAAQ,EACjDU,SAASC,gBAAgB,CAAC,CAAC,EAC3BC,OAAO,EACR,GAAGR;IAEJ,sCAAsC;IACtC,IAAIS,eAAoC;IACxC,IAAIL,aAAa,SAAS;QACxBK,eAAed,mBAAmB;YAChCO;YACAC;YACAE;QACF;IACF;IAEA,kDAAkD;IAClD,MAAMK,YAAYlC,oBAAoB;QACpCyB;QACAO;QACAG,aAAaP,aAAa,WAAW,YAAYQ;QACjDN,SAAS;YACP,MAAMA,UAAkC,aACnCC;gBACHM,OAAOX;;YAGT,IAAIC,UAAU;gBACZG,OAAO,CAAC,YAAY,GAAGH;YACzB;YAEA,6DAA6D;YAC7D,IAAIC,aAAa,WAAWK,cAAc;gBACxC,MAAMK,QAAQL,aAAaM,cAAc;gBACzC,IAAID,OAAO;oBACTR,OAAO,CAAC,gBAAgB,GAAG,CAAC,OAAO,EAAEQ,MAAM,CAAC;gBAC9C;YACF;YAEA,OAAOR;QACT;IACF;IAEA,oBAAoB;IACpB,MAAMU,cAAc;QAAEd;QAAOC;IAAS;IAEtC,MAAMc,sBAAsBxC,0BAA0BiC,WAAWM;IACjE,MAAME,cAAcxC,kBAAkBgC,WAAWM;IACjD,MAAMG,gBAAgBxC,oBAAoB+B,WAAWM;IACrD,MAAMI,WAAWxC,eAAe8B,WAAWM;IAC3C,MAAMK,eAAexC,mBAAmB6B,WAAWM;IACnD,MAAMM,mBAAmBxC,uBAAuB4B,WAAWM;IAC3D,MAAMO,qBAAqBxC,yBAAyB2B,WAAWM;IAC/D,MAAMQ,aAAaxC,iBAAiB0B,WAAWM;IAC/C,MAAMS,aAAaxC,iBAAiByB,WAAWM;IAC/C,MAAMU,cAAcxC,kBAAkBwB,WAAWM;IACjD,MAAMW,iBAAiBxC,qBAAqBuB,WAAWM;IACvD,MAAMY,eAAexC,mBAAmBsB,WAAWM;IACnD,MAAMa,eAAexC,mBAAmBqB,WAAWM;IACnD,MAAMc,aAAaxC,iBAAiBoB,WAAWM;IAC/C,MAAMe,cAAcxC,kBAAkBmB,WAAWM;IACjD,MAAMgB,cAAcxC,kBAAkBkB,WAAWM;IACjD,MAAMiB,kBAAkBxC,sBAAsBiB,WAAWM;IACzD,MAAMkB,kBAAkBxC,sBAAsBgB,WAAWM;IAEzD,4DAA4D;IAC5D,MAAMmB,cAAkC;QACtC,qCAAqC;QACrC,MAAMC,QAAOC,OAAsB;YACjC,MAAMC,WAAW,MAAMrB,oBAAoBsB,IAAI,CAACH,MAAM,CAACC;YAEvD,kCAAkC;YAClC,IAAIjC,aAAa,WAAWK,gBAAgB6B,SAASE,WAAW,EAAE;gBAChE/B,aAAagC,SAAS,CAACH,SAASE,WAAW,EAAEF,SAASI,YAAY;YACpE;YAEA,OAAOJ;QACT;QAEA,MAAMK,QAAON,OAAsB;YACjC,MAAMC,WAAW,MAAMrB,oBAAoBsB,IAAI,CAACI,MAAM,CAACN;YAEvD,oDAAoD;YACpD,IAAIjC,aAAa,WAAWK,gBAAgB6B,SAASE,WAAW,EAAE;gBAChE/B,aAAagC,SAAS,CAACH,SAASE,WAAW;YAC7C;YAEA,OAAOF;QACT;QAEA,MAAMM;YACJ,MAAM3B,oBAAoBsB,IAAI,CAACK,OAAO;YAEtC,6BAA6B;YAC7B,IAAIxC,aAAa,WAAWK,cAAc;gBACxCA,aAAaoC,WAAW;YAC1B;QACF;QAEA,MAAMC,iBAAgBT,OAA+B;YACnD,MAAMC,WAAW,MAAMrB,oBAAoBsB,IAAI,CAACO,eAAe,CAACT;YAEhE,IAAIjC,aAAa,WAAWK,gBAAgB6B,SAASE,WAAW,EAAE;gBAChE/B,aAAagC,SAAS,CAACH,SAASE,WAAW,EAAEF,SAASI,YAAY;YACpE;YAEA,OAAOJ;QACT;QAEA,MAAMS,kBAAiBV,OAAgC;YACrD,MAAMC,WAAW,MAAMrB,oBAAoBsB,IAAI,CAACQ,gBAAgB,CAACV;YAEjE,IAAIjC,aAAa,WAAWK,gBAAgB6B,SAASE,WAAW,EAAE;gBAChE/B,aAAagC,SAAS,CAACH,SAASE,WAAW,EAAEF,SAASI,YAAY;YACpE;YAEA,OAAOJ;QACT;QAEA,uBAAuB;QACvBU,eAAe/B,oBAAoBsB,IAAI,CAACS,aAAa,CAACC,IAAI,CAAChC,oBAAoBsB,IAAI;QACnFW,gBAAgBjC,oBAAoBsB,IAAI,CAACW,cAAc,CAACD,IAAI,CAAChC,oBAAoBsB,IAAI;QACrFY,sBAAsBlC,oBAAoBsB,IAAI,CAACY,oBAAoB,CAACF,IAAI,CAAChC,oBAAoBsB,IAAI;QACjGa,gBAAgBnC,oBAAoBsB,IAAI,CAACa,cAAc,CAACH,IAAI,CAAChC,oBAAoBsB,IAAI;QACrFG,cAAczB,oBAAoBsB,IAAI,CAACG,YAAY,CAACO,IAAI,CAAChC,oBAAoBsB,IAAI;QACjFc,kBAAkBpC,oBAAoBsB,IAAI,CAACc,gBAAgB,CAACJ,IAAI,CAAChC,oBAAoBsB,IAAI;QACzFe,gBAAgBrC,oBAAoBsB,IAAI,CAACe,cAAc,CAACL,IAAI,CAAChC,oBAAoBsB,IAAI;QACrFgB,cAActC,oBAAoBsB,IAAI,CAACgB,YAAY,CAACN,IAAI,CAAChC,oBAAoBsB,IAAI;QACjFiB,oBAAoBvC,oBAAoBsB,IAAI,CAACiB,kBAAkB,CAACP,IAAI,CAAChC,oBAAoBsB,IAAI;IAC/F;IAEA,OAAO;QACL,qCAAqC;QACrCA,MAAMJ;QACNsB,OAAOxC,oBAAoBwC,KAAK;QAChCC,OAAOzC,oBAAoByC,KAAK;QAChCC,SAAS1C,oBAAoB0C,OAAO;QACpCC,gBAAgB3C;QAEhB,mBAAmB;QACnB4C,QAAQ3C;QACR4C,UAAU3C;QACV4C,KAAK3C;QACL4C,SAAS3C;QACT4C,aAAa3C;QACb4C,eAAe3C;QACf4C,OAAO3C;QACP4C,OAAO3C;QACP4C,QAAQ3C;QACR4C,WAAW3C;QACX4C,SAAS3C;QACT4C,SAAS3C;QACT4C,OAAO3C;QACP4C,QAAQ3C;QACR4C,QAAQ3C;QACR4C,YAAY3C;QACZ4C,YAAY3C;QAEZ,YAAY;QACZnB;YACE,IAAIX,aAAa,WAAW,CAACK,cAAc,OAAO;YAClD,OAAOA,aAAaM,cAAc;QACpC;QAEA+D;YACE,IAAI1E,aAAa,WAAW,CAACK,cAAc,OAAO;YAClD,OAAOA,aAAaqE,eAAe;QACrC;QAEArC,WAAUD,WAAmB,EAAEE,YAAqB;YAClD,IAAItC,aAAa,WAAWK,cAAc;gBACxCA,aAAagC,SAAS,CAACD,aAAaE;YACtC;QACF;QAEAqC;YACE,IAAI3E,aAAa,WAAWK,cAAc;gBACxCA,aAAaoC,WAAW;YAC1B;QACF;QAEAmC;YACE,IAAI5E,aAAa,UAAU;gBACzB,2CAA2C;gBAC3C,OAAO;YACT;YACA,OAAOK,eAAe,CAAC,CAACA,aAAaM,cAAc,KAAK;QAC1D;IACF;AACF"}
|
package/dist/lib/sdk.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// Client Factory (Recommended API)
|
|
3
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
export { create23BlocksClient } from './client.js';
|
|
5
|
+
export { createTokenManager } from './token-manager.js';
|
|
6
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
7
|
// Core
|
|
3
8
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
4
9
|
export * from '@23blocks/contracts';
|
|
5
10
|
export * from '@23blocks/jsonapi-codec';
|
|
6
11
|
export * from '@23blocks/transport-http';
|
|
7
12
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
8
|
-
// Blocks
|
|
13
|
+
// Blocks (for advanced users who need custom transport)
|
|
9
14
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
10
15
|
export * from '@23blocks/block-authentication';
|
|
11
16
|
export * from '@23blocks/block-search';
|
package/dist/lib/sdk.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/sdk.ts"],"sourcesContent":["// ─────────────────────────────────────────────────────────────────────────────\n// Core\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport * from '@23blocks/contracts';\nexport * from '@23blocks/jsonapi-codec';\nexport * from '@23blocks/transport-http';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Blocks\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport * from '@23blocks/block-authentication';\nexport * from '@23blocks/block-search';\nexport * from '@23blocks/block-products';\nexport * from '@23blocks/block-crm';\nexport * from '@23blocks/block-content';\nexport * from '@23blocks/block-geolocation';\nexport * from '@23blocks/block-conversations';\nexport * from '@23blocks/block-files';\nexport * from '@23blocks/block-forms';\nexport * from '@23blocks/block-assets';\nexport * from '@23blocks/block-campaigns';\nexport * from '@23blocks/block-company';\nexport * from '@23blocks/block-rewards';\nexport * from '@23blocks/block-sales';\nexport * from '@23blocks/block-wallet';\nexport * from '@23blocks/block-jarvis';\nexport * from '@23blocks/block-onboarding';\nexport * from '@23blocks/block-university';\n"],"names":[],"rangeMappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/lib/sdk.ts"],"sourcesContent":["// ─────────────────────────────────────────────────────────────────────────────\n// Client Factory (Recommended API)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport {\n create23BlocksClient,\n type AuthMode,\n type ClientConfig,\n type Blocks23Client,\n type ManagedAuthService,\n type StorageType,\n type TokenManager,\n} from './client.js';\n\nexport { createTokenManager } from './token-manager.js';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Core\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport * from '@23blocks/contracts';\nexport * from '@23blocks/jsonapi-codec';\nexport * from '@23blocks/transport-http';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Blocks (for advanced users who need custom transport)\n// ─────────────────────────────────────────────────────────────────────────────\n\nexport * from '@23blocks/block-authentication';\nexport * from '@23blocks/block-search';\nexport * from '@23blocks/block-products';\nexport * from '@23blocks/block-crm';\nexport * from '@23blocks/block-content';\nexport * from '@23blocks/block-geolocation';\nexport * from '@23blocks/block-conversations';\nexport * from '@23blocks/block-files';\nexport * from '@23blocks/block-forms';\nexport * from '@23blocks/block-assets';\nexport * from '@23blocks/block-campaigns';\nexport * from '@23blocks/block-company';\nexport * from '@23blocks/block-rewards';\nexport * from '@23blocks/block-sales';\nexport * from '@23blocks/block-wallet';\nexport * from '@23blocks/block-jarvis';\nexport * from '@23blocks/block-onboarding';\nexport * from '@23blocks/block-university';\n"],"names":["create23BlocksClient","createTokenManager"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA,gFAAgF;AAChF,mCAAmC;AACnC,gFAAgF;AAEhF,SACEA,oBAAoB,QAOf,cAAc;AAErB,SAASC,kBAAkB,QAAQ,qBAAqB;AAExD,gFAAgF;AAChF,OAAO;AACP,gFAAgF;AAEhF,cAAc,sBAAsB;AACpC,cAAc,0BAA0B;AACxC,cAAc,2BAA2B;AAEzC,gFAAgF;AAChF,wDAAwD;AACxD,gFAAgF;AAEhF,cAAc,iCAAiC;AAC/C,cAAc,yBAAyB;AACvC,cAAc,2BAA2B;AACzC,cAAc,sBAAsB;AACpC,cAAc,0BAA0B;AACxC,cAAc,8BAA8B;AAC5C,cAAc,gCAAgC;AAC9C,cAAc,wBAAwB;AACtC,cAAc,wBAAwB;AACtC,cAAc,yBAAyB;AACvC,cAAc,4BAA4B;AAC1C,cAAc,0BAA0B;AACxC,cAAc,0BAA0B;AACxC,cAAc,wBAAwB;AACtC,cAAc,yBAAyB;AACvC,cAAc,yBAAyB;AACvC,cAAc,6BAA6B;AAC3C,cAAc,6BAA6B"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token storage types
|
|
3
|
+
*/ /**
|
|
4
|
+
* Generate storage key scoped to app and tenant
|
|
5
|
+
*/ function getStorageKey(type, appId, tenantId) {
|
|
6
|
+
const scope = tenantId ? `${appId}_${tenantId}` : appId;
|
|
7
|
+
return `23blocks_${scope}_${type}_token`;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* In-memory token storage (for SSR or when localStorage is unavailable)
|
|
11
|
+
*/ let MemoryStorage = class MemoryStorage {
|
|
12
|
+
getItem(key) {
|
|
13
|
+
var _this_data_get;
|
|
14
|
+
return (_this_data_get = this.data.get(key)) != null ? _this_data_get : null;
|
|
15
|
+
}
|
|
16
|
+
setItem(key, value) {
|
|
17
|
+
this.data.set(key, value);
|
|
18
|
+
}
|
|
19
|
+
removeItem(key) {
|
|
20
|
+
this.data.delete(key);
|
|
21
|
+
}
|
|
22
|
+
constructor(){
|
|
23
|
+
this.data = new Map();
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Detect if we're running in a browser environment
|
|
28
|
+
*/ function isBrowser() {
|
|
29
|
+
return typeof window !== 'undefined' && typeof window.localStorage !== 'undefined';
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Get the appropriate storage backend
|
|
33
|
+
*/ function getStorage(type) {
|
|
34
|
+
if (!isBrowser()) {
|
|
35
|
+
// In SSR/Node, always use memory storage
|
|
36
|
+
return new MemoryStorage();
|
|
37
|
+
}
|
|
38
|
+
switch(type){
|
|
39
|
+
case 'localStorage':
|
|
40
|
+
return window.localStorage;
|
|
41
|
+
case 'sessionStorage':
|
|
42
|
+
return window.sessionStorage;
|
|
43
|
+
case 'memory':
|
|
44
|
+
return new MemoryStorage();
|
|
45
|
+
default:
|
|
46
|
+
return window.localStorage;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Create a token manager instance
|
|
51
|
+
*
|
|
52
|
+
* @param config - Token manager configuration including appId for scoped storage
|
|
53
|
+
* @returns A TokenManager instance
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const tokenManager = createTokenManager({
|
|
58
|
+
* appId: 'my-app',
|
|
59
|
+
* storage: 'localStorage',
|
|
60
|
+
* });
|
|
61
|
+
*
|
|
62
|
+
* // Store tokens after sign in
|
|
63
|
+
* tokenManager.setTokens('access_token_value', 'refresh_token_value');
|
|
64
|
+
*
|
|
65
|
+
* // Get token for API requests
|
|
66
|
+
* const token = tokenManager.getAccessToken();
|
|
67
|
+
*
|
|
68
|
+
* // Clear on sign out
|
|
69
|
+
* tokenManager.clearTokens();
|
|
70
|
+
*
|
|
71
|
+
* // Listen for cross-tab changes
|
|
72
|
+
* const unsubscribe = tokenManager.onStorageChange(() => {
|
|
73
|
+
* console.log('Tokens changed in another tab');
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/ export function createTokenManager(config) {
|
|
77
|
+
const { appId, tenantId, storage: storageType = 'localStorage' } = config;
|
|
78
|
+
const storage = getStorage(storageType);
|
|
79
|
+
const accessTokenKey = getStorageKey('access', appId, tenantId);
|
|
80
|
+
const refreshTokenKey = getStorageKey('refresh', appId, tenantId);
|
|
81
|
+
// Track storage event listeners for cleanup
|
|
82
|
+
const listeners = new Set();
|
|
83
|
+
return {
|
|
84
|
+
getAccessToken () {
|
|
85
|
+
try {
|
|
86
|
+
return storage.getItem(accessTokenKey);
|
|
87
|
+
} catch (e) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
getRefreshToken () {
|
|
92
|
+
try {
|
|
93
|
+
return storage.getItem(refreshTokenKey);
|
|
94
|
+
} catch (e) {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
setTokens (accessToken, refreshToken) {
|
|
99
|
+
try {
|
|
100
|
+
storage.setItem(accessTokenKey, accessToken);
|
|
101
|
+
if (refreshToken) {
|
|
102
|
+
storage.setItem(refreshTokenKey, refreshToken);
|
|
103
|
+
}
|
|
104
|
+
} catch (e) {
|
|
105
|
+
// Storage might be full or disabled, silently fail
|
|
106
|
+
console.warn('[23blocks] Unable to store tokens');
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
clearTokens () {
|
|
110
|
+
try {
|
|
111
|
+
storage.removeItem(accessTokenKey);
|
|
112
|
+
storage.removeItem(refreshTokenKey);
|
|
113
|
+
} catch (e) {
|
|
114
|
+
// Silently fail
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
onStorageChange (callback) {
|
|
118
|
+
// Only works in browser with localStorage/sessionStorage
|
|
119
|
+
if (!isBrowser() || storageType === 'memory') {
|
|
120
|
+
// Return no-op unsubscribe for SSR/memory storage
|
|
121
|
+
return ()=>{};
|
|
122
|
+
}
|
|
123
|
+
const handler = (event)=>{
|
|
124
|
+
// Only trigger if our keys changed
|
|
125
|
+
if (event.key === accessTokenKey || event.key === refreshTokenKey) {
|
|
126
|
+
callback();
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
window.addEventListener('storage', handler);
|
|
130
|
+
listeners.add(callback);
|
|
131
|
+
// Return unsubscribe function
|
|
132
|
+
return ()=>{
|
|
133
|
+
window.removeEventListener('storage', handler);
|
|
134
|
+
listeners.delete(callback);
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
//# sourceMappingURL=token-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/token-manager.ts"],"sourcesContent":["/**\n * Token storage types\n */\nexport type StorageType = 'localStorage' | 'sessionStorage' | 'memory';\n\n/**\n * Token manager configuration\n */\nexport interface TokenManagerConfig {\n /**\n * Application ID - used to scope token storage\n * This ensures multiple apps on the same domain don't conflict\n */\n appId: string;\n\n /**\n * Tenant ID (optional) - further scopes token storage for multi-tenant apps\n */\n tenantId?: string;\n\n /**\n * Storage type\n * @default 'localStorage'\n */\n storage?: StorageType;\n}\n\n/**\n * Token manager interface for storing and retrieving auth tokens\n */\nexport interface TokenManager {\n /**\n * Get the current access token\n */\n getAccessToken(): string | null;\n\n /**\n * Get the current refresh token\n */\n getRefreshToken(): string | null;\n\n /**\n * Store tokens\n */\n setTokens(accessToken: string, refreshToken?: string): void;\n\n /**\n * Clear all stored tokens\n */\n clearTokens(): void;\n\n /**\n * Subscribe to storage changes (for cross-tab sync)\n * Returns an unsubscribe function\n */\n onStorageChange(callback: () => void): () => void;\n}\n\n/**\n * Generate storage key scoped to app and tenant\n */\nfunction getStorageKey(type: 'access' | 'refresh', appId: string, tenantId?: string): string {\n const scope = tenantId ? `${appId}_${tenantId}` : appId;\n return `23blocks_${scope}_${type}_token`;\n}\n\n/**\n * In-memory token storage (for SSR or when localStorage is unavailable)\n */\nclass MemoryStorage {\n private data: Map<string, string> = new Map();\n\n getItem(key: string): string | null {\n return this.data.get(key) ?? null;\n }\n\n setItem(key: string, value: string): void {\n this.data.set(key, value);\n }\n\n removeItem(key: string): void {\n this.data.delete(key);\n }\n}\n\n/**\n * Detect if we're running in a browser environment\n */\nfunction isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof window.localStorage !== 'undefined';\n}\n\n/**\n * Get the appropriate storage backend\n */\nfunction getStorage(type: StorageType): Storage | MemoryStorage {\n if (!isBrowser()) {\n // In SSR/Node, always use memory storage\n return new MemoryStorage();\n }\n\n switch (type) {\n case 'localStorage':\n return window.localStorage;\n case 'sessionStorage':\n return window.sessionStorage;\n case 'memory':\n return new MemoryStorage();\n default:\n return window.localStorage;\n }\n}\n\n/**\n * Create a token manager instance\n *\n * @param config - Token manager configuration including appId for scoped storage\n * @returns A TokenManager instance\n *\n * @example\n * ```typescript\n * const tokenManager = createTokenManager({\n * appId: 'my-app',\n * storage: 'localStorage',\n * });\n *\n * // Store tokens after sign in\n * tokenManager.setTokens('access_token_value', 'refresh_token_value');\n *\n * // Get token for API requests\n * const token = tokenManager.getAccessToken();\n *\n * // Clear on sign out\n * tokenManager.clearTokens();\n *\n * // Listen for cross-tab changes\n * const unsubscribe = tokenManager.onStorageChange(() => {\n * console.log('Tokens changed in another tab');\n * });\n * ```\n */\nexport function createTokenManager(config: TokenManagerConfig): TokenManager {\n const { appId, tenantId, storage: storageType = 'localStorage' } = config;\n const storage = getStorage(storageType);\n\n const accessTokenKey = getStorageKey('access', appId, tenantId);\n const refreshTokenKey = getStorageKey('refresh', appId, tenantId);\n\n // Track storage event listeners for cleanup\n const listeners: Set<() => void> = new Set();\n\n return {\n getAccessToken(): string | null {\n try {\n return storage.getItem(accessTokenKey);\n } catch {\n return null;\n }\n },\n\n getRefreshToken(): string | null {\n try {\n return storage.getItem(refreshTokenKey);\n } catch {\n return null;\n }\n },\n\n setTokens(accessToken: string, refreshToken?: string): void {\n try {\n storage.setItem(accessTokenKey, accessToken);\n if (refreshToken) {\n storage.setItem(refreshTokenKey, refreshToken);\n }\n } catch {\n // Storage might be full or disabled, silently fail\n console.warn('[23blocks] Unable to store tokens');\n }\n },\n\n clearTokens(): void {\n try {\n storage.removeItem(accessTokenKey);\n storage.removeItem(refreshTokenKey);\n } catch {\n // Silently fail\n }\n },\n\n onStorageChange(callback: () => void): () => void {\n // Only works in browser with localStorage/sessionStorage\n if (!isBrowser() || storageType === 'memory') {\n // Return no-op unsubscribe for SSR/memory storage\n return () => {};\n }\n\n const handler = (event: StorageEvent) => {\n // Only trigger if our keys changed\n if (event.key === accessTokenKey || event.key === refreshTokenKey) {\n callback();\n }\n };\n\n window.addEventListener('storage', handler);\n listeners.add(callback);\n\n // Return unsubscribe function\n return () => {\n window.removeEventListener('storage', handler);\n listeners.delete(callback);\n };\n },\n };\n}\n"],"names":["getStorageKey","type","appId","tenantId","scope","MemoryStorage","getItem","key","data","get","setItem","value","set","removeItem","delete","Map","isBrowser","window","localStorage","getStorage","sessionStorage","createTokenManager","config","storage","storageType","accessTokenKey","refreshTokenKey","listeners","Set","getAccessToken","getRefreshToken","setTokens","accessToken","refreshToken","console","warn","clearTokens","onStorageChange","callback","handler","event","addEventListener","add","removeEventListener"],"rangeMappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;","mappings":"AAAA;;CAEC,GAwDD;;CAEC,GACD,SAASA,cAAcC,IAA0B,EAAEC,KAAa,EAAEC,QAAiB;IACjF,MAAMC,QAAQD,WAAW,CAAC,EAAED,MAAM,CAAC,EAAEC,SAAS,CAAC,GAAGD;IAClD,OAAO,CAAC,SAAS,EAAEE,MAAM,CAAC,EAAEH,KAAK,MAAM,CAAC;AAC1C;AAEA;;CAEC,GACD,IAAA,AAAMI,gBAAN,MAAMA;IAGJC,QAAQC,GAAW,EAAiB;YAC3B;QAAP,OAAO,CAAA,iBAAA,IAAI,CAACC,IAAI,CAACC,GAAG,CAACF,gBAAd,iBAAsB;IAC/B;IAEAG,QAAQH,GAAW,EAAEI,KAAa,EAAQ;QACxC,IAAI,CAACH,IAAI,CAACI,GAAG,CAACL,KAAKI;IACrB;IAEAE,WAAWN,GAAW,EAAQ;QAC5B,IAAI,CAACC,IAAI,CAACM,MAAM,CAACP;IACnB;;aAZQC,OAA4B,IAAIO;;AAa1C;AAEA;;CAEC,GACD,SAASC;IACP,OAAO,OAAOC,WAAW,eAAe,OAAOA,OAAOC,YAAY,KAAK;AACzE;AAEA;;CAEC,GACD,SAASC,WAAWlB,IAAiB;IACnC,IAAI,CAACe,aAAa;QAChB,yCAAyC;QACzC,OAAO,IAAIX;IACb;IAEA,OAAQJ;QACN,KAAK;YACH,OAAOgB,OAAOC,YAAY;QAC5B,KAAK;YACH,OAAOD,OAAOG,cAAc;QAC9B,KAAK;YACH,OAAO,IAAIf;QACb;YACE,OAAOY,OAAOC,YAAY;IAC9B;AACF;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BC,GACD,OAAO,SAASG,mBAAmBC,MAA0B;IAC3D,MAAM,EAAEpB,KAAK,EAAEC,QAAQ,EAAEoB,SAASC,cAAc,cAAc,EAAE,GAAGF;IACnE,MAAMC,UAAUJ,WAAWK;IAE3B,MAAMC,iBAAiBzB,cAAc,UAAUE,OAAOC;IACtD,MAAMuB,kBAAkB1B,cAAc,WAAWE,OAAOC;IAExD,4CAA4C;IAC5C,MAAMwB,YAA6B,IAAIC;IAEvC,OAAO;QACLC;YACE,IAAI;gBACF,OAAON,QAAQjB,OAAO,CAACmB;YACzB,EAAE,UAAM;gBACN,OAAO;YACT;QACF;QAEAK;YACE,IAAI;gBACF,OAAOP,QAAQjB,OAAO,CAACoB;YACzB,EAAE,UAAM;gBACN,OAAO;YACT;QACF;QAEAK,WAAUC,WAAmB,EAAEC,YAAqB;YAClD,IAAI;gBACFV,QAAQb,OAAO,CAACe,gBAAgBO;gBAChC,IAAIC,cAAc;oBAChBV,QAAQb,OAAO,CAACgB,iBAAiBO;gBACnC;YACF,EAAE,UAAM;gBACN,mDAAmD;gBACnDC,QAAQC,IAAI,CAAC;YACf;QACF;QAEAC;YACE,IAAI;gBACFb,QAAQV,UAAU,CAACY;gBACnBF,QAAQV,UAAU,CAACa;YACrB,EAAE,UAAM;YACN,gBAAgB;YAClB;QACF;QAEAW,iBAAgBC,QAAoB;YAClC,yDAAyD;YACzD,IAAI,CAACtB,eAAeQ,gBAAgB,UAAU;gBAC5C,kDAAkD;gBAClD,OAAO,KAAO;YAChB;YAEA,MAAMe,UAAU,CAACC;gBACf,mCAAmC;gBACnC,IAAIA,MAAMjC,GAAG,KAAKkB,kBAAkBe,MAAMjC,GAAG,KAAKmB,iBAAiB;oBACjEY;gBACF;YACF;YAEArB,OAAOwB,gBAAgB,CAAC,WAAWF;YACnCZ,UAAUe,GAAG,CAACJ;YAEd,8BAA8B;YAC9B,OAAO;gBACLrB,OAAO0B,mBAAmB,CAAC,WAAWJ;gBACtCZ,UAAUb,MAAM,CAACwB;YACnB;QACF;IACF;AACF"}
|