@wavehouse/sdk 0.0.0-dev.h04a85f20bb96 → 0.0.0-dev.h70dbf5d8f5ed

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/README.md CHANGED
@@ -150,7 +150,7 @@ Generate TypeScript types from your live WaveHouse schema. The package ships a `
150
150
  npx wavehouse-codegen --url http://localhost:8080 --out ./src/db.d.ts
151
151
  ```
152
152
 
153
- This introspects `/v1/schema`, maps ClickHouse column types to TypeScript, and outputs a `Database` interface you can pass to `createClient<Database>()`. `/v1/schema` is **admin-only** — pass an admin-role token with `--auth <jwt>` (or `-a`) against any non-dev policy.
153
+ This introspects `/v1/ops/schema`, maps ClickHouse column types to TypeScript, and outputs a `Database` interface you can pass to `createClient<Database>()`. `/v1/ops/schema` is **admin-only** — pass an admin-role token with `--auth <jwt>` (or `-a`) against any non-dev policy.
154
154
 
155
155
  ## Development & Testing
156
156
 
@@ -1,5 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ // src/cli/codegen.ts
4
+ import { realpathSync } from "fs";
5
+ import { pathToFileURL } from "url";
6
+
3
7
  // src/url.ts
4
8
  function resolveURL(base, path, params) {
5
9
  const root = new URL(base);
@@ -107,15 +111,29 @@ function findTopLevelComma(s) {
107
111
  }
108
112
  return -1;
109
113
  }
114
+ function isColumn(value) {
115
+ if (typeof value !== "object" || value === null) return false;
116
+ const col = value;
117
+ return typeof col.name === "string" && typeof col.type === "string";
118
+ }
119
+ function isTableSchema(value) {
120
+ if (typeof value !== "object" || value === null) return false;
121
+ const table = value;
122
+ return typeof table.name === "string" && Array.isArray(table.columns) && table.columns.every(isColumn);
123
+ }
110
124
  async function fetchSchemas(url, auth) {
111
125
  const headers = {};
112
126
  if (auth) headers.Authorization = `Bearer ${auth}`;
113
- const res = await fetch(resolveURL(url, "/v1/schema").toString(), { headers });
127
+ const res = await fetch(resolveURL(url, "/v1/ops/schema").toString(), { headers });
114
128
  if (!res.ok) {
115
129
  const text = await res.text();
116
130
  throw new Error(`Schema fetch failed (${res.status}): ${text}`);
117
131
  }
118
- return await res.json();
132
+ const body = await res.json();
133
+ if (!Array.isArray(body) || !body.every(isTableSchema)) {
134
+ throw new Error("Unexpected /v1/ops/schema response: expected a JSON array of table schemas");
135
+ }
136
+ return body;
119
137
  }
