@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 +1 -1
- package/dist/cli/codegen.js +47 -18
- package/dist/index.cjs +14 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.global.js +2 -2
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +14 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
package/dist/cli/codegen.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
129
|
-
for (const
|
|
130
|
-
|
|
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
|
|
137
|
-
const
|
|
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
|
|
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
|
-
|
|
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 ${
|
|
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
|
-
|
|
171
|
-
|
|
172
|
-
|
|
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/
|
|
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/
|
|
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/
|
|
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/
|
|
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/
|
|
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/
|
|
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/
|
|
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/
|
|
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/
|
|
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);
|