@squadbase/vite-server 0.0.1-build-2 → 0.0.1-build-4
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/dist/cli/index.js +5 -194
- package/dist/index.d.ts +1 -120
- package/dist/index.js +27 -485
- package/dist/main.js +26 -215
- package/dist/types/data-source.d.ts +12 -5
- package/dist/vite-plugin.js +5 -194
- package/package.json +2 -9
package/dist/cli/index.js
CHANGED
|
@@ -113,11 +113,6 @@ function resolveEnvVar(entry, key, slug) {
|
|
|
113
113
|
}
|
|
114
114
|
return value;
|
|
115
115
|
}
|
|
116
|
-
function resolveEnvVarOptional(entry, key) {
|
|
117
|
-
const envVarName = entry.envVars[key];
|
|
118
|
-
if (!envVarName) return void 0;
|
|
119
|
-
return process.env[envVarName] || void 0;
|
|
120
|
-
}
|
|
121
116
|
|
|
122
117
|
// src/connector-client/bigquery.ts
|
|
123
118
|
function createBigQueryClient(entry, slug) {
|
|
@@ -186,176 +181,6 @@ function createSnowflakeClient(entry, slug) {
|
|
|
186
181
|
};
|
|
187
182
|
}
|
|
188
183
|
|
|
189
|
-
// src/connector-client/mysql.ts
|
|
190
|
-
function createMySQLClient(entry, slug) {
|
|
191
|
-
const connectionUrl = resolveEnvVar(entry, "connection-url", slug);
|
|
192
|
-
let poolPromise = null;
|
|
193
|
-
function getPool() {
|
|
194
|
-
if (!poolPromise) {
|
|
195
|
-
poolPromise = import("mysql2/promise").then(
|
|
196
|
-
(mysql) => mysql.default.createPool(connectionUrl)
|
|
197
|
-
);
|
|
198
|
-
}
|
|
199
|
-
return poolPromise;
|
|
200
|
-
}
|
|
201
|
-
return {
|
|
202
|
-
async query(sql, params) {
|
|
203
|
-
const pool = await getPool();
|
|
204
|
-
const [rows] = await pool.execute(sql, params);
|
|
205
|
-
return { rows };
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// src/connector-client/aws-athena.ts
|
|
211
|
-
function createAthenaClient(entry, slug) {
|
|
212
|
-
const region = resolveEnvVar(entry, "aws-region", slug);
|
|
213
|
-
const accessKeyId = resolveEnvVar(entry, "aws-access-key-id", slug);
|
|
214
|
-
const secretAccessKey = resolveEnvVar(entry, "aws-secret-access-key", slug);
|
|
215
|
-
const workgroup = resolveEnvVarOptional(entry, "workgroup") ?? "primary";
|
|
216
|
-
const outputLocation = resolveEnvVarOptional(entry, "output-location");
|
|
217
|
-
return {
|
|
218
|
-
async query(sql) {
|
|
219
|
-
const {
|
|
220
|
-
AthenaClient,
|
|
221
|
-
StartQueryExecutionCommand,
|
|
222
|
-
GetQueryExecutionCommand,
|
|
223
|
-
GetQueryResultsCommand
|
|
224
|
-
} = await import("@aws-sdk/client-athena");
|
|
225
|
-
const client = new AthenaClient({
|
|
226
|
-
region,
|
|
227
|
-
credentials: { accessKeyId, secretAccessKey }
|
|
228
|
-
});
|
|
229
|
-
const startParams = {
|
|
230
|
-
QueryString: sql,
|
|
231
|
-
WorkGroup: workgroup
|
|
232
|
-
};
|
|
233
|
-
if (outputLocation) {
|
|
234
|
-
startParams.ResultConfiguration = { OutputLocation: outputLocation };
|
|
235
|
-
}
|
|
236
|
-
const { QueryExecutionId } = await client.send(
|
|
237
|
-
new StartQueryExecutionCommand(startParams)
|
|
238
|
-
);
|
|
239
|
-
if (!QueryExecutionId) throw new Error("Athena: failed to start query execution");
|
|
240
|
-
while (true) {
|
|
241
|
-
const { QueryExecution } = await client.send(
|
|
242
|
-
new GetQueryExecutionCommand({ QueryExecutionId })
|
|
243
|
-
);
|
|
244
|
-
const state = QueryExecution?.Status?.State;
|
|
245
|
-
if (state === "SUCCEEDED") break;
|
|
246
|
-
if (state === "FAILED") {
|
|
247
|
-
throw new Error(
|
|
248
|
-
`Athena query failed: ${QueryExecution?.Status?.StateChangeReason ?? "unknown"}`
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
if (state === "CANCELLED") throw new Error("Athena query was cancelled");
|
|
252
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
253
|
-
}
|
|
254
|
-
const { ResultSet } = await client.send(
|
|
255
|
-
new GetQueryResultsCommand({ QueryExecutionId })
|
|
256
|
-
);
|
|
257
|
-
const resultRows = ResultSet?.Rows ?? [];
|
|
258
|
-
if (resultRows.length === 0) return { rows: [] };
|
|
259
|
-
const headers = resultRows[0].Data?.map((d) => d.VarCharValue ?? "") ?? [];
|
|
260
|
-
const rows = resultRows.slice(1).map((row) => {
|
|
261
|
-
const obj = {};
|
|
262
|
-
row.Data?.forEach((d, i) => {
|
|
263
|
-
obj[headers[i]] = d.VarCharValue ?? null;
|
|
264
|
-
});
|
|
265
|
-
return obj;
|
|
266
|
-
});
|
|
267
|
-
return { rows };
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// src/connector-client/redshift.ts
|
|
273
|
-
function createRedshiftClient(entry, slug) {
|
|
274
|
-
const region = resolveEnvVar(entry, "aws-region", slug);
|
|
275
|
-
const accessKeyId = resolveEnvVar(entry, "aws-access-key-id", slug);
|
|
276
|
-
const secretAccessKey = resolveEnvVar(entry, "aws-secret-access-key", slug);
|
|
277
|
-
const database = resolveEnvVar(entry, "database", slug);
|
|
278
|
-
const clusterIdentifier = resolveEnvVarOptional(entry, "cluster-identifier");
|
|
279
|
-
const workgroupName = resolveEnvVarOptional(entry, "workgroup-name");
|
|
280
|
-
const secretArn = resolveEnvVarOptional(entry, "secret-arn");
|
|
281
|
-
const dbUser = resolveEnvVarOptional(entry, "db-user");
|
|
282
|
-
return {
|
|
283
|
-
async query(sql) {
|
|
284
|
-
const {
|
|
285
|
-
RedshiftDataClient,
|
|
286
|
-
ExecuteStatementCommand,
|
|
287
|
-
DescribeStatementCommand,
|
|
288
|
-
GetStatementResultCommand
|
|
289
|
-
} = await import("@aws-sdk/client-redshift-data");
|
|
290
|
-
const client = new RedshiftDataClient({
|
|
291
|
-
region,
|
|
292
|
-
credentials: { accessKeyId, secretAccessKey }
|
|
293
|
-
});
|
|
294
|
-
const executeParams = {
|
|
295
|
-
Sql: sql,
|
|
296
|
-
Database: database
|
|
297
|
-
};
|
|
298
|
-
if (clusterIdentifier) executeParams.ClusterIdentifier = clusterIdentifier;
|
|
299
|
-
if (workgroupName) executeParams.WorkgroupName = workgroupName;
|
|
300
|
-
if (secretArn) executeParams.SecretArn = secretArn;
|
|
301
|
-
if (dbUser) executeParams.DbUser = dbUser;
|
|
302
|
-
const { Id } = await client.send(
|
|
303
|
-
new ExecuteStatementCommand(executeParams)
|
|
304
|
-
);
|
|
305
|
-
if (!Id) throw new Error("Redshift: failed to start statement execution");
|
|
306
|
-
while (true) {
|
|
307
|
-
const desc = await client.send(new DescribeStatementCommand({ Id }));
|
|
308
|
-
const status = desc.Status;
|
|
309
|
-
if (status === "FINISHED") break;
|
|
310
|
-
if (status === "FAILED") {
|
|
311
|
-
throw new Error(`Redshift query failed: ${desc.Error ?? "unknown"}`);
|
|
312
|
-
}
|
|
313
|
-
if (status === "ABORTED") throw new Error("Redshift query was aborted");
|
|
314
|
-
await new Promise((r) => setTimeout(r, 500));
|
|
315
|
-
}
|
|
316
|
-
const result = await client.send(new GetStatementResultCommand({ Id }));
|
|
317
|
-
const columns = result.ColumnMetadata?.map((c) => c.name ?? "") ?? [];
|
|
318
|
-
const rows = (result.Records ?? []).map((record) => {
|
|
319
|
-
const obj = {};
|
|
320
|
-
record.forEach((field, i) => {
|
|
321
|
-
const col = columns[i];
|
|
322
|
-
const value = field.stringValue ?? field.longValue ?? field.doubleValue ?? field.booleanValue ?? (field.isNull ? null : field.blobValue ?? null);
|
|
323
|
-
obj[col] = value;
|
|
324
|
-
});
|
|
325
|
-
return obj;
|
|
326
|
-
});
|
|
327
|
-
return { rows };
|
|
328
|
-
}
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
// src/connector-client/databricks.ts
|
|
333
|
-
function createDatabricksClient(entry, slug) {
|
|
334
|
-
const host = resolveEnvVar(entry, "host", slug);
|
|
335
|
-
const httpPath = resolveEnvVar(entry, "http-path", slug);
|
|
336
|
-
const token = resolveEnvVar(entry, "token", slug);
|
|
337
|
-
return {
|
|
338
|
-
async query(sql) {
|
|
339
|
-
const { DBSQLClient } = await import("@databricks/sql");
|
|
340
|
-
const client = new DBSQLClient();
|
|
341
|
-
await client.connect({ host, path: httpPath, token });
|
|
342
|
-
try {
|
|
343
|
-
const session = await client.openSession();
|
|
344
|
-
try {
|
|
345
|
-
const operation = await session.executeStatement(sql);
|
|
346
|
-
const result = await operation.fetchAll();
|
|
347
|
-
await operation.close();
|
|
348
|
-
return { rows: result };
|
|
349
|
-
} finally {
|
|
350
|
-
await session.close();
|
|
351
|
-
}
|
|
352
|
-
} finally {
|
|
353
|
-
await client.close();
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
|
|
359
184
|
// src/connector-client/registry.ts
|
|
360
185
|
function createConnectorRegistry() {
|
|
361
186
|
let connectionsCache = null;
|
|
@@ -363,7 +188,7 @@ function createConnectorRegistry() {
|
|
|
363
188
|
function getConnectionsFilePath() {
|
|
364
189
|
return process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), "../../.squadbase/connections.json");
|
|
365
190
|
}
|
|
366
|
-
function
|
|
191
|
+
function loadConnections() {
|
|
367
192
|
if (connectionsCache !== null) return connectionsCache;
|
|
368
193
|
const filePath = getConnectionsFilePath();
|
|
369
194
|
try {
|
|
@@ -387,7 +212,7 @@ function createConnectorRegistry() {
|
|
|
387
212
|
}
|
|
388
213
|
const cached = clientCache.get(connectorSlug);
|
|
389
214
|
if (cached) return cached;
|
|
390
|
-
const connections =
|
|
215
|
+
const connections = loadConnections();
|
|
391
216
|
const entry = connections[connectorSlug];
|
|
392
217
|
if (!entry) {
|
|
393
218
|
throw new Error(`connector slug '${connectorSlug}' not found in .squadbase/connections.json`);
|
|
@@ -404,20 +229,6 @@ function createConnectorRegistry() {
|
|
|
404
229
|
if (resolvedType === "bigquery") {
|
|
405
230
|
return createBigQueryClient(entry, connectorSlug);
|
|
406
231
|
}
|
|
407
|
-
if (resolvedType === "athena") {
|
|
408
|
-
return createAthenaClient(entry, connectorSlug);
|
|
409
|
-
}
|
|
410
|
-
if (resolvedType === "redshift") {
|
|
411
|
-
return createRedshiftClient(entry, connectorSlug);
|
|
412
|
-
}
|
|
413
|
-
if (resolvedType === "databricks") {
|
|
414
|
-
return createDatabricksClient(entry, connectorSlug);
|
|
415
|
-
}
|
|
416
|
-
if (resolvedType === "mysql") {
|
|
417
|
-
const client = createMySQLClient(entry, connectorSlug);
|
|
418
|
-
clientCache.set(connectorSlug, client);
|
|
419
|
-
return client;
|
|
420
|
-
}
|
|
421
232
|
if (resolvedType === "postgresql" || resolvedType === "squadbase-db") {
|
|
422
233
|
const urlEnvName = entry.envVars["connection-url"];
|
|
423
234
|
if (!urlEnvName) {
|
|
@@ -434,7 +245,7 @@ function createConnectorRegistry() {
|
|
|
434
245
|
return client;
|
|
435
246
|
}
|
|
436
247
|
throw new Error(
|
|
437
|
-
`connector type '${resolvedType}' is not supported
|
|
248
|
+
`connector type '${resolvedType}' is not supported. Supported: "snowflake", "bigquery", "postgresql", "squadbase-db"`
|
|
438
249
|
);
|
|
439
250
|
}
|
|
440
251
|
function reloadEnvFile2(envPath) {
|
|
@@ -466,11 +277,11 @@ function createConnectorRegistry() {
|
|
|
466
277
|
} catch {
|
|
467
278
|
}
|
|
468
279
|
}
|
|
469
|
-
return { getClient: getClient2,
|
|
280
|
+
return { getClient: getClient2, reloadEnvFile: reloadEnvFile2, watchConnectionsFile: watchConnectionsFile2 };
|
|
470
281
|
}
|
|
471
282
|
|
|
472
283
|
// src/connector-client/index.ts
|
|
473
|
-
var { getClient,
|
|
284
|
+
var { getClient, reloadEnvFile, watchConnectionsFile } = createConnectorRegistry();
|
|
474
285
|
|
|
475
286
|
// src/cli/env-loader.ts
|
|
476
287
|
import { readFileSync as readFileSync2 } from "fs";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,125 +1,6 @@
|
|
|
1
1
|
import * as hono_types from 'hono/types';
|
|
2
2
|
import { Hono } from 'hono';
|
|
3
3
|
|
|
4
|
-
interface DatabaseClient {
|
|
5
|
-
query(sql: string, params?: unknown[]): Promise<{
|
|
6
|
-
rows: Record<string, unknown>[];
|
|
7
|
-
}>;
|
|
8
|
-
}
|
|
9
|
-
interface ConnectionEntry {
|
|
10
|
-
connectorType: string;
|
|
11
|
-
envVars: Record<string, string>;
|
|
12
|
-
}
|
|
13
|
-
type ConnectionsMap = Record<string, ConnectionEntry>;
|
|
14
|
-
|
|
15
|
-
interface AirtableClient {
|
|
16
|
-
listRecords(tableIdOrName: string, options?: {
|
|
17
|
-
fields?: string[];
|
|
18
|
-
filterByFormula?: string;
|
|
19
|
-
maxRecords?: number;
|
|
20
|
-
sort?: {
|
|
21
|
-
field: string;
|
|
22
|
-
direction?: "asc" | "desc";
|
|
23
|
-
}[];
|
|
24
|
-
pageSize?: number;
|
|
25
|
-
offset?: string;
|
|
26
|
-
}): Promise<{
|
|
27
|
-
records: AirtableRecord[];
|
|
28
|
-
offset?: string;
|
|
29
|
-
}>;
|
|
30
|
-
getRecord(tableIdOrName: string, recordId: string): Promise<AirtableRecord>;
|
|
31
|
-
}
|
|
32
|
-
interface AirtableRecord {
|
|
33
|
-
id: string;
|
|
34
|
-
fields: Record<string, unknown>;
|
|
35
|
-
createdTime: string;
|
|
36
|
-
}
|
|
37
|
-
declare function createAirtableClient(entry: ConnectionEntry, slug: string): AirtableClient;
|
|
38
|
-
|
|
39
|
-
interface GoogleAnalyticsClient {
|
|
40
|
-
runReport(request: {
|
|
41
|
-
dateRanges: {
|
|
42
|
-
startDate: string;
|
|
43
|
-
endDate: string;
|
|
44
|
-
}[];
|
|
45
|
-
dimensions?: {
|
|
46
|
-
name: string;
|
|
47
|
-
}[];
|
|
48
|
-
metrics: {
|
|
49
|
-
name: string;
|
|
50
|
-
}[];
|
|
51
|
-
limit?: number;
|
|
52
|
-
offset?: number;
|
|
53
|
-
orderBys?: unknown[];
|
|
54
|
-
}): Promise<{
|
|
55
|
-
rows: {
|
|
56
|
-
dimensionValues: {
|
|
57
|
-
value: string;
|
|
58
|
-
}[];
|
|
59
|
-
metricValues: {
|
|
60
|
-
value: string;
|
|
61
|
-
}[];
|
|
62
|
-
}[];
|
|
63
|
-
rowCount: number;
|
|
64
|
-
}>;
|
|
65
|
-
}
|
|
66
|
-
declare function createGoogleAnalyticsClient(entry: ConnectionEntry, slug: string): GoogleAnalyticsClient;
|
|
67
|
-
|
|
68
|
-
interface KintoneClient {
|
|
69
|
-
getRecords(appId: string | number, options?: {
|
|
70
|
-
query?: string;
|
|
71
|
-
fields?: string[];
|
|
72
|
-
totalCount?: boolean;
|
|
73
|
-
}): Promise<{
|
|
74
|
-
records: Record<string, unknown>[];
|
|
75
|
-
totalCount: string | null;
|
|
76
|
-
}>;
|
|
77
|
-
getRecord(appId: string | number, recordId: string | number): Promise<{
|
|
78
|
-
record: Record<string, unknown>;
|
|
79
|
-
}>;
|
|
80
|
-
listApps(options?: {
|
|
81
|
-
ids?: (string | number)[];
|
|
82
|
-
name?: string;
|
|
83
|
-
limit?: number;
|
|
84
|
-
offset?: number;
|
|
85
|
-
}): Promise<{
|
|
86
|
-
apps: Record<string, unknown>[];
|
|
87
|
-
}>;
|
|
88
|
-
}
|
|
89
|
-
declare function createKintoneClient(entry: ConnectionEntry, slug: string): KintoneClient;
|
|
90
|
-
|
|
91
|
-
interface WixStoreClient {
|
|
92
|
-
queryProducts(options?: {
|
|
93
|
-
query?: Record<string, unknown>;
|
|
94
|
-
limit?: number;
|
|
95
|
-
offset?: number;
|
|
96
|
-
}): Promise<{
|
|
97
|
-
products: Record<string, unknown>[];
|
|
98
|
-
totalResults: number;
|
|
99
|
-
}>;
|
|
100
|
-
queryOrders(options?: {
|
|
101
|
-
query?: Record<string, unknown>;
|
|
102
|
-
limit?: number;
|
|
103
|
-
offset?: number;
|
|
104
|
-
}): Promise<{
|
|
105
|
-
orders: Record<string, unknown>[];
|
|
106
|
-
totalResults: number;
|
|
107
|
-
}>;
|
|
108
|
-
}
|
|
109
|
-
declare function createWixStoreClient(entry: ConnectionEntry, slug: string): WixStoreClient;
|
|
110
|
-
|
|
111
|
-
interface DbtClient {
|
|
112
|
-
query(graphqlQuery: string, variables?: Record<string, unknown>): Promise<Record<string, unknown>>;
|
|
113
|
-
getModels(options?: {
|
|
114
|
-
limit?: number;
|
|
115
|
-
}): Promise<Record<string, unknown>[]>;
|
|
116
|
-
getModelByName(uniqueId: string): Promise<Record<string, unknown> | null>;
|
|
117
|
-
}
|
|
118
|
-
declare function createDbtClient(entry: ConnectionEntry, slug: string): DbtClient;
|
|
119
|
-
|
|
120
|
-
declare const getClient: (connectorSlug?: string, connectorType?: string) => Promise<DatabaseClient>;
|
|
121
|
-
declare const loadConnections: () => ConnectionsMap;
|
|
122
|
-
|
|
123
4
|
declare const app: Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
|
|
124
5
|
|
|
125
|
-
export {
|
|
6
|
+
export { app as default };
|