@hypequery/cli 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +71 -149
  2. package/dist/bin/cli.js +21 -81
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -1
  5. package/dist/cli.js +74 -105
  6. package/dist/commands/dev.d.ts +1 -0
  7. package/dist/commands/dev.d.ts.map +1 -1
  8. package/dist/commands/dev.js +180 -255
  9. package/dist/commands/generate-datasets.d.ts +14 -0
  10. package/dist/commands/generate-datasets.d.ts.map +1 -0
  11. package/dist/commands/generate-datasets.js +96 -0
  12. package/dist/commands/generate.d.ts +2 -0
  13. package/dist/commands/generate.d.ts.map +1 -1
  14. package/dist/commands/generate.js +112 -167
  15. package/dist/commands/init.d.ts +7 -1
  16. package/dist/commands/init.d.ts.map +1 -1
  17. package/dist/commands/init.js +337 -390
  18. package/dist/generators/clickhouse.d.ts +1 -1
  19. package/dist/generators/clickhouse.d.ts.map +1 -1
  20. package/dist/generators/clickhouse.js +10 -269
  21. package/dist/generators/dataset-generator.d.ts +16 -0
  22. package/dist/generators/dataset-generator.d.ts.map +1 -0
  23. package/dist/generators/dataset-generator.js +213 -0
  24. package/dist/generators/index.js +4 -4
  25. package/dist/templates/api.d.ts +9 -0
  26. package/dist/templates/api.d.ts.map +1 -0
  27. package/dist/templates/api.js +26 -0
  28. package/dist/templates/auth-scaffold.d.ts +17 -0
  29. package/dist/templates/auth-scaffold.d.ts.map +1 -0
  30. package/dist/templates/auth-scaffold.js +41 -0
  31. package/dist/templates/client.js +10 -1
  32. package/dist/templates/datasets.d.ts +5 -0
  33. package/dist/templates/datasets.d.ts.map +1 -0
  34. package/dist/templates/datasets.js +23 -0
  35. package/dist/templates/env.d.ts +2 -1
  36. package/dist/templates/env.d.ts.map +1 -1
  37. package/dist/templates/env.js +19 -6
  38. package/dist/templates/gitignore.js +4 -1
  39. package/dist/templates/queries.d.ts +3 -0
  40. package/dist/templates/queries.d.ts.map +1 -1
  41. package/dist/templates/queries.js +66 -9
  42. package/dist/test-utils.d.ts +0 -72
  43. package/dist/test-utils.d.ts.map +1 -1
  44. package/dist/test-utils.js +12 -138
  45. package/dist/utils/clickhouse-client.js +11 -58
  46. package/dist/utils/clickhouse-sql.d.ts +6 -0
  47. package/dist/utils/clickhouse-sql.d.ts.map +1 -0
  48. package/dist/utils/clickhouse-sql.js +18 -0
  49. package/dist/utils/clickhouse-type-utils.d.ts +6 -0
  50. package/dist/utils/clickhouse-type-utils.d.ts.map +1 -0
  51. package/dist/utils/clickhouse-type-utils.js +59 -0
  52. package/dist/utils/dependency-installer.d.ts +5 -1
  53. package/dist/utils/dependency-installer.d.ts.map +1 -1
  54. package/dist/utils/dependency-installer.js +117 -134
  55. package/dist/utils/detect-database.js +84 -195
  56. package/dist/utils/find-files.d.ts +3 -1
  57. package/dist/utils/find-files.d.ts.map +1 -1
  58. package/dist/utils/find-files.js +82 -148
  59. package/dist/utils/load-api.d.ts.map +1 -1
  60. package/dist/utils/load-api.js +207 -396
  61. package/dist/utils/logger.js +38 -42
  62. package/dist/utils/prompts.d.ts +14 -5
  63. package/dist/utils/prompts.d.ts.map +1 -1
  64. package/dist/utils/prompts.js +170 -244
  65. package/dist/utils/runtime-guards.d.ts +4 -0
  66. package/dist/utils/runtime-guards.d.ts.map +1 -0
  67. package/dist/utils/runtime-guards.js +9 -0
  68. package/dist/utils/sha256.d.ts +2 -0
  69. package/dist/utils/sha256.d.ts.map +1 -0
  70. package/dist/utils/sha256.js +4 -0
  71. package/package.json +4 -4
  72. package/dist/utils/error-messages.d.ts +0 -6
  73. package/dist/utils/error-messages.d.ts.map +0 -1
  74. package/dist/utils/error-messages.js +0 -19
  75. package/dist/utils/load-hypequery-config.d.ts +0 -7
  76. package/dist/utils/load-hypequery-config.d.ts.map +0 -1
  77. package/dist/utils/load-hypequery-config.js +0 -89