120
138
  function generateTypes(schemas) {
121
139
  const lines = [
@@ -125,19 +143,16 @@ function generateTypes(schemas) {
125
143
  "",
126
144
  "export interface Database {"
127
145
  ];
128
- const tableNames = Object.keys(schemas).sort();
129
- for (const tableName of tableNames) {
130
- const _schema = schemas[tableName];
131
- const rowType = `${pascalCase(tableName)}Row`;
132
- lines.push(` ${tableName}: ${rowType};`);
146
+ const tables = [...schemas].sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0);
147
+ for (const table of tables) {
148
+ lines.push(` ${table.name}: ${pascalCase(table.name)}Row;`);
133
149
  }
134
150
  lines.push("}");
135
151
  lines.push("");
136
- for (const tableName of tableNames) {
137
- const schema = schemas[tableName];
138
- const rowType = `${pascalCase(tableName)}Row`;
152
+ for (const table of tables) {
153
+ const rowType = `${pascalCase(table.name)}Row`;
139
154
  lines.push(`export interface ${rowType} {`);
140
- for (const col of schema.columns) {
155
+ for (const col of table.columns) {
141
156
  const tsType = chTypeToTS(col.type);
142
157
  const optional = col.has_default ? "?" : "";
143
158
  lines.push(` ${col.name}${optional}: ${tsType};`);
@@ -154,12 +169,11 @@ async function main() {
154
169
  const args = parseArgs(process.argv);
155
170
  console.log(`Fetching schema from ${args.url}...`);
156
171
  const schemas = await fetchSchemas(args.url, args.auth);
157
- const tableCount = Object.keys(schemas).length;
158
- if (tableCount === 0) {
172
+ if (schemas.length === 0) {
159
173
  console.warn("No tables found. Is WaveHouse running with tables in ClickHouse?");
160
174
  process.exit(1);
161
175
  }
162
- console.log(`Found ${tableCount} table(s): ${Object.keys(schemas).join(", ")}`);
176
+ console.log(`Found ${schemas.length} table(s): ${schemas.map((t) => t.name).join(", ")}`);
163
177
  const output = generateTypes(schemas);
164
178
  const { writeFile } = await import("fs/promises");
165
179
  const { resolve } = await import("path");
@@ -167,7 +181,22 @@ async function main() {
167
181
  await writeFile(outPath, output, "utf-8");
168
182
  console.log(`\u2713 Types written to ${outPath}`);
169
183
  }
170
- main().catch((err) => {
171
- console.error("Codegen failed:", err.message);
172
- process.exit(1);
173
- });
184
+ function isDirectInvocation() {
185
+ if (!process.argv[1]) return false;
186
+ try {
187
+ return import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href;
188
+ } catch {
189
+ return false;
190
+ }
191
+ }
192
+ if (isDirectInvocation()) {
193
+ main().catch((err) => {
194
+ console.error("Codegen failed:", err.message);
195
+ process.exit(1);
196
+ });
197
+ }
198
+ export {
199
+ chTypeToTS,
200
+ fetchSchemas,
201
+ generateTypes
202
+ };
package/dist/index.cjs CHANGED
@@ -200,7 +200,7 @@ var DLQNamespace = class {
200
200
  async list(opts) {
201
201
  const { data, error } = await request(this._ctx, {
202
202
  method: "GET",
203
- path: "/v1/dlq/stats",
203
+ path: "/v1/ops/dlq/stats",
204
204
  signal: opts?.signal
205
205
  });
206
206
  if (error) return err(error);
@@ -210,7 +210,7 @@ var DLQNamespace = class {
210
210
  async table(name, opts) {
211
211
  const { data, error } = await request(this._ctx, {
212
212
  method: "GET",
213
- path: "/v1/dlq/stats",
213
+ path: "/v1/ops/dlq/stats",
214
214
  params: { table: name },
215
215
  signal: opts?.signal
216
216
  });
@@ -270,7 +270,7 @@ var PipesNamespace = class {
270
270
  async list(opts) {
271
271
  const { data, error } = await request(this._ctx, {
272
272
  method: "GET",
273
- path: "/v1/admin/pipes",
273
+ path: "/v1/ops/pipes",
274
274
  signal: opts?.signal
275
275
  });
276
276
  if (error) return err(error);
@@ -280,7 +280,7 @@ var PipesNamespace = class {
280
280
  async get(name, opts) {
281
281
  const { data, error } = await request(this._ctx, {
282
282
  method: "GET",
283
- path: `/v1/admin/pipes/${encodeURIComponent(name)}`,
283
+ path: `/v1/ops/pipes/${encodeURIComponent(name)}`,
284
284
  signal: opts?.signal
285
285
  });
286
286
  if (error) return err(error);
@@ -290,7 +290,7 @@ var PipesNamespace = class {
290
290
  async set(name, def, opts) {
291
291
  const { error } = await request(this._ctx, {
292
292
  method: "PUT",
293
- path: `/v1/admin/pipes/${encodeURIComponent(name)}`,
293
+ path: `/v1/ops/pipes/${encodeURIComponent(name)}`,
294
294
  body: def,
295
295
  signal: opts?.signal
296
296
  });
@@ -301,7 +301,7 @@ var PipesNamespace = class {
301
301
  async delete(name, opts) {
302
302
  const { error } = await request(this._ctx, {
303
303
  method: "DELETE",
304
- path: `/v1/admin/pipes/${encodeURIComponent(name)}`,
304
+ path: `/v1/ops/pipes/${encodeURIComponent(name)}`,
305
305
  signal: opts?.signal
306
306
  });
307
307
  if (error) return err(error);
@@ -319,7 +319,7 @@ var PolicyNamespace = class {
319
319
  async get(opts) {
320
320
  const { data, error } = await request(this._ctx, {
321
321
  method: "GET",
322
- path: "/v1/admin/policy",
322
+ path: "/v1/ops/policy",
323
323
  signal: opts?.signal
324
324
  });
325
325
  if (error) return err(error);
@@ -329,7 +329,7 @@ var PolicyNamespace = class {
329
329
  async set(policy, opts) {
330
330
  const { error } = await request(this._ctx, {
331
331
  method: "PUT",
332
- path: "/v1/admin/policy",
332
+ path: "/v1/ops/policy",
333
333
  body: policy,
334
334
  signal: opts?.signal
335
335
  });
@@ -340,7 +340,7 @@ var PolicyNamespace = class {
340
340
  async validate(policy, opts) {
341
341
  const { data, error } = await request(this._ctx, {
342
342
  method: "POST",
343
- path: "/v1/admin/policy/validate",
343
+ path: "/v1/ops/policy/validate",
344
344
  body: policy,
345
345
  signal: opts?.signal
346
346
  });
@@ -359,7 +359,7 @@ var SchemaNamespace = class {
359
359
  async list(opts) {
360
360
  const { data, error } = await request(this._ctx, {
361
361
  method: "GET",
362
- path: "/v1/schema",
362
+ path: "/v1/ops/schema",
363
363
  signal: opts?.signal
364
364
  });
365
365
  if (error) return err(error);
@@ -380,7 +380,7 @@ var SchemaNamespace = class {
380
380
  async refresh(opts) {
381
381
  const { error } = await request(this._ctx, {
382
382
  method: "POST",
383
- path: "/v1/schema/refresh",
383
+ path: "/v1/ops/schema/refresh",
384
384
  signal: opts?.signal
385
385
  });
386
386
  if (error) return err(error);
@@ -392,7 +392,7 @@ var SchemaNamespace = class {
392
392
  async function sql(ctx, query, opts) {
393
393
  const { data, error } = await request(ctx, {
394
394
  method: "POST",
395
- path: "/v1/admin/query",
395
+ path: "/v1/ops/query",
396
396
  body: { sql: query },
397
397
  signal: opts?.signal
398
398
  });
@@ -1104,7 +1104,7 @@ var TableRef = class {
1104
1104
  async schema(opts) {
1105
1105
  const { data, error } = await request(this._ctx, {
1106
1106
  method: "GET",
1107
- path: `/v1/schema?table=${encodeURIComponent(this._table)}`,
1107
+ path: `/v1/ops/schema?table=${encodeURIComponent(this._table)}`,
1108
1108
  signal: opts?.signal
1109
1109
  });
1110
1110
  if (error) return err(error);
@@ -1170,7 +1170,7 @@ var WaveHouseClient = class {
1170
1170
  sql(query, opts) {
1171
1171
  if (Array.isArray(opts)) {
1172
1172
  throw new Error(
1173
- "[WaveHouse SDK] client.sql(sql, params) was removed. The /v1/admin/query endpoint does not accept positional `?` params. Inline literals into the SQL, or use the structured query builder (wh.from(table)\u2026) for safe binding from user input."
1173
+ "[WaveHouse SDK] client.sql(sql, params) was removed. The /v1/ops/query endpoint does not accept positional `?` params. Inline literals into the SQL, or use the structured query builder (wh.from(table)\u2026) for safe binding from user input."
1174
1174
  );
1175
1175
  }
1176
1176
  return sql(this._ctx, query, opts);