midql-cli 0.1.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.
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/export/csv.ts
4
+ function escapeField(value) {
5
+ if (value === null || value === void 0) {
6
+ return "";
7
+ }
8
+ const text = value instanceof Date ? value.toISOString() : typeof value === "object" ? JSON.stringify(value) : String(value);
9
+ if (/[",\r\n]/.test(text)) {
10
+ return `"${text.replace(/"/g, '""')}"`;
11
+ }
12
+ return text;
13
+ }
14
+ function toCsv(result) {
15
+ const lines = [result.columns.map(escapeField).join(",")];
16
+ for (const row of result.rows) {
17
+ lines.push(result.columns.map((column) => escapeField(row[column])).join(","));
18
+ }
19
+ return `${lines.join("\r\n")}\r
20
+ `;
21
+ }
22
+
23
+ export {
24
+ toCsv
25
+ };
package/dist/cli.js ADDED
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/cli.ts
4
+ import { createRequire } from "module";
5
+ import { Command } from "commander";
6
+ import pc from "picocolors";
7
+ var pkg = createRequire(import.meta.url)("../package.json");
8
+ async function startRepl(target) {
9
+ const [{ render }, { createElement }, { App }, { ReplController }] = await Promise.all([
10
+ import("ink"),
11
+ import("react"),
12
+ import("./App-W6AAY42M.js"),
13
+ import("./controller-HDNDKU6K.js")
14
+ ]);
15
+ const controller = new ReplController();
16
+ const instance = render(
17
+ createElement(App, { controller, version: pkg.version, initialTarget: target }),
18
+ { exitOnCtrlC: false }
19
+ );
20
+ await instance.waitUntilExit();
21
+ await controller.manager.closeAll();
22
+ }
23
+ function fail(error) {
24
+ console.error(pc.red(error.message ?? String(error)));
25
+ process.exit(1);
26
+ }
27
+ var program = new Command();
28
+ program.name("midql").description(
29
+ "Fast, safety-first PostgreSQL/MySQL CLI \u2014 schema-aware autocomplete, natural-language shortcuts, destructive-op previews"
30
+ ).version(pkg.version);
31
+ program.argument("[connection]", "profile name or connection URL to connect on startup").action(async (connection) => {
32
+ try {
33
+ await startRepl(connection ?? null);
34
+ } catch (error) {
35
+ fail(error);
36
+ }
37
+ });
38
+ program.command("query <input>").description("run a single query (plain English or raw SQL) and exit").requiredOption("--db <target>", "profile name or connection URL").option("--yes", "allow destructive statements", false).option("--format <format>", "output format: table, json, csv", "table").action(async (input, options) => {
39
+ try {
40
+ const { runQueryCommand } = await import("./query-RCUXCOAF.js");
41
+ const format = ["table", "json", "csv"].includes(options.format) ? options.format : "table";
42
+ process.exit(await runQueryCommand(input, { db: options.db, yes: options.yes, format }));
43
+ } catch (error) {
44
+ fail(error);
45
+ }
46
+ });
47
+ program.command("backup [file]").description("back up a database via pg_dump / mysqldump").requiredOption("--db <target>", "profile name or connection URL").option("--sql", "write a plain SQL dump instead of the custom format", false).action(async (file, options) => {
48
+ try {
49
+ const { runBackupCommand } = await import("./maintenance-QHIUTVV3.js");
50
+ process.exit(await runBackupCommand(file, options));
51
+ } catch (error) {
52
+ fail(error);
53
+ }
54
+ });
55
+ program.command("restore <file>").description("restore a database from a backup file").requiredOption("--db <target>", "profile name or connection URL").option("--yes", "confirm overwriting the target database", false).action(async (file, options) => {
56
+ try {
57
+ const { runRestoreCommand } = await import("./maintenance-QHIUTVV3.js");
58
+ process.exit(await runRestoreCommand(file, options));
59
+ } catch (error) {
60
+ fail(error);
61
+ }
62
+ });
63
+ var profiles = program.command("profiles").description("manage saved connection profiles");
64
+ profiles.command("list").description("list saved profiles").action(async () => {
65
+ try {
66
+ const { runProfilesList } = await import("./profiles-4QGMCJAO.js");
67
+ runProfilesList();
68
+ } catch (error) {
69
+ fail(error);
70
+ }
71
+ });
72
+ profiles.command("add <name>").description("save a connection profile").requiredOption("--dialect <dialect>", "postgres or mysql").requiredOption("--host <host>", "database host").requiredOption("--database <database>", "database name").requiredOption("--user <user>", "database user").option("--port <port>", "database port").option("--password <password>", "password to store encrypted").option("--password-env <name>", "environment variable to read the password from").option("--env <env>", "environment tag: dev, staging, prod", "dev").option("--readonly", "open this connection read-only by default", false).option("--ssl", "connect over SSL", false).action(async (name, options) => {
73
+ try {
74
+ const { runProfilesAdd } = await import("./profiles-4QGMCJAO.js");
75
+ process.exit(
76
+ runProfilesAdd(name, {
77
+ dialect: String(options.dialect),
78
+ host: String(options.host),
79
+ port: options.port ? String(options.port) : void 0,
80
+ database: String(options.database),
81
+ user: String(options.user),
82
+ password: options.password ? String(options.password) : void 0,
83
+ passwordEnv: options.passwordEnv ? String(options.passwordEnv) : void 0,
84
+ env: String(options.env),
85
+ readonly: options.readonly === true,
86
+ ssl: options.ssl === true
87
+ })
88
+ );
89
+ } catch (error) {
90
+ fail(error);
91
+ }
92
+ });
93
+ profiles.command("remove <name>").description("delete a saved profile").action(async (name) => {
94
+ try {
95
+ const { runProfilesRemove } = await import("./profiles-4QGMCJAO.js");
96
+ process.exit(runProfilesRemove(name));
97
+ } catch (error) {
98
+ fail(error);
99
+ }
100
+ });
101
+ program.parseAsync(process.argv);
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ ReplController,
4
+ block,
5
+ hasSqlShape,
6
+ startsWithSqlKeyword
7
+ } from "./chunk-WN6T44OZ.js";
8
+ import "./chunk-3CIK5I4M.js";
9
+ import "./chunk-7WNCISNV.js";
10
+ import "./chunk-3QAR6XBK.js";
11
+ import "./chunk-PXDMSYWH.js";
12
+ import "./chunk-VFC3HWTF.js";
13
+ export {
14
+ ReplController,
15
+ block,
16
+ hasSqlShape,
17
+ startsWithSqlKeyword
18
+ };
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ toCsv
4
+ } from "./chunk-XJAN6OQ7.js";
5
+ export {
6
+ toCsv
7
+ };
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ backupDatabase,
4
+ defaultBackupFile
5
+ } from "./chunk-BAAEZXFH.js";
6
+ import "./chunk-NCN3ZBOJ.js";
7
+ import "./chunk-VFC3HWTF.js";
8
+ export {
9
+ backupDatabase,
10
+ defaultBackupFile
11
+ };
@@ -0,0 +1,155 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ countSelect,
4
+ previewSelect
5
+ } from "./chunk-ATZPL4EX.js";
6
+ import {
7
+ buildQuery,
8
+ dialectFor
9
+ } from "./chunk-TLTYYFT5.js";
10
+ import {
11
+ astIsWrite,
12
+ block,
13
+ classifyAst
14
+ } from "./chunk-WN6T44OZ.js";
15
+ import "./chunk-3CIK5I4M.js";
16
+ import {
17
+ describeTable,
18
+ formatResultSet,
19
+ formatTableList
20
+ } from "./chunk-7WNCISNV.js";
21
+ import "./chunk-3QAR6XBK.js";
22
+ import "./chunk-PXDMSYWH.js";
23
+ import {
24
+ ParseError
25
+ } from "./chunk-VFC3HWTF.js";
26
+
27
+ // src/repl/execute.ts
28
+ async function executeAst(controller, connection, input, ast) {
29
+ if (ast.kind === "showTables") {
30
+ return { blocks: [block("table", formatTableList(connection.schema))] };
31
+ }
32
+ if (ast.kind === "describe") {
33
+ const table = connection.schema.tables.find((entry) => entry.name === ast.table);
34
+ if (!table) {
35
+ throw new ParseError(`Table "${ast.table}" not found`);
36
+ }
37
+ return { blocks: [block("table", describeTable(table))] };
38
+ }
39
+ const dialect = dialectFor(connection.dialect);
40
+ const built = buildQuery(ast, dialect);
41
+ if (connection.readonly && astIsWrite(ast)) {
42
+ return {
43
+ blocks: [
44
+ block("sql", `\u2192 ${built.sql}`),
45
+ block("error", "Connection is read-only; write statements are blocked."),
46
+ block("info", "Use \\readonly off to allow writes on this connection.")
47
+ ]
48
+ };
49
+ }
50
+ const danger = classifyAst(ast);
51
+ if (danger === "safe" || !controller.safetyEnforced(connection)) {
52
+ return { blocks: await runBuilt(controller, connection, input, built) };
53
+ }
54
+ if (ast.kind === "dropTable") {
55
+ return confirmDropTable(controller, connection, input, ast.table, built);
56
+ }
57
+ return confirmDestructive(
58
+ controller,
59
+ connection,
60
+ input,
61
+ ast,
62
+ built,
63
+ danger
64
+ );
65
+ }
66
+ async function runBuilt(controller, connection, input, built) {
67
+ let result;
68
+ try {
69
+ result = await connection.adapter.sessionQuery(built.sql, built.params);
70
+ } catch (error) {
71
+ controller.record(connection.alias, input, built.sql, null, false);
72
+ throw error;
73
+ }
74
+ controller.lastResult = result;
75
+ controller.lastSql = built.sql;
76
+ controller.lastParams = built.params;
77
+ controller.record(connection.alias, input, built.sql, result.rowCount, true);
78
+ if (ddlAffectsSchema(built.sql)) {
79
+ await controller.manager.refreshSchema(connection.alias).catch(() => connection);
80
+ }
81
+ return [block("sql", `\u2192 ${built.sql}`), block("table", formatResultSet(result))];
82
+ }
83
+ function ddlAffectsSchema(sql) {
84
+ return /^\s*(create|drop|alter|truncate)\b/i.test(sql);
85
+ }
86
+ function confirmDropTable(controller, connection, input, table, built) {
87
+ const meta = connection.schema.tables.find((entry) => entry.name === table);
88
+ const rowNote = meta ? ` (~${meta.approxRowCount} rows)` : "";
89
+ const prodBanner = connection.env === "prod" ? " (PRODUCTION)" : "";
90
+ controller.setPending({
91
+ prompt: `type '${table}' to confirm`,
92
+ expectedText: table,
93
+ execute: () => runBuilt(controller, connection, input, built)
94
+ });
95
+ return {
96
+ blocks: [
97
+ block("sql", `\u2192 ${built.sql}`),
98
+ block("error", `\u26A0${prodBanner} This will permanently DROP the table "${table}"${rowNote}.`),
99
+ block("warn", `Type '${table}' to confirm:`)
100
+ ]
101
+ };
102
+ }
103
+ async function confirmDestructive(controller, connection, input, ast, built, danger) {
104
+ const dialect = dialectFor(connection.dialect);
105
+ const countQuery = buildQuery(countSelect(ast), dialect);
106
+ const sampleQuery = buildQuery(previewSelect(ast), dialect);
107
+ const [countResult, sampleResult] = await Promise.all([
108
+ connection.adapter.query(countQuery.sql, countQuery.params),
109
+ connection.adapter.query(sampleQuery.sql, sampleQuery.params)
110
+ ]);
111
+ const total = Number(Object.values(countResult.rows[0] ?? {})[0] ?? 0);
112
+ const verb = ast.kind === "delete" ? "DELETE" : "UPDATE";
113
+ const prodBanner = connection.env === "prod" ? " (PRODUCTION)" : "";
114
+ if (total === 0) {
115
+ return {
116
+ blocks: [
117
+ block("sql", `\u2192 ${built.sql}`),
118
+ block("info", `No rows match \u2014 nothing to ${verb.toLowerCase()}.`)
119
+ ]
120
+ };
121
+ }
122
+ const blocks = [
123
+ block("sql", `\u2192 ${built.sql}`),
124
+ block(
125
+ "warn",
126
+ `\u26A0${prodBanner} This will ${verb} ${total.toLocaleString("en-US")} row${total === 1 ? "" : "s"} from "${ast.table}"${danger === "catastrophic" ? " (no WHERE clause \u2014 affects every row)" : ""}.`
127
+ )
128
+ ];
129
+ if (sampleResult.rows.length > 0) {
130
+ const label = total > sampleResult.rows.length ? `Sample of affected rows (${sampleResult.rows.length} of ${total}):` : "Affected rows:";
131
+ blocks.push(block("info", label));
132
+ blocks.push(
133
+ block("table", formatResultSet({ ...sampleResult, rowCount: sampleResult.rows.length }))
134
+ );
135
+ }
136
+ if (danger === "catastrophic") {
137
+ blocks.push(block("warn", `Type '${ast.table}' to confirm:`));
138
+ controller.setPending({
139
+ prompt: `type '${ast.table}' to confirm`,
140
+ expectedText: ast.table,
141
+ execute: () => runBuilt(controller, connection, input, built)
142
+ });
143
+ } else {
144
+ blocks.push(block("warn", "Proceed? [y/N]"));
145
+ controller.setPending({
146
+ prompt: "y/N",
147
+ expectedText: null,
148
+ execute: () => runBuilt(controller, connection, input, built)
149
+ });
150
+ }
151
+ return { blocks };
152
+ }
153
+ export {
154
+ executeAst
155
+ };
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/explain/humanize.ts
4
+ function describeNode(node, depth) {
5
+ const indent = " ".repeat(depth);
6
+ const rows = node["Plan Rows"] !== void 0 ? ` (~${node["Plan Rows"]} rows)` : "";
7
+ const lines = [];
8
+ switch (node["Node Type"]) {
9
+ case "Seq Scan":
10
+ lines.push(
11
+ `${indent}- reads the whole "${node["Relation Name"]}" table row by row${rows}${node.Filter ? `, keeping rows where ${node.Filter}` : ""}`
12
+ );
13
+ break;
14
+ case "Index Scan":
15
+ case "Index Only Scan":
16
+ lines.push(
17
+ `${indent}- uses the index "${node["Index Name"]}" on "${node["Relation Name"]}"${rows}${node["Index Cond"] ? ` matching ${node["Index Cond"]}` : ""}`
18
+ );
19
+ break;
20
+ case "Bitmap Heap Scan":
21
+ lines.push(`${indent}- fetches matching pages from "${node["Relation Name"]}"${rows}`);
22
+ break;
23
+ case "Nested Loop":
24
+ lines.push(`${indent}- joins by looping over one side for each row of the other${rows}`);
25
+ break;
26
+ case "Hash Join":
27
+ lines.push(
28
+ `${indent}- joins using an in-memory hash table${node["Hash Cond"] ? ` on ${node["Hash Cond"]}` : ""}${rows}`
29
+ );
30
+ break;
31
+ case "Merge Join":
32
+ lines.push(`${indent}- joins two pre-sorted inputs${rows}`);
33
+ break;
34
+ case "Sort":
35
+ lines.push(`${indent}- sorts the intermediate result${rows}`);
36
+ break;
37
+ case "Aggregate":
38
+ case "HashAggregate":
39
+ case "GroupAggregate":
40
+ lines.push(`${indent}- computes the aggregate${rows}`);
41
+ break;
42
+ case "Limit":
43
+ lines.push(`${indent}- stops early after the LIMIT is reached`);
44
+ break;
45
+ default:
46
+ lines.push(`${indent}- ${node["Node Type"]}${rows}`);
47
+ }
48
+ for (const child of node.Plans ?? []) {
49
+ lines.push(...describeNode(child, depth + 1));
50
+ }
51
+ return lines;
52
+ }
53
+ function humanizePostgresPlan(planJson) {
54
+ const root = Array.isArray(planJson) ? planJson[0] : planJson;
55
+ if (!root?.Plan) {
56
+ return ["Could not parse the plan."];
57
+ }
58
+ const lines = describeNode(root.Plan, 0);
59
+ const seqScans = collectSeqScans(root.Plan);
60
+ if (seqScans.length > 0) {
61
+ lines.push(
62
+ `\u26A0 full table scan on ${seqScans.map((name) => `"${name}"`).join(", ")} \u2014 an index could speed this up if the table is large.`
63
+ );
64
+ }
65
+ return lines;
66
+ }
67
+ function collectSeqScans(node) {
68
+ const names = [];
69
+ if (node["Node Type"] === "Seq Scan" && node["Relation Name"]) {
70
+ names.push(node["Relation Name"]);
71
+ }
72
+ for (const child of node.Plans ?? []) {
73
+ names.push(...collectSeqScans(child));
74
+ }
75
+ return names;
76
+ }
77
+ function humanizeMysqlExplain(rows) {
78
+ const lines = [];
79
+ for (const raw of rows) {
80
+ if (!raw.table) {
81
+ continue;
82
+ }
83
+ if (raw.type === "ALL") {
84
+ lines.push(
85
+ `- reads the whole "${raw.table}" table (~${raw.rows ?? "?"} rows) \u2014 no index used; an index could speed this up.`
86
+ );
87
+ } else if (raw.key) {
88
+ lines.push(`- uses the index "${raw.key}" on "${raw.table}" (~${raw.rows ?? "?"} rows)`);
89
+ } else {
90
+ lines.push(
91
+ `- accesses "${raw.table}" via ${raw.type ?? "unknown"} (~${raw.rows ?? "?"} rows)`
92
+ );
93
+ }
94
+ }
95
+ return lines.length > 0 ? lines : ["Could not parse the plan."];
96
+ }
97
+ export {
98
+ humanizeMysqlExplain,
99
+ humanizePostgresPlan
100
+ };
@@ -0,0 +1,185 @@
1
+ type DialectName = "postgres" | "mysql";
2
+ type ColumnKind = "text" | "number" | "boolean" | "date" | "json" | "uuid" | "other";
3
+ interface Column {
4
+ name: string;
5
+ dataType: string;
6
+ kind: ColumnKind;
7
+ nullable: boolean;
8
+ isPrimaryKey: boolean;
9
+ hasDefault: boolean;
10
+ }
11
+ interface ForeignKey {
12
+ columns: string[];
13
+ referencedTable: string;
14
+ referencedColumns: string[];
15
+ }
16
+ interface Table {
17
+ name: string;
18
+ columns: Column[];
19
+ primaryKey: string[];
20
+ foreignKeys: ForeignKey[];
21
+ approxRowCount: number;
22
+ }
23
+ interface Schema {
24
+ tables: Table[];
25
+ }
26
+ interface ColumnRef {
27
+ table: string;
28
+ column: string;
29
+ }
30
+ type ScalarValue = string | number | boolean | null;
31
+ type ComparisonOperator = "=" | "!=" | ">" | "<" | ">=" | "<=" | "like" | "ilike" | "in" | "between" | "isNull" | "isNotNull";
32
+ interface Condition {
33
+ type: "condition";
34
+ column: ColumnRef;
35
+ operator: ComparisonOperator;
36
+ values: ScalarValue[];
37
+ }
38
+ interface ConditionGroup {
39
+ type: "group";
40
+ combinator: "and" | "or";
41
+ items: ConditionNode[];
42
+ }
43
+ type ConditionNode = Condition | ConditionGroup;
44
+ interface Join {
45
+ table: string;
46
+ leftColumn: ColumnRef;
47
+ rightColumn: ColumnRef;
48
+ }
49
+ type AggregateFunction = "count" | "sum" | "avg" | "min" | "max";
50
+ interface Aggregate {
51
+ fn: AggregateFunction;
52
+ column: ColumnRef | null;
53
+ }
54
+ interface OrderBy {
55
+ column: ColumnRef;
56
+ direction: "asc" | "desc";
57
+ }
58
+ interface SelectNode {
59
+ kind: "select";
60
+ table: string;
61
+ columns: ColumnRef[] | "*";
62
+ aggregate: Aggregate | null;
63
+ joins: Join[];
64
+ where: ConditionNode | null;
65
+ orderBy: OrderBy[];
66
+ limit: number | null;
67
+ offset: number | null;
68
+ }
69
+ interface InsertNode {
70
+ kind: "insert";
71
+ table: string;
72
+ values: Record<string, ScalarValue>;
73
+ }
74
+ interface UpdateNode {
75
+ kind: "update";
76
+ table: string;
77
+ set: Record<string, ScalarValue>;
78
+ joins: Join[];
79
+ where: ConditionNode | null;
80
+ keyColumn: string | null;
81
+ }
82
+ interface DeleteNode {
83
+ kind: "delete";
84
+ table: string;
85
+ joins: Join[];
86
+ where: ConditionNode | null;
87
+ keyColumn: string | null;
88
+ }
89
+ type NlColumnType = "text" | "number" | "decimal" | "boolean" | "date" | "timestamp" | "json" | "uuid" | "serial";
90
+ interface ColumnDefinition {
91
+ name: string;
92
+ type: NlColumnType;
93
+ nullable: boolean;
94
+ references: {
95
+ table: string;
96
+ column: string;
97
+ } | null;
98
+ }
99
+ interface CreateTableNode {
100
+ kind: "createTable";
101
+ table: string;
102
+ columns: ColumnDefinition[];
103
+ }
104
+ interface DropTableNode {
105
+ kind: "dropTable";
106
+ table: string;
107
+ }
108
+ interface DescribeNode {
109
+ kind: "describe";
110
+ table: string;
111
+ }
112
+ interface ShowTablesNode {
113
+ kind: "showTables";
114
+ }
115
+ type QueryAst = SelectNode | InsertNode | UpdateNode | DeleteNode | CreateTableNode | DropTableNode;
116
+ type MetaAst = DescribeNode | ShowTablesNode;
117
+ type Ast = QueryAst | MetaAst;
118
+ interface BuiltQuery {
119
+ sql: string;
120
+ params: ScalarValue[];
121
+ }
122
+ interface ResultSet {
123
+ columns: string[];
124
+ rows: Record<string, unknown>[];
125
+ rowCount: number;
126
+ durationMs: number;
127
+ command: string;
128
+ }
129
+ interface AmbiguityCandidate {
130
+ value: string;
131
+ label: string;
132
+ detail: string;
133
+ }
134
+ interface Ambiguity {
135
+ token: string;
136
+ candidates: AmbiguityCandidate[];
137
+ }
138
+ type DangerLevel = "safe" | "destructive" | "catastrophic";
139
+ type EnvironmentTag = "dev" | "staging" | "prod";
140
+ interface ConnectionProfile {
141
+ name: string;
142
+ dialect: DialectName;
143
+ host: string;
144
+ port: number;
145
+ database: string;
146
+ user: string;
147
+ encryptedPassword: string | null;
148
+ passwordEnv: string | null;
149
+ env: EnvironmentTag;
150
+ readonly: boolean;
151
+ ssl: boolean;
152
+ }
153
+
154
+ declare class MidqlError extends Error {
155
+ constructor(message: string);
156
+ }
157
+ declare class ParseError extends MidqlError {
158
+ readonly position: number | null;
159
+ readonly suggestions: string[];
160
+ constructor(message: string, options?: {
161
+ position?: number;
162
+ suggestions?: string[];
163
+ });
164
+ }
165
+ declare class AmbiguityError extends MidqlError {
166
+ readonly token: string;
167
+ readonly candidates: AmbiguityCandidate[];
168
+ constructor(token: string, candidates: AmbiguityCandidate[]);
169
+ }
170
+ declare class ConnectionError extends MidqlError {
171
+ }
172
+ declare class ExecutionError extends MidqlError {
173
+ }
174
+ declare class ReadonlyViolationError extends MidqlError {
175
+ constructor();
176
+ }
177
+ declare class ToolNotFoundError extends MidqlError {
178
+ readonly tool: string;
179
+ readonly hint: string;
180
+ constructor(tool: string, hint: string);
181
+ }
182
+ declare class ConfigError extends MidqlError {
183
+ }
184
+
185
+ export { type Aggregate, type AggregateFunction, type Ambiguity, type AmbiguityCandidate, AmbiguityError, type Ast, type BuiltQuery, type Column, type ColumnDefinition, type ColumnKind, type ColumnRef, type ComparisonOperator, type Condition, type ConditionGroup, type ConditionNode, ConfigError, ConnectionError, type ConnectionProfile, type CreateTableNode, type DangerLevel, type DeleteNode, type DescribeNode, type DialectName, type DropTableNode, type EnvironmentTag, ExecutionError, type ForeignKey, type InsertNode, type Join, type MetaAst, MidqlError, type NlColumnType, type OrderBy, ParseError, type QueryAst, ReadonlyViolationError, type ResultSet, type ScalarValue, type Schema, type SelectNode, type ShowTablesNode, type Table, ToolNotFoundError, type UpdateNode };
package/dist/index.js ADDED
@@ -0,0 +1,55 @@
1
+ // src/core/errors.ts
2
+ var MidqlError = class extends Error {
3
+ constructor(message) {
4
+ super(message);
5
+ this.name = new.target.name;
6
+ }
7
+ };
8
+ var ParseError = class extends MidqlError {
9
+ position;
10
+ suggestions;
11
+ constructor(message, options) {
12
+ super(message);
13
+ this.position = options?.position ?? null;
14
+ this.suggestions = options?.suggestions ?? [];
15
+ }
16
+ };
17
+ var AmbiguityError = class extends MidqlError {
18
+ token;
19
+ candidates;
20
+ constructor(token, candidates) {
21
+ super(`"${token}" is ambiguous`);
22
+ this.token = token;
23
+ this.candidates = candidates;
24
+ }
25
+ };
26
+ var ConnectionError = class extends MidqlError {
27
+ };
28
+ var ExecutionError = class extends MidqlError {
29
+ };
30
+ var ReadonlyViolationError = class extends MidqlError {
31
+ constructor() {
32
+ super("Connection is read-only; write statements are blocked");
33
+ }
34
+ };
35
+ var ToolNotFoundError = class extends MidqlError {
36
+ tool;
37
+ hint;
38
+ constructor(tool, hint) {
39
+ super(`${tool} not found. ${hint}`);
40
+ this.tool = tool;
41
+ this.hint = hint;
42
+ }
43
+ };
44
+ var ConfigError = class extends MidqlError {
45
+ };
46
+ export {
47
+ AmbiguityError,
48
+ ConfigError,
49
+ ConnectionError,
50
+ ExecutionError,
51
+ MidqlError,
52
+ ParseError,
53
+ ReadonlyViolationError,
54
+ ToolNotFoundError
55
+ };
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ toJson
4
+ } from "./chunk-GWY47EDH.js";
5
+ export {
6
+ toJson
7
+ };