crushdataai 1.0.0 → 1.2.1

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,13 @@ 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
+ ### 2. Secure Data Access
29
+ - **Check Connections**: Run `npx crushdataai connections` first.
30
+ - **Missing Data?**: If the data source is not listed (e.g. on Desktop/Database), **INSTRUCT** the user to run:
31
+ `npx crushdataai connect`
32
+ - **Get Code**: Use `npx crushdataai snippet <name>` to access data.
33
+ - **Security**: **DO NOT** ask for credentials or manual file moves.
34
+
28
35
  ---
29
36
 
30
37
  ## Step 2: Search Knowledge Base
@@ -29,8 +29,16 @@ 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
+ - What timezone should I use for dates?
32
33
  ```
33
34
 
35
+ ### 1b. Secure Data Access
36
+ - **Check Connections**: Run `npx crushdataai connections` first.
37
+ - **Missing Data?**: If the data source is not listed (e.g. on Desktop/Database), **INSTRUCT** the user to run:
38
+ `npx crushdataai connect`
39
+ - **Get Code**: Use `npx crushdataai snippet <name>` to access data.
40
+ - **Security**: **DO NOT** ask for credentials or manual file moves.
41
+
34
42
  ### Step 2: Search Relevant Domains
35
43
 
36
44
  Use `search.py` to gather comprehensive information:
@@ -19,7 +19,14 @@ Before coding, ask:
19
19
  - Which tables contain the data?
20
20
  - How does YOUR company define key metrics?
21
21
 
22
- ### 2. Search Knowledge Base
22
+ ### 2. Secure Data Access
23
+ - **Check Connections**: Run `npx crushdataai connections` first.
24
+ - **Missing Data?**: If the data source is not listed (e.g. on Desktop/Database), **INSTRUCT** the user to run:
25
+ `npx crushdataai connect`
26
+ - **Get Code**: Use `npx crushdataai snippet <name>` to access data.
27
+ - **Security**: **DO NOT** ask for credentials or manual file moves.
28
+
29
+ ### 3. Search Knowledge Base
23
30
  ```bash
24
31
  python3 .github/prompts/../.shared/data-analyst/scripts/search.py "<query>" --domain <domain>
25
32
  ```
@@ -16,6 +16,13 @@ Before coding, ask:
16
16
  - Which tables contain the data?
17
17
  - How does YOUR company define the key metrics?
18
18
 
19
+ ### 2. Secure Data Access
20
+ - **Check Connections**: Run `npx crushdataai connections` first.
21
+ - **Missing Data?**: If the data source is not listed (e.g. on Desktop/Database), **INSTRUCT** the user to run:
22
+ `npx crushdataai connect`
23
+ - **Get Code**: Use `npx crushdataai snippet <name>` to access data.
24
+ - **Security**: **DO NOT** ask for credentials or manual file moves.
25
+
19
26
  ### 2. Search Knowledge Base
20
27
  ```bash
21
28
  python3 .cursor/commands/../.shared/data-analyst/scripts/search.py "<query>" --domain <domain>
@@ -15,7 +15,14 @@ Before writing code, gather:
15
15
  - Company-specific metric definitions
16
16
  - Time range and filters
17
17
 
18
- ### 2. Search Before Implementing
18
+ ### 2. Secure Data Access
19
+ - **Check Connections**: Run `npx crushdataai connections` first.
20
+ - **Missing Data?**: If the data source is not listed (e.g. on Desktop/Database), **INSTRUCT** the user to run:
21
+ `npx crushdataai connect`
22
+ - **Get Code**: Use `npx crushdataai snippet <name>` to access data.
23
+ - **Security**: **DO NOT** ask for credentials or manual file moves.
24
+
25
+ ### 3. Search Before Implementing
19
26
  ```bash
20
27
  python3 .kiro/steering/../.shared/data-analyst/scripts/search.py "<query>" --domain <domain>
21
28
  ```
@@ -13,7 +13,14 @@ Ask before coding:
13
13
  - Which tables/databases contain the data
14
14
  - Company-specific metric definitions
15
15
 
16
- ### 2. Search Knowledge
16
+ ### 2. Secure Data Access
17
+ - **Check Connections**: Run `npx crushdataai connections` first.
18
+ - **Missing Data?**: If the data source is not listed (e.g. on Desktop/Database), **INSTRUCT** the user to run:
19
+ `npx crushdataai connect`
20
+ - **Get Code**: Use `npx crushdataai snippet <name>` to access data.
21
+ - **Security**: **DO NOT** ask for credentials or manual file moves.
22
+
23
+ ### 3. Search Knowledge
17
24
  ```bash
18
25
  python3 .windsurf/workflows/../.shared/data-analyst/scripts/search.py "<query>" --domain <domain>
19
26
  ```
@@ -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
+ }
package/dist/commands.js CHANGED
@@ -148,12 +148,12 @@ function init(aiType, force) {
148
148
  console.log(` - Search: python3 .shared/data-analyst/scripts/search.py "<query>" --domain <domain>\n`);
149
149
  }
150
150
  function update() {
151
- console.log('\n🔄 Checking for updates...');
152
- console.log(' Run: npm update -g crushdataai');
153
- console.log(' Then: crushdataai init --force\n');
151
+ console.log('\n🔄 To update CrushData AI:');
152
+ console.log(' 1. Run: npm install -g crushdataai@latest');
153
+ console.log(' 2. Run: crushdataai init --force (to update project files)\n');
154
154
  }
155
155
  function versions() {
156
156
  console.log('\n📦 CrushData AI Versions');
157
- console.log(' Installed: 1.0.0');
157
+ console.log(' Installed: 1.2.1');
158
158
  console.log(' Latest: Check npm: npm show crushdataai version\n');
159
159
  }
@@ -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
+ }