package/README.md CHANGED
@@ -1,211 +1,133 @@
1
1
  # @hypequery/cli
2
2
 
3
- Command-line interface for Hypequery - the type-safe analytics layer for ClickHouse.
3
+ CLI for scaffolding and running the main hypequery path.
4
4
 
5
- ## Quick Start
5
+ Use it to:
6
6
 
7
- The CLI scaffolds and runs the main hypequery path:
7
+ - generate schema types from ClickHouse
8
+ - scaffold `analytics/` files
9
+ - run the local dev server with docs
8
10
 
9
- 1. Generate schema types from ClickHouse
10
- 2. Build queries with the typed query builder
11
- 3. Wrap reusable queries with `query({ ... })`
12
- 4. Add `serve({ queries })` when you want HTTP routes and docs
11
+ ## Quick Start
13
12
 
14
- Use `npx` to run commands directly:
13
+ Run it directly:
15
14
 
16
15
  ```bash
17
- # Initialize a new project
18
16
  npx @hypequery/cli init
19
-
20
- # Start development server
21
17
  npx @hypequery/cli dev
22
-
23
- # Generate types from database
24
18
  npx @hypequery/cli generate
25
19
  ```
26
20
 
27
- ## Installation (Optional)
28
-
29
- For frequent use, install as a dev dependency:
21
+ Or install it once:
30
22
 
31
23
  ```bash
32
24
  npm install -D @hypequery/cli
33
- # or
34
- pnpm add -D @hypequery/cli
35
- # or
36
- yarn add -D @hypequery/cli
37
25
  ```
38
26
 
39
- Then use the shorter `hypequery` command:
40
-
41
- ```bash
42
- npx hypequery dev
43
- ```
44
-
45
- Or add to your `package.json` scripts:
46
-
47
- ```json
48
- {
49
- "scripts": {
50
- "hypequery:init": "hypequery init",
51
- "hypequery:dev": "hypequery dev",
52
- "hypequery:generate": "hypequery generate"
53
- }
54
- }
55
- ```
56
-
57
- ## TypeScript Support
58
-
59
- `hypequery dev` bundles a TypeScript runtime (powered by `tsx`), so pointing it at `analytics/queries.ts` or any `.ts/.tsx` file just works—no extra install or custom runner required. If your project already compiles to JavaScript you can keep targeting the generated `.js` file instead.
60
-
61
27
  ## Commands
62
28
 
63
29
  ### `hypequery init`
64
30
 
65
- Interactive setup wizard that scaffolds a new Hypequery project.
31
+ Scaffolds the standard hypequery setup.
66
32
 
67
33
  ```bash
68
- # Without installation
69
- npx @hypequery/cli init
70
-
71
- # With installation
72
34
  npx hypequery init
73
35
  ```
74
36
 
75
- **What it does:**
76
- - Connects to your ClickHouse database
77
- - Generates TypeScript types from your schema
78
- - Creates the client, query, and serve files for the main path
79
- - Sets up `.env` with connection details
80
- - Updates `.gitignore` to protect secrets
81
-
82
- **Options:**
83
- - `--database <type>` - Database type (currently only `clickhouse`)
84
- - `--path <path>` - Output directory (default: `analytics/`)
85
- - `--no-example` - Skip example query generation
86
- - `--no-interactive` - Non-interactive mode (uses environment variables)
87
- - `--force` - Overwrite existing files without confirmation
88
-
89
- **Example:**
90
- ```bash
91
- # Interactive mode (recommended)
92
- npx @hypequery/cli init
37
+ It will:
93
38
 
94
- # Non-interactive with custom path
95
- npx @hypequery/cli init --path src/analytics --no-interactive
96
- ```
39
+ - generate schema types
40
+ - create client and query files
41
+ - write `.env` values
42
+ - update `.gitignore`
43
+ - install scaffold dependencies, including `zod`
97
44
 
