@squadbase/vite-server 0.0.1-build-5 → 0.0.1-build-7

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.
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1,644 @@
1
+ #!/usr/bin/env node
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __esm = (fn, res) => function __init() {
5
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
+ };
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+
12
+ // src/cli/interactive.ts
13
+ var interactive_exports = {};
14
+ __export(interactive_exports, {
15
+ confirmRunAll: () => confirmRunAll,
16
+ inputParameters: () => inputParameters,
17
+ selectDataSource: () => selectDataSource
18
+ });
19
+ async function getPrompts() {
20
+ try {
21
+ const mod = await import("@clack/prompts");
22
+ return mod;
23
+ } catch {
24
+ throw new Error(
25
+ "@clack/prompts is not installed. Run: npm install @clack/prompts --save-dev"
26
+ );
27
+ }
28
+ }
29
+ async function selectDataSource(slugs) {
30
+ const { select, isCancel } = await getPrompts();
31
+ const result = await select({
32
+ message: "Select a data source to test:",
33
+ options: slugs.map((s) => ({ value: s, label: s }))
34
+ });
35
+ if (isCancel(result)) return null;
36
+ return result;
37
+ }
38
+ async function inputParameters(params) {
39
+ if (params.length === 0) return {};
40
+ const { text, isCancel } = await getPrompts();
41
+ const result = {};
42
+ for (const p of params) {
43
+ const defaultHint = p.default !== void 0 ? ` (default: ${p.default})` : "";
44
+ const requiredHint = p.required ? " *required*" : "";
45
+ const value = await text({
46
+ message: `${p.name}${requiredHint} [${p.type}]${defaultHint}: ${p.description}`,
47
+ placeholder: p.default !== void 0 ? String(p.default) : "",
48
+ validate: (v) => {
49
+ if (p.required && !v && p.default === void 0) {
50
+ return `${p.name} is required`;
51
+ }
52
+ }
53
+ });
54
+ if (isCancel(value)) {
55
+ process.exit(0);
56
+ }
57
+ const strValue = value;
58
+ if (!strValue && p.default !== void 0) {
59
+ result[p.name] = p.default;
60
+ } else if (strValue) {
61
+ if (p.type === "number") result[p.name] = Number(strValue);
62
+ else if (p.type === "boolean") result[p.name] = strValue === "true";
63
+ else result[p.name] = strValue;
64
+ }
65
+ }
66
+ return result;
67
+ }
68
+ async function confirmRunAll() {
69
+ const { confirm, isCancel } = await getPrompts();
70
+ const result = await confirm({
71
+ message: "Run all data sources?"
72
+ });
73
+ if (isCancel(result)) return false;
74
+ return result;
75
+ }
76
+ var init_interactive = __esm({
77
+ "src/cli/interactive.ts"() {
78
+ "use strict";
79
+ }
80
+ });
81
+
82
+ // src/cli/index.ts
83
+ import { parseArgs } from "util";
84
+ import path4 from "path";
85
+ import { readFile as readFile3 } from "fs/promises";
86
+
87
+ // src/connector-client/registry.ts
88
+ import { readFileSync, watch as fsWatch } from "fs";
89
+ import path from "path";
90
+
91
+ // src/connector-client/postgresql.ts
92
+ import pg from "pg";
93
+ var { Pool } = pg;
94
+ function createPostgreSQLClient(connectionString) {
95
+ const pool = new Pool({ connectionString, ssl: { rejectUnauthorized: false } });
96
+ return {
97
+ async query(sql, params) {
98
+ const result = await pool.query(sql, params);
99
+ return { rows: result.rows };
100
+ }
101
+ };
102
+ }
103
+
104
+ // src/connector-client/env.ts
105
+ function resolveEnvVar(entry, key, connectionId) {
106
+ const envVarName = entry.envVars[key];
107
+ if (!envVarName) {
108
+ throw new Error(`Connection "${connectionId}" is missing envVars mapping for key "${key}"`);
109
+ }
110
+ const value = process.env[envVarName];
111
+ if (!value) {
112
+ throw new Error(`Environment variable "${envVarName}" (for connection "${connectionId}", key "${key}") is not set`);
113
+ }
114
+ return value;
115
+ }
116
+
117
+ // src/connector-client/bigquery.ts
118
+ function createBigQueryClient(entry, connectionId) {
119
+ const projectId = resolveEnvVar(entry, "project-id", connectionId);
120
+ const serviceAccountJsonBase64 = resolveEnvVar(entry, "service-account-key-json-base64", connectionId);
121
+ const serviceAccountJson = Buffer.from(serviceAccountJsonBase64, "base64").toString("utf-8");
122
+ let gcpCredentials;
123
+ try {
124
+ gcpCredentials = JSON.parse(serviceAccountJson);
125
+ } catch {
126
+ throw new Error(
127
+ `BigQuery service account JSON (decoded from base64) is not valid JSON for connection "${connectionId}"`
128
+ );
129
+ }
130
+ return {
131
+ async query(sql) {
132
+ const { BigQuery } = await import("@google-cloud/bigquery");
133
+ const bq = new BigQuery({ projectId, credentials: gcpCredentials });
134
+ const [job] = await bq.createQueryJob({ query: sql });
135
+ const [allRows] = await job.getQueryResults({ timeoutMs: 3e4 });
136
+ return { rows: allRows };
137
+ }
138
+ };
139
+ }
140
+
141
+ // src/connector-client/snowflake.ts
142
+ function createSnowflakeClient(entry, connectionId) {
143
+ const accountIdentifier = resolveEnvVar(entry, "account", connectionId);
144
+ const user = resolveEnvVar(entry, "user", connectionId);
145
+ const role = resolveEnvVar(entry, "role", connectionId);
146
+ const warehouse = resolveEnvVar(entry, "warehouse", connectionId);
147
+ const privateKeyBase64 = resolveEnvVar(entry, "private-key-base64", connectionId);
148
+ const privateKey = Buffer.from(privateKeyBase64, "base64").toString("utf-8");
149
+ return {
150
+ async query(sql) {
151
+ const snowflake = (await import("snowflake-sdk")).default;
152
+ snowflake.configure({ logLevel: "ERROR" });
153
+ const connection = snowflake.createConnection({
154
+ account: accountIdentifier,
155
+ username: user,
156
+ role,
157
+ warehouse,
158
+ authenticator: "SNOWFLAKE_JWT",
159
+ privateKey
160
+ });
161
+ await new Promise((resolve, reject) => {
162
+ connection.connect((err) => {
163
+ if (err) reject(new Error(`Snowflake connect failed: ${err.message}`));
164
+ else resolve();
165
+ });
166
+ });
167
+ const rows = await new Promise((resolve, reject) => {
168
+ connection.execute({
169
+ sqlText: sql,
170
+ complete: (err, _stmt, rows2) => {
171
+ if (err) reject(new Error(`Snowflake query failed: ${err.message}`));
172
+ else resolve(rows2 ?? []);
173
+ }
174
+ });
175
+ });
176
+ connection.destroy((err) => {
177
+ if (err) console.warn(`[connector-client] Snowflake destroy error: ${err.message}`);
178
+ });
179
+ return { rows };
180
+ }
181
+ };
182
+ }
183
+
184
+ // src/connector-client/registry.ts
185
+ function createConnectorRegistry() {
186
+ let connectionsCache = null;
187
+ const clientCache = /* @__PURE__ */ new Map();
188
+ function getConnectionsFilePath() {
189
+ return process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
190
+ }
191
+ function loadConnections() {
192
+ if (connectionsCache !== null) return connectionsCache;
193
+ const filePath = getConnectionsFilePath();
194
+ try {
195
+ const raw = readFileSync(filePath, "utf-8");
196
+ connectionsCache = JSON.parse(raw);
197
+ } catch {
198
+ connectionsCache = {};
199
+ }
200
+ return connectionsCache;
201
+ }
202
+ async function getClient2(connectionId) {
203
+ const connections = loadConnections();
204
+ const entry = connections[connectionId];
205
+ if (!entry) {
206
+ throw new Error(`connection '${connectionId}' not found in .squadbase/connections.json`);
207
+ }
208
+ const connectorSlug = entry.connector.slug;
209
+ const cached = clientCache.get(connectionId);
210
+ if (cached) return { client: cached, connectorSlug };
211
+ if (connectorSlug === "snowflake") {
212
+ return { client: createSnowflakeClient(entry, connectionId), connectorSlug };
213
+ }
214
+ if (connectorSlug === "bigquery") {
215
+ return { client: createBigQueryClient(entry, connectionId), connectorSlug };
216
+ }
217
+ if (connectorSlug === "postgresql" || connectorSlug === "squadbase-db") {
218
+ const urlEnvName = entry.envVars["connection-url"];
219
+ if (!urlEnvName) {
220
+ throw new Error(`'connection-url' is not defined in envVars for connection '${connectionId}'`);
221
+ }
222
+ const connectionUrl = process.env[urlEnvName];
223
+ if (!connectionUrl) {
224
+ throw new Error(
225
+ `environment variable '${urlEnvName}' (mapped from connection '${connectionId}') is not set`
226
+ );
227
+ }
228
+ const client = createPostgreSQLClient(connectionUrl);
229
+ clientCache.set(connectionId, client);
230
+ return { client, connectorSlug };
231
+ }
232
+ throw new Error(
233
+ `connector type '${connectorSlug}' is not supported. Supported: "snowflake", "bigquery", "postgresql", "squadbase-db"`
234
+ );
235
+ }
236
+ function reloadEnvFile2(envPath) {
237
+ try {
238
+ const raw = readFileSync(envPath, "utf-8");
239
+ for (const line of raw.split("\n")) {
240
+ const trimmed = line.trim();
241
+ if (!trimmed || trimmed.startsWith("#")) continue;
242
+ const eqIdx = trimmed.indexOf("=");
243
+ if (eqIdx === -1) continue;
244
+ const key = trimmed.slice(0, eqIdx).trim();
245
+ const value = trimmed.slice(eqIdx + 1).trim();
246
+ if (key) process.env[key] = value;
247
+ }
248
+ console.log("[connector-client] .env reloaded");
249
+ } catch {
250
+ }
251
+ }
252
+ function watchConnectionsFile2() {
253
+ const filePath = getConnectionsFilePath();
254
+ const envPath = path.join(process.cwd(), ".env");
255
+ try {
256
+ fsWatch(filePath, { persistent: false }, () => {
257
+ console.log("[connector-client] connections.json changed, clearing cache");
258
+ connectionsCache = null;
259
+ clientCache.clear();
260
+ setImmediate(() => reloadEnvFile2(envPath));
261
+ });
262
+ } catch {
263
+ }
264
+ }
265
+ return { getClient: getClient2, reloadEnvFile: reloadEnvFile2, watchConnectionsFile: watchConnectionsFile2 };
266
+ }
267
+
268
+ // src/connector-client/index.ts
269
+ var { getClient, reloadEnvFile, watchConnectionsFile } = createConnectorRegistry();
270
+
271
+ // src/cli/env-loader.ts
272
+ import { readFileSync as readFileSync2 } from "fs";
273
+ function loadEnvFile(envPath) {
274
+ reloadEnvFile(envPath);
275
+ }
276
+
277
+ // src/cli/runner.ts
278
+ import { pathToFileURL } from "url";
279
+ import { readFile as readFile2, readdir as readdir2 } from "fs/promises";
280
+ import path3 from "path";
281
+
282
+ // src/registry.ts
283
+ import { readdir, readFile, mkdir } from "fs/promises";
284
+ import { watch as fsWatch2 } from "fs";
285
+ import path2 from "path";
286
+ function buildQuery(queryTemplate, parameterMeta, runtimeParams) {
287
+ const defaults = new Map(
288
+ parameterMeta.map((p) => [p.name, p.default ?? null])
289
+ );
290
+ const placeholderToIndex = /* @__PURE__ */ new Map();
291
+ const values = [];
292
+ const text = queryTemplate.replace(
293
+ /\{\{(\w+)\}\}/g,
294
+ (_match, name) => {
295
+ if (!placeholderToIndex.has(name)) {
296
+ const value = Object.prototype.hasOwnProperty.call(runtimeParams, name) ? runtimeParams[name] : defaults.get(name) ?? null;
297
+ values.push(value);
298
+ placeholderToIndex.set(name, values.length);
299
+ }
300
+ return `$${placeholderToIndex.get(name)}`;
301
+ }
302
+ );
303
+ return { text, values };
304
+ }
305
+ var defaultDataSourceDir = path2.join(process.cwd(), "data-source");
306
+
307
+ // src/cli/runner.ts
308
+ function createStubContext(params) {
309
+ const stub = {
310
+ req: {
311
+ json: () => Promise.resolve(params),
312
+ query: (name) => {
313
+ if (name === void 0) {
314
+ return Object.fromEntries(
315
+ Object.entries(params).map(([k, v2]) => [k, String(v2)])
316
+ );
317
+ }
318
+ const v = params[name];
319
+ return v !== void 0 ? String(v) : "";
320
+ },
321
+ param: (_name) => void 0,
322
+ header: (_name) => void 0,
323
+ raw: new Request("http://localhost/cli")
324
+ },
325
+ json: (data) => data,
326
+ text: (data) => data,
327
+ body: (data) => data,
328
+ env: {},
329
+ var: {},
330
+ get: (_key) => void 0,
331
+ set: () => {
332
+ }
333
+ };
334
+ return stub;
335
+ }
336
+ async function runSqlDataSource(slug, def, params, limit) {
337
+ const start = Date.now();
338
+ try {
339
+ const { client, connectorSlug } = await getClient(def.connectionId);
340
+ const isExternal = connectorSlug === "snowflake" || connectorSlug === "bigquery";
341
+ let queryText;
342
+ let queryValues;
343
+ if (isExternal) {
344
+ const defaults = new Map(
345
+ (def.parameters ?? []).map((p) => [p.name, p.default ?? null])
346
+ );
347
+ queryText = def.query.replace(/\{\{(\w+)\}\}/g, (_match, name) => {
348
+ const value = Object.prototype.hasOwnProperty.call(params, name) ? params[name] : defaults.get(name) ?? "";
349
+ if (typeof value === "string") return `'${value.replace(/'/g, "''")}'`;
350
+ if (value === null || value === void 0) return "NULL";
351
+ return String(value);
352
+ });
353
+ queryValues = [];
354
+ } else {
355
+ const built = buildQuery(def.query, def.parameters ?? [], params);
356
+ queryText = built.text;
357
+ queryValues = built.values;
358
+ }
359
+ const result = await client.query(queryText, queryValues);
360
+ const rows = result.rows.slice(0, limit);
361
+ return {
362
+ slug,
363
+ rows,
364
+ rowCount: result.rows.length,
365
+ durationMs: Date.now() - start,
366
+ query: queryText,
367
+ queryValues
368
+ };
369
+ } catch (error) {
370
+ return {
371
+ slug,
372
+ rows: [],
373
+ rowCount: 0,
374
+ durationMs: Date.now() - start,
375
+ error: error instanceof Error ? error : new Error(String(error))
376
+ };
377
+ }
378
+ }
379
+ async function runTypescriptDataSource(slug, handlerPath, params) {
380
+ const start = Date.now();
381
+ try {
382
+ const mod = await import(pathToFileURL(handlerPath).href);
383
+ const handler = mod.default;
384
+ if (typeof handler !== "function") {
385
+ throw new Error(`Handler must export a default function: ${handlerPath}`);
386
+ }
387
+ const ctx = createStubContext(params);
388
+ const raw = await handler(ctx);
389
+ let rows;
390
+ if (Array.isArray(raw)) {
391
+ rows = raw;
392
+ } else if (raw !== null && typeof raw === "object") {
393
+ rows = [raw];
394
+ } else {
395
+ rows = [{ result: raw }];
396
+ }
397
+ return {
398
+ slug,
399
+ rows,
400
+ rowCount: rows.length,
401
+ durationMs: Date.now() - start
402
+ };
403
+ } catch (error) {
404
+ return {
405
+ slug,
406
+ rows: [],
407
+ rowCount: 0,
408
+ durationMs: Date.now() - start,
409
+ error: error instanceof Error ? error : new Error(String(error))
410
+ };
411
+ }
412
+ }
413
+ async function runDataSource(slug, dirPath, params, limit) {
414
+ const jsonPath = path3.join(dirPath, `${slug}.json`);
415
+ let def;
416
+ try {
417
+ const raw = await readFile2(jsonPath, "utf-8");
418
+ def = JSON.parse(raw);
419
+ } catch {
420
+ return {
421
+ slug,
422
+ rows: [],
423
+ rowCount: 0,
424
+ durationMs: 0,
425
+ error: new Error(`Data source not found: ${jsonPath}`)
426
+ };
427
+ }
428
+ if (def.type === "typescript") {
429
+ const absolutePath = path3.resolve(dirPath, def.handlerPath);
430
+ return runTypescriptDataSource(slug, absolutePath, params);
431
+ }
432
+ return runSqlDataSource(slug, def, params, limit);
433
+ }
434
+ async function listSlugs(dirPath) {
435
+ try {
436
+ const files = await readdir2(dirPath);
437
+ return files.filter((f) => f.endsWith(".json")).map((f) => f.replace(/\.json$/, ""));
438
+ } catch {
439
+ return [];
440
+ }
441
+ }
442
+ async function runAll(dirPath, params, limit) {
443
+ const slugs = await listSlugs(dirPath);
444
+ return Promise.all(slugs.map((slug) => runDataSource(slug, dirPath, params, limit)));
445
+ }
446
+
447
+ // src/cli/display.ts
448
+ var RESET = "\x1B[0m";
449
+ var BOLD = "\x1B[1m";
450
+ var RED = "\x1B[31m";
451
+ var GREEN = "\x1B[32m";
452
+ var YELLOW = "\x1B[33m";
453
+ var CYAN = "\x1B[36m";
454
+ var DIM = "\x1B[2m";
455
+ function truncate(value, maxLen) {
456
+ return value.length > maxLen ? value.slice(0, maxLen - 1) + "\u2026" : value;
457
+ }
458
+ function formatValue(value) {
459
+ if (value === null || value === void 0) return DIM + "null" + RESET;
460
+ if (typeof value === "object") return JSON.stringify(value);
461
+ return String(value);
462
+ }
463
+ function displayTable(rows, limit) {
464
+ if (rows.length === 0) {
465
+ console.log(DIM + " (no rows)" + RESET);
466
+ return;
467
+ }
468
+ const display = rows.slice(0, limit);
469
+ const columns = Object.keys(display[0] ?? {});
470
+ const colWidths = columns.map((col) => {
471
+ const maxData = Math.max(...display.map((r) => formatValue(r[col]).replace(/\x1b\[[0-9;]*m/g, "").length));
472
+ return Math.min(40, Math.max(col.length, maxData));
473
+ });
474
+ const header = columns.map((c, i) => BOLD + CYAN + c.padEnd(colWidths[i] ?? 0) + RESET).join(" ");
475
+ const divider = colWidths.map((w) => "-".repeat(w)).join("--");
476
+ console.log(" " + header);
477
+ console.log(" " + DIM + divider + RESET);
478
+ for (const row of display) {
479
+ const line = columns.map((c, i) => {
480
+ const raw = formatValue(row[c]);
481
+ const plain = raw.replace(/\x1b\[[0-9;]*m/g, "");
482
+ const padded = truncate(plain, colWidths[i] ?? 40).padEnd(colWidths[i] ?? 0);
483
+ return raw.startsWith(DIM) ? DIM + padded + RESET : padded;
484
+ }).join(" ");
485
+ console.log(" " + line);
486
+ }
487
+ if (rows.length > limit) {
488
+ console.log(DIM + ` \u2026 and ${rows.length - limit} more rows (use --limit to show more)` + RESET);
489
+ }
490
+ }
491
+ function displaySummary(result) {
492
+ const status = result.error ? RED + "\u2717 FAIL" + RESET : GREEN + "\u2713 OK" + RESET;
493
+ const duration = DIM + `(${result.durationMs}ms)` + RESET;
494
+ console.log(`
495
+ ${BOLD}[${result.slug}]${RESET} ${status} ${duration}`);
496
+ if (result.error) {
497
+ console.log(RED + ` Error: ${result.error.message}` + RESET);
498
+ return;
499
+ }
500
+ console.log(DIM + ` ${result.rowCount} row(s)` + RESET);
501
+ }
502
+ function displayDebug(result) {
503
+ if (result.query) {
504
+ console.log(YELLOW + " Query:" + RESET);
505
+ console.log(DIM + ` ${result.query.replace(/\n/g, "\n ")}` + RESET);
506
+ }
507
+ if (result.queryValues && result.queryValues.length > 0) {
508
+ console.log(YELLOW + " Params:" + RESET, result.queryValues);
509
+ }
510
+ }
511
+ function displayJson(results) {
512
+ const output = results.map((r) => ({
513
+ slug: r.slug,
514
+ rowCount: r.rowCount,
515
+ durationMs: r.durationMs,
516
+ rows: r.rows,
517
+ error: r.error?.message
518
+ }));
519
+ console.log(JSON.stringify(output, null, 2));
520
+ }
521
+ function displayError(error) {
522
+ console.error(RED + "Error: " + error.message + RESET);
523
+ }
524
+
525
+ // src/cli/index.ts
526
+ var HELP = `
527
+ Usage: squadbase-ds-test [options]
528
+
529
+ Options:
530
+ --slug <slug> Run a specific data source
531
+ --all Run all data sources
532
+ --params k=v,... Comma-separated key=value parameters
533
+ --env <path> Path to .env file (default: ../../.env)
534
+ --dir <path> Data source directory (default: ./data-source)
535
+ --format table|json Output format (default: table)
536
+ --limit <n> Max rows to display (default: 50)
537
+ --debug Show SQL query and parameter values
538
+ --help Show this help
539
+
540
+ Examples:
541
+ npx tsx src/cli/index.ts --slug sales-summary
542
+ npx tsx src/cli/index.ts --slug sales-summary --params year=2024,limit=10
543
+ npx tsx src/cli/index.ts --all --format json
544
+ npx tsx src/cli/index.ts # interactive mode
545
+ `;
546
+ async function main() {
547
+ const { values } = parseArgs({
548
+ options: {
549
+ slug: { type: "string" },
550
+ all: { type: "boolean", default: false },
551
+ params: { type: "string" },
552
+ env: { type: "string" },
553
+ dir: { type: "string" },
554
+ format: { type: "string", default: "table" },
555
+ limit: { type: "string", default: "50" },
556
+ debug: { type: "boolean", default: false },
557
+ help: { type: "boolean", default: false }
558
+ },
559
+ allowPositionals: false
560
+ });
561
+ if (values.help) {
562
+ console.log(HELP);
563
+ process.exit(0);
564
+ }
565
+ const cwd = process.cwd();
566
+ const dirPath = values.dir ? path4.resolve(cwd, values.dir) : path4.join(cwd, "data-source");
567
+ const envPath = values.env ? path4.resolve(cwd, values.env) : path4.join(cwd, "../../.env");
568
+ const limit = parseInt(values.limit ?? "50", 10);
569
+ const format = values.format ?? "table";
570
+ loadEnvFile(envPath);
571
+ const params = {};
572
+ if (values.params) {
573
+ for (const pair of values.params.split(",")) {
574
+ const eqIdx = pair.indexOf("=");
575
+ if (eqIdx === -1) continue;
576
+ const key = pair.slice(0, eqIdx).trim();
577
+ const val = pair.slice(eqIdx + 1).trim();
578
+ params[key] = val;
579
+ }
580
+ }
581
+ if (values.slug) {
582
+ const result = await runDataSource(values.slug, dirPath, params, limit);
583
+ if (format === "json") {
584
+ displayJson([result]);
585
+ } else {
586
+ displaySummary(result);
587
+ if (values.debug) displayDebug(result);
588
+ if (!result.error) displayTable(result.rows, limit);
589
+ }
590
+ if (result.error) process.exit(1);
591
+ } else if (values.all) {
592
+ const results = await runAll(dirPath, params, limit);
593
+ if (format === "json") {
594
+ displayJson(results);
595
+ } else {
596
+ for (const r of results) {
597
+ displaySummary(r);
598
+ if (values.debug) displayDebug(r);
599
+ if (!r.error) displayTable(r.rows, limit);
600
+ }
601
+ const failed = results.filter((r) => r.error).length;
602
+ console.log(`
603
+ Total: ${results.length}, Failed: ${failed}`);
604
+ }
605
+ const anyFailed = results.some((r) => r.error);
606
+ if (anyFailed) process.exit(1);
607
+ } else {
608
+ const slugs = await listSlugs(dirPath);
609
+ if (slugs.length === 0) {
610
+ displayError(new Error(`No data sources found in ${dirPath}`));
611
+ process.exit(1);
612
+ }
613
+ try {
614
+ const { selectDataSource: selectDataSource2, inputParameters: inputParameters2 } = await Promise.resolve().then(() => (init_interactive(), interactive_exports));
615
+ const slug = await selectDataSource2(slugs);
616
+ if (!slug) {
617
+ console.log("Cancelled.");
618
+ process.exit(0);
619
+ }
620
+ const jsonPath = path4.join(dirPath, `${slug}.json`);
621
+ let paramMeta = [];
622
+ try {
623
+ const raw = await readFile3(jsonPath, "utf-8");
624
+ const def = JSON.parse(raw);
625
+ paramMeta = def.parameters ?? [];
626
+ } catch {
627
+ }
628
+ const interactiveParams = await inputParameters2(paramMeta);
629
+ const merged = { ...interactiveParams, ...params };
630
+ const result = await runDataSource(slug, dirPath, merged, limit);
631
+ displaySummary(result);
632
+ if (values.debug) displayDebug(result);
633
+ if (!result.error) displayTable(result.rows, limit);
634
+ if (result.error) process.exit(1);
635
+ } catch (err) {
636
+ displayError(err instanceof Error ? err : new Error(String(err)));
637
+ process.exit(1);
638
+ }
639
+ }
640
+ }
641
+ main().catch((err) => {
642
+ displayError(err instanceof Error ? err : new Error(String(err)));
643
+ process.exit(1);
644
+ });
package/dist/index.js CHANGED
@@ -41,7 +41,7 @@ function resolveEnvVar(entry, key, connectionId) {
41
41
  // src/connector-client/bigquery.ts
42
42
  function createBigQueryClient(entry, connectionId) {
43
43
  const projectId = resolveEnvVar(entry, "project-id", connectionId);
44
- const serviceAccountJsonBase64 = resolveEnvVar(entry, "service-account-json-base64", connectionId);
44
+ const serviceAccountJsonBase64 = resolveEnvVar(entry, "service-account-key-json-base64", connectionId);
45
45
  const serviceAccountJson = Buffer.from(serviceAccountJsonBase64, "base64").toString("utf-8");
46
46
  let gcpCredentials;
47
47
  try {
@@ -110,7 +110,7 @@ function createConnectorRegistry() {
110
110
  let connectionsCache = null;
111
111
  const clientCache = /* @__PURE__ */ new Map();
112
112
  function getConnectionsFilePath() {
113
- return process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), "../../.squadbase/connections.json");
113
+ return process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
114
114
  }
115
115
  function loadConnections() {
116
116
  if (connectionsCache !== null) return connectionsCache;
@@ -175,7 +175,7 @@ function createConnectorRegistry() {
175
175
  }
176
176
  function watchConnectionsFile2() {
177
177
  const filePath = getConnectionsFilePath();
178
- const envPath = path.join(process.cwd(), "..", "..", ".env");
178
+ const envPath = path.join(process.cwd(), ".env");
179
179
  try {
180
180
  fsWatch(filePath, { persistent: false }, () => {
181
181
  console.log("[connector-client] connections.json changed, clearing cache");
@@ -726,7 +726,7 @@ apiApp.route("/data-source", data_source_default);
726
726
  apiApp.route("/data-source-meta", data_source_meta_default);
727
727
  apiApp.route("/cache", cache_default);
728
728
  apiApp.route("/", pages_default);
729
- reloadEnvFile(path4.join(process.cwd(), "..", "..", ".env"));
729
+ reloadEnvFile(path4.join(process.cwd(), ".env"));
730
730
  await initialize();
731
731
  startWatching();
732
732
  watchConnectionsFile();
package/dist/main.js CHANGED
@@ -41,7 +41,7 @@ function resolveEnvVar(entry, key, connectionId) {
41
41
  // src/connector-client/bigquery.ts
42
42
  function createBigQueryClient(entry, connectionId) {
43
43
  const projectId = resolveEnvVar(entry, "project-id", connectionId);
44
- const serviceAccountJsonBase64 = resolveEnvVar(entry, "service-account-json-base64", connectionId);
44
+ const serviceAccountJsonBase64 = resolveEnvVar(entry, "service-account-key-json-base64", connectionId);
45
45
  const serviceAccountJson = Buffer.from(serviceAccountJsonBase64, "base64").toString("utf-8");
46
46
  let gcpCredentials;
47
47
  try {
@@ -110,7 +110,7 @@ function createConnectorRegistry() {
110
110
  let connectionsCache = null;
111
111
  const clientCache = /* @__PURE__ */ new Map();
112
112
  function getConnectionsFilePath() {
113
- return process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), "../../.squadbase/connections.json");
113
+ return process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
114
114
  }
115
115
  function loadConnections() {
116
116
  if (connectionsCache !== null) return connectionsCache;
@@ -175,7 +175,7 @@ function createConnectorRegistry() {
175
175
  }
176
176
  function watchConnectionsFile2() {
177
177
  const filePath = getConnectionsFilePath();
178
- const envPath = path.join(process.cwd(), "..", "..", ".env");
178
+ const envPath = path.join(process.cwd(), ".env");
179
179
  try {
180
180
  fsWatch(filePath, { persistent: false }, () => {
181
181
  console.log("[connector-client] connections.json changed, clearing cache");
@@ -726,7 +726,7 @@ apiApp.route("/data-source", data_source_default);
726
726
  apiApp.route("/data-source-meta", data_source_meta_default);
727
727
  apiApp.route("/cache", cache_default);
728
728
  apiApp.route("/", pages_default);
729
- reloadEnvFile(path4.join(process.cwd(), "..", "..", ".env"));
729
+ reloadEnvFile(path4.join(process.cwd(), ".env"));
730
730
  await initialize();
731
731
  startWatching();
732
732
  watchConnectionsFile();
@@ -41,7 +41,7 @@ function resolveEnvVar(entry, key, connectionId) {
41
41
  // src/connector-client/bigquery.ts
42
42
  function createBigQueryClient(entry, connectionId) {
43
43
  const projectId = resolveEnvVar(entry, "project-id", connectionId);
44
- const serviceAccountJsonBase64 = resolveEnvVar(entry, "service-account-json-base64", connectionId);
44
+ const serviceAccountJsonBase64 = resolveEnvVar(entry, "service-account-key-json-base64", connectionId);
45
45
  const serviceAccountJson = Buffer.from(serviceAccountJsonBase64, "base64").toString("utf-8");
46
46
  let gcpCredentials;
47
47
  try {
@@ -110,7 +110,7 @@ function createConnectorRegistry() {
110
110
  let connectionsCache = null;
111
111
  const clientCache = /* @__PURE__ */ new Map();
112
112
  function getConnectionsFilePath() {
113
- return process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), "../../.squadbase/connections.json");
113
+ return process.env.CONNECTIONS_PATH ?? path.join(process.cwd(), ".squadbase/connections.json");
114
114
  }
115
115
  function loadConnections() {
116
116
  if (connectionsCache !== null) return connectionsCache;
@@ -175,7 +175,7 @@ function createConnectorRegistry() {
175
175
  }
176
176
  function watchConnectionsFile2() {
177
177
  const filePath = getConnectionsFilePath();
178
- const envPath = path.join(process.cwd(), "..", "..", ".env");
178
+ const envPath = path.join(process.cwd(), ".env");
179
179
  try {
180
180
  fsWatch(filePath, { persistent: false }, () => {
181
181
  console.log("[connector-client] connections.json changed, clearing cache");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squadbase/vite-server",
3
- "version": "0.0.1-build-5",
3
+ "version": "0.0.1-build-7",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -20,7 +20,9 @@
20
20
  "types": "./dist/vite-plugin.d.ts"
21
21
  }
22
22
  },
23
- "files": ["dist"],
23
+ "files": [
24
+ "dist"
25
+ ],
24
26
  "publishConfig": {
25
27
  "access": "public"
26
28
  },