@plyaz/types 1.11.0 → 1.11.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.
@@ -4,4 +4,4 @@
4
4
  *
5
5
  * @module core
6
6
  */
7
- export type { ApiEnvironmentConfig } from './services';
7
+ export type { ApiEnvironmentConfig, ApiProviderProps } from './services';
@@ -2,6 +2,8 @@
2
2
  * Service Layer Types for @plyaz/core
3
3
  * Types specific to core package services
4
4
  */
5
+ import type { ReactNode } from 'react';
6
+ import type { ApiClientOptions } from '../api/client';
5
7
  /**
6
8
  * Environment configuration for API client initialization
7
9
  *
@@ -180,3 +182,265 @@ export interface ApiEnvironmentConfig {
180
182
  */
181
183
  setAsDefault?: boolean;
182
184
  }
185
+ /**
186
+ * Props for ApiProvider component
187
+ *
188
+ * React provider component that initializes the API client service for React/Next.js applications.
189
+ * Wraps your app to ensure the API client is ready before rendering children.
190
+ *
191
+ * **Features**:
192
+ * - Automatic API client initialization on mount
193
+ * - Loading state management during initialization
194
+ * - Error handling with customizable error UI
195
+ * - Success/error callbacks for integration with state management
196
+ * - Singleton pattern - only initializes once per app lifecycle
197
+ *
198
+ * **Important**:
199
+ * - Initialization runs ONCE on mount, regardless of prop changes
200
+ * - Config changes after mount are NOT supported (singleton pattern)
201
+ * - If you need to change config, use `ApiClientService.reinitialize()` manually
202
+ * - To avoid unnecessary re-renders, memoize `envConfig` and `apiConfig` in parent component
203
+ *
204
+ * @example
205
+ * ```tsx
206
+ * // Basic usage in Next.js app layout
207
+ * // IMPORTANT: For client components, pass sensitive config from server-side props/actions
208
+ * import { ApiProvider } from '@plyaz/core';
209
+ * import { useMemo } from 'react';
210
+ *
211
+ * export default function RootLayout({ children }) {
212
+ * // Memoize configs to prevent unnecessary re-renders
213
+ * const envConfig = useMemo(() => ({
214
+ * env: process.env.NODE_ENV as 'production',
215
+ * // ✅ OK: API keys can be public (handled by API gateway)
216
+ * apiKey: process.env.NEXT_PUBLIC_API_KEY,
217
+ * }), []);
218
+ *
219
+ * const apiConfig = useMemo(() => ({
220
+ * // ✅ OK: Public configuration
221
+ * baseURL: process.env.NEXT_PUBLIC_API_URL!,
222
+ * timeout: 30000,
223
+ * retry: { attempts: 3 },
224
+ * }), []);
225
+ *
226
+ * return (
227
+ * <ApiProvider envConfig={envConfig} apiConfig={apiConfig}>
228
+ * {children}
229
+ * </ApiProvider>
230
+ * );
231
+ * }
232
+ * ```
233
+ *
234
+ * @example
235
+ * ```tsx
236
+ * // Server-side initialization with encryption (Next.js Server Component)
237
+ * // Use this pattern when you need encryption keys or other sensitive config
238
+ * import { ApiProvider } from '@plyaz/core';
239
+ *
240
+ * export default async function RootLayout({ children }) {
241
+ * // Server-only: Get encryption key from server environment
242
+ * // ❌ NEVER use NEXT_PUBLIC_* for encryption keys!
243
+ * const encryptionKey = process.env.ENCRYPTION_KEY; // Server-only
244
+ *
245
+ * const envConfig = {
246
+ * env: process.env.NODE_ENV as 'production',
247
+ * };
248
+ *
249
+ * const apiConfig = {
250
+ * baseURL: process.env.NEXT_PUBLIC_API_URL!,
251
+ * // ✅ Correct encryption key shape
252
+ * encryption: {
253
+ * enabled: true,
254
+ * key: {
255
+ * id: 'prod-key-v1',
256
+ * key: encryptionKey!, // From server environment
257
+ * algorithm: 'AES-GCM' as const,
258
+ * format: 'raw' as const,
259
+ * },
260
+ * // Optional: Specify fields to encrypt
261
+ * fields: [
262
+ * '*.email',
263
+ * '*.ssn',
264
+ * 'user.*.phone',
265
+ * 'payment.cardNumber',
266
+ * ],
267
+ * },
268
+ * };
269
+ *
270
+ * return (
271
+ * <ApiProvider envConfig={envConfig} apiConfig={apiConfig}>
272
+ * {children}
273
+ * </ApiProvider>
274
+ * );
275
+ * }
276
+ * ```
277
+ *
278
+ * @example
279
+ * ```tsx
280
+ * // With custom loading and error components
281
+ * <ApiProvider
282
+ * envConfig={envConfig}
283
+ * apiConfig={apiConfig}
284
+ * loadingComponent={
285
+ * <div className="loading">
286
+ * <Spinner />
287
+ * <p>Initializing API client...</p>
288
+ * </div>
289
+ * }
290
+ * errorComponent={(error) => (
291
+ * <div className="error">
292
+ * <h2>API Initialization Failed</h2>
293
+ * <p>{error.message}</p>
294
+ * <button onClick={() => window.location.reload()}>Retry</button>
295
+ * </div>
296
+ * )}
297
+ * onInitialized={() => {
298
+ * console.log('[App] API client ready');
299
+ * }}
300
+ * onError={(error) => {
301
+ * console.error('[App] API initialization error:', error);
302
+ * }}
303
+ * >
304
+ * {children}
305
+ * </ApiProvider>
306
+ * ```
307
+ *
308
+ * @example
309
+ * ```tsx
310
+ * // With state management integration
311
+ * <ApiProvider
312
+ * envConfig={envConfig}
313
+ * apiConfig={{
314
+ * ...apiConfig,
315
+ * clientEvents: {
316
+ * onRequestStart: (event) => {
317
+ * apiStore.setState({ loading: true, requestId: event.data.id });
318
+ * },
319
+ * onResponseReceived: (event) => {
320
+ * apiStore.setState({ loading: false, lastResponse: event.data });
321
+ * },
322
+ * },
323
+ * }}
324
+ * onInitialized={() => {
325
+ * appStore.setState({ apiReady: true });
326
+ * }}
327
+ * >
328
+ * {children}
329
+ * </ApiProvider>
330
+ * ```
331
+ *
332
+ * @see {@link ApiEnvironmentConfig} - Environment configuration options
333
+ * @see {@link ApiClientOptions} from @plyaz/types/api - Full API configuration options
334
+ * @since 1.1.0
335
+ */
336
+ export interface ApiProviderProps {
337
+ /**
338
+ * React children to render after successful initialization
339
+ *
340
+ * Children are only rendered once the API client is fully initialized and ready.
341
+ * If initialization fails, the error component is rendered instead.
342
+ */
343
+ children: ReactNode;
344
+ /**
345
+ * Environment configuration
346
+ *
347
+ * Contains environment-level metadata (env, apiKey, rateLimit, setAsDefault).
348
+ * Determines which default configuration to apply from @plyaz/config.
349
+ *
350
+ * @see {@link ApiEnvironmentConfig} - Full configuration options
351
+ */
352
+ envConfig: ApiEnvironmentConfig;
353
+ /**
354
+ * API configuration
355
+ *
356
+ * Contains API-specific settings (baseURL, encryption, timeout, event handlers).
357
+ * All options from @plyaz/api's `ApiClientOptions` interface are supported.
358
+ *
359
+ * **Required fields**:
360
+ * - `baseURL`: API base URL
361
+ *
362
+ * **Commonly configured**:
363
+ * - `encryption`: Encryption configuration with key
364
+ * - `timeout`: Request timeout in milliseconds
365
+ * - `clientEvents`: Event handlers for monitoring
366
+ * - `retry`: Retry strategy configuration
367
+ *
368
+ * @see {@link ApiClientOptions} from @plyaz/types/api - Complete options reference
369
+ */
370
+ apiConfig: Partial<ApiClientOptions>;
371
+ /**
372
+ * Loading component to show while initializing
373
+ *
374
+ * Rendered while the API client is being initialized. If not provided,
375
+ * a default loading message is shown.
376
+ *
377
+ * @optional
378
+ *
379
+ * @example
380
+ * ```tsx
381
+ * loadingComponent={
382
+ * <div className="loading">
383
+ * <Spinner size="large" />
384
+ * <p>Setting up API connection...</p>
385
+ * </div>
386
+ * }
387
+ * ```
388
+ */
389
+ loadingComponent?: ReactNode;
390
+ /**
391
+ * Error component to show if initialization fails
392
+ *
393
+ * Rendered when API client initialization fails. Receives the error as a parameter.
394
+ * If not provided, a default error message is shown.
395
+ *
396
+ * @optional
397
+ *
398
+ * @example
399
+ * ```tsx
400
+ * errorComponent={(error) => (
401
+ * <ErrorBoundary error={error}>
402
+ * <button onClick={() => window.location.reload()}>
403
+ * Retry
404
+ * </button>
405
+ * </ErrorBoundary>
406
+ * )}
407
+ * ```
408
+ */
409
+ errorComponent?: (error: Error) => ReactNode;
410
+ /**
411
+ * Callback when initialization completes successfully
412
+ *
413
+ * Called once the API client is fully initialized and ready to use.
414
+ * Useful for tracking initialization success or triggering post-init logic.
415
+ *
416
+ * @optional
417
+ *
418
+ * @example
419
+ * ```tsx
420
+ * onInitialized={() => {
421
+ * console.log('[App] API client initialized');
422
+ * analytics.track('api_client_ready');
423
+ * appStore.setState({ apiReady: true });
424
+ * }}
425
+ * ```
426
+ */
427
+ onInitialized?: () => void;
428
+ /**
429
+ * Callback when initialization fails
430
+ *
431
+ * Called if API client initialization throws an error.
432
+ * Useful for error tracking, logging, or showing user notifications.
433
+ *
434
+ * @optional
435
+ *
436
+ * @example
437
+ * ```tsx
438
+ * onError={(error) => {
439
+ * console.error('[App] API initialization failed:', error);
440
+ * Sentry.captureException(error);
441
+ * toast.error('Failed to connect to API');
442
+ * }}
443
+ * ```
444
+ */
445
+ onError?: (error: Error) => void;
446
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plyaz/types",
3
- "version": "1.11.0",
3
+ "version": "1.11.2",
4
4
  "author": "Redeemer Pace",
5
5
  "license": "ISC",
6
6
  "description": "Provides shared TypeScript types and schema utilities for validation and parsing in the @playz ecosystem.",