@feelflow/ffid-sdk 1.9.1 → 1.10.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.
@@ -0,0 +1,416 @@
1
+ export { D as DEFAULT_API_BASE_URL } from '../constants-DvTGHPZn.js';
2
+
3
+ /** Cache adapter interface for FFID SDK token verification */
4
+ /**
5
+ * Pluggable cache adapter interface.
6
+ * Implement this to use custom cache backends (Redis, Memcached, etc.)
7
+ */
8
+ interface FFIDCacheAdapter {
9
+ /** Get a cached value by key. Returns null if not found or expired. */
10
+ get(key: string): Promise<unknown | null>;
11
+ /** Set a value with TTL in seconds. */
12
+ set(key: string, value: unknown, ttlSeconds: number): Promise<void>;
13
+ /** Delete a cached value. */
14
+ delete(key: string): Promise<void>;
15
+ }
16
+ /** Cache configuration for createFFIDClient */
17
+ interface FFIDCacheConfig {
18
+ /** Cache adapter instance */
19
+ adapter: FFIDCacheAdapter;
20
+ /** Cache TTL in seconds (how long to cache userinfo/introspect results) */
21
+ ttl: number;
22
+ }
23
+
24
+ /**
25
+ * FFID SDK Type Definitions
26
+ *
27
+ * Core types for the FeelFlow ID SDK
28
+ */
29
+
30
+ /**
31
+ * User information from FFID
32
+ */
33
+ type FFIDSeatModel = 'organization';
34
+ /** Userinfo member role for OAuth responses */
35
+ type FFIDOAuthUserInfoMemberRole = 'owner' | 'admin' | 'member' | 'viewer';
36
+ interface FFIDUser {
37
+ /** User ID (UUID) */
38
+ id: string;
39
+ /** Email address */
40
+ email: string;
41
+ /** Display name */
42
+ displayName: string | null;
43
+ /** Avatar URL */
44
+ avatarUrl: string | null;
45
+ /** Locale setting (e.g., 'ja', 'en') */
46
+ locale: string | null;
47
+ /** Timezone (e.g., 'Asia/Tokyo') */
48
+ timezone: string | null;
49
+ /** Account creation timestamp */
50
+ createdAt: string;
51
+ }
52
+ /**
53
+ * Agency branding information for white-label support.
54
+ * Included in organization when it is linked to an agency.
55
+ */
56
+ interface FFIDAgencyBranding {
57
+ /** Agency ID (UUID) */
58
+ agencyId: string;
59
+ /** Agency display name */
60
+ agencyName: string;
61
+ /** Custom logo URL */
62
+ logoUrl?: string;
63
+ /** Custom favicon URL */
64
+ faviconUrl?: string;
65
+ /** Primary brand color (hex) */
66
+ primaryColor?: string;
67
+ /** Secondary brand color (hex) */
68
+ secondaryColor?: string;
69
+ /** White-label company name */
70
+ companyName?: string;
71
+ }
72
+ /**
73
+ * Organization membership information
74
+ */
75
+ interface FFIDOrganization {
76
+ /** Organization ID (UUID) */
77
+ id: string;
78
+ /** Organization name */
79
+ name: string;
80
+ /** URL-safe slug */
81
+ slug: string;
82
+ /** User's role in this organization */
83
+ role: 'owner' | 'admin' | 'member';
84
+ /** Membership status */
85
+ status: 'active' | 'invited' | 'suspended';
86
+ /** Agency branding (null if org is not linked to an agency) */
87
+ agencyBranding: FFIDAgencyBranding | null;
88
+ }
89
+ /**
90
+ * Subscription/contract information
91
+ */
92
+ interface FFIDSubscription {
93
+ /** Subscription ID (UUID) */
94
+ id: string;
95
+ /** Service code (e.g., 'chatbot') */
96
+ serviceCode: string;
97
+ /** Service display name */
98
+ serviceName: string;
99
+ /** Plan code (e.g., 'basic', 'pro') */
100
+ planCode: string;
101
+ /** Plan display name */
102
+ planName: string;
103
+ /** Subscription status */
104
+ status: 'trialing' | 'active' | 'past_due' | 'canceled' | 'paused';
105
+ /** Current billing period end date */
106
+ currentPeriodEnd: string | null;
107
+ /** Service seat model (available when sourced from OAuth userinfo) */
108
+ seatModel?: FFIDSeatModel | undefined;
109
+ /** Member role in the resolved organization context */
110
+ memberRole?: FFIDOAuthUserInfoMemberRole | undefined;
111
+ /** Organization ID used to resolve subscription access */
112
+ organizationId?: string | null | undefined;
113
+ }
114
+ /** OAuth userinfo subscription summary */
115
+ interface FFIDOAuthUserInfoSubscription {
116
+ subscriptionId: string | null;
117
+ status: 'trialing' | 'active' | 'past_due' | 'canceled' | 'paused' | null;
118
+ planCode: string | null;
119
+ seatModel: FFIDSeatModel | null;
120
+ memberRole: FFIDOAuthUserInfoMemberRole | null;
121
+ organizationId: string | null;
122
+ }
123
+ /** OAuth userinfo response exposed by FFID */
124
+ interface FFIDOAuthUserInfo {
125
+ sub: string;
126
+ email: string | null;
127
+ name: string | null;
128
+ picture: string | null;
129
+ organizationId?: string | null | undefined;
130
+ subscription?: FFIDOAuthUserInfoSubscription | undefined;
131
+ }
132
+ /**
133
+ * SDK configuration options
134
+ */
135
+ interface FFIDConfig {
136
+ /** Service code to identify your application */
137
+ serviceCode: string;
138
+ /** FFID API base URL (defaults to production) */
139
+ apiBaseUrl?: string | undefined;
140
+ /**
141
+ * Enable debug logging (deprecated: use logger instead)
142
+ * When true and no logger provided, uses console for logging
143
+ * @deprecated Use `logger` option for custom logging
144
+ */
145
+ debug?: boolean | undefined;
146
+ /**
147
+ * Custom logger for SDK debug output
148
+ * If not provided: uses no-op logger (silent)
149
+ * If debug=true and no logger: uses console
150
+ */
151
+ logger?: FFIDLogger | undefined;
152
+ /** Session refresh interval in milliseconds */
153
+ refreshInterval?: number | undefined;
154
+ /** Callback when authentication state changes */
155
+ onAuthStateChange?: ((user: FFIDUser | null) => void) | undefined;
156
+ /** Callback on authentication error */
157
+ onError?: ((error: FFIDError) => void) | undefined;
158
+ /** Authentication mode: 'cookie' (default), 'token' (OAuth Bearer), or 'service-key' (server-to-server) */
159
+ authMode?: 'cookie' | 'token' | 'service-key' | undefined;
160
+ /** Client ID for token mode (defaults to serviceCode if not set) */
161
+ clientId?: string | undefined;
162
+ /** Custom redirect URI for OAuth flow (defaults to window.location.origin + window.location.pathname) */
163
+ redirectUri?: string | undefined;
164
+ /** Service API key for service-key mode (X-Service-Api-Key header) */
165
+ serviceApiKey?: string | undefined;
166
+ /**
167
+ * Token verification strategy for service-key mode.
168
+ * - 'jwt': Local JWT verification via JWKS (default, lower latency)
169
+ * - 'introspect': Remote introspection via /api/v1/oauth/introspect
170
+ *
171
+ * JWT verification returns limited claims (no email/name/picture/subscription).
172
+ * Use 'introspect' if you need full user profile data.
173
+ */
174
+ verifyStrategy?: 'jwt' | 'introspect' | undefined;
175
+ /**
176
+ * Cache configuration for token verification results.
177
+ * When set, introspect/userinfo responses are cached to reduce API calls.
178
+ * Only effective in service-key mode with verifyStrategy: 'introspect'.
179
+ */
180
+ cache?: FFIDCacheConfig | undefined;
181
+ /**
182
+ * Request timeout in milliseconds for FFID API calls.
183
+ * Applies to token verification and introspection requests.
184
+ * @default undefined (no timeout, uses fetch default)
185
+ */
186
+ timeout?: number | undefined;
187
+ }
188
+ /**
189
+ * Logger interface for SDK debug output
190
+ *
191
+ * Allows injection of custom loggers (e.g., winston, pino)
192
+ * or use of the built-in console logger when debug is enabled
193
+ */
194
+ interface FFIDLogger {
195
+ /** Debug level logging */
196
+ debug: (...args: unknown[]) => void;
197
+ /** Info level logging */
198
+ info: (...args: unknown[]) => void;
199
+ /** Warning level logging */
200
+ warn: (...args: unknown[]) => void;
201
+ /** Error level logging */
202
+ error: (...args: unknown[]) => void;
203
+ }
204
+ /**
205
+ * FFID error object
206
+ */
207
+ interface FFIDError {
208
+ /** Error code */
209
+ code: string;
210
+ /** Human-readable error message */
211
+ message: string;
212
+ /** Additional error details */
213
+ details?: Record<string, unknown>;
214
+ }
215
+ /**
216
+ * Session response from FFID API
217
+ */
218
+ interface FFIDSessionResponse {
219
+ user: FFIDUser;
220
+ organizations: FFIDOrganization[];
221
+ subscriptions: FFIDSubscription[];
222
+ }
223
+ /**
224
+ * API response wrapper (discriminated union for type safety)
225
+ *
226
+ * Either data is present (success) or error is present (failure), never both.
227
+ * This pattern ensures callers handle both cases explicitly.
228
+ */
229
+ type FFIDApiResponse<T> = {
230
+ data: T;
231
+ error?: undefined;
232
+ } | {
233
+ data?: undefined;
234
+ error: FFIDError;
235
+ };
236
+ /**
237
+ * Subscription check response from ext/check endpoint
238
+ */
239
+ /** Subscription status values matching the FFID platform's SubscriptionStatus type */
240
+ type FFIDSubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'canceled' | 'pending_invoice' | 'paused' | 'incomplete' | 'incomplete_expired' | 'unpaid';
241
+ interface FFIDSubscriptionCheckResponse {
242
+ hasActiveSubscription: boolean;
243
+ organizationId: string | null;
244
+ subscriptionId: string | null;
245
+ status: FFIDSubscriptionStatus | null;
246
+ planCode: string | null;
247
+ currentPeriodEnd: string | null;
248
+ }
249
+ /**
250
+ * Checkout session response from billing checkout endpoint
251
+ */
252
+ interface FFIDCheckoutSessionResponse {
253
+ /** Stripe Checkout session ID */
254
+ sessionId: string;
255
+ /** Stripe Checkout session URL (null if session creation had issues) */
256
+ url: string | null;
257
+ }
258
+ /**
259
+ * Portal session response from billing portal endpoint
260
+ */
261
+ interface FFIDPortalSessionResponse {
262
+ /** Stripe Billing Portal URL */
263
+ url: string;
264
+ }
265
+ /**
266
+ * Parameters for creating a checkout session
267
+ */
268
+ interface FFIDCreateCheckoutParams {
269
+ /** Organization ID (UUID) */
270
+ organizationId: string;
271
+ /** Subscription ID (UUID) */
272
+ subscriptionId: string;
273
+ /** URL to redirect after successful checkout */
274
+ successUrl: string;
275
+ /** URL to redirect after cancelled checkout */
276
+ cancelUrl: string;
277
+ /** Optional plan ID for upgrade or resubscription */
278
+ planId?: string;
279
+ }
280
+ /**
281
+ * Parameters for creating a billing portal session
282
+ */
283
+ interface FFIDCreatePortalParams {
284
+ /** Organization ID (UUID) */
285
+ organizationId: string;
286
+ /** URL to redirect when user exits the portal */
287
+ returnUrl: string;
288
+ }
289
+
290
+ /**
291
+ * Token Store
292
+ *
293
+ * Manages OAuth 2.0 tokens (access + refresh) with dual-storage support.
294
+ * Falls back to in-memory storage when localStorage is unavailable
295
+ * (e.g., Safari private browsing mode).
296
+ */
297
+ /**
298
+ * Token data stored by the token store
299
+ */
300
+ interface TokenData {
301
+ /** OAuth 2.0 access token */
302
+ accessToken: string;
303
+ /** OAuth 2.0 refresh token */
304
+ refreshToken: string;
305
+ /** Expiration timestamp in milliseconds (Unix epoch) */
306
+ expiresAt: number;
307
+ }
308
+ /**
309
+ * Token store interface for managing OAuth tokens
310
+ */
311
+ interface TokenStore {
312
+ /** Get stored tokens (null if not stored) */
313
+ getTokens(): TokenData | null;
314
+ /** Store new tokens */
315
+ setTokens(tokens: TokenData): void;
316
+ /** Clear all stored tokens */
317
+ clearTokens(): void;
318
+ /** Check if access token is expired (with 30s buffer) */
319
+ isAccessTokenExpired(): boolean;
320
+ }
321
+ /**
322
+ * Create a token store with the specified storage type.
323
+ *
324
+ * When storageType is 'localStorage' (default in browser), falls back
325
+ * to memory if localStorage is not available (e.g., Safari private mode).
326
+ *
327
+ * @param storageType - 'localStorage' (default) or 'memory'
328
+ */
329
+ declare function createTokenStore(storageType?: 'localStorage' | 'memory'): TokenStore;
330
+
331
+ /** Creates an FFID API client instance */
332
+ declare function createFFIDClient(config: FFIDConfig): {
333
+ getSession: () => Promise<FFIDApiResponse<FFIDSessionResponse>>;
334
+ signOut: () => Promise<FFIDApiResponse<void>>;
335
+ redirectToLogin: () => boolean;
336
+ getLoginUrl: (redirectUrl?: string) => string;
337
+ getSignupUrl: (redirectUrl?: string) => string;
338
+ createError: (code: string, message: string) => FFIDError;
339
+ exchangeCodeForTokens: (code: string, codeVerifier?: string) => Promise<FFIDApiResponse<void>>;
340
+ refreshAccessToken: () => Promise<FFIDApiResponse<void>>;
341
+ checkSubscription: (params: {
342
+ userId: string;
343
+ organizationId: string;
344
+ }) => Promise<FFIDApiResponse<FFIDSubscriptionCheckResponse>>;
345
+ createCheckoutSession: (params: FFIDCreateCheckoutParams) => Promise<FFIDApiResponse<FFIDCheckoutSessionResponse>>;
346
+ createPortalSession: (params: FFIDCreatePortalParams) => Promise<FFIDApiResponse<FFIDPortalSessionResponse>>;
347
+ verifyAccessToken: (accessToken: string) => Promise<FFIDApiResponse<FFIDOAuthUserInfo>>;
348
+ /** Token store (token mode only) */
349
+ tokenStore: TokenStore;
350
+ /** Resolved auth mode */
351
+ authMode: "cookie" | "token" | "service-key";
352
+ /** Resolved logger instance */
353
+ logger: FFIDLogger;
354
+ baseUrl: string;
355
+ serviceCode: string;
356
+ clientId: string;
357
+ redirectUri: string | null;
358
+ };
359
+ /** Type of the FFID client */
360
+ type FFIDClient = ReturnType<typeof createFFIDClient>;
361
+
362
+ /** Token verification - verifyAccessToken() implementation */
363
+
364
+ /** Dependencies required by verifyAccessToken */
365
+ interface VerifyAccessTokenDeps {
366
+ authMode: string;
367
+ baseUrl: string;
368
+ serviceCode: string;
369
+ serviceApiKey: string | undefined;
370
+ verifyStrategy: 'jwt' | 'introspect';
371
+ logger: FFIDLogger;
372
+ createError: (code: string, message: string) => FFIDError;
373
+ errorCodes: {
374
+ NETWORK_ERROR: string;
375
+ PARSE_ERROR: string;
376
+ TOKEN_VERIFICATION_ERROR: string;
377
+ };
378
+ cache?: {
379
+ adapter: FFIDCacheAdapter;
380
+ ttl: number;
381
+ } | undefined;
382
+ timeout?: number | undefined;
383
+ }
384
+ /**
385
+ * Creates a verifyAccessToken function bound to the given client dependencies.
386
+ *
387
+ * Supports two strategies:
388
+ * - 'jwt': Local JWT verification via JWKS (default, lower latency)
389
+ * - 'introspect': Remote token introspection (full user profile data)
390
+ */
391
+ declare function createVerifyAccessToken(deps: VerifyAccessTokenDeps): (accessToken: string) => Promise<FFIDApiResponse<FFIDOAuthUserInfo>>;
392
+
393
+ /**
394
+ * Create an in-memory cache adapter using a Map.
395
+ * Suitable for single-process environments (e.g., development, testing).
396
+ */
397
+ declare function createMemoryCacheAdapter(): FFIDCacheAdapter;
398
+
399
+ /**
400
+ * Minimal KVNamespace-compatible interface.
401
+ * Matches Cloudflare Workers KV without requiring the CF Workers dependency.
402
+ */
403
+ interface KVNamespaceLike {
404
+ get(key: string, type: 'json'): Promise<unknown | null>;
405
+ put(key: string, value: string, options?: {
406
+ expirationTtl?: number;
407
+ }): Promise<void>;
408
+ delete(key: string): Promise<void>;
409
+ }
410
+ /**
411
+ * Create a cache adapter backed by a KVNamespace-compatible store.
412
+ * Suitable for Cloudflare Workers and other KV-based environments.
413
+ */
414
+ declare function createKVCacheAdapter(kv: KVNamespaceLike): FFIDCacheAdapter;
415
+
416
+ export { type FFIDCacheAdapter, type FFIDCacheConfig, type FFIDClient, type FFIDConfig, type FFIDOAuthUserInfo, type FFIDOrganization, type FFIDSubscription, type FFIDUser, type KVNamespaceLike, type TokenData, type TokenStore, createFFIDClient, createKVCacheAdapter, createMemoryCacheAdapter, createTokenStore, createVerifyAccessToken };