csv-charts-ai 1.8.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +144 -34
- package/dist/charts.d.ts +69 -0
- package/dist/charts.js +978 -0
- package/dist/charts.js.map +1 -0
- package/dist/constants-hUsrIT8W.d.ts +59 -0
- package/dist/index.d.ts +165 -137
- package/dist/index.js +419 -853
- package/dist/index.js.map +1 -1
- package/package.json +26 -13
package/README.md
CHANGED
|
@@ -7,23 +7,39 @@ AI-powered CSV analysis, chart generation, and interactive visualization. Built
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
pnpm add csv-charts-ai
|
|
10
|
+
pnpm add csv-charts-ai
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
**
|
|
13
|
+
Then install **only the AI provider(s) you need**:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Pick one or more
|
|
17
|
+
pnpm add @ai-sdk/openai # OpenAI / OpenAI-compatible (Ollama, vLLM, LM Studio…)
|
|
18
|
+
pnpm add @ai-sdk/anthropic # Anthropic
|
|
19
|
+
pnpm add @ai-sdk/google # Google Generative AI
|
|
20
|
+
pnpm add @ai-sdk/mistral # Mistral
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Core dependencies (`ai`, `zod`, `read-excel-file`) are bundled. AI provider SDKs are **optional peer dependencies** — you only install what you use.
|
|
24
|
+
|
|
25
|
+
**Optional peer dependencies** (only for React chart components): `react`, `recharts`, `lucide-react`.
|
|
14
26
|
|
|
15
27
|
## Quick Start
|
|
16
28
|
|
|
17
29
|
```ts
|
|
18
|
-
import { parseCSV, analyzeData, suggestQuestions } from "csv-charts-ai";
|
|
30
|
+
import { registerProvider, fromSDK, parseCSV, analyzeData, suggestQuestions } from "csv-charts-ai";
|
|
31
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
32
|
+
|
|
33
|
+
// 1. Register your provider(s) — once, at app startup
|
|
34
|
+
registerProvider("openai", fromSDK(createOpenAI));
|
|
19
35
|
|
|
20
|
-
//
|
|
36
|
+
// 2. Parse CSV string into structured data
|
|
21
37
|
const data = parseCSV(`name,age,city,salary
|
|
22
38
|
Alice,30,Paris,75000
|
|
23
39
|
Bob,25,London,62000
|
|
24
40
|
Charlie,35,Berlin,88000`);
|
|
25
41
|
|
|
26
|
-
//
|
|
42
|
+
// 3. Run full AI analysis (summary + anomalies + charts) in parallel
|
|
27
43
|
const result = await analyzeData({
|
|
28
44
|
model: { apiKey: "sk-...", model: "gpt-4o" },
|
|
29
45
|
data,
|
|
@@ -33,7 +49,7 @@ console.log(result.summary.keyInsights);
|
|
|
33
49
|
console.log(`Found ${result.anomalies.length} anomalies`);
|
|
34
50
|
console.log(`Generated ${result.charts.length} chart suggestions`);
|
|
35
51
|
|
|
36
|
-
//
|
|
52
|
+
// 4. Suggest questions the user could ask
|
|
37
53
|
const questions = await suggestQuestions({
|
|
38
54
|
model: { apiKey: "sk-...", model: "gpt-4o" },
|
|
39
55
|
data,
|
|
@@ -41,6 +57,56 @@ const questions = await suggestQuestions({
|
|
|
41
57
|
questions.forEach(q => console.log(`[${q.category}] ${q.question}`));
|
|
42
58
|
```
|
|
43
59
|
|
|
60
|
+
## Provider Setup
|
|
61
|
+
|
|
62
|
+
Register AI providers **once** at app startup, before calling any AI function. You only install and register the providers you need.
|
|
63
|
+
|
|
64
|
+
### Using `@ai-sdk/*` packages
|
|
65
|
+
|
|
66
|
+
The `fromSDK()` helper wraps any `@ai-sdk/*` creator into the format the library expects:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { registerProvider, fromSDK } from "csv-charts-ai";
|
|
70
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
71
|
+
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
72
|
+
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
73
|
+
import { createMistral } from "@ai-sdk/mistral";
|
|
74
|
+
|
|
75
|
+
registerProvider("openai", fromSDK(createOpenAI));
|
|
76
|
+
registerProvider("anthropic", fromSDK(createAnthropic));
|
|
77
|
+
registerProvider("google", fromSDK(createGoogleGenerativeAI));
|
|
78
|
+
registerProvider("mistral", fromSDK(createMistral));
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Custom / self-hosted providers
|
|
82
|
+
|
|
83
|
+
For full control, pass a `ProviderFactory` directly — a function that receives `{ apiKey, model, baseURL?, headers? }` and returns a `LanguageModel`:
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
import { registerProvider } from "csv-charts-ai";
|
|
87
|
+
|
|
88
|
+
registerProvider("my-llm", (config) => {
|
|
89
|
+
return myCustomSDK.createModel(config.apiKey, config.model);
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Batch registration
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
import { registerProviders, fromSDK } from "csv-charts-ai";
|
|
97
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
98
|
+
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
99
|
+
|
|
100
|
+
registerProviders({
|
|
101
|
+
openai: fromSDK(createOpenAI),
|
|
102
|
+
anthropic: fromSDK(createAnthropic),
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Aliases
|
|
107
|
+
|
|
108
|
+
npm package names are resolved automatically — `"@ai-sdk/openai"` and `"openai"` map to the same slot. So `createModel({ provider: "openai" })` and `createAppModel({ providerNpm: "@ai-sdk/openai" })` both work after a single registration.
|
|
109
|
+
|
|
44
110
|
## CSV Parsing
|
|
45
111
|
|
|
46
112
|
Parse CSV strings into the `TabularData` format with automatic delimiter detection and column type inference.
|
|
@@ -69,11 +135,7 @@ console.log(data.columns); // [{ name: "name", type: "string", index: 0 }, ...
|
|
|
69
135
|
|
|
70
136
|
## XLSX Parsing
|
|
71
137
|
|
|
72
|
-
Parse Excel (.xlsx) files into the same `TabularData` format.
|
|
73
|
-
|
|
74
|
-
```bash
|
|
75
|
-
pnpm add read-excel-file
|
|
76
|
-
```
|
|
138
|
+
Parse Excel (.xlsx) files into the same `TabularData` format. `read-excel-file` is bundled.
|
|
77
139
|
|
|
78
140
|
### Browser
|
|
79
141
|
|
|
@@ -107,13 +169,13 @@ All AI functions accept either a simple config object or a pre-built `LanguageMo
|
|
|
107
169
|
```ts
|
|
108
170
|
import { suggestCharts } from "csv-charts-ai";
|
|
109
171
|
|
|
110
|
-
// Simple — OpenAI
|
|
172
|
+
// Simple — OpenAI (provider must be registered, see Provider Setup)
|
|
111
173
|
const charts = await suggestCharts({
|
|
112
174
|
model: { apiKey: "sk-...", model: "gpt-4o" },
|
|
113
175
|
data,
|
|
114
176
|
});
|
|
115
177
|
|
|
116
|
-
// Custom endpoint — Ollama / vLLM / LM Studio
|
|
178
|
+
// Custom endpoint — Ollama / vLLM / LM Studio (uses the "openai" provider)
|
|
117
179
|
const charts = await suggestCharts({
|
|
118
180
|
model: { apiKey: "", model: "llama3", baseURL: "http://localhost:11434/v1" },
|
|
119
181
|
data,
|
|
@@ -125,8 +187,9 @@ const charts = await suggestCharts({
|
|
|
125
187
|
data,
|
|
126
188
|
});
|
|
127
189
|
|
|
128
|
-
// Advanced — any LanguageModel instance
|
|
129
|
-
import {
|
|
190
|
+
// Advanced — any LanguageModel instance (no registration needed)
|
|
191
|
+
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
192
|
+
const anthropic = createAnthropic({ apiKey: "sk-ant-..." });
|
|
130
193
|
const charts = await suggestCharts({
|
|
131
194
|
model: anthropic("claude-sonnet-4-20250514"),
|
|
132
195
|
data,
|
|
@@ -278,14 +341,19 @@ useEffect(() => {
|
|
|
278
341
|
}, [data]);
|
|
279
342
|
```
|
|
280
343
|
|
|
281
|
-
## React Components
|
|
344
|
+
## React Components (`csv-charts-ai/charts`)
|
|
282
345
|
|
|
283
|
-
|
|
346
|
+
Chart components are available as a **separate entry point** so projects that only need AI/parsing don't pull in React, Recharts, or Lucide.
|
|
347
|
+
|
|
348
|
+
```bash
|
|
349
|
+
# Optional peer dependencies — only needed if you import from csv-charts-ai/charts
|
|
350
|
+
pnpm add react recharts lucide-react
|
|
351
|
+
```
|
|
284
352
|
|
|
285
353
|
### Display Charts
|
|
286
354
|
|
|
287
355
|
```tsx
|
|
288
|
-
import { ChartDisplay } from "csv-charts-ai";
|
|
356
|
+
import { ChartDisplay } from "csv-charts-ai/charts";
|
|
289
357
|
|
|
290
358
|
<ChartDisplay data={data} charts={charts} />
|
|
291
359
|
```
|
|
@@ -293,7 +361,7 @@ import { ChartDisplay } from "csv-charts-ai";
|
|
|
293
361
|
### With Theme
|
|
294
362
|
|
|
295
363
|
```tsx
|
|
296
|
-
import { ChartDisplay, defaultLightTheme } from "csv-charts-ai";
|
|
364
|
+
import { ChartDisplay, defaultLightTheme } from "csv-charts-ai/charts";
|
|
297
365
|
|
|
298
366
|
<ChartDisplay data={data} charts={charts} theme={defaultLightTheme} />
|
|
299
367
|
```
|
|
@@ -301,6 +369,9 @@ import { ChartDisplay, defaultLightTheme } from "csv-charts-ai";
|
|
|
301
369
|
### Custom Card Wrapper
|
|
302
370
|
|
|
303
371
|
```tsx
|
|
372
|
+
import { ChartDisplay } from "csv-charts-ai/charts";
|
|
373
|
+
import { repairChart } from "csv-charts-ai";
|
|
374
|
+
|
|
304
375
|
<ChartDisplay
|
|
305
376
|
data={data}
|
|
306
377
|
charts={charts}
|
|
@@ -340,12 +411,15 @@ You can also pass `className` to any component to add classes alongside the buil
|
|
|
340
411
|
|
|
341
412
|
### Headless Usage (No React)
|
|
342
413
|
|
|
343
|
-
The
|
|
414
|
+
The core entry point (`csv-charts-ai`) works without React — use it in Node.js scripts, APIs, or CLI tools:
|
|
344
415
|
|
|
345
416
|
```ts
|
|
346
|
-
import { parseCSV, analyzeData } from "csv-charts-ai";
|
|
417
|
+
import { registerProvider, fromSDK, parseCSV, analyzeData } from "csv-charts-ai";
|
|
418
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
347
419
|
import { readFileSync } from "fs";
|
|
348
420
|
|
|
421
|
+
registerProvider("openai", fromSDK(createOpenAI));
|
|
422
|
+
|
|
349
423
|
const csv = readFileSync("sales.csv", "utf-8");
|
|
350
424
|
const data = parseCSV(csv);
|
|
351
425
|
|
|
@@ -357,7 +431,7 @@ const result = await analyzeData({
|
|
|
357
431
|
console.log(result.summary.keyInsights);
|
|
358
432
|
```
|
|
359
433
|
|
|
360
|
-
## Components Reference
|
|
434
|
+
## Components Reference (`csv-charts-ai/charts`)
|
|
361
435
|
|
|
362
436
|
| Export | Description |
|
|
363
437
|
|--------|-------------|
|
|
@@ -381,16 +455,30 @@ console.log(result.summary.keyInsights);
|
|
|
381
455
|
| `suggestQuestions(options)` | Suggest interesting questions to ask about the data |
|
|
382
456
|
| `analyzeData(options)` | Full pipeline: summary + anomalies + charts in parallel |
|
|
383
457
|
|
|
458
|
+
## Provider Registry Reference
|
|
459
|
+
|
|
460
|
+
| Export | Description |
|
|
461
|
+
|--------|-------------|
|
|
462
|
+
| `registerProvider(name, factory)` | Register a provider by name |
|
|
463
|
+
| `registerProviders(map)` | Register multiple providers at once |
|
|
464
|
+
| `fromSDK(creator)` | Wrap an `@ai-sdk/*` creator into a `ProviderFactory` |
|
|
465
|
+
| `getProvider(name)` | Get a registered provider (or `undefined`) |
|
|
466
|
+
| `hasProvider(name)` | Check if a provider is registered |
|
|
467
|
+
| `clearProviders()` | Remove all registered providers (for testing) |
|
|
468
|
+
|
|
384
469
|
## Utilities Reference
|
|
385
470
|
|
|
386
471
|
| Export | Description |
|
|
387
472
|
|--------|-------------|
|
|
388
473
|
| `parseCSV(csv, options?)` | Parse CSV string into `TabularData` |
|
|
389
|
-
| `parseXLSX(file, options?)` | Parse XLSX file into `TabularData` (browser
|
|
390
|
-
| `convertXLSXRows(rows, options?)` | Convert raw XLSX rows into `TabularData` (universal
|
|
474
|
+
| `parseXLSX(file, options?)` | Parse XLSX file into `TabularData` (browser) |
|
|
475
|
+
| `convertXLSXRows(rows, options?)` | Convert raw XLSX rows into `TabularData` (universal) |
|
|
476
|
+
| `computeDiff(dataA, dataB, options)` | Compare two datasets (index, key, or content matching) |
|
|
391
477
|
| `createModel(config)` | Create a LanguageModel from an AIConfig |
|
|
392
|
-
| `
|
|
393
|
-
| `
|
|
478
|
+
| `createAppModel(config)` | Create a LanguageModel from multi-provider app config |
|
|
479
|
+
| `resolveModel(input)` | Resolve AIConfig, AppModelConfig, or LanguageModel |
|
|
480
|
+
| `generateDataSummary(data)` | Detailed human-readable data summary with sample rows |
|
|
481
|
+
| `summarizeTabularData(data)` | Compact data summary for AI prompt consumption |
|
|
394
482
|
| `getAIErrorMessage(error)` | Extract user-friendly error messages |
|
|
395
483
|
| `processChartData(data, chart)` | Process and aggregate chart data |
|
|
396
484
|
| `processChartDataMultiSeries(data, chart)` | Multi-series data processing |
|
|
@@ -413,16 +501,38 @@ Multi-series supported via `groupBy` for bar, line, and area charts.
|
|
|
413
501
|
|
|
414
502
|
`sum` | `avg` | `count` | `min` | `max` | `none`
|
|
415
503
|
|
|
504
|
+
## CSV Diff
|
|
505
|
+
|
|
506
|
+
Compare two datasets and detect added, removed, and changed rows:
|
|
507
|
+
|
|
508
|
+
```ts
|
|
509
|
+
import { computeDiff } from "csv-charts-ai";
|
|
510
|
+
|
|
511
|
+
const diff = computeDiff(dataA, dataB, { matchMode: "key", keyColumn: "id" });
|
|
512
|
+
|
|
513
|
+
console.log(diff.counts); // { same: 10, changed: 3, added: 2, removed: 1 }
|
|
514
|
+
diff.rows.forEach(r => {
|
|
515
|
+
if (r.status === "changed") {
|
|
516
|
+
console.log(`Row ${r.indexA}: changed columns: ${[...r.changedCols].join(", ")}`);
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
Match modes: `"index"` (positional), `"key"` (by column value), `"content"` (full row match).
|
|
522
|
+
|
|
416
523
|
## Provider Support
|
|
417
524
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
|
421
|
-
|
|
422
|
-
|
|
|
423
|
-
| Anthropic | `{ provider: "anthropic", apiKey, model }` |
|
|
424
|
-
| Google | `{ provider: "google", apiKey, model }` |
|
|
425
|
-
|
|
|
525
|
+
Install only the provider(s) you need and register them at startup (see [Provider Setup](#provider-setup)).
|
|
526
|
+
|
|
527
|
+
| Provider | Install | Config |
|
|
528
|
+
|----------|---------|--------|
|
|
529
|
+
| OpenAI | `@ai-sdk/openai` | `{ apiKey, model }` |
|
|
530
|
+
| Anthropic | `@ai-sdk/anthropic` | `{ provider: "anthropic", apiKey, model }` |
|
|
531
|
+
| Google | `@ai-sdk/google` | `{ provider: "google", apiKey, model }` |
|
|
532
|
+
| Mistral | `@ai-sdk/mistral` | `{ provider: "mistral", apiKey, model }` |
|
|
533
|
+
| Ollama / vLLM / LM Studio | `@ai-sdk/openai` | `{ apiKey: "", model, baseURL }` |
|
|
534
|
+
| Custom provider | — | `registerProvider("name", factory)` |
|
|
535
|
+
| Any LanguageModel | — | Pass instance directly |
|
|
426
536
|
|
|
427
537
|
## License
|
|
428
538
|
|
package/dist/charts.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { T as TabularData, C as ChartConfig, c as ChartTheme, d as ChartType, S as SortOrder } from './constants-hUsrIT8W.js';
|
|
3
|
+
export { A as AggregationType, a as COLORS, b as ChartDataPoint, P as ProcessedChartResult, e as defaultDarkTheme, f as defaultLightTheme, p as processChartData, g as processChartDataMultiSeries } from './constants-hUsrIT8W.js';
|
|
4
|
+
|
|
5
|
+
interface ChartDisplayProps {
|
|
6
|
+
data: TabularData;
|
|
7
|
+
charts: ChartConfig[];
|
|
8
|
+
onRegenerate?: (chart: ChartConfig) => Promise<void>;
|
|
9
|
+
/** Optional wrapper component for each chart card */
|
|
10
|
+
cardWrapper?: React.ComponentType<{
|
|
11
|
+
children: React.ReactNode;
|
|
12
|
+
title?: string;
|
|
13
|
+
className?: string;
|
|
14
|
+
}>;
|
|
15
|
+
/** Optional theme override */
|
|
16
|
+
theme?: ChartTheme;
|
|
17
|
+
/** Additional CSS class for the outer container */
|
|
18
|
+
className?: string;
|
|
19
|
+
/** Additional CSS class for each chart card */
|
|
20
|
+
chartClassName?: string;
|
|
21
|
+
/** Additional CSS class for chart title */
|
|
22
|
+
titleClassName?: string;
|
|
23
|
+
/** Additional CSS class for chart description */
|
|
24
|
+
descriptionClassName?: string;
|
|
25
|
+
/** When true, removes all built-in Tailwind classes. You must style everything yourself. */
|
|
26
|
+
unstyled?: boolean;
|
|
27
|
+
}
|
|
28
|
+
declare function ChartDisplay({ data, charts, onRegenerate, cardWrapper: CardWrapper, theme, className, chartClassName, titleClassName, descriptionClassName, unstyled, }: ChartDisplayProps): react_jsx_runtime.JSX.Element | null;
|
|
29
|
+
|
|
30
|
+
interface SingleChartProps {
|
|
31
|
+
data: TabularData;
|
|
32
|
+
chart: ChartConfig;
|
|
33
|
+
onRegenerate?: (chart: ChartConfig) => Promise<void>;
|
|
34
|
+
/** Additional CSS class for the chart container */
|
|
35
|
+
className?: string;
|
|
36
|
+
/** When true, removes all built-in Tailwind classes from toolbar and metadata tags */
|
|
37
|
+
unstyled?: boolean;
|
|
38
|
+
}
|
|
39
|
+
declare function SingleChart({ data, chart, onRegenerate, className, unstyled }: SingleChartProps): react_jsx_runtime.JSX.Element;
|
|
40
|
+
|
|
41
|
+
interface ChartToolbarProps {
|
|
42
|
+
chartType: ChartType;
|
|
43
|
+
sortOrder: SortOrder;
|
|
44
|
+
limitResults: number;
|
|
45
|
+
showBrush: boolean;
|
|
46
|
+
showTrendline: boolean;
|
|
47
|
+
isRegenerating: boolean;
|
|
48
|
+
hasRegenerate: boolean;
|
|
49
|
+
onToggleSort: () => void;
|
|
50
|
+
onLimitChange: (limit: number) => void;
|
|
51
|
+
onToggleBrush: () => void;
|
|
52
|
+
onToggleTrendline: () => void;
|
|
53
|
+
onExportCSV: () => void;
|
|
54
|
+
onExportPNG: () => void;
|
|
55
|
+
onRegenerate: () => void;
|
|
56
|
+
/** Additional CSS class for the toolbar container */
|
|
57
|
+
className?: string;
|
|
58
|
+
/** When true, removes all built-in Tailwind classes */
|
|
59
|
+
unstyled?: boolean;
|
|
60
|
+
}
|
|
61
|
+
declare function ChartToolbar({ chartType, sortOrder, limitResults, showBrush, showTrendline, isRegenerating, hasRegenerate, onToggleSort, onLimitChange, onToggleBrush, onToggleTrendline, onExportCSV, onExportPNG, onRegenerate, className, unstyled, }: ChartToolbarProps): react_jsx_runtime.JSX.Element;
|
|
62
|
+
|
|
63
|
+
declare function ChartThemeProvider({ theme, children, }: {
|
|
64
|
+
theme: ChartTheme;
|
|
65
|
+
children: React.ReactNode;
|
|
66
|
+
}): react_jsx_runtime.JSX.Element;
|
|
67
|
+
declare function useChartTheme(): ChartTheme;
|
|
68
|
+
|
|
69
|
+
export { ChartConfig, ChartDisplay, type ChartDisplayProps, ChartTheme, ChartThemeProvider, ChartToolbar, ChartType, SingleChart, type SingleChartProps, SortOrder, TabularData, useChartTheme };
|