98
- ### `hypequery dev`
45
+ Options:
99
46
 
100
- Start development server with live reload and query playground.
47
+ - `--path <path>`: output directory, default `analytics/`
48
+ - `--style <style>`: `queries` (default) or `datasets`
49
+ - `--auth <mode>`: `none` (default) or `context`
50
+ - `--all-tables`: with `--style datasets`, scaffold every table
51
+ - `--tables <names>`: with `--style datasets`, scaffold these comma-separated tables
52
+ - `--exclude-tables <names>`: with `--style datasets`, exclude these comma-separated tables
53
+ - `--no-example`: skip the example query
54
+ - `--no-interactive`: read connection details from env vars
55
+ - `--force`: overwrite existing scaffold files
56
+ - `--skip-connection`: skip testing the ClickHouse connection before scaffolding
101
57
 
102
- ```bash
103
- # Without installation
104
- npx @hypequery/cli dev
58
+ Set `HYPEQUERY_SKIP_INSTALL=1` to skip the automatic dependency install.
105
59
 
106
- # With installation
107
- npx hypequery dev
60
+ ### `hypequery dev`
108
61
 
109
- # With TypeScript file
110
- npx @hypequery/cli dev src/analytics/queries.ts
111
- ```
62
+ Runs the local serve runtime with docs and hot reload.
112
63
 
113
- **What it does:**
114
- - Starts a local HTTP server for your queries
115
- - Provides interactive API documentation at `/docs`
116
- - Auto-reloads on file changes
117
- - Displays query execution stats
118
-
119
- **Options:**
120
- - `-p, --port <port>` - Port number (default: `4000`)
121
- - `-h, --hostname <host>` - Hostname to bind (default: `localhost`)
122
- - `--no-watch` - Disable file watching
123
- - `--cache <provider>` - Cache provider (`memory` | `redis` | `none`)
124
- - `--open` - Open browser automatically
125
- - `--cors` - Enable CORS
126
- - `-q, --quiet` - Suppress startup messages
127
-
128
- **Example:**
129
64
  ```bash
130
- # Basic usage
131
- npx @hypequery/cli dev
132
-
133
- # Custom port with browser auto-open
134
- npx @hypequery/cli dev --port 3000 --open
135
-
136
- # Disable caching for debugging
137
- npx @hypequery/cli dev --cache none
65
+ npx hypequery dev
138
66
  ```
139
67
 
140
- **Common Issues:**
68
+ Options:
69
+
70
+ - `--port <port>`: default `4000`
71
+ - `--hostname <host>`: default `localhost`
72
+ - `--path <path>`: analytics directory to load (`<path>/api.ts` or `<path>/queries.ts`)
73
+ - `--no-watch`: disable file watching
74
+ - `--open`: open the browser automatically
75
+ - `--quiet`: reduce startup output
141
76
 
142
- If you see "Unexpected token" errors while loading your queries, double-check that you're pointing the CLI at the TypeScript source file (e.g. `analytics/queries.ts`). The CLI bundles the loader and should not require additional dependencies.
77
+ The CLI understands TypeScript entry files directly, so `analytics/queries.ts` works without an extra runner.
143
78
 
144
79
  ### `hypequery generate`
145
80
 
146
- Regenerate TypeScript types from ClickHouse schema.
81
+ Regenerates schema types from ClickHouse.
147
82
 
148
83
  ```bash
149
- # Without installation
150
- npx @hypequery/cli generate
151
-
152
- # With installation
153
84
  npx hypequery generate
154
85
  ```
155
86
 
156
- The CLI bundles the ClickHouse driver directly, so you can run this command without installing `@hypequery/clickhouse`. Specify `--database <type>` once additional drivers become available.
87
+ Options:
157
88
 
