crushdataai 1.0.0 → 1.2.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.
@@ -25,6 +25,11 @@ Before writing any code, ask the user:
25
25
  2. **Data Context**: Which tables contain the data? What time range?
26
26
  3. **Metric Definitions**: How does YOUR company define the key metrics? Any filters?
27
27
 
28
+ ## Step 1b: Secure Access
29
+ - Check connections: `npx crushdataai connections`
30
+ - Get connection code: `npx crushdataai snippet <name>`
31
+ - **DO NOT** ask for API credentials.
32
+
28
33
  ---
29
34
 
30
35
  ## Step 2: Search Knowledge Base
@@ -29,7 +29,23 @@ When user requests data analysis work (analyze, query, dashboard, metrics, EDA,
29
29
  - How does YOUR company define the key metrics?
30
30
  - Any filters to apply? (exclude test users, internal accounts?)
31
31
  - What timezone should I use for dates?
32
- ```
32
+ - What timezone should I use for dates?
33
+
34
+ ### Step 1b: Access Data (SECURE)
35
+
36
+ **To access data, DO NOT ask for API keys/credentials.**
37
+
38
+ 1. Check available connections:
39
+ ```bash
40
+ npx crushdataai connections
41
+ ```
42
+
43
+ 2. Get the connection code snippet:
44
+ ```bash
45
+ npx crushdataai snippet <connection_name> --lang python
46
+ ```
47
+
48
+ 3. Paste the snippet into your analysis script to load the data.
33
49
 
34
50
  ### Step 2: Search Relevant Domains
35
51
 
@@ -19,6 +19,11 @@ Before coding, ask:
19
19
  - Which tables contain the data?
20
20
  - How does YOUR company define key metrics?
21
21
 
22
+ ### 1b. Secure Access
23
+ - Check connections: `npx crushdataai connections`
24
+ - Get connection code: `npx crushdataai snippet <name>`
25
+ - **DO NOT** ask for API credentials.
26
+
22
27
  ### 2. Search Knowledge Base
23
28
  ```bash
24
29
  python3 .github/prompts/../.shared/data-analyst/scripts/search.py "<query>" --domain <domain>
@@ -16,6 +16,11 @@ Before coding, ask:
16
16
  - Which tables contain the data?
17
17
  - How does YOUR company define the key metrics?
18
18
 
19
+ 3. **Secure Access**:
20
+ - Check connections: `npx crushdataai connections`
21
+ - Get connection code: `npx crushdataai snippet <name>`
22
+ - **DO NOT** ask for API credentials.
23
+
19
24
  ### 2. Search Knowledge Base
20
25
  ```bash
21
26
  python3 .cursor/commands/../.shared/data-analyst/scripts/search.py "<query>" --domain <domain>
@@ -15,6 +15,11 @@ Before writing code, gather:
15
15
  - Company-specific metric definitions
16
16
  - Time range and filters
17
17
 
18
+ ### 1b. Secure Access
19
+ - Check connections: `npx crushdataai connections`
20
+ - Get connection code: `npx crushdataai snippet <name>`
21
+ - **DO NOT** ask for API credentials.
22
+
18
23
  ### 2. Search Before Implementing
19
24
  ```bash
20
25
  python3 .kiro/steering/../.shared/data-analyst/scripts/search.py "<query>" --domain <domain>
@@ -13,6 +13,11 @@ Ask before coding:
13
13
  - Which tables/databases contain the data
14
14
  - Company-specific metric definitions
15
15
 
16
+ ### 1b. Secure Access
17
+ - Check connections: `npx crushdataai connections`
18
+ - Get connection code: `npx crushdataai snippet <name>`
19
+ - **DO NOT** ask for API credentials.
20
+
16
21
  ### 2. Search Knowledge
17
22
  ```bash
18
23
  python3 .windsurf/workflows/../.shared/data-analyst/scripts/search.py "<query>" --domain <domain>
@@ -0,0 +1 @@
1
+ export declare function snippet(connectionName: string, lang?: string): Promise<void>;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.snippet = snippet;
4
+ const connections_1 = require("../connections");
5
+ const connectors_1 = require("../connectors");
6
+ async function snippet(connectionName, lang = 'python') {
7
+ const connection = (0, connections_1.getConnection)(connectionName);
8
+ if (!connection) {
9
+ console.error(`❌ Connection '${connectionName}' not found.`);
10
+ console.error(` Run 'crushdataai connections' to see available connections.`);
11
+ process.exit(1);
12
+ }
13
+ try {
14
+ const connector = connectors_1.ConnectorRegistry.get(connection.type);
15
+ if (!connector) {
16
+ console.error(`❌ No connector found for type: ${connection.type}`);
17
+ process.exit(1);
18
+ }
19
+ const code = connector.getSnippet(connection, lang);
20
+ console.log(code);
21
+ }
22
+ catch (error) {
23
+ console.error(`❌ Error generating snippet: ${error.message}`);
24
+ process.exit(1);
25
+ }
26
+ }
@@ -0,0 +1,37 @@
1
+ export type ConnectionType = 'mysql' | 'postgresql' | 'bigquery' | 'snowflake' | 'shopify' | 'csv';
2
+ export interface Connection {
3
+ name: string;
4
+ type: ConnectionType;
5
+ host?: string;
6
+ port?: number;
7
+ database?: string;
8
+ user?: string;
9
+ password?: string;
10
+ projectId?: string;
11
+ keyFile?: string;
12
+ account?: string;
13
+ warehouse?: string;
14
+ store?: string;
15
+ apiKey?: string;
16
+ apiSecret?: string;
17
+ filePath?: string;
18
+ createdAt: string;
19
+ updatedAt: string;
20
+ }
21
+ export interface ConnectionsConfig {
22
+ version: string;
23
+ connections: Connection[];
24
+ }
25
+ export declare function encrypt(text: string): string;
26
+ export declare function decrypt(encryptedText: string): string;
27
+ export declare function loadConnections(): ConnectionsConfig;
28
+ export declare function saveConnections(config: ConnectionsConfig): void;
29
+ export declare function saveConnection(connection: Connection): void;
30
+ export declare function getConnection(name: string): Connection | null;
31
+ export declare function deleteConnection(name: string): boolean;
32
+ export declare function listConnections(): Array<{
33
+ name: string;
34
+ type: ConnectionType;
35
+ host?: string;
36
+ createdAt: string;
37
+ }>;
@@ -0,0 +1,176 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.encrypt = encrypt;
37
+ exports.decrypt = decrypt;
38
+ exports.loadConnections = loadConnections;
39
+ exports.saveConnections = saveConnections;
40
+ exports.saveConnection = saveConnection;
41
+ exports.getConnection = getConnection;
42
+ exports.deleteConnection = deleteConnection;
43
+ exports.listConnections = listConnections;
44
+ const crypto = __importStar(require("crypto"));
45
+ const fs = __importStar(require("fs-extra"));
46
+ const os = __importStar(require("os"));
47
+ const path = __importStar(require("path"));
48
+ // Get config directory
49
+ function getConfigDir() {
50
+ return path.join(os.homedir(), '.crushdataai');
51
+ }
52
+ function getConfigPath() {
53
+ return path.join(getConfigDir(), 'connections.json');
54
+ }
55
+ // Get machine-specific encryption key
56
+ function getEncryptionKey() {
57
+ const machineId = os.hostname() + os.userInfo().username;
58
+ return crypto.scryptSync(machineId, 'crushdataai-salt', 32);
59
+ }
60
+ // Encrypt sensitive data
61
+ function encrypt(text) {
62
+ if (!text)
63
+ return '';
64
+ const key = getEncryptionKey();
65
+ const iv = crypto.randomBytes(16);
66
+ const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
67
+ let encrypted = cipher.update(text, 'utf8', 'hex');
68
+ encrypted += cipher.final('hex');
69
+ return iv.toString('hex') + ':' + encrypted;
70
+ }
71
+ // Decrypt sensitive data
72
+ function decrypt(encryptedText) {
73
+ if (!encryptedText || !encryptedText.includes(':'))
74
+ return encryptedText;
75
+ try {
76
+ const key = getEncryptionKey();
77
+ const [ivHex, encrypted] = encryptedText.split(':');
78
+ const iv = Buffer.from(ivHex, 'hex');
79
+ const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
80
+ let decrypted = decipher.update(encrypted, 'hex', 'utf8');
81
+ decrypted += decipher.final('utf8');
82
+ return decrypted;
83
+ }
84
+ catch {
85
+ return '';
86
+ }
87
+ }
88
+ // Load connections from config file
89
+ function loadConnections() {
90
+ const configPath = getConfigPath();
91
+ if (!fs.existsSync(configPath)) {
92
+ return { version: '2.0.0', connections: [] };
93
+ }
94
+ try {
95
+ const data = fs.readJsonSync(configPath);
96
+ return data;
97
+ }
98
+ catch {
99
+ return { version: '2.0.0', connections: [] };
100
+ }
101
+ }
102
+ // Save connections to config file
103
+ function saveConnections(config) {
104
+ const configDir = getConfigDir();
105
+ const configPath = getConfigPath();
106
+ fs.ensureDirSync(configDir);
107
+ fs.writeJsonSync(configPath, config, { spaces: 2 });
108
+ // Set file permissions (user-only on Unix)
109
+ if (process.platform !== 'win32') {
110
+ fs.chmodSync(configPath, 0o600);
111
+ }
112
+ }
113
+ // Add or update a connection
114
+ function saveConnection(connection) {
115
+ const config = loadConnections();
116
+ // Encrypt sensitive fields
117
+ const secureConnection = { ...connection };
118
+ if (secureConnection.password) {
119
+ secureConnection.password = encrypt(secureConnection.password);
120
+ }
121
+ if (secureConnection.apiKey) {
122
+ secureConnection.apiKey = encrypt(secureConnection.apiKey);
123
+ }
124
+ if (secureConnection.apiSecret) {
125
+ secureConnection.apiSecret = encrypt(secureConnection.apiSecret);
126
+ }
127
+ // Update or add
128
+ const existingIndex = config.connections.findIndex(c => c.name === connection.name);
129
+ if (existingIndex >= 0) {
130
+ config.connections[existingIndex] = secureConnection;
131
+ }
132
+ else {
133
+ config.connections.push(secureConnection);
134
+ }
135
+ saveConnections(config);
136
+ }
137
+ // Get a connection (with decrypted credentials)
138
+ function getConnection(name) {
139
+ const config = loadConnections();
140
+ const connection = config.connections.find(c => c.name === name);
141
+ if (!connection)
142
+ return null;
143
+ // Decrypt sensitive fields
144
+ const decrypted = { ...connection };
145
+ if (decrypted.password) {
146
+ decrypted.password = decrypt(decrypted.password);
147
+ }
148
+ if (decrypted.apiKey) {
149
+ decrypted.apiKey = decrypt(decrypted.apiKey);
150
+ }
151
+ if (decrypted.apiSecret) {
152
+ decrypted.apiSecret = decrypt(decrypted.apiSecret);
153
+ }
154
+ return decrypted;
155
+ }
156
+ // Delete a connection
157
+ function deleteConnection(name) {
158
+ const config = loadConnections();
159
+ const initialLength = config.connections.length;
160
+ config.connections = config.connections.filter(c => c.name !== name);
161
+ if (config.connections.length < initialLength) {
162
+ saveConnections(config);
163
+ return true;
164
+ }
165
+ return false;
166
+ }
167
+ // List all connections (without sensitive data)
168
+ function listConnections() {
169
+ const config = loadConnections();
170
+ return config.connections.map(c => ({
171
+ name: c.name,
172
+ type: c.type,
173
+ host: c.host || c.store || c.account || c.filePath,
174
+ createdAt: c.createdAt
175
+ }));
176
+ }
@@ -0,0 +1,16 @@
1
+ import { Connector, Table, TableData } from '../index';
2
+ import { Connection } from '../../connections';
3
+ export declare class BigQueryConnector implements Connector {
4
+ type: string;
5
+ test(connection: Connection): Promise<boolean>;
6
+ getTables(connection: Connection): Promise<Table[]>;
7
+ getData(connection: Connection, table: string, page: number, limit: number): Promise<TableData>;
8
+ getSnippet(connection: Connection, lang: string): string;
9
+ }
10
+ export declare class SnowflakeConnector implements Connector {
11
+ type: string;
12
+ test(connection: Connection): Promise<boolean>;
13
+ getTables(connection: Connection): Promise<Table[]>;
14
+ getData(connection: Connection, table: string, page: number, limit: number): Promise<TableData>;
15
+ getSnippet(connection: Connection, lang: string): string;
16
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SnowflakeConnector = exports.BigQueryConnector = void 0;
4
+ class BigQueryConnector {
5
+ constructor() {
6
+ this.type = 'bigquery';
7
+ }
8
+ async test(connection) {
9
+ return true;
10
+ }
11
+ async getTables(connection) {
12
+ return [];
13
+ }
14
+ async getData(connection, table, page, limit) {
15
+ return { columns: [], rows: [], pagination: { page, limit, totalRows: 0, totalPages: 0, startIdx: 0, endIdx: 0 } };
16
+ }
17
+ getSnippet(connection, lang) {
18
+ return `# BigQuery snippet generation not implemented yet`;
19
+ }
20
+ }
21
+ exports.BigQueryConnector = BigQueryConnector;
22
+ class SnowflakeConnector {
23
+ constructor() {
24
+ this.type = 'snowflake';
25
+ }
26
+ async test(connection) {
27
+ return true;
28
+ }
29
+ async getTables(connection) {
30
+ return [];
31
+ }
32
+ async getData(connection, table, page, limit) {
33
+ return { columns: [], rows: [], pagination: { page, limit, totalRows: 0, totalPages: 0, startIdx: 0, endIdx: 0 } };
34
+ }
35
+ getSnippet(connection, lang) {
36
+ return `# Snowflake snippet generation not implemented yet`;
37
+ }
38
+ }
39
+ exports.SnowflakeConnector = SnowflakeConnector;
@@ -0,0 +1,9 @@
1
+ import { Connector, Table, TableData } from '../index';
2
+ import { Connection } from '../../connections';
3
+ export declare class CSVConnector implements Connector {
4
+ type: string;
5
+ test(connection: Connection): Promise<boolean>;
6
+ getTables(connection: Connection): Promise<Table[]>;
7
+ getData(connection: Connection, tableName: string, page: number, limit: number): Promise<TableData>;
8
+ getSnippet(connection: Connection, lang: string): string;
9
+ }
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.CSVConnector = void 0;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const papaparse_1 = __importDefault(require("papaparse"));
43
+ class CSVConnector {
44
+ constructor() {
45
+ this.type = 'csv';
46
+ }
47
+ async test(connection) {
48
+ if (!connection.filePath) {
49
+ throw new Error('File path is required');
50
+ }
51
+ // Remove surrounding quotes if present
52
+ let filePath = connection.filePath;
53
+ if (filePath.startsWith('"') && filePath.endsWith('"')) {
54
+ filePath = filePath.slice(1, -1);
55
+ }
56
+ // Check if file exists
57
+ if (!fs.existsSync(filePath)) {
58
+ throw new Error('File not found');
59
+ }
60
+ return true;
61
+ }
62
+ async getTables(connection) {
63
+ if (!connection.filePath) {
64
+ return [];
65
+ }
66
+ let filePath = connection.filePath;
67
+ if (filePath.startsWith('"') && filePath.endsWith('"')) {
68
+ filePath = filePath.slice(1, -1);
69
+ }
70
+ const fileName = path.basename(filePath, '.csv');
71
+ // Basic check if file exists, if not it might have been deleted
72
+ if (fs.existsSync(filePath)) {
73
+ return [{ name: fileName, type: 'csv', rowCount: null }];
74
+ }
75
+ return [];
76
+ }
77
+ async getData(connection, tableName, page, limit) {
78
+ let filePath = connection.filePath;
79
+ if (filePath && filePath.startsWith('"') && filePath.endsWith('"')) {
80
+ filePath = filePath.slice(1, -1);
81
+ }
82
+ if (!filePath || !fs.existsSync(filePath)) {
83
+ throw new Error('CSV file not found');
84
+ }
85
+ const fileContent = fs.readFileSync(filePath, 'utf8');
86
+ const result = papaparse_1.default.parse(fileContent, {
87
+ header: true,
88
+ skipEmptyLines: true
89
+ });
90
+ const data = result.data;
91
+ const columns = result.meta.fields || [];
92
+ const totalRows = data.length;
93
+ const totalPages = Math.ceil(totalRows / limit);
94
+ const startIdx = (page - 1) * limit;
95
+ const endIdx = Math.min(startIdx + limit, totalRows);
96
+ const rows = data.slice(startIdx, endIdx);
97
+ return {
98
+ columns,
99
+ rows,
100
+ pagination: {
101
+ page,
102
+ limit,
103
+ totalRows,
104
+ totalPages,
105
+ startIdx: startIdx + 1,
106
+ endIdx
107
+ }
108
+ };
109
+ }
110
+ getSnippet(connection, lang) {
111
+ let filePath = connection.filePath || '';
112
+ if (filePath.startsWith('"') && filePath.endsWith('"')) {
113
+ filePath = filePath.slice(1, -1);
114
+ }
115
+ // Escape backslashes for string literals
116
+ const escapedPath = filePath.replace(/\\/g, '\\\\');
117
+ if (lang === 'python') {
118
+ return `import pandas as pd
119
+
120
+ # Connection: ${connection.name}
121
+ # Type: csv
122
+ file_path = "${escapedPath}"
123
+
124
+ try:
125
+ df = pd.read_csv(file_path)
126
+ print(f"Successfully loaded {len(df)} rows from ${connection.name}")
127
+ print(df.head())
128
+ except Exception as e:
129
+ print(f"Error loading CSV: {e}")
130
+ `;
131
+ }
132
+ return `# Language ${lang} not supported for CSV connector yet.`;
133
+ }
134
+ }
135
+ exports.CSVConnector = CSVConnector;
@@ -0,0 +1,30 @@
1
+ import { Connection } from '../connections';
2
+ export interface Table {
3
+ name: string;
4
+ type?: string;
5
+ rowCount?: number | null;
6
+ }
7
+ export interface TableData {
8
+ columns: string[];
9
+ rows: any[];
10
+ pagination: {
11
+ page: number;
12
+ limit: number;
13
+ totalRows: number;
14
+ totalPages: number;
15
+ startIdx: number;
16
+ endIdx: number;
17
+ };
18
+ }
19
+ export interface Connector {
20
+ type: string;
21
+ test(connection: Connection): Promise<boolean>;
22
+ getTables(connection: Connection): Promise<Table[]>;
23
+ getData(connection: Connection, tableName: string, page: number, limit: number): Promise<TableData>;
24
+ getSnippet(connection: Connection, lang: string): string;
25
+ }
26
+ export declare class ConnectorRegistry {
27
+ private static connectors;
28
+ static register(connector: Connector): void;
29
+ static get(type: string): Connector;
30
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ConnectorRegistry = void 0;
4
+ class ConnectorRegistry {
5
+ static register(connector) {
6
+ this.connectors.set(connector.type, connector);
7
+ }
8
+ static get(type) {
9
+ const connector = this.connectors.get(type);
10
+ if (!connector) {
11
+ throw new Error(`No connector found for type: ${type}`);
12
+ }
13
+ return connector;
14
+ }
15
+ }
16
+ exports.ConnectorRegistry = ConnectorRegistry;
17
+ ConnectorRegistry.connectors = new Map();
@@ -0,0 +1,9 @@
1
+ import { Connector, Table, TableData } from '../index';
2
+ import { Connection } from '../../connections';
3
+ export declare class MySQLConnector implements Connector {
4
+ type: string;
5
+ test(connection: Connection): Promise<boolean>;
6
+ getTables(connection: Connection): Promise<Table[]>;
7
+ getData(connection: Connection, tableName: string, page: number, limit: number): Promise<TableData>;
8
+ getSnippet(connection: Connection, lang: string): string;
9
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MySQLConnector = void 0;
4
+ class MySQLConnector {
5
+ constructor() {
6
+ this.type = 'mysql';
7
+ }
8
+ async test(connection) {
9
+ // Stub implementation
10
+ if (!connection.host || !connection.user || !connection.database) {
11
+ throw new Error('Host, user, and database are required');
12
+ }
13
+ return true;
14
+ }
15
+ async getTables(connection) {
16
+ return [];
17
+ }
18
+ async getData(connection, tableName, page, limit) {
19
+ return {
20
+ columns: [],
21
+ rows: [],
22
+ pagination: { page, limit, totalRows: 0, totalPages: 0, startIdx: 0, endIdx: 0 }
23
+ };
24
+ }
25
+ getSnippet(connection, lang) {
26
+ return `# MySQL snippet generation not implemented yet`;
27
+ }
28
+ }
29
+ exports.MySQLConnector = MySQLConnector;
@@ -0,0 +1,9 @@
1
+ import { Connector, Table, TableData } from '../index';
2
+ import { Connection } from '../../connections';
3
+ export declare class PostgreSQLConnector implements Connector {
4
+ type: string;
5
+ test(connection: Connection): Promise<boolean>;
6
+ getTables(connection: Connection): Promise<Table[]>;
7
+ getData(connection: Connection, tableName: string, page: number, limit: number): Promise<TableData>;
8
+ getSnippet(connection: Connection, lang: string): string;
9
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PostgreSQLConnector = void 0;
4
+ class PostgreSQLConnector {
5
+ constructor() {
6
+ this.type = 'postgresql';
7
+ }
8
+ async test(connection) {
9
+ if (!connection.host || !connection.user || !connection.database) {
10
+ throw new Error('Host, user, and database are required');
11
+ }
12
+ return true;
13
+ }
14
+ async getTables(connection) {
15
+ return [];
16
+ }
17
+ async getData(connection, tableName, page, limit) {
18
+ return {
19
+ columns: [],
20
+ rows: [],
21
+ pagination: { page, limit, totalRows: 0, totalPages: 0, startIdx: 0, endIdx: 0 }
22
+ };
23
+ }
24
+ getSnippet(connection, lang) {
25
+ return `# PostgreSQL snippet generation not implemented yet`;
26
+ }
27
+ }
28
+ exports.PostgreSQLConnector = PostgreSQLConnector;
@@ -0,0 +1,9 @@
1
+ import { Connector, Table, TableData } from '../index';
2
+ import { Connection } from '../../connections';
3
+ export declare class ShopifyConnector implements Connector {
4
+ type: string;
5
+ test(connection: Connection): Promise<boolean>;
6
+ getTables(connection: Connection): Promise<Table[]>;
7
+ getData(connection: Connection, tableName: string, page: number, limit: number): Promise<TableData>;
8
+ getSnippet(connection: Connection, lang: string): string;
9
+ }