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 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 ai zod
10
+ pnpm add csv-charts-ai
11
11
  ```
12
12
 
13
- **Peer dependencies:** `ai`, `zod` (required). `react`, `recharts`, `lucide-react` (optional — only needed for React chart components).
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
- // 1. Parse CSV string into structured data
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
- // 2. Run full AI analysis (summary + anomalies + charts) in parallel
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
- // 3. Suggest questions the user could ask
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. Requires `read-excel-file` as an optional peer dependency.
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 { anthropic } from "@ai-sdk/anthropic";
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
- > **Requires** `react`, `recharts`, `lucide-react`, and **Tailwind CSS** for styling.
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 AI functions and CSV parsing work without React — use them in Node.js scripts, APIs, or CLI tools:
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, requires `read-excel-file`) |
390
- | `convertXLSXRows(rows, options?)` | Convert raw XLSX rows into `TabularData` (universal, zero deps) |
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
- | `resolveModel(input)` | Resolve AIConfig or LanguageModel to LanguageModel |
393
- | `summarizeTabularData(data)` | Generate text summary for AI consumption |
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
- | Provider | Config | Extra install |
419
- |----------|--------|---------------|
420
- | OpenAI | `{ apiKey, model }` | None (bundled) |
421
- | Ollama / vLLM / LM Studio | `{ apiKey: "", model, baseURL }` | None |
422
- | Mistral (via OpenAI compat) | `{ apiKey, model, baseURL: "https://api.mistral.ai/v1" }` | None |
423
- | Anthropic | `{ provider: "anthropic", apiKey, model }` | `@ai-sdk/anthropic` |
424
- | Google | `{ provider: "google", apiKey, model }` | `@ai-sdk/google` |
425
- | Any LanguageModel | Pass instance directly | Provider SDK |
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
 
@@ -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 };