158
- **What it does:**
159
- - Connects to ClickHouse
160
- - Introspects your database schema
161
- - Generates TypeScript interfaces for all tables
162
- - Updates your schema file with type-safe definitions
89
+ - `--output <path>`: default `analytics/schema.ts`
90
+ - `--path <path>`: analytics directory (derives `<path>/schema.ts`)
91
+ - `--tables <names>`: comma-separated table list
92
+ - `--database <type>`: currently `clickhouse`
163
93
 
164
- **Options:**
165
- - `-o, --output <path>` - Output file (default: `analytics/schema.ts`)
166
- - `--tables <names>` - Only generate for specific tables (comma-separated)
167
- - `--database <type>` - Override detected database (currently only `clickhouse`)
94
+ `hypequery generate:types` is an alias for `hypequery generate`.
168
95
 
169
- **Example:**
170
- ```bash
171
- # Generate all tables
172
- npx @hypequery/cli generate
96
+ ### `hypequery generate:datasets`
173
97
 
174
- # Generate specific tables
175
- npx @hypequery/cli generate --tables users,events
98
+ Generates dataset (semantic layer) definitions from ClickHouse.
176
99
 
177
- # Custom output path
178
- npx @hypequery/cli generate --output src/schema.ts
100
+ ```bash
101
+ npx hypequery generate:datasets
179
102
  ```
180
103
 
181
- ## Package Scripts
104
+ Options:
182
105
 
183
- Add these to your `package.json` for easy access:
106
+ - `--output <path>`: default `src/datasets/generated.ts`
107
+ - `--path <path>`: analytics directory (derives `<path>/datasets.ts`)
108
+ - `--tables <names>`: comma-separated table list
109
+ - `--exclude-tables <names>`: comma-separated tables to exclude
184
110
 
185
- ```json
186
- {
187
- "scripts": {
188
- "db:init": "hypequery init",
189
- "db:dev": "hypequery dev",
190
- "db:generate": "hypequery generate"
191
- }
192
- }
193
- ```
111
+ ## Non-interactive Setup
194
112
 
195
- Then run with:
196
- ```bash
197
- npm run db:dev
198
- ```
113
+ `hypequery init --no-interactive` reads:
114
+
115
+ - `CLICKHOUSE_URL` or deprecated `CLICKHOUSE_HOST`
116
+ - `CLICKHOUSE_DATABASE`
117
+ - `CLICKHOUSE_USERNAME` or `CLICKHOUSE_USER`
118
+ - `CLICKHOUSE_PASSWORD`
119
+
120
+ ## Notes
199
121
 
200
- ## Documentation
122
+ - generated scaffold files use NodeNext-safe local `.js` imports
123
+ - `CLICKHOUSE_URL` is now the preferred connection variable
124
+ - the CLI bundles the ClickHouse driver for schema generation
201
125
 
202
- Visit the main docs flow:
126
+ ## Docs
203
127
 
204
- - [Quick Start](https://hypequery.com/docs/quick-start)
205
- - [Core Concepts](https://hypequery.com/docs/core-concepts)
206
- - [Query Building](https://hypequery.com/docs/query-building/basics)
207
- - [Serve Runtime Reference](https://hypequery.com/docs/reference/runtime)
128
+ - [Quick start](https://hypequery.com/docs/quick-start)
129
+ - [CLI reference](https://hypequery.com/docs/reference/api/cli)
208
130
 
209
131
  ## License
210
132
 
211
- Apache-2.0
133
+ Apache-2.0.
package/dist/bin/cli.js CHANGED
@@ -1,86 +1,26 @@
1
1
  #!/usr/bin/env node
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
37
- };
38
2
  import { program } from '../cli.js';
39
- function loadEnv() {
40
- return __awaiter(this, void 0, void 0, function () {
41
- var dotenvx, _a, config, _b;
42
- return __generator(this, function (_c) {
43
- switch (_c.label) {
44
- case 0:
45
- _c.trys.push([0, 4, , 5]);
46
- return [4 /*yield*/, import('@dotenvx/dotenvx')];
47
- case 1:
48
- dotenvx = _c.sent();
49
- if (!((dotenvx === null || dotenvx === void 0 ? void 0 : dotenvx.config) && typeof dotenvx.config.load === 'function')) return [3 /*break*/, 3];
50
- return [4 /*yield*/, dotenvx.config.load()];
51
- case 2:
52
- _c.sent();
53
- return [2 /*return*/];
54
- case 3: return [3 /*break*/, 5];
55
- case 4:
56
- _a = _c.sent();
57
- return [3 /*break*/, 5];
58
- case 5:
59
- _c.trys.push([5, 7, , 8]);
60
- return [4 /*yield*/, import('dotenv')];
61
- case 6:
62
- config = (_c.sent()).config;
63
- config();
64
- return [3 /*break*/, 8];
65
- case 7:
66
- _b = _c.sent();
67
- return [3 /*break*/, 8];
68
- case 8: return [2 /*return*/];
69
- }
70
- });
71
- });
3
+ async function loadEnv() {
4
+ try {
5
+ const dotenvx = await import('@dotenvx/dotenvx');
6
+ if (dotenvx?.config && typeof dotenvx.config.load === 'function') {
7
+ await dotenvx.config.load();
8
+ return;
9
+ }
10
+ }
11
+ catch {
12
+ // Optional dependency, ignore if missing
13
+ }
14
+ try {
15
+ const { config } = await import('dotenv');
16
+ config();
17
+ }
18
+ catch {
19
+ // dotenv is optional; continue if not available
20
+ }
72
21
  }
73
- function main() {
74
- return __awaiter(this, void 0, void 0, function () {
75
- return __generator(this, function (_a) {
76
- switch (_a.label) {
77
- case 0: return [4 /*yield*/, loadEnv()];
78
- case 1:
79
- _a.sent();
80
- program.parse(process.argv);
81
- return [2 /*return*/];
82
- }
83
- });
84
- });
22
+ async function main() {
23
+ await loadEnv();
24
+ program.parse(process.argv);
85
25
  }
86
26
  main();
package/dist/cli.d.ts CHANGED
@@ -1,4 +1,7 @@
1
1
  import { Command } from 'commander';
2
2
  declare const program: Command;
3
+ export declare function normalizeInitOptions(options: Record<string, unknown>): {
4
+ noInteractive: boolean;
5
+ };
3
6
  export { program };
4
7
  //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AA8F9B,OAAO,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,QAAA,MAAM,OAAO,SAAgB,CAAC;AAa9B,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;EAKpE;AAuHD,OAAO,EAAE,OAAO,EAAE,CAAC"}
package/dist/cli.js CHANGED
@@ -1,82 +1,71 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- var __generator = (this && this.__generator) || function (thisArg, body) {
11
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
12
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13
- function verb(n) { return function (v) { return step([n, v]); }; }
14
- function step(op) {
15
- if (f) throw new TypeError("Generator is already executing.");
16
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
17
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
18
- if (y = 0, t) op = [op[0] & 2, t.value];
19
- switch (op[0]) {
20
- case 0: case 1: t = op; break;
21
- case 4: _.label++; return { value: op[1], done: false };
22
- case 5: _.label++; y = op[1]; op = [0]; continue;
23
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
24
- default:
25
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29
- if (t[2]) _.ops.pop();
30
- _.trys.pop(); continue;
31
- }
32
- op = body.call(thisArg, _);
33
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35
- }
36
- };
1
+ import { readFileSync } from 'node:fs';
2
+ import { fileURLToPath } from 'node:url';
37
3
  import { Command } from 'commander';
38
4
  import { initCommand } from './commands/init.js';
39
5
  import { devCommand } from './commands/dev.js';
40
6
  import { generateCommand } from './commands/generate.js';
41
- var program = new Command();
7
+ import { generateDatasetsCommand } from './commands/generate-datasets.js';
8
+ const program = new Command();
9
+ function getCliVersion() {
10
+ try {
11
+ const pkg = JSON.parse(readFileSync(fileURLToPath(new URL('../package.json', import.meta.url)), 'utf8'));
12
+ return pkg.version ?? '0.0.0';
13
+ }
14
+ catch {
15
+ return '0.0.0';
16
+ }
17
+ }
18
+ export function normalizeInitOptions(options) {
19
+ return {
20
+ ...options,
21
+ noInteractive: options.noInteractive === true || options.interactive === false,
22
+ };
23
+ }
42
24
  program
43
25
  .name('hypequery')
44
26
  .description('Type-safe analytics layer for ClickHouse')
45
- .version('0.0.1');
27
+ .version(getCliVersion());
28
+ function runCommand(action) {
29
+ return async (...args) => {
30
+ try {
31
+ await action(...args);
32
+ }
33
+ catch (error) {
34
+ console.error(error instanceof Error ? error.message : error);
35
+ process.exit(1);
36
+ }
37
+ };
38
+ }
39
+ function addTypeGenerationOptions(command) {
40
+ return command
41
+ .description('Regenerate types from ClickHouse')
42
+ .option('-o, --output <path>', 'Output file (default: analytics/schema.ts)')
43
+ .option('--path <path>', 'Analytics directory (derives <path>/schema.ts)')
44
+ .option('--tables <names>', 'Only generate for specific tables (comma-separated)')
45
+ .option('--database <type>', 'Database driver to use (default: auto-detect)');
46
+ }
46
47
  // Init command
47
48
  program
48
49
  .command('init')
49
50
  .description('Initialize a new hypequery project')
50
- .option('--database <type>', 'Database type (clickhouse|bigquery)')
51
51
  .option('--path <path>', 'Output directory (default: analytics/)')
52
+ .option('--style <style>', 'Scaffold style: queries or datasets')
53
+ .option('--auth <mode>', 'Auth scaffold mode: none or context')
54
+ .option('--all-tables', 'Generate datasets for all discovered tables when using --style datasets')
55
+ .option('--tables <names>', 'Generate datasets for specific tables when using --style datasets (comma-separated)')
56
+ .option('--exclude-tables <names>', 'Exclude tables from dataset generation when using --style datasets (comma-separated)')
52
57
  .option('--no-example', 'Skip example query generation')
53
58
  .option('--no-interactive', 'Non-interactive mode (use env vars)')
54
59
  .option('--force', 'Overwrite existing files')
55
60
  .option('--skip-connection', 'Skip database connectivity test')
56
- .action(function (options) { return __awaiter(void 0, void 0, void 0, function () {
57
- var error_1;
58
- return __generator(this, function (_a) {
59
- switch (_a.label) {
60
- case 0:
61
- _a.trys.push([0, 2, , 3]);
62
- return [4 /*yield*/, initCommand(options)];
63
- case 1:
64
- _a.sent();
65
- return [3 /*break*/, 3];
66
- case 2:
67
- error_1 = _a.sent();
68
- console.error(error_1 instanceof Error ? error_1.message : error_1);
69
- process.exit(1);
70
- return [3 /*break*/, 3];
71
- case 3: return [2 /*return*/];
72
- }
73
- });
74
- }); });
61
+ .action(runCommand(async (options) => {
62
+ await initCommand(normalizeInitOptions(options));
63
+ }));
75
64
  // Dev command
76
65
  program
77
66
  .command('dev [file]')
78
67
  .description('Start development server')
79
- .option('-p, --port <port>', 'Port number', function (val) { return parseInt(val, 10); })
68
+ .option('-p, --port <port>', 'Port number', (val) => parseInt(val, 10))
80
69
  .option('-h, --hostname <host>', 'Host to bind (default: localhost)')
81
70
  .option('--no-watch', 'Disable file watching')
82
71
  .option('--no-cache', 'Disable caching')
@@ -84,64 +73,42 @@ program
84
73
  .option('--redis-url <url>', 'Redis connection URL')
85
74
  .option('--open', 'Open browser automatically')
86
75
  .option('--cors', 'Enable CORS')
76
+ .option('--path <path>', 'Analytics directory (loads <path>/api.ts or <path>/queries.ts)')
87
77
  .option('-q, --quiet', 'Suppress startup messages')
88
- .action(function (file, options) { return __awaiter(void 0, void 0, void 0, function () {
89
- var error_2;
90
- return __generator(this, function (_a) {
91
- switch (_a.label) {
92
- case 0:
93
- _a.trys.push([0, 2, , 3]);
94
- return [4 /*yield*/, devCommand(file, options)];
95
- case 1:
96
- _a.sent();
97
- return [3 /*break*/, 3];
98
- case 2:
99
- error_2 = _a.sent();
100
- console.error(error_2 instanceof Error ? error_2.message : error_2);
101
- process.exit(1);
102
- return [3 /*break*/, 3];
103
- case 3: return [2 /*return*/];
104
- }
105
- });
106
- }); });
78
+ .action(runCommand(async (file, options) => {
79
+ await devCommand(file, options);
80
+ }));
107
81
  // Generate command
82
+ addTypeGenerationOptions(program.command('generate'))
83
+ .action(runCommand(async (options) => {
84
+ await generateCommand(options);
85
+ }));
86
+ addTypeGenerationOptions(program.command('generate:types'))
87
+ .action(runCommand(async (options) => {
88
+ await generateCommand({ ...options, commandName: 'hypequery generate:types' });
89
+ }));
108
90
  program
109
- .command('generate')
110
- .description('Regenerate types from ClickHouse')
111
- .option('-o, --output <path>', 'Output file (default: analytics/schema.ts)')
91
+ .command('generate:datasets')
92
+ .description('Generate dataset definitions from ClickHouse schema')
93
+ .option('-o, --output <path>', 'Output file (default: src/datasets/generated.ts)')
94
+ .option('--path <path>', 'Analytics directory (derives <path>/datasets.ts)')
112
95
  .option('--tables <names>', 'Only generate for specific tables (comma-separated)')
113
- .option('--database <type>', 'Database driver to use (default: auto-detect)')
114
- .action(function (options) { return __awaiter(void 0, void 0, void 0, function () {
115
- var error_3;
116
- return __generator(this, function (_a) {
117
- switch (_a.label) {
118
- case 0:
119
- _a.trys.push([0, 2, , 3]);
120
- return [4 /*yield*/, generateCommand(options)];
121
- case 1:
122
- _a.sent();
123
- return [3 /*break*/, 3];
124
- case 2:
125
- error_3 = _a.sent();
126
- console.error(error_3 instanceof Error ? error_3.message : error_3);
127
- process.exit(1);
128
- return [3 /*break*/, 3];
129
- case 3: return [2 /*return*/];
130
- }
131
- });
132
- }); });
96
+ .option('--exclude-tables <names>', 'Exclude specific tables (comma-separated)')
97
+ .action(runCommand(async (options) => {
98
+ await generateDatasetsCommand(options);
99
+ }));
133
100
  // Help command
134
101
  program
135
102
  .command('help [command]')
136
103
  .description('Show help for command')
137
- .action(function (command) {
104
+ .action((command) => {
138
105
  if (command) {
139
- var cmd = program.commands.find(function (c) { return c.name() === command; });
106
+ const cmd = program.commands.find((c) => c.name() === command);
140
107
  if (cmd) {
141
108
  cmd.help();
142
109
  }
143
110
  else {
144
- console.error("Unknown command: ".concat(command));
111
+ console.error(`Unknown command: ${command}`);
145
112
  process.exit(1);
146
113
  }
147
114
  }
@@ -150,13 +117,15 @@ program
150
117
  }
151
118
  });
152
119
  // Custom help
153
- program.on('--help', function () {
120
+ program.on('--help', () => {
154
121
  console.log('');
155
122
  console.log('Examples:');
156
123
  console.log(' hypequery init');
157
124
  console.log(' hypequery dev');
158
125
  console.log(' hypequery dev --port 3000');
159
126
  console.log(' hypequery generate --output analytics/schema.ts');
127
+ console.log(' hypequery generate:types --output analytics/schema.ts');
128
+ console.log(' hypequery generate:datasets');
160
129
  console.log('');
161
130
  console.log('Docs: https://hypequery.com/docs');
162
131
  });
@@ -7,6 +7,7 @@ export interface DevOptions {
7
7
  redisUrl?: string;
8
8
  open?: boolean;
9
9
  cors?: boolean;
10
+ path?: string;
10
11
  }
11
12
  export declare function devCommand(file?: string, options?: DevOptions): Promise<void>;
12
13
  //# sourceMappingURL=dev.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AASA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,iBAqLvE"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AA8BA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,UAAe,iBAyLvE"}