chartsplat 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/README.md +311 -0
- package/dist/index.d.mts +246 -0
- package/dist/index.d.ts +246 -0
- package/dist/index.js +219 -0
- package/dist/index.mjs +192 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
# chartsplat
|
|
2
|
+
|
|
3
|
+
Official TypeScript/JavaScript client for [Chart Splat](https://chartsplat.com) - Generate beautiful charts via API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install chartsplat
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { ChartSplat } from 'chartsplat';
|
|
15
|
+
|
|
16
|
+
const client = new ChartSplat('YOUR_API_KEY');
|
|
17
|
+
|
|
18
|
+
// Generate a bar chart
|
|
19
|
+
const chart = await client.generateChart({
|
|
20
|
+
type: 'bar',
|
|
21
|
+
data: {
|
|
22
|
+
labels: ['Jan', 'Feb', 'Mar', 'Apr'],
|
|
23
|
+
datasets: [{
|
|
24
|
+
label: 'Revenue',
|
|
25
|
+
data: [12, 19, 3, 5],
|
|
26
|
+
backgroundColor: '#8b5cf6'
|
|
27
|
+
}]
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Use the base64 image
|
|
32
|
+
console.log(chart.image); // data:image/png;base64,...
|
|
33
|
+
|
|
34
|
+
// Use in HTML
|
|
35
|
+
const img = document.createElement('img');
|
|
36
|
+
img.src = chart.image;
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- Full TypeScript support
|
|
42
|
+
- Works in Node.js (18+) and browsers
|
|
43
|
+
- Convenience methods for all chart types
|
|
44
|
+
- Rate limit tracking
|
|
45
|
+
- Timeout handling
|
|
46
|
+
- Custom fetch support for older Node.js versions
|
|
47
|
+
|
|
48
|
+
## Usage
|
|
49
|
+
|
|
50
|
+
### Basic Example
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { ChartSplat } from 'chartsplat';
|
|
54
|
+
|
|
55
|
+
const client = new ChartSplat('cs_your_api_key');
|
|
56
|
+
|
|
57
|
+
const chart = await client.generateChart({
|
|
58
|
+
type: 'line',
|
|
59
|
+
data: {
|
|
60
|
+
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
|
|
61
|
+
datasets: [{
|
|
62
|
+
label: 'Visitors',
|
|
63
|
+
data: [100, 200, 150, 300, 250],
|
|
64
|
+
borderColor: '#3b82f6',
|
|
65
|
+
fill: false
|
|
66
|
+
}]
|
|
67
|
+
},
|
|
68
|
+
options: {
|
|
69
|
+
width: 1200,
|
|
70
|
+
height: 800
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Convenience Methods
|
|
76
|
+
|
|
77
|
+
```typescript
|
|
78
|
+
// Line chart
|
|
79
|
+
const lineChart = await client.lineChart({
|
|
80
|
+
labels: ['A', 'B', 'C'],
|
|
81
|
+
datasets: [{ data: [1, 2, 3], borderColor: '#3b82f6' }]
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Bar chart
|
|
85
|
+
const barChart = await client.barChart({
|
|
86
|
+
labels: ['A', 'B', 'C'],
|
|
87
|
+
datasets: [{ data: [1, 2, 3], backgroundColor: '#8b5cf6' }]
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Pie chart
|
|
91
|
+
const pieChart = await client.pieChart({
|
|
92
|
+
labels: ['Red', 'Blue', 'Yellow'],
|
|
93
|
+
datasets: [{ data: [30, 50, 20], backgroundColor: ['#ef4444', '#3b82f6', '#eab308'] }]
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Doughnut chart
|
|
97
|
+
const doughnutChart = await client.doughnutChart({
|
|
98
|
+
labels: ['Desktop', 'Mobile'],
|
|
99
|
+
datasets: [{ data: [60, 40], backgroundColor: ['#8b5cf6', '#ec4899'] }]
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Radar chart
|
|
103
|
+
const radarChart = await client.radarChart({
|
|
104
|
+
labels: ['Speed', 'Power', 'Range'],
|
|
105
|
+
datasets: [{ label: 'Player', data: [65, 59, 90], borderColor: '#f59e0b' }]
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Polar area chart
|
|
109
|
+
const polarChart = await client.polarAreaChart({
|
|
110
|
+
labels: ['Red', 'Green', 'Blue'],
|
|
111
|
+
datasets: [{ data: [11, 16, 7], backgroundColor: ['#ef4444', '#10b981', '#3b82f6'] }]
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Save to File (Node.js)
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
import fs from 'fs';
|
|
119
|
+
import { ChartSplat } from 'chartsplat';
|
|
120
|
+
|
|
121
|
+
const client = new ChartSplat('cs_your_api_key');
|
|
122
|
+
|
|
123
|
+
const chart = await client.generateChart({
|
|
124
|
+
type: 'bar',
|
|
125
|
+
data: {
|
|
126
|
+
labels: ['A', 'B', 'C'],
|
|
127
|
+
datasets: [{ data: [1, 2, 3] }]
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// Remove the data URI prefix and decode
|
|
132
|
+
const base64Data = chart.image.replace(/^data:image\/png;base64,/, '');
|
|
133
|
+
fs.writeFileSync('chart.png', Buffer.from(base64Data, 'base64'));
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### React Example
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
import { ChartSplat } from 'chartsplat';
|
|
140
|
+
import { useState, useEffect } from 'react';
|
|
141
|
+
|
|
142
|
+
const client = new ChartSplat('cs_your_api_key');
|
|
143
|
+
|
|
144
|
+
function MyChart() {
|
|
145
|
+
const [chartUrl, setChartUrl] = useState<string | null>(null);
|
|
146
|
+
const [error, setError] = useState<string | null>(null);
|
|
147
|
+
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
async function loadChart() {
|
|
150
|
+
try {
|
|
151
|
+
const chart = await client.generateChart({
|
|
152
|
+
type: 'line',
|
|
153
|
+
data: {
|
|
154
|
+
labels: ['Jan', 'Feb', 'Mar'],
|
|
155
|
+
datasets: [{
|
|
156
|
+
label: 'Sales',
|
|
157
|
+
data: [100, 200, 150],
|
|
158
|
+
borderColor: '#ec4899'
|
|
159
|
+
}]
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
setChartUrl(chart.image);
|
|
163
|
+
} catch (err) {
|
|
164
|
+
setError(err.message);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
loadChart();
|
|
168
|
+
}, []);
|
|
169
|
+
|
|
170
|
+
if (error) return <div>Error: {error}</div>;
|
|
171
|
+
if (!chartUrl) return <div>Loading...</div>;
|
|
172
|
+
return <img src={chartUrl} alt="Chart" />;
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Rate Limit Handling
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import { ChartSplat, ChartSplatAPIError } from 'chartsplat';
|
|
180
|
+
|
|
181
|
+
const client = new ChartSplat('cs_your_api_key');
|
|
182
|
+
|
|
183
|
+
try {
|
|
184
|
+
const chart = await client.generateChart({ /* ... */ });
|
|
185
|
+
|
|
186
|
+
// Check rate limit after request
|
|
187
|
+
const rateLimit = client.getRateLimit();
|
|
188
|
+
console.log(`${rateLimit.remaining}/${rateLimit.limit} requests remaining`);
|
|
189
|
+
console.log(`Resets at: ${rateLimit.reset}`);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
if (error instanceof ChartSplatAPIError && error.status === 429) {
|
|
192
|
+
console.log('Rate limited!');
|
|
193
|
+
console.log(`Limit: ${error.rateLimit?.limit}`);
|
|
194
|
+
console.log(`Resets at: ${error.rateLimit?.reset}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Custom Configuration
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
import { ChartSplat } from 'chartsplat';
|
|
203
|
+
|
|
204
|
+
const client = new ChartSplat('cs_your_api_key', {
|
|
205
|
+
// Custom base URL (for local development)
|
|
206
|
+
baseUrl: 'http://localhost:3001',
|
|
207
|
+
|
|
208
|
+
// Request timeout in milliseconds
|
|
209
|
+
timeout: 60000,
|
|
210
|
+
|
|
211
|
+
// Custom fetch (for Node.js < 18)
|
|
212
|
+
fetch: require('node-fetch'),
|
|
213
|
+
});
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## API Reference
|
|
217
|
+
|
|
218
|
+
### `ChartSplat` Class
|
|
219
|
+
|
|
220
|
+
#### Constructor
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
new ChartSplat(apiKey: string, options?: ChartSplatOptions)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
- `apiKey` - Your Chart Splat API key (starts with `cs_`)
|
|
227
|
+
- `options.baseUrl` - Base URL for the API (default: `https://api.chartsplat.com`)
|
|
228
|
+
- `options.timeout` - Request timeout in ms (default: `30000`)
|
|
229
|
+
- `options.fetch` - Custom fetch implementation
|
|
230
|
+
|
|
231
|
+
#### Methods
|
|
232
|
+
|
|
233
|
+
- `generateChart(request: ChartRequest): Promise<ChartResponse>` - Generate any chart type
|
|
234
|
+
- `lineChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>` - Generate a line chart
|
|
235
|
+
- `barChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>` - Generate a bar chart
|
|
236
|
+
- `pieChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>` - Generate a pie chart
|
|
237
|
+
- `doughnutChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>` - Generate a doughnut chart
|
|
238
|
+
- `radarChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>` - Generate a radar chart
|
|
239
|
+
- `polarAreaChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>` - Generate a polar area chart
|
|
240
|
+
- `getRateLimit(): RateLimitInfo | undefined` - Get rate limit info from last request
|
|
241
|
+
|
|
242
|
+
### Types
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
interface ChartRequest {
|
|
246
|
+
type?: 'line' | 'bar' | 'pie' | 'doughnut' | 'radar' | 'polarArea';
|
|
247
|
+
data: ChartData;
|
|
248
|
+
options?: ChartOptions;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
interface ChartData {
|
|
252
|
+
labels: string[];
|
|
253
|
+
datasets: Dataset[];
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
interface Dataset {
|
|
257
|
+
label?: string;
|
|
258
|
+
data: number[];
|
|
259
|
+
backgroundColor?: string | string[];
|
|
260
|
+
borderColor?: string | string[];
|
|
261
|
+
borderWidth?: number;
|
|
262
|
+
fill?: boolean;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
interface ChartOptions {
|
|
266
|
+
width?: number; // Default: 800
|
|
267
|
+
height?: number; // Default: 600
|
|
268
|
+
plugins?: Record<string, unknown>;
|
|
269
|
+
scales?: Record<string, unknown>;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
interface ChartResponse {
|
|
273
|
+
image: string; // Base64 PNG with data URI prefix
|
|
274
|
+
format: 'png';
|
|
275
|
+
width: number;
|
|
276
|
+
height: number;
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
## Error Handling
|
|
281
|
+
|
|
282
|
+
The client throws typed errors for different failure scenarios:
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
import { ChartSplat, ChartSplatAPIError, ChartSplatTimeoutError } from 'chartsplat';
|
|
286
|
+
|
|
287
|
+
try {
|
|
288
|
+
const chart = await client.generateChart({ /* ... */ });
|
|
289
|
+
} catch (error) {
|
|
290
|
+
if (error instanceof ChartSplatAPIError) {
|
|
291
|
+
console.log('API Error:', error.message);
|
|
292
|
+
console.log('Status:', error.status);
|
|
293
|
+
console.log('Code:', error.code);
|
|
294
|
+
} else if (error instanceof ChartSplatTimeoutError) {
|
|
295
|
+
console.log('Request timed out');
|
|
296
|
+
} else {
|
|
297
|
+
console.log('Unknown error:', error);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## License
|
|
303
|
+
|
|
304
|
+
MIT - see [LICENSE](./LICENSE) for details.
|
|
305
|
+
|
|
306
|
+
## Links
|
|
307
|
+
|
|
308
|
+
- [Website](https://chartsplat.com)
|
|
309
|
+
- [Documentation](https://chartsplat.com/docs)
|
|
310
|
+
- [Pricing](https://chartsplat.com/pricing)
|
|
311
|
+
- [OpenAPI Spec](https://chartsplat.com/openapi.yaml)
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chart Splat - Official TypeScript/JavaScript Client
|
|
3
|
+
*
|
|
4
|
+
* Generate beautiful charts via API using Chart.js configuration.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { ChartSplat } from 'chartsplat';
|
|
9
|
+
*
|
|
10
|
+
* const client = new ChartSplat('YOUR_API_KEY');
|
|
11
|
+
*
|
|
12
|
+
* const chart = await client.generateChart({
|
|
13
|
+
* type: 'bar',
|
|
14
|
+
* data: {
|
|
15
|
+
* labels: ['Jan', 'Feb', 'Mar'],
|
|
16
|
+
* datasets: [{
|
|
17
|
+
* label: 'Revenue',
|
|
18
|
+
* data: [12, 19, 3],
|
|
19
|
+
* backgroundColor: '#8b5cf6'
|
|
20
|
+
* }]
|
|
21
|
+
* }
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* console.log(chart.image); // data:image/png;base64,...
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
/** Chart types supported by Chart Splat */
|
|
28
|
+
type ChartType = 'line' | 'bar' | 'pie' | 'doughnut' | 'radar' | 'polarArea';
|
|
29
|
+
/** Dataset configuration for a chart */
|
|
30
|
+
interface Dataset {
|
|
31
|
+
/** Label for the dataset (shown in legend) */
|
|
32
|
+
label?: string;
|
|
33
|
+
/** Data points for the dataset */
|
|
34
|
+
data: number[];
|
|
35
|
+
/** Background color(s) for the dataset */
|
|
36
|
+
backgroundColor?: string | string[];
|
|
37
|
+
/** Border color(s) for the dataset */
|
|
38
|
+
borderColor?: string | string[];
|
|
39
|
+
/** Border width in pixels */
|
|
40
|
+
borderWidth?: number;
|
|
41
|
+
/** Whether to fill the area under line charts */
|
|
42
|
+
fill?: boolean;
|
|
43
|
+
/** Additional Chart.js dataset options */
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
}
|
|
46
|
+
/** Chart data configuration */
|
|
47
|
+
interface ChartData {
|
|
48
|
+
/** Labels for the X-axis or segments */
|
|
49
|
+
labels: string[];
|
|
50
|
+
/** Array of datasets to display */
|
|
51
|
+
datasets: Dataset[];
|
|
52
|
+
}
|
|
53
|
+
/** Chart options configuration */
|
|
54
|
+
interface ChartOptions {
|
|
55
|
+
/** Image width in pixels (default: 800) */
|
|
56
|
+
width?: number;
|
|
57
|
+
/** Image height in pixels (default: 600) */
|
|
58
|
+
height?: number;
|
|
59
|
+
/** Chart.js plugin options */
|
|
60
|
+
plugins?: Record<string, unknown>;
|
|
61
|
+
/** Chart.js scale options */
|
|
62
|
+
scales?: Record<string, unknown>;
|
|
63
|
+
/** Additional Chart.js options */
|
|
64
|
+
[key: string]: unknown;
|
|
65
|
+
}
|
|
66
|
+
/** Request payload for chart generation */
|
|
67
|
+
interface ChartRequest {
|
|
68
|
+
/** The type of chart to generate (default: 'line') */
|
|
69
|
+
type?: ChartType;
|
|
70
|
+
/** Chart data configuration */
|
|
71
|
+
data: ChartData;
|
|
72
|
+
/** Chart options */
|
|
73
|
+
options?: ChartOptions;
|
|
74
|
+
}
|
|
75
|
+
/** Response from chart generation */
|
|
76
|
+
interface ChartResponse {
|
|
77
|
+
/** Base64-encoded PNG image with data URI prefix */
|
|
78
|
+
image: string;
|
|
79
|
+
/** Image format (always 'png') */
|
|
80
|
+
format: 'png';
|
|
81
|
+
/** Image width in pixels */
|
|
82
|
+
width: number;
|
|
83
|
+
/** Image height in pixels */
|
|
84
|
+
height: number;
|
|
85
|
+
}
|
|
86
|
+
/** Error response from the API */
|
|
87
|
+
interface ChartSplatError {
|
|
88
|
+
/** Error type or message */
|
|
89
|
+
error: string;
|
|
90
|
+
/** Detailed error message */
|
|
91
|
+
message?: string;
|
|
92
|
+
/** Rate limit (if applicable) */
|
|
93
|
+
limit?: number;
|
|
94
|
+
/** Requests used (if applicable) */
|
|
95
|
+
used?: number;
|
|
96
|
+
/** Current plan (if applicable) */
|
|
97
|
+
plan?: string;
|
|
98
|
+
}
|
|
99
|
+
/** Rate limit information from response headers */
|
|
100
|
+
interface RateLimitInfo {
|
|
101
|
+
/** Monthly request limit */
|
|
102
|
+
limit: number;
|
|
103
|
+
/** Requests remaining this month */
|
|
104
|
+
remaining: number;
|
|
105
|
+
/** When the limit resets (ISO 8601 date) */
|
|
106
|
+
reset: string;
|
|
107
|
+
}
|
|
108
|
+
/** Options for the ChartSplat client */
|
|
109
|
+
interface ChartSplatOptions {
|
|
110
|
+
/** Base URL for the API (default: https://api.chartsplat.com) */
|
|
111
|
+
baseUrl?: string;
|
|
112
|
+
/** Request timeout in milliseconds (default: 30000) */
|
|
113
|
+
timeout?: number;
|
|
114
|
+
/** Custom fetch implementation (for Node.js < 18 or testing) */
|
|
115
|
+
fetch?: typeof fetch;
|
|
116
|
+
}
|
|
117
|
+
/** Error thrown when the API returns an error response */
|
|
118
|
+
declare class ChartSplatAPIError extends Error {
|
|
119
|
+
/** HTTP status code */
|
|
120
|
+
readonly status: number;
|
|
121
|
+
/** Error code from the API */
|
|
122
|
+
readonly code: string;
|
|
123
|
+
/** Rate limit info (if rate limited) */
|
|
124
|
+
readonly rateLimit?: RateLimitInfo;
|
|
125
|
+
constructor(message: string, status: number, code: string, rateLimit?: RateLimitInfo);
|
|
126
|
+
}
|
|
127
|
+
/** Error thrown when a request times out */
|
|
128
|
+
declare class ChartSplatTimeoutError extends Error {
|
|
129
|
+
constructor(timeout: number);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Chart Splat API Client
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* const client = new ChartSplat('YOUR_API_KEY');
|
|
137
|
+
*
|
|
138
|
+
* // Generate a simple bar chart
|
|
139
|
+
* const chart = await client.generateChart({
|
|
140
|
+
* type: 'bar',
|
|
141
|
+
* data: {
|
|
142
|
+
* labels: ['A', 'B', 'C'],
|
|
143
|
+
* datasets: [{ data: [1, 2, 3] }]
|
|
144
|
+
* }
|
|
145
|
+
* });
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
declare class ChartSplat {
|
|
149
|
+
private readonly apiKey;
|
|
150
|
+
private readonly baseUrl;
|
|
151
|
+
private readonly timeout;
|
|
152
|
+
private readonly fetchFn;
|
|
153
|
+
/** Rate limit info from the last request */
|
|
154
|
+
lastRateLimit?: RateLimitInfo;
|
|
155
|
+
/**
|
|
156
|
+
* Create a new Chart Splat client
|
|
157
|
+
*
|
|
158
|
+
* @param apiKey - Your Chart Splat API key (starts with 'cs_')
|
|
159
|
+
* @param options - Client configuration options
|
|
160
|
+
*/
|
|
161
|
+
constructor(apiKey: string, options?: ChartSplatOptions);
|
|
162
|
+
/**
|
|
163
|
+
* Generate a chart image
|
|
164
|
+
*
|
|
165
|
+
* @param request - Chart configuration
|
|
166
|
+
* @returns Chart response with base64 image
|
|
167
|
+
* @throws {ChartSplatAPIError} If the API returns an error
|
|
168
|
+
* @throws {ChartSplatTimeoutError} If the request times out
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* const chart = await client.generateChart({
|
|
173
|
+
* type: 'line',
|
|
174
|
+
* data: {
|
|
175
|
+
* labels: ['Jan', 'Feb', 'Mar'],
|
|
176
|
+
* datasets: [{
|
|
177
|
+
* label: 'Sales',
|
|
178
|
+
* data: [100, 200, 150],
|
|
179
|
+
* borderColor: '#3b82f6'
|
|
180
|
+
* }]
|
|
181
|
+
* },
|
|
182
|
+
* options: {
|
|
183
|
+
* width: 1200,
|
|
184
|
+
* height: 800
|
|
185
|
+
* }
|
|
186
|
+
* });
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
generateChart(request: ChartRequest): Promise<ChartResponse>;
|
|
190
|
+
/**
|
|
191
|
+
* Generate a line chart
|
|
192
|
+
*
|
|
193
|
+
* @param data - Chart data
|
|
194
|
+
* @param options - Chart options
|
|
195
|
+
* @returns Chart response with base64 image
|
|
196
|
+
*/
|
|
197
|
+
lineChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>;
|
|
198
|
+
/**
|
|
199
|
+
* Generate a bar chart
|
|
200
|
+
*
|
|
201
|
+
* @param data - Chart data
|
|
202
|
+
* @param options - Chart options
|
|
203
|
+
* @returns Chart response with base64 image
|
|
204
|
+
*/
|
|
205
|
+
barChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>;
|
|
206
|
+
/**
|
|
207
|
+
* Generate a pie chart
|
|
208
|
+
*
|
|
209
|
+
* @param data - Chart data
|
|
210
|
+
* @param options - Chart options
|
|
211
|
+
* @returns Chart response with base64 image
|
|
212
|
+
*/
|
|
213
|
+
pieChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>;
|
|
214
|
+
/**
|
|
215
|
+
* Generate a doughnut chart
|
|
216
|
+
*
|
|
217
|
+
* @param data - Chart data
|
|
218
|
+
* @param options - Chart options
|
|
219
|
+
* @returns Chart response with base64 image
|
|
220
|
+
*/
|
|
221
|
+
doughnutChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>;
|
|
222
|
+
/**
|
|
223
|
+
* Generate a radar chart
|
|
224
|
+
*
|
|
225
|
+
* @param data - Chart data
|
|
226
|
+
* @param options - Chart options
|
|
227
|
+
* @returns Chart response with base64 image
|
|
228
|
+
*/
|
|
229
|
+
radarChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>;
|
|
230
|
+
/**
|
|
231
|
+
* Generate a polar area chart
|
|
232
|
+
*
|
|
233
|
+
* @param data - Chart data
|
|
234
|
+
* @param options - Chart options
|
|
235
|
+
* @returns Chart response with base64 image
|
|
236
|
+
*/
|
|
237
|
+
polarAreaChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>;
|
|
238
|
+
/**
|
|
239
|
+
* Get rate limit information from the last request
|
|
240
|
+
*
|
|
241
|
+
* @returns Rate limit info or undefined if no request has been made
|
|
242
|
+
*/
|
|
243
|
+
getRateLimit(): RateLimitInfo | undefined;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export { type ChartData, type ChartOptions, type ChartRequest, type ChartResponse, ChartSplat, ChartSplatAPIError, type ChartSplatError, type ChartSplatOptions, ChartSplatTimeoutError, type ChartType, type Dataset, type RateLimitInfo, ChartSplat as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chart Splat - Official TypeScript/JavaScript Client
|
|
3
|
+
*
|
|
4
|
+
* Generate beautiful charts via API using Chart.js configuration.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { ChartSplat } from 'chartsplat';
|
|
9
|
+
*
|
|
10
|
+
* const client = new ChartSplat('YOUR_API_KEY');
|
|
11
|
+
*
|
|
12
|
+
* const chart = await client.generateChart({
|
|
13
|
+
* type: 'bar',
|
|
14
|
+
* data: {
|
|
15
|
+
* labels: ['Jan', 'Feb', 'Mar'],
|
|
16
|
+
* datasets: [{
|
|
17
|
+
* label: 'Revenue',
|
|
18
|
+
* data: [12, 19, 3],
|
|
19
|
+
* backgroundColor: '#8b5cf6'
|
|
20
|
+
* }]
|
|
21
|
+
* }
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* console.log(chart.image); // data:image/png;base64,...
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
/** Chart types supported by Chart Splat */
|
|
28
|
+
type ChartType = 'line' | 'bar' | 'pie' | 'doughnut' | 'radar' | 'polarArea';
|
|
29
|
+
/** Dataset configuration for a chart */
|
|
30
|
+
interface Dataset {
|
|
31
|
+
/** Label for the dataset (shown in legend) */
|
|
32
|
+
label?: string;
|
|
33
|
+
/** Data points for the dataset */
|
|
34
|
+
data: number[];
|
|
35
|
+
/** Background color(s) for the dataset */
|
|
36
|
+
backgroundColor?: string | string[];
|
|
37
|
+
/** Border color(s) for the dataset */
|
|
38
|
+
borderColor?: string | string[];
|
|
39
|
+
/** Border width in pixels */
|
|
40
|
+
borderWidth?: number;
|
|
41
|
+
/** Whether to fill the area under line charts */
|
|
42
|
+
fill?: boolean;
|
|
43
|
+
/** Additional Chart.js dataset options */
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
}
|
|
46
|
+
/** Chart data configuration */
|
|
47
|
+
interface ChartData {
|
|
48
|
+
/** Labels for the X-axis or segments */
|
|
49
|
+
labels: string[];
|
|
50
|
+
/** Array of datasets to display */
|
|
51
|
+
datasets: Dataset[];
|
|
52
|
+
}
|
|
53
|
+
/** Chart options configuration */
|
|
54
|
+
interface ChartOptions {
|
|
55
|
+
/** Image width in pixels (default: 800) */
|
|
56
|
+
width?: number;
|
|
57
|
+
/** Image height in pixels (default: 600) */
|
|
58
|
+
height?: number;
|
|
59
|
+
/** Chart.js plugin options */
|
|
60
|
+
plugins?: Record<string, unknown>;
|
|
61
|
+
/** Chart.js scale options */
|
|
62
|
+
scales?: Record<string, unknown>;
|
|
63
|
+
/** Additional Chart.js options */
|
|
64
|
+
[key: string]: unknown;
|
|
65
|
+
}
|
|
66
|
+
/** Request payload for chart generation */
|
|
67
|
+
interface ChartRequest {
|
|
68
|
+
/** The type of chart to generate (default: 'line') */
|
|
69
|
+
type?: ChartType;
|
|
70
|
+
/** Chart data configuration */
|
|
71
|
+
data: ChartData;
|
|
72
|
+
/** Chart options */
|
|
73
|
+
options?: ChartOptions;
|
|
74
|
+
}
|
|
75
|
+
/** Response from chart generation */
|
|
76
|
+
interface ChartResponse {
|
|
77
|
+
/** Base64-encoded PNG image with data URI prefix */
|
|
78
|
+
image: string;
|
|
79
|
+
/** Image format (always 'png') */
|
|
80
|
+
format: 'png';
|
|
81
|
+
/** Image width in pixels */
|
|
82
|
+
width: number;
|
|
83
|
+
/** Image height in pixels */
|
|
84
|
+
height: number;
|
|
85
|
+
}
|
|
86
|
+
/** Error response from the API */
|
|
87
|
+
interface ChartSplatError {
|
|
88
|
+
/** Error type or message */
|
|
89
|
+
error: string;
|
|
90
|
+
/** Detailed error message */
|
|
91
|
+
message?: string;
|
|
92
|
+
/** Rate limit (if applicable) */
|
|
93
|
+
limit?: number;
|
|
94
|
+
/** Requests used (if applicable) */
|
|
95
|
+
used?: number;
|
|
96
|
+
/** Current plan (if applicable) */
|
|
97
|
+
plan?: string;
|
|
98
|
+
}
|
|
99
|
+
/** Rate limit information from response headers */
|
|
100
|
+
interface RateLimitInfo {
|
|
101
|
+
/** Monthly request limit */
|
|
102
|
+
limit: number;
|
|
103
|
+
/** Requests remaining this month */
|
|
104
|
+
remaining: number;
|
|
105
|
+
/** When the limit resets (ISO 8601 date) */
|
|
106
|
+
reset: string;
|
|
107
|
+
}
|
|
108
|
+
/** Options for the ChartSplat client */
|
|
109
|
+
interface ChartSplatOptions {
|
|
110
|
+
/** Base URL for the API (default: https://api.chartsplat.com) */
|
|
111
|
+
baseUrl?: string;
|
|
112
|
+
/** Request timeout in milliseconds (default: 30000) */
|
|
113
|
+
timeout?: number;
|
|
114
|
+
/** Custom fetch implementation (for Node.js < 18 or testing) */
|
|
115
|
+
fetch?: typeof fetch;
|
|
116
|
+
}
|
|
117
|
+
/** Error thrown when the API returns an error response */
|
|
118
|
+
declare class ChartSplatAPIError extends Error {
|
|
119
|
+
/** HTTP status code */
|
|
120
|
+
readonly status: number;
|
|
121
|
+
/** Error code from the API */
|
|
122
|
+
readonly code: string;
|
|
123
|
+
/** Rate limit info (if rate limited) */
|
|
124
|
+
readonly rateLimit?: RateLimitInfo;
|
|
125
|
+
constructor(message: string, status: number, code: string, rateLimit?: RateLimitInfo);
|
|
126
|
+
}
|
|
127
|
+
/** Error thrown when a request times out */
|
|
128
|
+
declare class ChartSplatTimeoutError extends Error {
|
|
129
|
+
constructor(timeout: number);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Chart Splat API Client
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* const client = new ChartSplat('YOUR_API_KEY');
|
|
137
|
+
*
|
|
138
|
+
* // Generate a simple bar chart
|
|
139
|
+
* const chart = await client.generateChart({
|
|
140
|
+
* type: 'bar',
|
|
141
|
+
* data: {
|
|
142
|
+
* labels: ['A', 'B', 'C'],
|
|
143
|
+
* datasets: [{ data: [1, 2, 3] }]
|
|
144
|
+
* }
|
|
145
|
+
* });
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
declare class ChartSplat {
|
|
149
|
+
private readonly apiKey;
|
|
150
|
+
private readonly baseUrl;
|
|
151
|
+
private readonly timeout;
|
|
152
|
+
private readonly fetchFn;
|
|
153
|
+
/** Rate limit info from the last request */
|
|
154
|
+
lastRateLimit?: RateLimitInfo;
|
|
155
|
+
/**
|
|
156
|
+
* Create a new Chart Splat client
|
|
157
|
+
*
|
|
158
|
+
* @param apiKey - Your Chart Splat API key (starts with 'cs_')
|
|
159
|
+
* @param options - Client configuration options
|
|
160
|
+
*/
|
|
161
|
+
constructor(apiKey: string, options?: ChartSplatOptions);
|
|
162
|
+
/**
|
|
163
|
+
* Generate a chart image
|
|
164
|
+
*
|
|
165
|
+
* @param request - Chart configuration
|
|
166
|
+
* @returns Chart response with base64 image
|
|
167
|
+
* @throws {ChartSplatAPIError} If the API returns an error
|
|
168
|
+
* @throws {ChartSplatTimeoutError} If the request times out
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```typescript
|
|
172
|
+
* const chart = await client.generateChart({
|
|
173
|
+
* type: 'line',
|
|
174
|
+
* data: {
|
|
175
|
+
* labels: ['Jan', 'Feb', 'Mar'],
|
|
176
|
+
* datasets: [{
|
|
177
|
+
* label: 'Sales',
|
|
178
|
+
* data: [100, 200, 150],
|
|
179
|
+
* borderColor: '#3b82f6'
|
|
180
|
+
* }]
|
|
181
|
+
* },
|
|
182
|
+
* options: {
|
|
183
|
+
* width: 1200,
|
|
184
|
+
* height: 800
|
|
185
|
+
* }
|
|
186
|
+
* });
|
|
187
|
+
* ```
|
|
188
|
+
*/
|
|
189
|
+
generateChart(request: ChartRequest): Promise<ChartResponse>;
|
|
190
|
+
/**
|
|
191
|
+
* Generate a line chart
|
|
192
|
+
*
|
|
193
|
+
* @param data - Chart data
|
|
194
|
+
* @param options - Chart options
|
|
195
|
+
* @returns Chart response with base64 image
|
|
196
|
+
*/
|
|
197
|
+
lineChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>;
|
|
198
|
+
/**
|
|
199
|
+
* Generate a bar chart
|
|
200
|
+
*
|
|
201
|
+
* @param data - Chart data
|
|
202
|
+
* @param options - Chart options
|
|
203
|
+
* @returns Chart response with base64 image
|
|
204
|
+
*/
|
|
205
|
+
barChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>;
|
|
206
|
+
/**
|
|
207
|
+
* Generate a pie chart
|
|
208
|
+
*
|
|
209
|
+
* @param data - Chart data
|
|
210
|
+
* @param options - Chart options
|
|
211
|
+
* @returns Chart response with base64 image
|
|
212
|
+
*/
|
|
213
|
+
pieChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>;
|
|
214
|
+
/**
|
|
215
|
+
* Generate a doughnut chart
|
|
216
|
+
*
|
|
217
|
+
* @param data - Chart data
|
|
218
|
+
* @param options - Chart options
|
|
219
|
+
* @returns Chart response with base64 image
|
|
220
|
+
*/
|
|
221
|
+
doughnutChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>;
|
|
222
|
+
/**
|
|
223
|
+
* Generate a radar chart
|
|
224
|
+
*
|
|
225
|
+
* @param data - Chart data
|
|
226
|
+
* @param options - Chart options
|
|
227
|
+
* @returns Chart response with base64 image
|
|
228
|
+
*/
|
|
229
|
+
radarChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>;
|
|
230
|
+
/**
|
|
231
|
+
* Generate a polar area chart
|
|
232
|
+
*
|
|
233
|
+
* @param data - Chart data
|
|
234
|
+
* @param options - Chart options
|
|
235
|
+
* @returns Chart response with base64 image
|
|
236
|
+
*/
|
|
237
|
+
polarAreaChart(data: ChartData, options?: ChartOptions): Promise<ChartResponse>;
|
|
238
|
+
/**
|
|
239
|
+
* Get rate limit information from the last request
|
|
240
|
+
*
|
|
241
|
+
* @returns Rate limit info or undefined if no request has been made
|
|
242
|
+
*/
|
|
243
|
+
getRateLimit(): RateLimitInfo | undefined;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
export { type ChartData, type ChartOptions, type ChartRequest, type ChartResponse, ChartSplat, ChartSplatAPIError, type ChartSplatError, type ChartSplatOptions, ChartSplatTimeoutError, type ChartType, type Dataset, type RateLimitInfo, ChartSplat as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ChartSplat: () => ChartSplat,
|
|
24
|
+
ChartSplatAPIError: () => ChartSplatAPIError,
|
|
25
|
+
ChartSplatTimeoutError: () => ChartSplatTimeoutError,
|
|
26
|
+
default: () => index_default
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
var ChartSplatAPIError = class extends Error {
|
|
30
|
+
constructor(message, status, code, rateLimit) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.name = "ChartSplatAPIError";
|
|
33
|
+
this.status = status;
|
|
34
|
+
this.code = code;
|
|
35
|
+
this.rateLimit = rateLimit;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var ChartSplatTimeoutError = class extends Error {
|
|
39
|
+
constructor(timeout) {
|
|
40
|
+
super(`Request timed out after ${timeout}ms`);
|
|
41
|
+
this.name = "ChartSplatTimeoutError";
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var ChartSplat = class {
|
|
45
|
+
/**
|
|
46
|
+
* Create a new Chart Splat client
|
|
47
|
+
*
|
|
48
|
+
* @param apiKey - Your Chart Splat API key (starts with 'cs_')
|
|
49
|
+
* @param options - Client configuration options
|
|
50
|
+
*/
|
|
51
|
+
constructor(apiKey, options = {}) {
|
|
52
|
+
if (!apiKey) {
|
|
53
|
+
throw new Error("API key is required");
|
|
54
|
+
}
|
|
55
|
+
if (!apiKey.startsWith("cs_")) {
|
|
56
|
+
throw new Error('Invalid API key format. API keys start with "cs_"');
|
|
57
|
+
}
|
|
58
|
+
this.apiKey = apiKey;
|
|
59
|
+
this.baseUrl = options.baseUrl || "https://api.chartsplat.com";
|
|
60
|
+
this.timeout = options.timeout || 3e4;
|
|
61
|
+
this.fetchFn = options.fetch || globalThis.fetch;
|
|
62
|
+
if (!this.fetchFn) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
"fetch is not available. Please provide a fetch implementation or upgrade to Node.js 18+"
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Generate a chart image
|
|
70
|
+
*
|
|
71
|
+
* @param request - Chart configuration
|
|
72
|
+
* @returns Chart response with base64 image
|
|
73
|
+
* @throws {ChartSplatAPIError} If the API returns an error
|
|
74
|
+
* @throws {ChartSplatTimeoutError} If the request times out
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const chart = await client.generateChart({
|
|
79
|
+
* type: 'line',
|
|
80
|
+
* data: {
|
|
81
|
+
* labels: ['Jan', 'Feb', 'Mar'],
|
|
82
|
+
* datasets: [{
|
|
83
|
+
* label: 'Sales',
|
|
84
|
+
* data: [100, 200, 150],
|
|
85
|
+
* borderColor: '#3b82f6'
|
|
86
|
+
* }]
|
|
87
|
+
* },
|
|
88
|
+
* options: {
|
|
89
|
+
* width: 1200,
|
|
90
|
+
* height: 800
|
|
91
|
+
* }
|
|
92
|
+
* });
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
async generateChart(request) {
|
|
96
|
+
if (!request.data) {
|
|
97
|
+
throw new Error("data is required");
|
|
98
|
+
}
|
|
99
|
+
if (!request.data.labels || !Array.isArray(request.data.labels)) {
|
|
100
|
+
throw new Error("data.labels is required and must be an array");
|
|
101
|
+
}
|
|
102
|
+
if (!request.data.datasets || !Array.isArray(request.data.datasets)) {
|
|
103
|
+
throw new Error("data.datasets is required and must be an array");
|
|
104
|
+
}
|
|
105
|
+
const controller = new AbortController();
|
|
106
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
107
|
+
try {
|
|
108
|
+
const response = await this.fetchFn(`${this.baseUrl}/chart`, {
|
|
109
|
+
method: "POST",
|
|
110
|
+
headers: {
|
|
111
|
+
"X-Api-Key": this.apiKey,
|
|
112
|
+
"Content-Type": "application/json"
|
|
113
|
+
},
|
|
114
|
+
body: JSON.stringify(request),
|
|
115
|
+
signal: controller.signal
|
|
116
|
+
});
|
|
117
|
+
this.lastRateLimit = {
|
|
118
|
+
limit: parseInt(response.headers.get("X-RateLimit-Limit") || "0", 10),
|
|
119
|
+
remaining: parseInt(response.headers.get("X-RateLimit-Remaining") || "0", 10),
|
|
120
|
+
reset: response.headers.get("X-RateLimit-Reset") || ""
|
|
121
|
+
};
|
|
122
|
+
if (!response.ok) {
|
|
123
|
+
const errorData = await response.json();
|
|
124
|
+
throw new ChartSplatAPIError(
|
|
125
|
+
errorData.message || errorData.error,
|
|
126
|
+
response.status,
|
|
127
|
+
errorData.error,
|
|
128
|
+
response.status === 429 ? this.lastRateLimit : void 0
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
return await response.json();
|
|
132
|
+
} catch (error) {
|
|
133
|
+
if (error instanceof ChartSplatAPIError) {
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
137
|
+
throw new ChartSplatTimeoutError(this.timeout);
|
|
138
|
+
}
|
|
139
|
+
throw error;
|
|
140
|
+
} finally {
|
|
141
|
+
clearTimeout(timeoutId);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Generate a line chart
|
|
146
|
+
*
|
|
147
|
+
* @param data - Chart data
|
|
148
|
+
* @param options - Chart options
|
|
149
|
+
* @returns Chart response with base64 image
|
|
150
|
+
*/
|
|
151
|
+
async lineChart(data, options) {
|
|
152
|
+
return this.generateChart({ type: "line", data, options });
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Generate a bar chart
|
|
156
|
+
*
|
|
157
|
+
* @param data - Chart data
|
|
158
|
+
* @param options - Chart options
|
|
159
|
+
* @returns Chart response with base64 image
|
|
160
|
+
*/
|
|
161
|
+
async barChart(data, options) {
|
|
162
|
+
return this.generateChart({ type: "bar", data, options });
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Generate a pie chart
|
|
166
|
+
*
|
|
167
|
+
* @param data - Chart data
|
|
168
|
+
* @param options - Chart options
|
|
169
|
+
* @returns Chart response with base64 image
|
|
170
|
+
*/
|
|
171
|
+
async pieChart(data, options) {
|
|
172
|
+
return this.generateChart({ type: "pie", data, options });
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Generate a doughnut chart
|
|
176
|
+
*
|
|
177
|
+
* @param data - Chart data
|
|
178
|
+
* @param options - Chart options
|
|
179
|
+
* @returns Chart response with base64 image
|
|
180
|
+
*/
|
|
181
|
+
async doughnutChart(data, options) {
|
|
182
|
+
return this.generateChart({ type: "doughnut", data, options });
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Generate a radar chart
|
|
186
|
+
*
|
|
187
|
+
* @param data - Chart data
|
|
188
|
+
* @param options - Chart options
|
|
189
|
+
* @returns Chart response with base64 image
|
|
190
|
+
*/
|
|
191
|
+
async radarChart(data, options) {
|
|
192
|
+
return this.generateChart({ type: "radar", data, options });
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Generate a polar area chart
|
|
196
|
+
*
|
|
197
|
+
* @param data - Chart data
|
|
198
|
+
* @param options - Chart options
|
|
199
|
+
* @returns Chart response with base64 image
|
|
200
|
+
*/
|
|
201
|
+
async polarAreaChart(data, options) {
|
|
202
|
+
return this.generateChart({ type: "polarArea", data, options });
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Get rate limit information from the last request
|
|
206
|
+
*
|
|
207
|
+
* @returns Rate limit info or undefined if no request has been made
|
|
208
|
+
*/
|
|
209
|
+
getRateLimit() {
|
|
210
|
+
return this.lastRateLimit;
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
var index_default = ChartSplat;
|
|
214
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
215
|
+
0 && (module.exports = {
|
|
216
|
+
ChartSplat,
|
|
217
|
+
ChartSplatAPIError,
|
|
218
|
+
ChartSplatTimeoutError
|
|
219
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
var ChartSplatAPIError = class extends Error {
|
|
3
|
+
constructor(message, status, code, rateLimit) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "ChartSplatAPIError";
|
|
6
|
+
this.status = status;
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.rateLimit = rateLimit;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
var ChartSplatTimeoutError = class extends Error {
|
|
12
|
+
constructor(timeout) {
|
|
13
|
+
super(`Request timed out after ${timeout}ms`);
|
|
14
|
+
this.name = "ChartSplatTimeoutError";
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var ChartSplat = class {
|
|
18
|
+
/**
|
|
19
|
+
* Create a new Chart Splat client
|
|
20
|
+
*
|
|
21
|
+
* @param apiKey - Your Chart Splat API key (starts with 'cs_')
|
|
22
|
+
* @param options - Client configuration options
|
|
23
|
+
*/
|
|
24
|
+
constructor(apiKey, options = {}) {
|
|
25
|
+
if (!apiKey) {
|
|
26
|
+
throw new Error("API key is required");
|
|
27
|
+
}
|
|
28
|
+
if (!apiKey.startsWith("cs_")) {
|
|
29
|
+
throw new Error('Invalid API key format. API keys start with "cs_"');
|
|
30
|
+
}
|
|
31
|
+
this.apiKey = apiKey;
|
|
32
|
+
this.baseUrl = options.baseUrl || "https://api.chartsplat.com";
|
|
33
|
+
this.timeout = options.timeout || 3e4;
|
|
34
|
+
this.fetchFn = options.fetch || globalThis.fetch;
|
|
35
|
+
if (!this.fetchFn) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
"fetch is not available. Please provide a fetch implementation or upgrade to Node.js 18+"
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Generate a chart image
|
|
43
|
+
*
|
|
44
|
+
* @param request - Chart configuration
|
|
45
|
+
* @returns Chart response with base64 image
|
|
46
|
+
* @throws {ChartSplatAPIError} If the API returns an error
|
|
47
|
+
* @throws {ChartSplatTimeoutError} If the request times out
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const chart = await client.generateChart({
|
|
52
|
+
* type: 'line',
|
|
53
|
+
* data: {
|
|
54
|
+
* labels: ['Jan', 'Feb', 'Mar'],
|
|
55
|
+
* datasets: [{
|
|
56
|
+
* label: 'Sales',
|
|
57
|
+
* data: [100, 200, 150],
|
|
58
|
+
* borderColor: '#3b82f6'
|
|
59
|
+
* }]
|
|
60
|
+
* },
|
|
61
|
+
* options: {
|
|
62
|
+
* width: 1200,
|
|
63
|
+
* height: 800
|
|
64
|
+
* }
|
|
65
|
+
* });
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
async generateChart(request) {
|
|
69
|
+
if (!request.data) {
|
|
70
|
+
throw new Error("data is required");
|
|
71
|
+
}
|
|
72
|
+
if (!request.data.labels || !Array.isArray(request.data.labels)) {
|
|
73
|
+
throw new Error("data.labels is required and must be an array");
|
|
74
|
+
}
|
|
75
|
+
if (!request.data.datasets || !Array.isArray(request.data.datasets)) {
|
|
76
|
+
throw new Error("data.datasets is required and must be an array");
|
|
77
|
+
}
|
|
78
|
+
const controller = new AbortController();
|
|
79
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
80
|
+
try {
|
|
81
|
+
const response = await this.fetchFn(`${this.baseUrl}/chart`, {
|
|
82
|
+
method: "POST",
|
|
83
|
+
headers: {
|
|
84
|
+
"X-Api-Key": this.apiKey,
|
|
85
|
+
"Content-Type": "application/json"
|
|
86
|
+
},
|
|
87
|
+
body: JSON.stringify(request),
|
|
88
|
+
signal: controller.signal
|
|
89
|
+
});
|
|
90
|
+
this.lastRateLimit = {
|
|
91
|
+
limit: parseInt(response.headers.get("X-RateLimit-Limit") || "0", 10),
|
|
92
|
+
remaining: parseInt(response.headers.get("X-RateLimit-Remaining") || "0", 10),
|
|
93
|
+
reset: response.headers.get("X-RateLimit-Reset") || ""
|
|
94
|
+
};
|
|
95
|
+
if (!response.ok) {
|
|
96
|
+
const errorData = await response.json();
|
|
97
|
+
throw new ChartSplatAPIError(
|
|
98
|
+
errorData.message || errorData.error,
|
|
99
|
+
response.status,
|
|
100
|
+
errorData.error,
|
|
101
|
+
response.status === 429 ? this.lastRateLimit : void 0
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
return await response.json();
|
|
105
|
+
} catch (error) {
|
|
106
|
+
if (error instanceof ChartSplatAPIError) {
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
110
|
+
throw new ChartSplatTimeoutError(this.timeout);
|
|
111
|
+
}
|
|
112
|
+
throw error;
|
|
113
|
+
} finally {
|
|
114
|
+
clearTimeout(timeoutId);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Generate a line chart
|
|
119
|
+
*
|
|
120
|
+
* @param data - Chart data
|
|
121
|
+
* @param options - Chart options
|
|
122
|
+
* @returns Chart response with base64 image
|
|
123
|
+
*/
|
|
124
|
+
async lineChart(data, options) {
|
|
125
|
+
return this.generateChart({ type: "line", data, options });
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Generate a bar chart
|
|
129
|
+
*
|
|
130
|
+
* @param data - Chart data
|
|
131
|
+
* @param options - Chart options
|
|
132
|
+
* @returns Chart response with base64 image
|
|
133
|
+
*/
|
|
134
|
+
async barChart(data, options) {
|
|
135
|
+
return this.generateChart({ type: "bar", data, options });
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Generate a pie chart
|
|
139
|
+
*
|
|
140
|
+
* @param data - Chart data
|
|
141
|
+
* @param options - Chart options
|
|
142
|
+
* @returns Chart response with base64 image
|
|
143
|
+
*/
|
|
144
|
+
async pieChart(data, options) {
|
|
145
|
+
return this.generateChart({ type: "pie", data, options });
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Generate a doughnut chart
|
|
149
|
+
*
|
|
150
|
+
* @param data - Chart data
|
|
151
|
+
* @param options - Chart options
|
|
152
|
+
* @returns Chart response with base64 image
|
|
153
|
+
*/
|
|
154
|
+
async doughnutChart(data, options) {
|
|
155
|
+
return this.generateChart({ type: "doughnut", data, options });
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Generate a radar chart
|
|
159
|
+
*
|
|
160
|
+
* @param data - Chart data
|
|
161
|
+
* @param options - Chart options
|
|
162
|
+
* @returns Chart response with base64 image
|
|
163
|
+
*/
|
|
164
|
+
async radarChart(data, options) {
|
|
165
|
+
return this.generateChart({ type: "radar", data, options });
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Generate a polar area chart
|
|
169
|
+
*
|
|
170
|
+
* @param data - Chart data
|
|
171
|
+
* @param options - Chart options
|
|
172
|
+
* @returns Chart response with base64 image
|
|
173
|
+
*/
|
|
174
|
+
async polarAreaChart(data, options) {
|
|
175
|
+
return this.generateChart({ type: "polarArea", data, options });
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get rate limit information from the last request
|
|
179
|
+
*
|
|
180
|
+
* @returns Rate limit info or undefined if no request has been made
|
|
181
|
+
*/
|
|
182
|
+
getRateLimit() {
|
|
183
|
+
return this.lastRateLimit;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
var index_default = ChartSplat;
|
|
187
|
+
export {
|
|
188
|
+
ChartSplat,
|
|
189
|
+
ChartSplatAPIError,
|
|
190
|
+
ChartSplatTimeoutError,
|
|
191
|
+
index_default as default
|
|
192
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "chartsplat",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official TypeScript/JavaScript client for Chart Splat API - Generate beautiful charts via API",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
21
|
+
"dev": "tsup src/index.ts --format cjs,esm --dts --watch",
|
|
22
|
+
"prepublishOnly": "npm run build",
|
|
23
|
+
"test": "vitest",
|
|
24
|
+
"typecheck": "tsc --noEmit"
|
|
25
|
+
},
|
|
26
|
+
"keywords": [
|
|
27
|
+
"chart",
|
|
28
|
+
"charts",
|
|
29
|
+
"chartjs",
|
|
30
|
+
"chart.js",
|
|
31
|
+
"api",
|
|
32
|
+
"image",
|
|
33
|
+
"png",
|
|
34
|
+
"visualization",
|
|
35
|
+
"data-visualization",
|
|
36
|
+
"chartsplat"
|
|
37
|
+
],
|
|
38
|
+
"author": "Chart Splat",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/chartsplat/chartsplat.git",
|
|
43
|
+
"directory": "packages/chartsplat"
|
|
44
|
+
},
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/chartsplat/chartsplat/issues"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://chartsplat.com",
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"tsup": "^8.0.0",
|
|
51
|
+
"typescript": "^5.3.0",
|
|
52
|
+
"vitest": "^1.0.0"
|
|
53
|
+
},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=16.0.0"
|
|
56
|
+
}
|
|
57
|
+
}
|