@onivoro/isomorphic-common 24.0.0 → 24.0.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,314 +0,0 @@
1
- # @onivoro/isomorphic-axios
2
-
3
- HTTP client utilities and Axios configuration for both browser and server environments. This package provides a comprehensive set of tools for creating configurable Axios instances with built-in retry logic, error handling, and request/response interceptors that work seamlessly across client and server codebases.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install @onivoro/isomorphic-axios
9
- ```
10
-
11
- ## Features
12
-
13
- - **Isomorphic Design**: Works identically in browser and Node.js environments
14
- - **Advanced Axios Factory**: Create pre-configured Axios instances with custom interceptors
15
- - **Retry Logic**: Built-in request retry mechanism with configurable delays
16
- - **Error Handling**: Flexible error handling with status-specific handlers
17
- - **Header Management**: Dynamic header setting based on request context
18
- - **API Client Factory**: Streamlined creation of API clients from OpenAPI specs
19
- - **TypeScript Support**: Full TypeScript support with comprehensive type definitions
20
-
21
- ## Quick Start
22
-
23
- ### Basic Axios Instance Creation
24
-
25
- ```typescript
26
- import { createAxiosInstance } from '@onivoro/isomorphic-axios';
27
-
28
- // Create a simple axios instance
29
- const apiClient = createAxiosInstance({
30
- apiUrl: 'https://api.example.com',
31
- accessToken: 'your-token-here'
32
- });
33
-
34
- // Use the instance
35
- const response = await apiClient.get('/users');
36
- ```
37
-
38
- ### Advanced Axios Factory with Custom Configuration
39
-
40
- ```typescript
41
- import { axiosInstanceFactory } from '@onivoro/isomorphic-axios';
42
-
43
- const axiosInstance = axiosInstanceFactory({
44
- headerSetters: {
45
- 'Authorization': (req) => `Bearer ${getToken()}`,
46
- 'X-API-Key': (req) => process.env.API_KEY,
47
- 'Content-Type': (req) => 'application/json'
48
- },
49
- errorHandlers: {
50
- 401: async (error, response) => {
51
- // Handle unauthorized errors
52
- await refreshToken();
53
- return retry(error);
54
- },
55
- 500: async (error, response) => {
56
- // Handle server errors
57
- console.error('Server error:', response?.data);
58
- throw error;
59
- },
60
- 0: async (error, response) => {
61
- // Default error handler
62
- console.error('Request failed:', error.message);
63
- throw error;
64
- }
65
- },
66
- beforeRetryHandlers: {
67
- 429: async (error, response) => {
68
- // Handle rate limiting before retry
69
- const retryAfter = response?.headers['retry-after'];
70
- if (retryAfter) {
71
- await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
72
- }
73
- }
74
- },
75
- axiosConfigOverride: {
76
- timeout: 10000,
77
- retry: 3,
78
- retryDelay: 2000
79
- }
80
- });
81
- ```
82
-
83
- ## Usage Examples
84
-
85
- ### Creating API Clients
86
-
87
- ```typescript
88
- import { createApi } from '@onivoro/isomorphic-axios';
89
- import { DefaultApi } from './generated-client';
90
-
91
- // Create an API client from generated OpenAPI client
92
- const apiClient = createApi(DefaultApi, {
93
- apiUrl: 'https://api.example.com',
94
- accessToken: 'your-token'
95
- });
96
-
97
- // Use the generated API methods
98
- const users = await apiClient.getUsers();
99
- const user = await apiClient.createUser({ name: 'John Doe' });
100
- ```
101
-
102
- ### Manual Retry Logic
103
-
104
- ```typescript
105
- import { retryAxiosCall } from '@onivoro/isomorphic-axios';
106
- import axios from 'axios';
107
-
108
- const instance = axios.create();
109
-
110
- instance.interceptors.response.use(
111
- response => response,
112
- async (error) => {
113
- if (shouldRetry(error)) {
114
- return retryAxiosCall(error, instance);
115
- }
116
- throw error;
117
- }
118
- );
119
- ```
120
-
121
- ### Environment-Specific Configuration
122
-
123
- ```typescript
124
- import { createAxiosInstance } from '@onivoro/isomorphic-axios';
125
-
126
- // Browser environment
127
- const browserClient = createAxiosInstance({
128
- apiUrl: window.location.origin + '/api',
129
- accessToken: localStorage.getItem('token')
130
- });
131
-
132
- // Server environment
133
- const serverClient = createAxiosInstance({
134
- apiUrl: process.env.INTERNAL_API_URL,
135
- accessToken: process.env.SERVICE_TOKEN
136
- });
137
- ```
138
-
139
- ### Request/Response Interceptors
140
-
141
- ```typescript
142
- import { axiosInstanceFactory } from '@onivoro/isomorphic-axios';
143
-
144
- const client = axiosInstanceFactory({
145
- headerSetters: {
146
- 'X-Request-ID': () => generateRequestId(),
147
- 'X-User-Agent': () => getUserAgent(),
148
- 'X-Timestamp': () => new Date().toISOString()
149
- },
150
- errorHandlers: {
151
- // Retry on network errors
152
- 0: async (error) => {
153
- if (error.code === 'NETWORK_ERROR') {
154
- throw new Error('Network connection failed');
155
- }
156
- throw error;
157
- },
158
- // Handle authentication errors
159
- 401: async (error) => {
160
- await signOut();
161
- window.location.href = '/login';
162
- throw error;
163
- },
164
- // Handle validation errors
165
- 422: async (error) => {
166
- const validationErrors = error.response?.data?.errors;
167
- throw new ValidationError(validationErrors);
168
- }
169
- }
170
- });
171
- ```
172
-
173
- ## API Reference
174
-
175
- ### Functions
176
-
177
- #### `axiosInstanceFactory<TData>(params)`
178
-
179
- Creates a fully configured Axios instance with interceptors, retry logic, and error handling.
180
-
181
- **Parameters:**
182
- - `headerSetters`: Object mapping header names to functions that return header values
183
- - `errorHandlers`: Object mapping HTTP status codes to error handling functions
184
- - `beforeRetryHandlers`: Object mapping status codes to functions called before retries
185
- - `axiosConfigOverride`: Optional Axios configuration overrides
186
-
187
- **Returns:** Configured Axios instance
188
-
189
- #### `createApi<TApi>(DefaultApi, config)`
190
-
191
- Creates an API client instance from a generated OpenAPI client class.
192
-
193
- **Parameters:**
194
- - `DefaultApi`: Constructor function for the generated API client
195
- - `config`: API configuration object with `apiUrl` and optional `accessToken`
196
-
197
- **Returns:** Configured API client instance
198
-
199
- #### `createAxiosInstance(config)`
200
-
201
- Creates a simple Axios instance with basic authentication and URL configuration.
202
-
203
- **Parameters:**
204
- - `config`: Configuration object with `apiUrl` and optional `accessToken`
205
-
206
- **Returns:** Configured Axios instance
207
-
208
- #### `retryAxiosCall<TData>(error, instance)`
209
-
210
- Manually retry a failed Axios request with exponential backoff.
211
-
212
- **Parameters:**
213
- - `error`: The error object from the failed request
214
- - `instance`: The Axios instance to use for the retry
215
-
216
- **Returns:** Promise resolving to the retry response
217
-
218
- ### Types
219
-
220
- #### `TApiConfig`
221
-
222
- Configuration interface for API clients:
223
- ```typescript
224
- interface TApiConfig {
225
- apiUrl: string;
226
- accessToken?: string;
227
- }
228
- ```
229
-
230
- #### `THeaderSetterMap<TData>`
231
-
232
- Map of header names to functions that set header values:
233
- ```typescript
234
- type THeaderSetterMap<TData> = {
235
- [headerName: string]: (request: AxiosRequestConfig) => string;
236
- };
237
- ```
238
-
239
- #### `TErrorHandlerMap<TData>`
240
-
241
- Map of HTTP status codes to error handling functions:
242
- ```typescript
243
- type TErrorHandlerMap<TData> = {
244
- [statusCode: number]: TErrorHandler<TData>;
245
- };
246
- ```
247
-
248
- ### Constants
249
-
250
- #### `defaultAxiosConfig`
251
-
252
- Default Axios configuration with sensible defaults:
253
- ```typescript
254
- {
255
- timeout: 30000,
256
- retry: 2,
257
- retryDelay: 1000
258
- }
259
- ```
260
-
261
- ## Advanced Configuration
262
-
263
- ### Custom Error Recovery
264
-
265
- ```typescript
266
- import { axiosInstanceFactory } from '@onivoro/isomorphic-axios';
267
-
268
- const resilientClient = axiosInstanceFactory({
269
- errorHandlers: {
270
- // Implement circuit breaker pattern
271
- 0: async (error) => {
272
- if (circuitBreaker.isOpen()) {
273
- throw new Error('Circuit breaker is open');
274
- }
275
- circuitBreaker.recordFailure();
276
- throw error;
277
- }
278
- },
279
- beforeRetryHandlers: {
280
- // Implement exponential backoff with jitter
281
- 0: async (error) => {
282
- const attempt = error.config.__retryCount || 0;
283
- const delay = Math.min(1000 * Math.pow(2, attempt), 30000);
284
- const jitter = Math.random() * 1000;
285
- await new Promise(resolve => setTimeout(resolve, delay + jitter));
286
- }
287
- }
288
- });
289
- ```
290
-
291
- ### Request/Response Logging
292
-
293
- ```typescript
294
- const debugClient = axiosInstanceFactory({
295
- headerSetters: {
296
- 'X-Debug-Mode': () => process.env.NODE_ENV === 'development' ? 'true' : 'false'
297
- },
298
- errorHandlers: {
299
- 0: async (error) => {
300
- console.error('Request failed:', {
301
- url: error.config?.url,
302
- method: error.config?.method,
303
- status: error.response?.status,
304
- data: error.response?.data
305
- });
306
- throw error;
307
- }
308
- }
309
- });
310
- ```
311
-
312
- ## License
313
-
314
- MIT
@@ -1,10 +0,0 @@
1
- {
2
- "name": "@onivoro/isomorphic-axios",
3
- "version": "23.0.0",
4
- "type": "commonjs",
5
- "main": "./src/index.js",
6
- "types": "./src/index.d.ts",
7
- "dependencies": {
8
- "tslib": "^2.3.0"
9
- }
10
- }
@@ -1,393 +0,0 @@
1
- # @onivoro/isomorphic-common
2
-
3
- Common utilities, functions, types, and constants shared between browser and server environments. This comprehensive library provides essential building blocks for TypeScript applications with a focus on type safety, reliability, and consistent behavior across different runtime environments.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install @onivoro/isomorphic-common
9
- ```
10
-
11
- ## Features
12
-
13
- - **Isomorphic Design**: Works identically in browser and Node.js environments
14
- - **String Manipulation**: Case conversion, formatting, and validation utilities
15
- - **Array Operations**: Chunking, sorting, deduplication, and transformation functions
16
- - **Date/Time Utilities**: Calendar operations, offset calculations, and formatting
17
- - **Financial Functions**: Currency formatting, money calculations, and validation
18
- - **Type Utilities**: Advanced TypeScript type helpers and interfaces
19
- - **Validation Functions**: Data validation and parsing utilities
20
- - **Testing Helpers**: Mock functions and test arrangement utilities
21
- - **Constants**: Common values, regex patterns, and configuration constants
22
-
23
- ## Quick Start
24
-
25
- ### String Operations
26
-
27
- ```typescript
28
- import {
29
- camelCase,
30
- kebabCase,
31
- snakeCase,
32
- upperFirst,
33
- sanitizeFilename,
34
- formatUsd
35
- } from '@onivoro/isomorphic-common';
36
-
37
- // Case conversions
38
- camelCase('hello world'); // 'helloWorld'
39
- kebabCase('Hello World'); // 'hello-world'
40
- snakeCase('Hello World'); // 'hello_world'
41
- upperFirst('hello'); // 'Hello'
42
-
43
- // File operations
44
- sanitizeFilename('My File/Name?.txt'); // 'My File Name .txt'
45
-
46
- // Currency formatting
47
- formatUsd(1234.56); // '$1,234.56'
48
- formatUsd('1234.56'); // '$1,234.56'
49
- ```
50
-
51
- ### Array Manipulation
52
-
53
- ```typescript
54
- import {
55
- chunk,
56
- toUniqueArray,
57
- removeElementAtIndex,
58
- sortByName,
59
- sortById,
60
- sortNumbers
61
- } from '@onivoro/isomorphic-common';
62
-
63
- // Chunking arrays
64
- chunk([1, 2, 3, 4, 5, 6], 3); // [[1, 2], [3, 4], [5, 6]]
65
-
66
- // Remove duplicates
67
- toUniqueArray([1, 2, 2, 3, 3, 4]); // [1, 2, 3, 4]
68
-
69
- // Remove element by index
70
- removeElementAtIndex(['a', 'b', 'c'], 1); // ['a', 'c']
71
-
72
- // Sorting utilities
73
- sortByName([{name: 'Bob'}, {name: 'Alice'}]); // [{name: 'Alice'}, {name: 'Bob'}]
74
- sortById([{id: 3}, {id: 1}, {id: 2}]); // [{id: 1}, {id: 2}, {id: 3}]
75
- sortNumbers([3, 1, 4, 1, 5]); // [1, 1, 3, 4, 5]
76
- ```
77
-
78
- ### Date and Time Operations
79
-
80
- ```typescript
81
- import {
82
- addOffset,
83
- subtractOffset,
84
- getDateRangeForMonth,
85
- splitDateRangeIntoDays,
86
- isValidDate,
87
- tryParseDate,
88
- toCalendarDate,
89
- fromCalendarDate
90
- } from '@onivoro/isomorphic-common';
91
-
92
- // Date offset calculations
93
- const date = new Date('2023-01-15');
94
- addOffset(date, 7); // Add 7 days
95
- subtractOffset(date, 2); // Subtract 2 days
96
-
97
- // Monthly date ranges
98
- getDateRangeForMonth(2023, 0); // January 2023 range
99
-
100
- // Date validation
101
- isValidDate(new Date('2023-01-15')); // true
102
- isValidDate(new Date('invalid')); // false
103
-
104
- // Safe date parsing
105
- tryParseDate('2023-01-15'); // Date object or null
106
- ```
107
-
108
- ### Financial and Money Operations
109
-
110
- ```typescript
111
- import {
112
- money,
113
- toDollarsAndCents,
114
- round,
115
- formatUsd
116
- } from '@onivoro/isomorphic-common';
117
-
118
- // Money calculations (in cents)
119
- const price = money(19.99); // 1999 cents
120
- const tax = money(price * 0.08); // Calculate tax
121
- const total = price + tax;
122
-
123
- // Convert back to dollars
124
- toDollarsAndCents(total); // { dollars: 21, cents: 59 }
125
-
126
- // Rounding
127
- round(19.999, 2); // 20.00
128
- round(19.994, 2); // 19.99
129
-
130
- // Currency display
131
- formatUsd(total / 100); // '$21.59'
132
- ```
133
-
134
- ## Usage Examples
135
-
136
- ### Data Transformation
137
-
138
- ```typescript
139
- import {
140
- mapEnumToOptions,
141
- mapEntitiesToOptions,
142
- convertObjectToLiteral,
143
- propertiestoArray
144
- } from '@onivoro/isomorphic-common';
145
-
146
- enum Status {
147
- ACTIVE = 'active',
148
- INACTIVE = 'inactive',
149
- PENDING = 'pending'
150
- }
151
-
152
- // Convert enum to dropdown options
153
- const statusOptions = mapEnumToOptions(Status);
154
- // [{ label: 'Active', value: 'active' }, ...]
155
-
156
- // Convert entities to options
157
- const users = [{ id: 1, name: 'John' }, { id: 2, name: 'Jane' }];
158
- const userOptions = mapEntitiesToOptions(users, 'name', 'id');
159
- // [{ label: 'John', value: 1 }, { label: 'Jane', value: 2 }]
160
- ```
161
-
162
- ### Boolean and String Parsing
163
-
164
- ```typescript
165
- import {
166
- parseBool,
167
- fromBooleanString,
168
- toBooleanString,
169
- fromCsvString,
170
- toCsvString
171
- } from '@onivoro/isomorphic-common';
172
-
173
- // Boolean parsing
174
- parseBool('true'); // true
175
- parseBool('1'); // true
176
- parseBool('yes'); // true
177
- parseBool('false'); // false
178
-
179
- // CSV operations
180
- const items = fromCsvString('apple,banana,cherry');
181
- // ['apple', 'banana', 'cherry']
182
-
183
- toCsvString(['apple', 'banana', 'cherry']);
184
- // 'apple,banana,cherry'
185
- ```
186
-
187
- ### Testing Utilities
188
-
189
- ```typescript
190
- import {
191
- arrangeActAssert,
192
- mockCalls
193
- } from '@onivoro/isomorphic-common';
194
-
195
- // Test structure helper
196
- const testCase = arrangeActAssert({
197
- arrange: () => ({ input: 'test data' }),
198
- act: (arranged) => processData(arranged.input),
199
- assert: (result) => expect(result).toBeTruthy()
200
- });
201
-
202
- // Mock function calls tracking
203
- const mockTracker = mockCalls();
204
- mockTracker.track('functionName', ['arg1', 'arg2']);
205
- mockTracker.getCalls('functionName'); // [['arg1', 'arg2']]
206
- ```
207
-
208
- ## API Reference
209
-
210
- ### String Functions
211
-
212
- #### Case Conversion
213
- - `camelCase(string)` - Convert to camelCase
214
- - `kebabCase(string)` - Convert to kebab-case
215
- - `snakeCase(string)` - Convert to snake_case
216
- - `upperFirst(string)` - Capitalize first letter
217
-
218
- #### String Utilities
219
- - `sanitizeFilename(filename)` - Remove invalid filename characters
220
- - `removeAlphaChars(string)` - Remove alphabetic characters
221
- - `words(string)` - Split string into words array
222
- - `toString(value)` - Convert value to string safely
223
-
224
- ### Array Functions
225
-
226
- #### Array Manipulation
227
- - `chunk<T>(array, numDivisions)` - Split array into chunks
228
- - `toUniqueArray<T>(array)` - Remove duplicate elements
229
- - `removeElementAtIndex<T>(array, index)` - Remove element by index
230
-
231
- #### Sorting Functions
232
- - `sortByName<T>(array)` - Sort objects by name property
233
- - `sortById<T>(array)` - Sort objects by id property
234
- - `sortByFullName<T>(array)` - Sort objects by full name
235
- - `sortByCreatedAt<T>(array)` - Sort objects by creation date
236
- - `sortNumbers(array)` - Sort numeric array
237
-
238
- ### Date/Time Functions
239
-
240
- #### Date Operations
241
- - `addOffset(date, days)` - Add days to date
242
- - `subtractOffset(date, days)` - Subtract days from date
243
- - `getDateRangeForMonth(year, month)` - Get month's date range
244
- - `getDateLastMonth()` - Get previous month's date
245
- - `splitDateRangeIntoDays(start, end)` - Split range into daily intervals
246
-
247
- #### Date Utilities
248
- - `isValidDate(date)` - Check if date is valid
249
- - `tryParseDate(string)` - Safely parse date string
250
- - `toCalendarDate(date)` - Convert to calendar format
251
- - `fromCalendarDate(string)` - Parse calendar date string
252
- - `useDate(date)` - React hook for date handling
253
-
254
- #### Time Constants
255
- - `MILLIS_PER_MINUTE` - Milliseconds in a minute
256
- - `MILLIS_PER_HOUR` - Milliseconds in an hour
257
- - `MILLIS_PER_DAY` - Milliseconds in a day
258
-
259
- ### Financial Functions
260
-
261
- #### Money Operations
262
- - `money(amount)` - Convert dollars to cents
263
- - `toDollarsAndCents(cents)` - Convert cents to dollars/cents object
264
- - `formatUsd(amount)` - Format as USD currency
265
- - `round(number, precision)` - Round to decimal places
266
-
267
- ### Type Utilities
268
-
269
- #### Interfaces
270
- - `ILookup<T>` - Key-value lookup interface
271
- - `IAccessToken` - Access token structure
272
- - `IEntityProvider<T>` - Entity provider interface
273
-
274
- #### Type Helpers
275
- - `KeysOf<T>` - Extract keys of type T
276
- - `Createable<T>` - Type for creatable entities
277
- - `Nameable` - Type for entities with name property
278
- - `Company` - Company type definition
279
-
280
- ### Data Transformation
281
-
282
- #### Enum Utilities
283
- - `mapEnumToOptions(enum)` - Convert enum to option array
284
- - `mapEnumToArrayOfValues(enum)` - Convert enum to value array
285
- - `mapEnumToLookupArray(enum)` - Convert enum to lookup array
286
-
287
- #### Object Utilities
288
- - `convertObjectToLiteral(object)` - Convert to literal object
289
- - `propertiesToArray(object)` - Convert properties to array
290
- - `mapEntitiesToOptions(entities, labelKey, valueKey)` - Convert entities to options
291
-
292
- ### Validation Functions
293
-
294
- #### Data Validation
295
- - `parseBool(value)` - Parse boolean from various formats
296
- - `isSymbol(value)` - Check if value is symbol
297
- - `tryJsonParse(string)` - Safely parse JSON
298
- - `tryJsonStringify(object)` - Safely stringify JSON
299
-
300
- #### String Validation
301
- - `fromBooleanString(string)` - Convert string to boolean
302
- - `toBooleanString(boolean)` - Convert boolean to string
303
- - `fromCsvString(string)` - Parse CSV string
304
- - `toCsvString(array)` - Convert array to CSV
305
-
306
- ### Utility Functions
307
-
308
- #### General Utilities
309
- - `sleep(milliseconds)` - Async sleep function
310
- - `getTag(value)` - Get object type tag
311
- - `getUserFullName(user)` - Get user's full name
312
- - `toDecimalBase(number, base)` - Convert to decimal base
313
-
314
- #### Testing Helpers
315
- - `arrangeActAssert(config)` - Structure test cases
316
- - `mockCalls()` - Track mock function calls
317
-
318
- ### Constants
319
-
320
- #### Headers and Authentication
321
- - `API_ID_HEADER` - API ID header constant
322
- - `API_KEY_HEADER` - API key header constant
323
- - `AUTH_COOKIE_NAME` - Authentication cookie name
324
-
325
- #### Regular Expressions
326
- - `REGEXES` - Common regex patterns object
327
-
328
- ## Advanced Usage
329
-
330
- ### Custom Type Guards
331
-
332
- ```typescript
333
- import { isSymbol, isValidDate } from '@onivoro/isomorphic-common';
334
-
335
- function processValue(value: unknown) {
336
- if (isSymbol(value)) {
337
- return value.toString();
338
- }
339
-
340
- if (value instanceof Date && isValidDate(value)) {
341
- return value.toISOString();
342
- }
343
-
344
- return String(value);
345
- }
346
- ```
347
-
348
- ### Complex Data Transformations
349
-
350
- ```typescript
351
- import {
352
- chunk,
353
- mapEntitiesToOptions,
354
- sortByName,
355
- toUniqueArray
356
- } from '@onivoro/isomorphic-common';
357
-
358
- function processUserData(users: User[]) {
359
- return chunk(
360
- toUniqueArray(
361
- sortByName(users)
362
- ),
363
- 10 // Process in batches of 10
364
- ).map(batch =>
365
- mapEntitiesToOptions(batch, 'fullName', 'id')
366
- );
367
- }
368
- ```
369
-
370
- ### Date Range Operations
371
-
372
- ```typescript
373
- import {
374
- getDateRangeForMonth,
375
- splitDateRangeIntoDays,
376
- addOffset,
377
- subtractOffset
378
- } from '@onivoro/isomorphic-common';
379
-
380
- function getMonthlyReportDates(year: number, month: number) {
381
- const { start, end } = getDateRangeForMonth(year, month);
382
-
383
- // Add buffer days
384
- const reportStart = subtractOffset(start, 1);
385
- const reportEnd = addOffset(end, 1);
386
-
387
- return splitDateRangeIntoDays(reportStart, reportEnd);
388
- }
389
- ```
390
-
391
- ## License
392
-
393
- MIT