@smallwebco/tinypivot-server 1.0.57
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.md +78 -0
- package/README.md +362 -0
- package/dist/index.cjs +635 -0
- package/dist/index.d.cts +180 -0
- package/dist/index.d.ts +180 -0
- package/dist/index.js +594 -0
- package/package.json +54 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
export { AIColumnSchema, AIProxyRequest, AIProxyResponse, AITableSchema, QueryRequest, QueryResponse, SchemaRequest, SchemaResponse } from '@smallwebco/tinypivot-core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TinyPivot Server - Type Definitions
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generic request handler type
|
|
9
|
+
* Compatible with Express, Fastify, Next.js API routes, etc.
|
|
10
|
+
*/
|
|
11
|
+
type RequestHandler = (req: Request) => Promise<Response>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Table filtering options for controlling which tables are exposed
|
|
15
|
+
*/
|
|
16
|
+
interface TableFilterOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Only include tables matching these patterns (exact string or regex)
|
|
19
|
+
* If not provided, all tables in the specified schemas are included.
|
|
20
|
+
*
|
|
21
|
+
* Example: `['sales', 'customers', /^app_.+/]`
|
|
22
|
+
*/
|
|
23
|
+
include?: (string | RegExp)[];
|
|
24
|
+
/**
|
|
25
|
+
* Exclude tables matching these patterns (applied after include)
|
|
26
|
+
*
|
|
27
|
+
* Example: `[/^_/, 'migrations', 'sessions']`
|
|
28
|
+
*/
|
|
29
|
+
exclude?: (string | RegExp)[];
|
|
30
|
+
/**
|
|
31
|
+
* Only include tables from these schemas (default: ['public'])
|
|
32
|
+
*
|
|
33
|
+
* Example: `['public', 'analytics']`
|
|
34
|
+
*/
|
|
35
|
+
schemas?: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Descriptions to show to the AI for context
|
|
38
|
+
* Keys are table names, values are human-readable descriptions
|
|
39
|
+
*/
|
|
40
|
+
descriptions?: Record<string, string>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Options for creating the unified TinyPivot handler
|
|
44
|
+
*/
|
|
45
|
+
interface TinyPivotHandlerOptions {
|
|
46
|
+
/**
|
|
47
|
+
* PostgreSQL connection string
|
|
48
|
+
* @default process.env.DATABASE_URL
|
|
49
|
+
*/
|
|
50
|
+
connectionString?: string;
|
|
51
|
+
/**
|
|
52
|
+
* AI API key - auto-detects provider from key format:
|
|
53
|
+
* - `sk-ant-...` → Anthropic
|
|
54
|
+
* - `sk-or-...` → OpenRouter
|
|
55
|
+
* - `sk-...` → OpenAI
|
|
56
|
+
* @default process.env.AI_API_KEY
|
|
57
|
+
*/
|
|
58
|
+
apiKey?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Table filtering options
|
|
61
|
+
* By default, all tables in the 'public' schema are exposed.
|
|
62
|
+
*/
|
|
63
|
+
tables?: TableFilterOptions;
|
|
64
|
+
/**
|
|
65
|
+
* Maximum rows to return from queries.
|
|
66
|
+
* If not set, no limit is enforced (queries may return large result sets).
|
|
67
|
+
*/
|
|
68
|
+
maxRows?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Query timeout in milliseconds.
|
|
71
|
+
* If not set, uses PostgreSQL default (no timeout).
|
|
72
|
+
*/
|
|
73
|
+
timeout?: number;
|
|
74
|
+
/**
|
|
75
|
+
* Override the AI model.
|
|
76
|
+
*
|
|
77
|
+
* Priority: options.model > AI_MODEL env var > cheap default per provider
|
|
78
|
+
*
|
|
79
|
+
* Defaults (cheap/fast):
|
|
80
|
+
* - Anthropic: claude-3-haiku-20240307
|
|
81
|
+
* - OpenAI: gpt-4o-mini
|
|
82
|
+
* - OpenRouter: anthropic/claude-3-haiku
|
|
83
|
+
*
|
|
84
|
+
* @example 'claude-sonnet-4-20250514', 'gpt-4o'
|
|
85
|
+
*/
|
|
86
|
+
model?: string;
|
|
87
|
+
/**
|
|
88
|
+
* Maximum tokens for AI responses
|
|
89
|
+
* @default 2048
|
|
90
|
+
*/
|
|
91
|
+
maxTokens?: number;
|
|
92
|
+
/**
|
|
93
|
+
* Custom error handler
|
|
94
|
+
*/
|
|
95
|
+
onError?: (error: Error) => void;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Request body for the unified endpoint
|
|
99
|
+
*/
|
|
100
|
+
interface TinyPivotRequest {
|
|
101
|
+
/** Action to perform */
|
|
102
|
+
action: 'list-tables' | 'get-schema' | 'query' | 'chat';
|
|
103
|
+
tables?: string[];
|
|
104
|
+
sql?: string;
|
|
105
|
+
table?: string;
|
|
106
|
+
messages?: Array<{
|
|
107
|
+
role: 'user' | 'assistant' | 'system';
|
|
108
|
+
content: string;
|
|
109
|
+
}>;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Response for list-tables action
|
|
113
|
+
*/
|
|
114
|
+
interface ListTablesResponse {
|
|
115
|
+
tables: Array<{
|
|
116
|
+
name: string;
|
|
117
|
+
description?: string;
|
|
118
|
+
}>;
|
|
119
|
+
error?: string;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Create a unified TinyPivot handler
|
|
123
|
+
*
|
|
124
|
+
* This single endpoint handles:
|
|
125
|
+
* - `action: 'list-tables'` - Auto-discover tables from PostgreSQL
|
|
126
|
+
* - `action: 'get-schema'` - Get column schema for tables
|
|
127
|
+
* - `action: 'query'` - Execute validated SELECT queries
|
|
128
|
+
* - `action: 'chat'` - Proxy to AI provider
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* // Next.js App Router - app/api/tinypivot/route.ts
|
|
133
|
+
* import { createTinyPivotHandler } from '@smallwebco/tinypivot-server'
|
|
134
|
+
*
|
|
135
|
+
* export const POST = createTinyPivotHandler()
|
|
136
|
+
* ```
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* // With options
|
|
141
|
+
* const handler = createTinyPivotHandler({
|
|
142
|
+
* tables: {
|
|
143
|
+
* include: ['sales', 'customers', 'products'],
|
|
144
|
+
* exclude: [/^_/, 'migrations'],
|
|
145
|
+
* descriptions: {
|
|
146
|
+
* sales: 'Sales transactions with revenue data',
|
|
147
|
+
* }
|
|
148
|
+
* }
|
|
149
|
+
* })
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
declare function createTinyPivotHandler(options?: TinyPivotHandlerOptions): RequestHandler;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* TinyPivot Server - SQL Validation
|
|
156
|
+
* Ensures queries are safe and read-only
|
|
157
|
+
*/
|
|
158
|
+
interface ValidationResult {
|
|
159
|
+
valid: boolean;
|
|
160
|
+
error?: string;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Validate that a SQL query is safe to execute
|
|
164
|
+
*/
|
|
165
|
+
declare function validateSQL(sql: string, allowedTables: string[]): ValidationResult;
|
|
166
|
+
/**
|
|
167
|
+
* Extract table names from a SELECT query
|
|
168
|
+
* This is a simplified parser - for production, consider using a proper SQL parser
|
|
169
|
+
*/
|
|
170
|
+
declare function extractTableNames(sql: string): string[];
|
|
171
|
+
/**
|
|
172
|
+
* Sanitize a table name to prevent SQL injection
|
|
173
|
+
*/
|
|
174
|
+
declare function sanitizeTableName(name: string): string;
|
|
175
|
+
/**
|
|
176
|
+
* Add LIMIT clause if not present
|
|
177
|
+
*/
|
|
178
|
+
declare function ensureLimit(sql: string, maxRows: number): string;
|
|
179
|
+
|
|
180
|
+
export { type ListTablesResponse, type RequestHandler, type TableFilterOptions, type TinyPivotHandlerOptions, type TinyPivotRequest, type ValidationResult, createTinyPivotHandler, ensureLimit, extractTableNames, sanitizeTableName, validateSQL };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
export { AIColumnSchema, AIProxyRequest, AIProxyResponse, AITableSchema, QueryRequest, QueryResponse, SchemaRequest, SchemaResponse } from '@smallwebco/tinypivot-core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* TinyPivot Server - Type Definitions
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Generic request handler type
|
|
9
|
+
* Compatible with Express, Fastify, Next.js API routes, etc.
|
|
10
|
+
*/
|
|
11
|
+
type RequestHandler = (req: Request) => Promise<Response>;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Table filtering options for controlling which tables are exposed
|
|
15
|
+
*/
|
|
16
|
+
interface TableFilterOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Only include tables matching these patterns (exact string or regex)
|
|
19
|
+
* If not provided, all tables in the specified schemas are included.
|
|
20
|
+
*
|
|
21
|
+
* Example: `['sales', 'customers', /^app_.+/]`
|
|
22
|
+
*/
|
|
23
|
+
include?: (string | RegExp)[];
|
|
24
|
+
/**
|
|
25
|
+
* Exclude tables matching these patterns (applied after include)
|
|
26
|
+
*
|
|
27
|
+
* Example: `[/^_/, 'migrations', 'sessions']`
|
|
28
|
+
*/
|
|
29
|
+
exclude?: (string | RegExp)[];
|
|
30
|
+
/**
|
|
31
|
+
* Only include tables from these schemas (default: ['public'])
|
|
32
|
+
*
|
|
33
|
+
* Example: `['public', 'analytics']`
|
|
34
|
+
*/
|
|
35
|
+
schemas?: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Descriptions to show to the AI for context
|
|
38
|
+
* Keys are table names, values are human-readable descriptions
|
|
39
|
+
*/
|
|
40
|
+
descriptions?: Record<string, string>;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Options for creating the unified TinyPivot handler
|
|
44
|
+
*/
|
|
45
|
+
interface TinyPivotHandlerOptions {
|
|
46
|
+
/**
|
|
47
|
+
* PostgreSQL connection string
|
|
48
|
+
* @default process.env.DATABASE_URL
|
|
49
|
+
*/
|
|
50
|
+
connectionString?: string;
|
|
51
|
+
/**
|
|
52
|
+
* AI API key - auto-detects provider from key format:
|
|
53
|
+
* - `sk-ant-...` → Anthropic
|
|
54
|
+
* - `sk-or-...` → OpenRouter
|
|
55
|
+
* - `sk-...` → OpenAI
|
|
56
|
+
* @default process.env.AI_API_KEY
|
|
57
|
+
*/
|
|
58
|
+
apiKey?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Table filtering options
|
|
61
|
+
* By default, all tables in the 'public' schema are exposed.
|
|
62
|
+
*/
|
|
63
|
+
tables?: TableFilterOptions;
|
|
64
|
+
/**
|
|
65
|
+
* Maximum rows to return from queries.
|
|
66
|
+
* If not set, no limit is enforced (queries may return large result sets).
|
|
67
|
+
*/
|
|
68
|
+
maxRows?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Query timeout in milliseconds.
|
|
71
|
+
* If not set, uses PostgreSQL default (no timeout).
|
|
72
|
+
*/
|
|
73
|
+
timeout?: number;
|
|
74
|
+
/**
|
|
75
|
+
* Override the AI model.
|
|
76
|
+
*
|
|
77
|
+
* Priority: options.model > AI_MODEL env var > cheap default per provider
|
|
78
|
+
*
|
|
79
|
+
* Defaults (cheap/fast):
|
|
80
|
+
* - Anthropic: claude-3-haiku-20240307
|
|
81
|
+
* - OpenAI: gpt-4o-mini
|
|
82
|
+
* - OpenRouter: anthropic/claude-3-haiku
|
|
83
|
+
*
|
|
84
|
+
* @example 'claude-sonnet-4-20250514', 'gpt-4o'
|
|
85
|
+
*/
|
|
86
|
+
model?: string;
|
|
87
|
+
/**
|
|
88
|
+
* Maximum tokens for AI responses
|
|
89
|
+
* @default 2048
|
|
90
|
+
*/
|
|
91
|
+
maxTokens?: number;
|
|
92
|
+
/**
|
|
93
|
+
* Custom error handler
|
|
94
|
+
*/
|
|
95
|
+
onError?: (error: Error) => void;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Request body for the unified endpoint
|
|
99
|
+
*/
|
|
100
|
+
interface TinyPivotRequest {
|
|
101
|
+
/** Action to perform */
|
|
102
|
+
action: 'list-tables' | 'get-schema' | 'query' | 'chat';
|
|
103
|
+
tables?: string[];
|
|
104
|
+
sql?: string;
|
|
105
|
+
table?: string;
|
|
106
|
+
messages?: Array<{
|
|
107
|
+
role: 'user' | 'assistant' | 'system';
|
|
108
|
+
content: string;
|
|
109
|
+
}>;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Response for list-tables action
|
|
113
|
+
*/
|
|
114
|
+
interface ListTablesResponse {
|
|
115
|
+
tables: Array<{
|
|
116
|
+
name: string;
|
|
117
|
+
description?: string;
|
|
118
|
+
}>;
|
|
119
|
+
error?: string;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Create a unified TinyPivot handler
|
|
123
|
+
*
|
|
124
|
+
* This single endpoint handles:
|
|
125
|
+
* - `action: 'list-tables'` - Auto-discover tables from PostgreSQL
|
|
126
|
+
* - `action: 'get-schema'` - Get column schema for tables
|
|
127
|
+
* - `action: 'query'` - Execute validated SELECT queries
|
|
128
|
+
* - `action: 'chat'` - Proxy to AI provider
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* // Next.js App Router - app/api/tinypivot/route.ts
|
|
133
|
+
* import { createTinyPivotHandler } from '@smallwebco/tinypivot-server'
|
|
134
|
+
*
|
|
135
|
+
* export const POST = createTinyPivotHandler()
|
|
136
|
+
* ```
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* ```typescript
|
|
140
|
+
* // With options
|
|
141
|
+
* const handler = createTinyPivotHandler({
|
|
142
|
+
* tables: {
|
|
143
|
+
* include: ['sales', 'customers', 'products'],
|
|
144
|
+
* exclude: [/^_/, 'migrations'],
|
|
145
|
+
* descriptions: {
|
|
146
|
+
* sales: 'Sales transactions with revenue data',
|
|
147
|
+
* }
|
|
148
|
+
* }
|
|
149
|
+
* })
|
|
150
|
+
* ```
|
|
151
|
+
*/
|
|
152
|
+
declare function createTinyPivotHandler(options?: TinyPivotHandlerOptions): RequestHandler;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* TinyPivot Server - SQL Validation
|
|
156
|
+
* Ensures queries are safe and read-only
|
|
157
|
+
*/
|
|
158
|
+
interface ValidationResult {
|
|
159
|
+
valid: boolean;
|
|
160
|
+
error?: string;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Validate that a SQL query is safe to execute
|
|
164
|
+
*/
|
|
165
|
+
declare function validateSQL(sql: string, allowedTables: string[]): ValidationResult;
|
|
166
|
+
/**
|
|
167
|
+
* Extract table names from a SELECT query
|
|
168
|
+
* This is a simplified parser - for production, consider using a proper SQL parser
|
|
169
|
+
*/
|
|
170
|
+
declare function extractTableNames(sql: string): string[];
|
|
171
|
+
/**
|
|
172
|
+
* Sanitize a table name to prevent SQL injection
|
|
173
|
+
*/
|
|
174
|
+
declare function sanitizeTableName(name: string): string;
|
|
175
|
+
/**
|
|
176
|
+
* Add LIMIT clause if not present
|
|
177
|
+
*/
|
|
178
|
+
declare function ensureLimit(sql: string, maxRows: number): string;
|
|
179
|
+
|
|
180
|
+
export { type ListTablesResponse, type RequestHandler, type TableFilterOptions, type TinyPivotHandlerOptions, type TinyPivotRequest, type ValidationResult, createTinyPivotHandler, ensureLimit, extractTableNames, sanitizeTableName, validateSQL };
|