@hypequery/cli 1.16.4 → 1.17.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.
package/dist/bin/cli.js CHANGED
@@ -1,11 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import { program } from '../cli.js';
3
+ import { envFiles } from '../utils/env-files.js';
3
4
  async function loadEnv() {
4
5
  try {
5
6
  const dotenvx = await import('@dotenvx/dotenvx');
6
7
  if (dotenvx?.config && typeof dotenvx.config.load === 'function') {
7
8
  await dotenvx.config.load();
8
- return;
9
+ // Deliberately falls through to the dotenv cascade below. dotenvx has
10
+ // already set whatever it found, and dotenv will not overwrite it, so this
11
+ // only fills in files dotenvx does not read (notably `.env.local`).
9
12
  }
10
13
  }
11
14
  catch {
@@ -13,7 +16,10 @@ async function loadEnv() {
13
16
  }
14
17
  try {
15
18
  const { config } = await import('dotenv');
16
- config();
19
+ for (const path of envFiles(process.env.NODE_ENV)) {
20
+ // Missing files are a no-op.
21
+ config({ path });
22
+ }
17
23
  }
18
24
  catch {
19
25
  // dotenv is optional; continue if not available
package/dist/cli.js CHANGED
@@ -138,7 +138,7 @@ addTypeGenerationOptions(program.command('generate:types'))
138
138
  program
139
139
  .command('generate:datasets')
140
140
  .description('Generate dataset definitions from ClickHouse schema')
141
- .option('-o, --output <path>', 'Output file (default: src/datasets/generated.ts)')
141
+ .option('-o, --output <path>', 'Output file (default: analytics/datasets.ts)')
142
142
  .option('--path <path>', 'Analytics directory (derives <path>/datasets.ts)')
143
143
  .option('--tables <names>', 'Only generate for specific tables (comma-separated)')
144
144
  .option('--exclude-tables <names>', 'Exclude specific tables (comma-separated)')
@@ -1 +1 @@
1
- {"version":3,"file":"generate-datasets.d.ts","sourceRoot":"","sources":["../../src/commands/generate-datasets.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAWD,wBAAsB,uBAAuB,CAAC,OAAO,GAAE,uBAA4B,iBA0FlF"}
1
+ {"version":3,"file":"generate-datasets.d.ts","sourceRoot":"","sources":["../../src/commands/generate-datasets.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAqBD,wBAAsB,uBAAuB,CAAC,OAAO,GAAE,uBAA4B,iBA0GlF"}
@@ -10,6 +10,15 @@ import { logger } from '../utils/logger.js';
10
10
  import { getTableCount } from '../utils/detect-database.js';
11
11
  import { generateDatasets } from '../generators/dataset-generator.js';
12
12
  import { redactConnectionUrl } from '../utils/redact-connection-url.js';
13
+ /**
14
+ * Turns the written path into something pasteable into an import statement:
15
+ * strips the `.ts` extension and makes it explicitly relative.
16
+ */
17
+ function toImportSpecifier(relativePath) {
18
+ const withoutExtension = relativePath.replace(/\.tsx?$/, '');
19
+ const normalized = withoutExtension.split(path.sep).join('/');
20
+ return normalized.startsWith('.') ? normalized : `./${normalized}`;
21
+ }
13
22
  function parseTableList(value) {
14
23
  const parsed = value
15
24
  ?.split(',')
@@ -27,8 +36,9 @@ export async function generateDatasetsCommand(options = {}) {
27
36
  outputPath = path.resolve(process.cwd(), options.path, 'datasets.ts');
28
37
  }
29
38
  else {
30
- // Default to src/datasets/generated.ts
31
- outputPath = path.join(process.cwd(), 'src', 'datasets', 'generated.ts');
39
+ // Sibling of `hypequery generate`, which writes analytics/schema.ts. Keeping
40
+ // both commands in one directory is what the docs have always described.
41
+ outputPath = path.join(process.cwd(), 'analytics', 'datasets.ts');
32
42
  }
33
43
  const parsedTables = parseTableList(options.tables);
34
44
  const excludedTables = parseTableList(options.excludeTables);
@@ -39,30 +49,38 @@ export async function generateDatasetsCommand(options = {}) {
39
49
  // Get table count
40
50
  const tableCount = await getTableCount('clickhouse');
41
51
  spinner.succeed('Connected to ClickHouse');
42
- logger.success(`Found ${tableCount} tables`);
52
+ logger.success(parsedTables
53
+ ? `Found ${tableCount} tables, filtering to ${parsedTables.length}`
54
+ : `Found ${tableCount} tables`);
43
55
  // Generate datasets
44
56
  const datasetSpinner = ora('Generating dataset definitions...').start();
45
- await generateDatasets({
57
+ const generated = await generateDatasets({
46
58
  outputPath,
47
59
  includeTables: parsedTables,
48
60
  excludeTables: excludedTables,
49
61
  });
50
- datasetSpinner.succeed(`Generated dataset definitions for ${parsedTables?.length || tableCount} tables`);
51
- logger.success(`Created ${path.relative(process.cwd(), outputPath)}`);
62
+ const generatedTables = generated?.tables ?? parsedTables ?? [];
63
+ const generatedCount = generatedTables.length || tableCount;
64
+ datasetSpinner.succeed(`Generated dataset definitions for ${generatedCount} ${generatedCount === 1 ? 'table' : 'tables'}`);
65
+ const relativeOutput = path.relative(process.cwd(), outputPath);
66
+ logger.success(`Created ${relativeOutput}`);
52
67
  logger.newline();
53
68
  logger.header('Next steps:');
54
69
  logger.indent('1. Review and customize the generated datasets');
55
70
  logger.indent('2. Import datasets in your application code');
56
71
  logger.indent('3. Create an analytics client and start querying!');
57
72
  logger.newline();
73
+ // Built from what was actually written, so the snippet can be pasted as-is.
74
+ const importPath = toImportSpecifier(relativeOutput);
75
+ const firstTable = generatedTables[0] ?? 'orders';
58
76
  logger.info('Example usage:');
59
- logger.indent('import { datasets } from \'./datasets/generated\';');
77
+ logger.indent(`import { datasets } from '${importPath}';`);
60
78
  logger.indent('import { createDatasetClient } from \'@hypequery/datasets\';');
61
79
  logger.indent('import { createQueryBuilder } from \'@hypequery/clickhouse\';');
62
80
  logger.indent('');
63
81
  logger.indent('const db = createQueryBuilder({ url, username, password, database });');
64
82
  logger.indent('const analytics = createDatasetClient({ queryBuilder: db });');
65
- logger.indent('const rowCount = datasets.orders.metric(\'rowCount\', { measure: \'totalCount\' });');
83
+ logger.indent(`const rowCount = datasets['${firstTable}'].metric('rowCount', { measure: 'totalCount' });`);
66
84
  logger.indent('const result = await analytics.execute(rowCount);');
67
85
  logger.newline();
68
86
  }
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiC,KAAK,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAK/F,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,eAAe,CAAC,OAAO,GAAE,eAAoB,iBAoJlE"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/commands/generate.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiC,KAAK,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAK/F,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wBAAsB,eAAe,CAAC,OAAO,GAAE,eAAoB,iBA6JlE"}
@@ -57,17 +57,22 @@ export async function generateCommand(options = {}) {
57
57
  // Get table count
58
58
  const tableCount = await getTableCount(dbType, { chdbPath });
59
59
  spinner.succeed(`Connected to ${dbType === 'clickhouse' ? 'ClickHouse' : dbType === 'chdb' ? 'embedded chDB' : dbType}`);
60
- logger.success(`Found ${tableCount} tables`);
60
+ logger.success(parsedTables
61
+ ? `Found ${tableCount} tables, applying --tables filter`
62
+ : `Found ${tableCount} tables`);
61
63
  // Generate types
62
64
  const typeSpinner = ora('Generating types...').start();
63
65
  activeSpinner = typeSpinner;
64
66
  failureMessage = 'Failed to generate types';
65
- await generator({
67
+ const generatedTables = await generator({
66
68
  outputPath,
67
69
  includeTables: parsedTables,
68
70
  chdbPath,
69
71
  });
70
- typeSpinner.succeed(`Generated types for ${tableCount} tables`);
72
+ // The generator returns what it actually wrote after applying filters.
73
+ // Requested names may contain duplicates or tables that do not exist.
74
+ const generatedCount = generatedTables.length;
75
+ typeSpinner.succeed(`Generated types for ${generatedCount} ${generatedCount === 1 ? 'table' : 'tables'}`);
71
76
  logger.success(`Updated ${path.relative(process.cwd(), outputPath)}`);
72
77
  logger.newline();
73
78
  logger.header('Types regenerated successfully!');
@@ -9,5 +9,5 @@ export interface ChdbGeneratorOptions {
9
9
  * DESCRIBE TABLE) is identical on the embedded engine — but the client seam
10
10
  * is backed by a chDB session instead of an HTTP connection.
11
11
  */
12
- export declare function generateChdbTypes(options: ChdbGeneratorOptions): Promise<void>;
12
+ export declare function generateChdbTypes(options: ChdbGeneratorOptions): Promise<string[]>;
13
13
  //# sourceMappingURL=chdb.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chdb.d.ts","sourceRoot":"","sources":["../../src/generators/chdb.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,oBAAoB,iBAUpE"}
1
+ {"version":3,"file":"chdb.d.ts","sourceRoot":"","sources":["../../src/generators/chdb.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,oBAAoB,qBAUpE"}
@@ -13,5 +13,5 @@ export async function generateChdbTypes(options) {
13
13
  ...(options.includeTables ? { includeTables: options.includeTables } : {}),
14
14
  ...(options.excludeTables ? { excludeTables: options.excludeTables } : {}),
15
15
  };
16
- await generateTypes(options.outputPath, generatorOptions);
16
+ return generateTypes(options.outputPath, generatorOptions);
17
17
  }
@@ -5,5 +5,5 @@ export interface ClickHouseGeneratorOptions {
5
5
  excludeTables?: string[];
6
6
  }
7
7
  export { clickhouseToTsType };
8
- export declare function generateClickHouseTypes(options: ClickHouseGeneratorOptions): Promise<void>;
8
+ export declare function generateClickHouseTypes(options: ClickHouseGeneratorOptions): Promise<string[]>;
9
9
  //# sourceMappingURL=clickhouse.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"clickhouse.d.ts","sourceRoot":"","sources":["../../src/generators/clickhouse.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAGnB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAE9B,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,0BAA0B,iBAUhF"}
1
+ {"version":3,"file":"clickhouse.d.ts","sourceRoot":"","sources":["../../src/generators/clickhouse.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAGnB,MAAM,qBAAqB,CAAC;AAG7B,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAE9B,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,0BAA0B,qBAUhF"}
@@ -9,5 +9,5 @@ export async function generateClickHouseTypes(options) {
9
9
  ...(options.includeTables ? { includeTables: options.includeTables } : {}),
10
10
  ...(options.excludeTables ? { excludeTables: options.excludeTables } : {}),
11
11
  };
12
- await generateTypes(options.outputPath, generatorOptions);
12
+ return generateTypes(options.outputPath, generatorOptions);
13
13
  }
@@ -14,5 +14,11 @@ export interface DatasetGeneratorOptions {
14
14
  /**
15
15
  * Generate dataset definitions from ClickHouse schema
16
16
  */
17
- export declare function generateDatasets(options: DatasetGeneratorOptions): Promise<void>;
17
+ export declare function generateDatasets(options: DatasetGeneratorOptions): Promise<{
18
+ tables: string[];
19
+ exports: {
20
+ table: string;
21
+ exportName: string;
22
+ }[];
23
+ }>;
18
24
  //# sourceMappingURL=dataset-generator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dataset-generator.d.ts","sourceRoot":"","sources":["../../src/generators/dataset-generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AAG1E,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE,8BAA8B,CAAC;CACzC;AAuPD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,iBAyDtE"}
1
+ {"version":3,"file":"dataset-generator.d.ts","sourceRoot":"","sources":["../../src/generators/dataset-generator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AAG1E,MAAM,WAAW,uBAAuB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE,8BAA8B,CAAC;CACzC;AAuPD;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB;;;;;;GAmEtE"}
@@ -243,4 +243,13 @@ ${tables.map((table) => ` ${table.name}: ${tableToPascalCase(table.name)}Datase
243
243
  await fs.mkdir(outputDir, { recursive: true });
244
244
  // Write the file
245
245
  await fs.writeFile(path.resolve(options.outputPath), output);
246
+ // Returned so the CLI can report what it actually generated, and print an
247
+ // example that matches the file rather than a hardcoded placeholder.
248
+ return {
249
+ tables: tables.map((table) => table.name),
250
+ exports: tables.map((table) => ({
251
+ table: table.name,
252
+ exportName: `${tableToPascalCase(table.name)}Dataset`,
253
+ })),
254
+ };
246
255
  }
@@ -2,7 +2,7 @@ import type { DatabaseType } from '../utils/detect-database.js';
2
2
  import type { ClickHouseGeneratorOptions } from './clickhouse.js';
3
3
  import type { ChdbGeneratorOptions } from './chdb.js';
4
4
  export type TypeGeneratorOptions = ClickHouseGeneratorOptions & ChdbGeneratorOptions;
5
- type GeneratorFn = (options: TypeGeneratorOptions) => Promise<void>;
5
+ type GeneratorFn = (options: TypeGeneratorOptions) => Promise<string[]>;
6
6
  export declare function getTypeGenerator(dbType: DatabaseType): GeneratorFn;
7
7
  export {};
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generators/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEtD,MAAM,MAAM,oBAAoB,GAAG,0BAA0B,GAAG,oBAAoB,CAAC;AAErF,KAAK,WAAW,GAAG,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAiBpE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,CAYlE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/generators/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAEtD,MAAM,MAAM,oBAAoB,GAAG,0BAA0B,GAAG,oBAAoB,CAAC;AAErF,KAAK,WAAW,GAAG,CAAC,OAAO,EAAE,oBAAoB,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AAiBxE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,WAAW,CAYlE"}
@@ -5,11 +5,11 @@
5
5
  const generators = {
6
6
  clickhouse: async (options) => {
7
7
  const { generateClickHouseTypes } = await import('./clickhouse.js');
8
- await generateClickHouseTypes(options);
8
+ return generateClickHouseTypes(options);
9
9
  },
10
10
  chdb: async (options) => {
11
11
  const { generateChdbTypes } = await import('./chdb.js');
12
- await generateChdbTypes(options);
12
+ return generateChdbTypes(options);
13
13
  },
14
14
  };
15
15
  export function getTypeGenerator(dbType) {
@@ -41,6 +41,7 @@ export declare function generateTypeDefinitions(client: TypeGenerationClickHouse
41
41
  /**
42
42
  * Generates TypeScript type definitions from the ClickHouse database schema and
43
43
  * writes them to `outputPath`, creating the containing directory if needed.
44
+ * Returns the names of the tables represented in the generated file.
44
45
  */
45
- export declare function generateTypes(outputPath: string, options: GenerateTypesOptions): Promise<void>;
46
+ export declare function generateTypes(outputPath: string, options: GenerateTypesOptions): Promise<string[]>;
46
47
  //# sourceMappingURL=generate-types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generate-types.d.ts","sourceRoot":"","sources":["../../src/typegen/generate-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH;;;GAGG;AACH,MAAM,WAAW,8BAA8B;IAC7C,KAAK,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,GAAG,OAAO,CAAC;QAChE,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;KAChD,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,oBAAoB;IACnC,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,qCAAqC;IACrC,MAAM,EAAE,8BAA8B,CAAC;IACvC,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAqBD;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,8BAA8B,EACtC,OAAO,GAAE,IAAI,CAAC,oBAAoB,EAAE,QAAQ,CAAM,GACjD,OAAO,CAAC,MAAM,CAAC,CAsFjB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUpG"}
1
+ {"version":3,"file":"generate-types.d.ts","sourceRoot":"","sources":["../../src/typegen/generate-types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH;;;GAGG;AACH,MAAM,WAAW,8BAA8B;IAC7C,KAAK,CAAC,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,aAAa,CAAA;KAAE,GAAG,OAAO,CAAC;QAChE,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;KAChD,CAAC,CAAC;CACJ;AAED,MAAM,WAAW,oBAAoB;IACnC,6EAA6E;IAC7E,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,qCAAqC;IACrC,MAAM,EAAE,8BAA8B,CAAC;IACvC,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AA2HD;;GAEG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,8BAA8B,EACtC,OAAO,GAAE,IAAI,CAAC,oBAAoB,EAAE,QAAQ,CAAM,GACjD,OAAO,CAAC,MAAM,CAAC,CAGjB;AAED;;;;GAIG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,EAAE,CAAC,CAYnB"}
@@ -29,7 +29,7 @@ async function describeTable(client, tableName) {
29
29
  /**
30
30
  * Generates the TypeScript type definition source from a ClickHouse client.
31
31
  */
32
- export async function generateTypeDefinitions(client, options = {}) {
32
+ async function buildTypeDefinitions(client, options = {}) {
33
33
  const { includeTables = [], excludeTables = [], generatedBy = 'hypequery', includeUsageExample = true, } = options;
34
34
  // Get all tables
35
35
  const tablesQuery = await client.query({
@@ -98,18 +98,30 @@ export interface IntrospectedSchema {`;
98
98
  */
99
99
  `;
100
100
  }
101
- return typeDefinitions;
101
+ return {
102
+ contents: typeDefinitions,
103
+ tableNames: tables.map((table) => table.name),
104
+ };
105
+ }
106
+ /**
107
+ * Generates the TypeScript type definition source from a ClickHouse client.
108
+ */
109
+ export async function generateTypeDefinitions(client, options = {}) {
110
+ const generated = await buildTypeDefinitions(client, options);
111
+ return generated.contents;
102
112
  }
103
113
  /**
104
114
  * Generates TypeScript type definitions from the ClickHouse database schema and
105
115
  * writes them to `outputPath`, creating the containing directory if needed.
116
+ * Returns the names of the tables represented in the generated file.
106
117
  */
107
118
  export async function generateTypes(outputPath, options) {
108
119
  const { client, ...definitionOptions } = options;
109
- const typeDefinitions = await generateTypeDefinitions(client, definitionOptions);
120
+ const generated = await buildTypeDefinitions(client, definitionOptions);
110
121
  // Ensure the output directory exists
111
122
  const outputDir = path.dirname(path.resolve(outputPath));
112
123
  await fs.mkdir(outputDir, { recursive: true });
113
124
  // Write the file
114
- await fs.writeFile(path.resolve(outputPath), typeDefinitions);
125
+ await fs.writeFile(path.resolve(outputPath), generated.contents);
126
+ return generated.tableNames;
115
127
  }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Env files the CLI loads, in precedence order, most specific first.
3
+ *
4
+ * This mirrors the cascade Next.js and Vite use. `dotenv` never overwrites a
5
+ * variable that is already set, so loading in this order means earlier entries
6
+ * win, and a real `process.env` value beats every file.
7
+ *
8
+ * `.env.local` matters in particular: it is the file those frameworks read, so
9
+ * without it a project could have working app credentials and a CLI that could
10
+ * not connect — with an error that never mentions the env file.
11
+ */
12
+ export declare function envFiles(nodeEnv: string | undefined): string[];
13
+ //# sourceMappingURL=env-files.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-files.d.ts","sourceRoot":"","sources":["../../src/utils/env-files.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAO9D"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Env files the CLI loads, in precedence order, most specific first.
3
+ *
4
+ * This mirrors the cascade Next.js and Vite use. `dotenv` never overwrites a
5
+ * variable that is already set, so loading in this order means earlier entries
6
+ * win, and a real `process.env` value beats every file.
7
+ *
8
+ * `.env.local` matters in particular: it is the file those frameworks read, so
9
+ * without it a project could have working app credentials and a CLI that could
10
+ * not connect — with an error that never mentions the env file.
11
+ */
12
+ export function envFiles(nodeEnv) {
13
+ return [
14
+ ...(nodeEnv ? [`.env.${nodeEnv}.local`] : []),
15
+ '.env.local',
16
+ ...(nodeEnv ? [`.env.${nodeEnv}`] : []),
17
+ '.env',
18
+ ];
19
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypequery/cli",
3
- "version": "1.16.4",
3
+ "version": "1.17.0",
4
4
  "description": "CLI for scaffolding type-safe ClickHouse analytics, semantic datasets, React manifests, and deployments",
5
5
  "keywords": [
6
6
  "clickhouse",
@@ -30,8 +30,8 @@
30
30
  "open": "^10.0.0",
31
31
  "ora": "^8.0.1",
32
32
  "prompts": "^2.4.2",
33
- "@hypequery/deployment": "0.7.3",
34
- "@hypequery/protocol": "0.11.0"
33
+ "@hypequery/protocol": "0.11.0",
34
+ "@hypequery/deployment": "0.7.3"
35
35
  },
36
36
  "optionalDependencies": {
37
37
  "@napi-rs/keyring": "1.3.0"
@@ -45,7 +45,7 @@
45
45
  "@vitest/coverage-v8": "^3.2.6",
46
46
  "typescript": "^5.7.3",
47
47
  "vitest": "^3.2.6",
48
- "@hypequery/serve": "0.15.3"
48
+ "@hypequery/serve": "0.16.0"
49
49
  },
50
50
  "repository": {
51
51
  "type": "git",