Skip to content

Commit a4c6376

Browse files
committed
fix: QueryModeError in edge-mode SDK + query validation
- index.ts: tables()/append()/drop() throw QueryModeError instead of plain Error - index.ts: add getExecutor() for API symmetry with local.ts - query-schema: parseAndValidateQuery throws QueryModeError("INVALID_FILTER")
1 parent 2eb9bea commit a4c6376

File tree

2 files changed

+11
-4
lines changed

2 files changed

+11
-4
lines changed

src/index.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export {
2929
} from "./operators.js";
3030
export type { Operator, RowBatch, FragmentSource, PipelineOptions, PipelineResult } from "./operators.js";
3131
export { QueryModeError } from "./errors.js";
32+
import { QueryModeError } from "./errors.js";
3233
export type { ErrorCode } from "./errors.js";
3334
export { LocalExecutor } from "./local-executor.js";
3435
export { bigIntReplacer } from "./decode.js";
@@ -168,11 +169,16 @@ export class QueryMode {
168169
/** List all known tables with column names and row counts (edge mode only). */
169170
async tables(): Promise<{ name: string; columns: string[]; totalRows: number; updatedAt?: number; accessCount?: number }[]> {
170171
if (!(this.executor instanceof RemoteExecutor)) {
171-
throw new Error("tables() is only available in edge mode. Use .table(path).describe() for local files.");
172+
throw new QueryModeError("QUERY_FAILED", "tables() is only available in edge mode. Use .table(path).describe() for local files.");
172173
}
173174
const result = await (this.executor as RemoteExecutor).listTables();
174175
return result.tables as { name: string; columns: string[]; totalRows: number; updatedAt?: number; accessCount?: number }[];
175176
}
177+
178+
/** @internal Get the underlying executor (for pg-wire and similar integrations). */
179+
getExecutor(): QueryExecutor {
180+
return this.executor;
181+
}
176182
}
177183

178184
/**
@@ -212,7 +218,7 @@ class RemoteExecutor implements QueryExecutor {
212218
/** Append rows via RPC to Master DO. Partitioned writes fan out to separate MasterDOs. */
213219
async append(table: string, rows: Record<string, unknown>[], options?: AppendOptions): Promise<AppendResult> {
214220
if (!this.masterNamespace) {
215-
throw new Error("append() requires masterDoNamespace — pass it via QueryMode.remote(queryDO, { masterDO })");
221+
throw new QueryModeError("QUERY_FAILED", "append() requires masterDoNamespace — pass it via QueryMode.remote(queryDO, { masterDO })");
216222
}
217223

218224
// Partitioned writes: split by partition key, route each group to a different MasterDO
@@ -252,7 +258,7 @@ class RemoteExecutor implements QueryExecutor {
252258
/** Drop a table via RPC to Master DO — deletes all R2 objects and metadata. */
253259
async drop(table: string): Promise<DropResult> {
254260
if (!this.masterNamespace) {
255-
throw new Error("drop() requires masterDoNamespace — pass it via QueryMode.remote(queryDO, { masterDO })");
261+
throw new QueryModeError("QUERY_FAILED", "drop() requires masterDoNamespace — pass it via QueryMode.remote(queryDO, { masterDO })");
256262
}
257263
const id = this.masterNamespace.idFromName("master");
258264
const masterRpc = this.masterNamespace.get(id) as unknown as MasterDORpc;

src/query-schema.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* bad aggregate fns, etc. with clear error messages.
77
*/
88
import { z } from "zod/v4";
9+
import { QueryModeError } from "./errors.js";
910

1011
const filterOpSchema = z.object({
1112
column: z.string().min(1, "Filter column name cannot be empty"),
@@ -76,7 +77,7 @@ export function parseAndValidateQuery(body: unknown): {
7677
const issues = result.error.issues.map(i =>
7778
`${i.path.join(".")}: ${i.message}`
7879
).join("; ");
79-
throw new Error(`Invalid query: ${issues}`);
80+
throw new QueryModeError("INVALID_FILTER", `Invalid query: ${issues}`);
8081
}
8182

8283
const data = result.data;

0 commit comments

Comments
 (0)