characterforge-js 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/LICENSE +22 -0
- package/README.md +472 -0
- package/dist/index.d.mts +226 -0
- package/dist/index.d.ts +226 -0
- package/dist/index.js +1170 -0
- package/dist/index.mjs +1119 -0
- package/package.json +59 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 CharacterForge
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
# CharacterForge SDK
|
|
2
|
+
|
|
3
|
+
AI-powered 3D character generation SDK for web and React Native applications.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/characterforge)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- 🎨 **Generate stylized 3D vinyl toy characters** using AI
|
|
11
|
+
- ⚡ **Zero dependencies** - lightweight and fast
|
|
12
|
+
- 🔄 **Built-in caching** - IndexedDB for web, file system for React Native
|
|
13
|
+
- 🔁 **Automatic retry logic** - with exponential backoff
|
|
14
|
+
- 📱 **Cross-platform** - works on web and React Native
|
|
15
|
+
- 🎯 **TypeScript support** - fully typed for excellent IDE support
|
|
16
|
+
- 🖼️ **Transparent backgrounds** - production-ready PNG images
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install characterforge
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### React Native Additional Setup
|
|
25
|
+
|
|
26
|
+
For React Native, you'll need to install one of the following file system packages:
|
|
27
|
+
|
|
28
|
+
**Expo:**
|
|
29
|
+
```bash
|
|
30
|
+
npx expo install expo-file-system @react-native-async-storage/async-storage
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Bare React Native:**
|
|
34
|
+
```bash
|
|
35
|
+
npm install react-native-fs @react-native-async-storage/async-storage
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Quick Start
|
|
39
|
+
|
|
40
|
+
### Web / React
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { createCharacterForgeClient } from 'characterforge';
|
|
44
|
+
|
|
45
|
+
// Create a client instance
|
|
46
|
+
const client = createCharacterForgeClient({
|
|
47
|
+
apiKey: 'your-api-key-here',
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Generate a character
|
|
51
|
+
const imageUrl = await client.generate({
|
|
52
|
+
gender: 'female',
|
|
53
|
+
skinTone: 'medium',
|
|
54
|
+
hairStyle: 'bob',
|
|
55
|
+
hairColor: 'brown',
|
|
56
|
+
clothing: 'hoodie',
|
|
57
|
+
clothingColor: 'blue',
|
|
58
|
+
eyeColor: 'brown',
|
|
59
|
+
accessories: ['glasses'],
|
|
60
|
+
transparent: true,
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Use the image URL
|
|
64
|
+
console.log('Generated image:', imageUrl);
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### React Native
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { createCharacterForgeClient } from 'characterforge';
|
|
71
|
+
import { Image } from 'react-native';
|
|
72
|
+
|
|
73
|
+
// Create a client instance
|
|
74
|
+
const client = createCharacterForgeClient({
|
|
75
|
+
apiKey: 'your-api-key-here',
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// In your component
|
|
79
|
+
function MyComponent() {
|
|
80
|
+
const [imageUrl, setImageUrl] = React.useState(null);
|
|
81
|
+
|
|
82
|
+
const generateCharacter = async () => {
|
|
83
|
+
const url = await client.generate({
|
|
84
|
+
gender: 'male',
|
|
85
|
+
skinTone: 'light',
|
|
86
|
+
hairStyle: 'quiff',
|
|
87
|
+
hairColor: 'blonde',
|
|
88
|
+
clothing: 'tshirt',
|
|
89
|
+
clothingColor: 'red',
|
|
90
|
+
eyeColor: 'blue',
|
|
91
|
+
accessories: ['cap'],
|
|
92
|
+
transparent: true,
|
|
93
|
+
});
|
|
94
|
+
setImageUrl(url);
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<>
|
|
99
|
+
<Button title="Generate Character" onPress={generateCharacter} />
|
|
100
|
+
{imageUrl && <Image source={{ uri: imageUrl }} style={{ width: 300, height: 300 }} />}
|
|
101
|
+
</>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## API Reference
|
|
107
|
+
|
|
108
|
+
### `createCharacterForgeClient(config)`
|
|
109
|
+
|
|
110
|
+
Creates a new SDK client instance.
|
|
111
|
+
|
|
112
|
+
**Parameters:**
|
|
113
|
+
|
|
114
|
+
- `config` - Client configuration object
|
|
115
|
+
|
|
116
|
+
**Configuration Options:**
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
interface CharacterForgeClientConfig {
|
|
120
|
+
/** API key for authentication (required) */
|
|
121
|
+
apiKey: string;
|
|
122
|
+
|
|
123
|
+
/** Base URL for the API (optional, defaults to production) */
|
|
124
|
+
baseUrl?: string;
|
|
125
|
+
|
|
126
|
+
/** Enable/disable client-side caching (default: true) */
|
|
127
|
+
cache?: boolean;
|
|
128
|
+
|
|
129
|
+
/** Custom cache manager implementation (optional) */
|
|
130
|
+
cacheManager?: CacheManager;
|
|
131
|
+
|
|
132
|
+
/** Request timeout in milliseconds (default: 60000) */
|
|
133
|
+
timeout?: number;
|
|
134
|
+
|
|
135
|
+
/** Retry configuration (optional) */
|
|
136
|
+
retry?: {
|
|
137
|
+
maxRetries: number; // default: 3
|
|
138
|
+
baseDelayMs: number; // default: 1000
|
|
139
|
+
maxDelayMs: number; // default: 10000
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Returns:** `CharacterForgeClient` instance
|
|
145
|
+
|
|
146
|
+
### `client.generate(config, onStatusUpdate?)`
|
|
147
|
+
|
|
148
|
+
Generates a character image based on the provided configuration.
|
|
149
|
+
|
|
150
|
+
**Parameters:**
|
|
151
|
+
|
|
152
|
+
- `config` - Character configuration object
|
|
153
|
+
- `onStatusUpdate` (optional) - Callback function for status updates
|
|
154
|
+
|
|
155
|
+
**Character Configuration:**
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
interface CharacterConfig {
|
|
159
|
+
/** Gender: 'male' | 'female' */
|
|
160
|
+
gender: Gender;
|
|
161
|
+
|
|
162
|
+
/** Age group (optional): 'kid' | 'preteen' | 'teen' | 'young_adult' | 'adult' */
|
|
163
|
+
ageGroup?: AgeGroupId;
|
|
164
|
+
|
|
165
|
+
/** Skin tone: 'porcelain' | 'fair' | 'light' | 'medium' | 'olive' | 'brown' | 'dark' | 'deep' */
|
|
166
|
+
skinTone: SkinToneId;
|
|
167
|
+
|
|
168
|
+
/** Hair style: 'bob' | 'ponytail' | 'buns' | 'long' | 'pixie' | 'undercut' | 'quiff' | 'sidepart' | 'buzz' | 'combover' | 'messy' | 'afro' | 'curly' */
|
|
169
|
+
hairStyle: HairStyleId;
|
|
170
|
+
|
|
171
|
+
/** Hair color: 'black' | 'dark_brown' | 'brown' | 'auburn' | 'ginger' | 'dark_blonde' | 'blonde' | 'platinum' | 'grey' | 'white' | 'blue' | 'purple' */
|
|
172
|
+
hairColor: HairColorId;
|
|
173
|
+
|
|
174
|
+
/** Clothing: 'tshirt' | 'hoodie' | 'sweater' | 'jacket' | 'tank' | 'dress' | 'blouse' | 'polo' | 'buttonup' | 'henley' */
|
|
175
|
+
clothing: ClothingItemId;
|
|
176
|
+
|
|
177
|
+
/** Clothing color: 'white' | 'black' | 'navy' | 'red' | 'blue' | 'green' | 'yellow' | 'purple' | 'pink' | 'orange' | 'teal' */
|
|
178
|
+
clothingColor: ClothingColorId;
|
|
179
|
+
|
|
180
|
+
/** Eye color: 'dark' | 'brown' | 'blue' | 'green' | 'hazel' | 'grey' */
|
|
181
|
+
eyeColor: EyeColorId;
|
|
182
|
+
|
|
183
|
+
/** Accessories: array of 'none' | 'glasses' | 'sunglasses' | 'headphones' | 'cap' | 'beanie' */
|
|
184
|
+
accessories: AccessoryId[];
|
|
185
|
+
|
|
186
|
+
/** Generate with transparent background (default: true) */
|
|
187
|
+
transparent: boolean;
|
|
188
|
+
|
|
189
|
+
/** Use caching for this generation (default: true) */
|
|
190
|
+
cache?: boolean;
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
**Returns:** `Promise<string>` - URL to the generated image
|
|
195
|
+
|
|
196
|
+
**Example with status updates:**
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
const imageUrl = await client.generate(
|
|
200
|
+
{
|
|
201
|
+
gender: 'female',
|
|
202
|
+
skinTone: 'medium',
|
|
203
|
+
hairStyle: 'bob',
|
|
204
|
+
hairColor: 'brown',
|
|
205
|
+
clothing: 'hoodie',
|
|
206
|
+
clothingColor: 'blue',
|
|
207
|
+
eyeColor: 'brown',
|
|
208
|
+
accessories: ['glasses'],
|
|
209
|
+
transparent: true,
|
|
210
|
+
},
|
|
211
|
+
(status) => {
|
|
212
|
+
console.log('Status:', status);
|
|
213
|
+
// "Calling AI Cloud..."
|
|
214
|
+
// "Caching result..."
|
|
215
|
+
// "Retrieved from Client Cache!"
|
|
216
|
+
}
|
|
217
|
+
);
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### `client.clearCache()`
|
|
221
|
+
|
|
222
|
+
Clears all cached images.
|
|
223
|
+
|
|
224
|
+
**Returns:** `Promise<void>`
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
await client.clearCache();
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## Error Handling
|
|
231
|
+
|
|
232
|
+
The SDK provides specific error classes for different failure scenarios:
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
import {
|
|
236
|
+
AuthenticationError,
|
|
237
|
+
InsufficientCreditsError,
|
|
238
|
+
NetworkError,
|
|
239
|
+
RateLimitError,
|
|
240
|
+
GenerationError,
|
|
241
|
+
} from 'characterforge';
|
|
242
|
+
|
|
243
|
+
try {
|
|
244
|
+
const imageUrl = await client.generate(config);
|
|
245
|
+
} catch (error) {
|
|
246
|
+
if (error instanceof AuthenticationError) {
|
|
247
|
+
console.error('Invalid API key');
|
|
248
|
+
} else if (error instanceof InsufficientCreditsError) {
|
|
249
|
+
console.error('Not enough credits. Please purchase more.');
|
|
250
|
+
} else if (error instanceof NetworkError) {
|
|
251
|
+
console.error('Network error. Please check your connection.');
|
|
252
|
+
} else if (error instanceof RateLimitError) {
|
|
253
|
+
console.error('Rate limited. Please slow down.');
|
|
254
|
+
} else if (error instanceof GenerationError) {
|
|
255
|
+
console.error('Generation failed:', error.message);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Caching
|
|
261
|
+
|
|
262
|
+
The SDK automatically caches generated images to reduce API calls and improve performance.
|
|
263
|
+
|
|
264
|
+
### Web Caching
|
|
265
|
+
|
|
266
|
+
- Uses **IndexedDB** for persistent storage
|
|
267
|
+
- Automatically manages object URLs to prevent memory leaks
|
|
268
|
+
- Configurable cache size (default: 100 images)
|
|
269
|
+
- Auto-expires after 7 days
|
|
270
|
+
- Automatically cleans up old entries
|
|
271
|
+
|
|
272
|
+
### React Native Caching
|
|
273
|
+
|
|
274
|
+
- Uses **file system** for image storage
|
|
275
|
+
- Uses **AsyncStorage** for metadata
|
|
276
|
+
- Platform-specific implementations for Expo and bare React Native
|
|
277
|
+
- Same cache size and expiry settings as web
|
|
278
|
+
|
|
279
|
+
### Disabling Cache
|
|
280
|
+
|
|
281
|
+
You can disable caching globally or per-request:
|
|
282
|
+
|
|
283
|
+
```typescript
|
|
284
|
+
// Disable globally
|
|
285
|
+
const client = createCharacterForgeClient({
|
|
286
|
+
apiKey: 'your-api-key',
|
|
287
|
+
cache: false,
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// Disable per-request
|
|
291
|
+
const imageUrl = await client.generate({
|
|
292
|
+
...config,
|
|
293
|
+
cache: false,
|
|
294
|
+
});
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Custom Cache Manager
|
|
298
|
+
|
|
299
|
+
For advanced use cases, you can provide a custom cache implementation:
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
import { CacheManager } from 'characterforge';
|
|
303
|
+
|
|
304
|
+
class MyCustomCache implements CacheManager {
|
|
305
|
+
async get(key: string): Promise<string | null> {
|
|
306
|
+
// Your implementation
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
async set(key: string, data: Blob | string): Promise<string> {
|
|
310
|
+
// Your implementation
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
async clear(): Promise<void> {
|
|
314
|
+
// Your implementation
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const client = createCharacterForgeClient({
|
|
319
|
+
apiKey: 'your-api-key',
|
|
320
|
+
cacheManager: new MyCustomCache(),
|
|
321
|
+
});
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
## Advanced Configuration
|
|
325
|
+
|
|
326
|
+
### Custom Base URL
|
|
327
|
+
|
|
328
|
+
If you're self-hosting or using a custom endpoint:
|
|
329
|
+
|
|
330
|
+
```typescript
|
|
331
|
+
const client = createCharacterForgeClient({
|
|
332
|
+
apiKey: 'your-api-key',
|
|
333
|
+
baseUrl: 'https://your-custom-domain.com/functions/v1',
|
|
334
|
+
});
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### Custom Timeout
|
|
338
|
+
|
|
339
|
+
Adjust the request timeout (default is 60 seconds):
|
|
340
|
+
|
|
341
|
+
```typescript
|
|
342
|
+
const client = createCharacterForgeClient({
|
|
343
|
+
apiKey: 'your-api-key',
|
|
344
|
+
timeout: 30000, // 30 seconds
|
|
345
|
+
});
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Custom Retry Configuration
|
|
349
|
+
|
|
350
|
+
Adjust the retry behavior:
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
const client = createCharacterForgeClient({
|
|
354
|
+
apiKey: 'your-api-key',
|
|
355
|
+
retry: {
|
|
356
|
+
maxRetries: 5,
|
|
357
|
+
baseDelayMs: 2000,
|
|
358
|
+
maxDelayMs: 20000,
|
|
359
|
+
},
|
|
360
|
+
});
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
## TypeScript Support
|
|
364
|
+
|
|
365
|
+
The SDK is written in TypeScript and provides full type definitions:
|
|
366
|
+
|
|
367
|
+
```typescript
|
|
368
|
+
import type {
|
|
369
|
+
CharacterConfig,
|
|
370
|
+
CharacterForgeClientConfig,
|
|
371
|
+
Gender,
|
|
372
|
+
SkinToneId,
|
|
373
|
+
HairStyleId,
|
|
374
|
+
// ... and more
|
|
375
|
+
} from 'characterforge';
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
All types are exported for your convenience, enabling excellent IDE autocomplete and type checking.
|
|
379
|
+
|
|
380
|
+
## Examples
|
|
381
|
+
|
|
382
|
+
### Complete React Component
|
|
383
|
+
|
|
384
|
+
```tsx
|
|
385
|
+
import React, { useState } from 'react';
|
|
386
|
+
import { createCharacterForgeClient } from 'characterforge';
|
|
387
|
+
|
|
388
|
+
const client = createCharacterForgeClient({
|
|
389
|
+
apiKey: process.env.REACT_APP_CHARACTER_FORGE_KEY!,
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
export function CharacterGenerator() {
|
|
393
|
+
const [imageUrl, setImageUrl] = useState<string | null>(null);
|
|
394
|
+
const [loading, setLoading] = useState(false);
|
|
395
|
+
const [status, setStatus] = useState('');
|
|
396
|
+
const [error, setError] = useState<string | null>(null);
|
|
397
|
+
|
|
398
|
+
const handleGenerate = async () => {
|
|
399
|
+
setLoading(true);
|
|
400
|
+
setError(null);
|
|
401
|
+
|
|
402
|
+
try {
|
|
403
|
+
const url = await client.generate(
|
|
404
|
+
{
|
|
405
|
+
gender: 'female',
|
|
406
|
+
skinTone: 'medium',
|
|
407
|
+
hairStyle: 'bob',
|
|
408
|
+
hairColor: 'brown',
|
|
409
|
+
clothing: 'hoodie',
|
|
410
|
+
clothingColor: 'blue',
|
|
411
|
+
eyeColor: 'brown',
|
|
412
|
+
accessories: ['glasses'],
|
|
413
|
+
transparent: true,
|
|
414
|
+
},
|
|
415
|
+
(status) => setStatus(status)
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
setImageUrl(url);
|
|
419
|
+
} catch (err) {
|
|
420
|
+
setError(err instanceof Error ? err.message : 'Generation failed');
|
|
421
|
+
} finally {
|
|
422
|
+
setLoading(false);
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
return (
|
|
427
|
+
<div>
|
|
428
|
+
<button onClick={handleGenerate} disabled={loading}>
|
|
429
|
+
{loading ? 'Generating...' : 'Generate Character'}
|
|
430
|
+
</button>
|
|
431
|
+
|
|
432
|
+
{status && <p>Status: {status}</p>}
|
|
433
|
+
{error && <p style={{ color: 'red' }}>Error: {error}</p>}
|
|
434
|
+
|
|
435
|
+
{imageUrl && (
|
|
436
|
+
<img
|
|
437
|
+
src={imageUrl}
|
|
438
|
+
alt="Generated character"
|
|
439
|
+
style={{ width: 300, height: 300 }}
|
|
440
|
+
/>
|
|
441
|
+
)}
|
|
442
|
+
</div>
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## Getting an API Key
|
|
448
|
+
|
|
449
|
+
1. Visit [characterforge.app](https://characterforge.app)
|
|
450
|
+
2. Sign up for an account
|
|
451
|
+
3. Navigate to the Developer Dashboard
|
|
452
|
+
4. Create a new API key
|
|
453
|
+
5. Copy your API key and use it in your application
|
|
454
|
+
|
|
455
|
+
**Important:** Keep your API key secret and never commit it to version control. Use environment variables or secure key management systems.
|
|
456
|
+
|
|
457
|
+
## Support
|
|
458
|
+
|
|
459
|
+
- 📧 Email: support@characterforge.app
|
|
460
|
+
- 🐛 Issues: [GitHub Issues](https://github.com/characterforge/sdk/issues)
|
|
461
|
+
- 📖 Documentation: [characterforge.app/docs](https://characterforge.app/docs)
|
|
462
|
+
|
|
463
|
+
**Note:** This package is published as `characterforge` on npm.
|
|
464
|
+
|
|
465
|
+
## License
|
|
466
|
+
|
|
467
|
+
MIT © CharacterForge
|
|
468
|
+
|
|
469
|
+
## Contributing
|
|
470
|
+
|
|
471
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
472
|
+
|