stitchdb 1.1.0 → 1.3.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.
- package/dist/index.d.mts +11 -12
- package/dist/index.d.ts +11 -12
- package/dist/index.js +45 -53
- package/dist/index.mjs +45 -53
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -32,6 +32,12 @@ declare class StitchDBError extends Error {
|
|
|
32
32
|
status: number;
|
|
33
33
|
constructor(message: string, status?: number);
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* StitchDB client.
|
|
37
|
+
*
|
|
38
|
+
* Uses WebSocket for queries (1 connection, unlimited queries, $0.019/M cost).
|
|
39
|
+
* Falls back to HTTP if WebSocket unavailable.
|
|
40
|
+
*/
|
|
35
41
|
declare class StitchDB {
|
|
36
42
|
private url;
|
|
37
43
|
private wsUrl;
|
|
@@ -40,38 +46,31 @@ declare class StitchDB {
|
|
|
40
46
|
private pending;
|
|
41
47
|
private msgId;
|
|
42
48
|
private connecting;
|
|
43
|
-
private
|
|
49
|
+
private wsSupported;
|
|
50
|
+
private wsFailed;
|
|
44
51
|
constructor(config: StitchDBConfig);
|
|
45
52
|
private connect;
|
|
46
53
|
private wsSend;
|
|
47
|
-
private
|
|
48
|
-
|
|
54
|
+
private httpPost;
|
|
55
|
+
private send;
|
|
49
56
|
query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<QueryResult<T>>;
|
|
50
|
-
/** Run multiple queries atomically in a single batch. */
|
|
51
57
|
batch(queries: {
|
|
52
58
|
sql: string;
|
|
53
59
|
params?: unknown[];
|
|
54
60
|
}[]): Promise<BatchResult>;
|
|
55
|
-
/** Run a DDL statement (CREATE TABLE, ALTER TABLE, DROP TABLE, etc.) */
|
|
56
61
|
run(sql: string): Promise<ExecResult>;
|
|
57
|
-
/** Insert a row. */
|
|
58
62
|
insert(table: string, data: Record<string, unknown>): Promise<QueryResult>;
|
|
59
|
-
|
|
63
|
+
insertMany(table: string, rows: Record<string, unknown>[]): Promise<BatchResult>;
|
|
60
64
|
update(table: string, data: Record<string, unknown>, where: string, whereParams?: unknown[]): Promise<QueryResult>;
|
|
61
|
-
/** Delete rows matching a WHERE clause. */
|
|
62
65
|
remove(table: string, where: string, whereParams?: unknown[]): Promise<QueryResult>;
|
|
63
|
-
/** Find one row by ID. */
|
|
64
66
|
find<T = Record<string, unknown>>(table: string, id: unknown, idColumn?: string): Promise<T | null>;
|
|
65
|
-
/** Select rows with optional WHERE, ORDER BY, LIMIT, OFFSET. */
|
|
66
67
|
select<T = Record<string, unknown>>(table: string, where?: string, params?: unknown[], opts?: {
|
|
67
68
|
orderBy?: string;
|
|
68
69
|
limit?: number;
|
|
69
70
|
offset?: number;
|
|
70
71
|
}): Promise<T[]>;
|
|
71
|
-
/** Close the WebSocket connection. */
|
|
72
72
|
close(): void;
|
|
73
73
|
}
|
|
74
|
-
/** Create a StitchDB client. */
|
|
75
74
|
declare function createClient(config: StitchDBConfig): StitchDB;
|
|
76
75
|
|
|
77
76
|
export { type BatchResult, type ExecResult, type QueryResult, StitchDB, type StitchDBConfig, StitchDBError, createClient, StitchDB as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,12 @@ declare class StitchDBError extends Error {
|
|
|
32
32
|
status: number;
|
|
33
33
|
constructor(message: string, status?: number);
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* StitchDB client.
|
|
37
|
+
*
|
|
38
|
+
* Uses WebSocket for queries (1 connection, unlimited queries, $0.019/M cost).
|
|
39
|
+
* Falls back to HTTP if WebSocket unavailable.
|
|
40
|
+
*/
|
|
35
41
|
declare class StitchDB {
|
|
36
42
|
private url;
|
|
37
43
|
private wsUrl;
|
|
@@ -40,38 +46,31 @@ declare class StitchDB {
|
|
|
40
46
|
private pending;
|
|
41
47
|
private msgId;
|
|
42
48
|
private connecting;
|
|
43
|
-
private
|
|
49
|
+
private wsSupported;
|
|
50
|
+
private wsFailed;
|
|
44
51
|
constructor(config: StitchDBConfig);
|
|
45
52
|
private connect;
|
|
46
53
|
private wsSend;
|
|
47
|
-
private
|
|
48
|
-
|
|
54
|
+
private httpPost;
|
|
55
|
+
private send;
|
|
49
56
|
query<T = Record<string, unknown>>(sql: string, params?: unknown[]): Promise<QueryResult<T>>;
|
|
50
|
-
/** Run multiple queries atomically in a single batch. */
|
|
51
57
|
batch(queries: {
|
|
52
58
|
sql: string;
|
|
53
59
|
params?: unknown[];
|
|
54
60
|
}[]): Promise<BatchResult>;
|
|
55
|
-
/** Run a DDL statement (CREATE TABLE, ALTER TABLE, DROP TABLE, etc.) */
|
|
56
61
|
run(sql: string): Promise<ExecResult>;
|
|
57
|
-
/** Insert a row. */
|
|
58
62
|
insert(table: string, data: Record<string, unknown>): Promise<QueryResult>;
|
|
59
|
-
|
|
63
|
+
insertMany(table: string, rows: Record<string, unknown>[]): Promise<BatchResult>;
|
|
60
64
|
update(table: string, data: Record<string, unknown>, where: string, whereParams?: unknown[]): Promise<QueryResult>;
|
|
61
|
-
/** Delete rows matching a WHERE clause. */
|
|
62
65
|
remove(table: string, where: string, whereParams?: unknown[]): Promise<QueryResult>;
|
|
63
|
-
/** Find one row by ID. */
|
|
64
66
|
find<T = Record<string, unknown>>(table: string, id: unknown, idColumn?: string): Promise<T | null>;
|
|
65
|
-
/** Select rows with optional WHERE, ORDER BY, LIMIT, OFFSET. */
|
|
66
67
|
select<T = Record<string, unknown>>(table: string, where?: string, params?: unknown[], opts?: {
|
|
67
68
|
orderBy?: string;
|
|
68
69
|
limit?: number;
|
|
69
70
|
offset?: number;
|
|
70
71
|
}): Promise<T[]>;
|
|
71
|
-
/** Close the WebSocket connection. */
|
|
72
72
|
close(): void;
|
|
73
73
|
}
|
|
74
|
-
/** Create a StitchDB client. */
|
|
75
74
|
declare function createClient(config: StitchDBConfig): StitchDB;
|
|
76
75
|
|
|
77
76
|
export { type BatchResult, type ExecResult, type QueryResult, StitchDB, type StitchDBConfig, StitchDBError, createClient, StitchDB as default };
|
package/dist/index.js
CHANGED
|
@@ -39,11 +39,13 @@ var StitchDB = class {
|
|
|
39
39
|
this.pending = /* @__PURE__ */ new Map();
|
|
40
40
|
this.msgId = 0;
|
|
41
41
|
this.connecting = null;
|
|
42
|
+
this.wsFailed = false;
|
|
42
43
|
this.url = (config.url || "https://db.stitchdb.com").replace(/\/$/, "");
|
|
43
44
|
this.wsUrl = this.url.replace("https://", "wss://").replace("http://", "ws://");
|
|
44
45
|
this.apiKey = config.apiKey;
|
|
45
|
-
this.
|
|
46
|
+
this.wsSupported = typeof WebSocket !== "undefined";
|
|
46
47
|
}
|
|
48
|
+
// ---- WebSocket ----
|
|
47
49
|
async connect() {
|
|
48
50
|
if (this.ws?.readyState === 1) return;
|
|
49
51
|
if (this.connecting) return this.connecting;
|
|
@@ -55,17 +57,13 @@ var StitchDB = class {
|
|
|
55
57
|
this.connecting = null;
|
|
56
58
|
resolve();
|
|
57
59
|
};
|
|
58
|
-
ws.onmessage = (
|
|
60
|
+
ws.onmessage = (e) => {
|
|
59
61
|
try {
|
|
60
|
-
const data = JSON.parse(typeof
|
|
61
|
-
const
|
|
62
|
-
if (
|
|
62
|
+
const data = JSON.parse(typeof e.data === "string" ? e.data : "");
|
|
63
|
+
const p = this.pending.get(data.id);
|
|
64
|
+
if (p) {
|
|
63
65
|
this.pending.delete(data.id);
|
|
64
|
-
|
|
65
|
-
pending.reject(new StitchDBError(data.error));
|
|
66
|
-
} else {
|
|
67
|
-
pending.resolve(data);
|
|
68
|
-
}
|
|
66
|
+
data.error ? p.reject(new StitchDBError(data.error)) : p.resolve(data);
|
|
69
67
|
}
|
|
70
68
|
} catch {
|
|
71
69
|
}
|
|
@@ -73,29 +71,29 @@ var StitchDB = class {
|
|
|
73
71
|
ws.onclose = () => {
|
|
74
72
|
this.ws = null;
|
|
75
73
|
this.connecting = null;
|
|
76
|
-
for (const [
|
|
77
|
-
|
|
78
|
-
this.pending.delete(id);
|
|
79
|
-
}
|
|
74
|
+
for (const [, p] of this.pending) p.reject(new StitchDBError("Connection closed"));
|
|
75
|
+
this.pending.clear();
|
|
80
76
|
};
|
|
81
77
|
ws.onerror = () => {
|
|
82
78
|
this.ws = null;
|
|
83
79
|
this.connecting = null;
|
|
84
|
-
|
|
80
|
+
this.wsFailed = true;
|
|
81
|
+
resolve();
|
|
85
82
|
};
|
|
86
83
|
} catch {
|
|
87
84
|
this.connecting = null;
|
|
88
|
-
this.
|
|
85
|
+
this.wsFailed = true;
|
|
89
86
|
resolve();
|
|
90
87
|
}
|
|
91
88
|
});
|
|
92
89
|
return this.connecting;
|
|
93
90
|
}
|
|
94
91
|
async wsSend(msg) {
|
|
92
|
+
if (this.wsFailed) return this.httpPost(msg);
|
|
95
93
|
await this.connect();
|
|
96
94
|
if (!this.ws || this.ws.readyState !== 1) {
|
|
97
|
-
this.
|
|
98
|
-
return this.
|
|
95
|
+
this.wsFailed = true;
|
|
96
|
+
return this.httpPost(msg);
|
|
99
97
|
}
|
|
100
98
|
const id = String(++this.msgId);
|
|
101
99
|
msg.id = id;
|
|
@@ -114,12 +112,19 @@ var StitchDB = class {
|
|
|
114
112
|
reject(e);
|
|
115
113
|
}
|
|
116
114
|
});
|
|
117
|
-
|
|
115
|
+
try {
|
|
116
|
+
this.ws.send(JSON.stringify(msg));
|
|
117
|
+
} catch {
|
|
118
|
+
clearTimeout(timeout);
|
|
119
|
+
this.pending.delete(id);
|
|
120
|
+
this.wsFailed = true;
|
|
121
|
+
this.httpPost(msg).then(resolve, reject);
|
|
122
|
+
}
|
|
118
123
|
});
|
|
119
124
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
let body = { sql: msg.sql, params: msg.params };
|
|
125
|
+
// ---- HTTP fallback ----
|
|
126
|
+
async httpPost(msg) {
|
|
127
|
+
let path = "/v1/query", body = { sql: msg.sql, params: msg.params };
|
|
123
128
|
if (msg.action === "batch") {
|
|
124
129
|
path = "/v1/batch";
|
|
125
130
|
body = { queries: msg.queries };
|
|
@@ -129,60 +134,48 @@ var StitchDB = class {
|
|
|
129
134
|
}
|
|
130
135
|
const res = await fetch(`${this.url}${path}`, {
|
|
131
136
|
method: "POST",
|
|
132
|
-
headers: {
|
|
133
|
-
"Authorization": `Bearer ${this.apiKey}`,
|
|
134
|
-
"Content-Type": "application/json"
|
|
135
|
-
},
|
|
137
|
+
headers: { "Authorization": `Bearer ${this.apiKey}`, "Content-Type": "application/json" },
|
|
136
138
|
body: JSON.stringify(body)
|
|
137
139
|
});
|
|
138
140
|
const data = await res.json();
|
|
139
|
-
if (!res.ok || data.error) {
|
|
140
|
-
throw new StitchDBError(data.error || `Request failed: ${res.status}`, res.status);
|
|
141
|
-
}
|
|
141
|
+
if (!res.ok || data.error) throw new StitchDBError(data.error || `HTTP ${res.status}`, res.status);
|
|
142
142
|
return data;
|
|
143
143
|
}
|
|
144
|
-
|
|
144
|
+
// ---- Public API ----
|
|
145
|
+
async send(action, data) {
|
|
146
|
+
const msg = { action, ...data };
|
|
147
|
+
if (this.wsSupported && !this.wsFailed) return this.wsSend(msg);
|
|
148
|
+
return this.httpPost(msg);
|
|
149
|
+
}
|
|
145
150
|
async query(sql, params) {
|
|
146
|
-
|
|
147
|
-
return this.wsSend({ action: "query", sql, params });
|
|
148
|
-
}
|
|
149
|
-
return this.httpQuery({ action: "query", sql, params });
|
|
151
|
+
return this.send("query", { sql, params });
|
|
150
152
|
}
|
|
151
|
-
/** Run multiple queries atomically in a single batch. */
|
|
152
153
|
async batch(queries) {
|
|
153
|
-
|
|
154
|
-
return this.wsSend({ action: "batch", queries });
|
|
155
|
-
}
|
|
156
|
-
return this.httpQuery({ action: "batch", queries });
|
|
154
|
+
return this.send("batch", { queries });
|
|
157
155
|
}
|
|
158
|
-
/** Run a DDL statement (CREATE TABLE, ALTER TABLE, DROP TABLE, etc.) */
|
|
159
156
|
async run(sql) {
|
|
160
|
-
|
|
161
|
-
return this.wsSend({ action: "exec", sql });
|
|
162
|
-
}
|
|
163
|
-
return this.httpQuery({ action: "exec", sql });
|
|
157
|
+
return this.send("exec", { sql });
|
|
164
158
|
}
|
|
165
|
-
/** Insert a row. */
|
|
166
159
|
async insert(table, data) {
|
|
167
160
|
const cols = Object.keys(data);
|
|
161
|
+
return this.query(`INSERT INTO "${table}" (${cols.map((c) => `"${c}"`).join(", ")}) VALUES (${cols.map(() => "?").join(", ")})`, Object.values(data));
|
|
162
|
+
}
|
|
163
|
+
async insertMany(table, rows) {
|
|
164
|
+
if (!rows.length) return { results: [], meta: { rows_read: 0, rows_written: 0, duration_ms: 0, queries_count: 0 } };
|
|
165
|
+
const cols = Object.keys(rows[0]);
|
|
168
166
|
const sql = `INSERT INTO "${table}" (${cols.map((c) => `"${c}"`).join(", ")}) VALUES (${cols.map(() => "?").join(", ")})`;
|
|
169
|
-
return this.
|
|
167
|
+
return this.batch(rows.map((row) => ({ sql, params: cols.map((c) => row[c]) })));
|
|
170
168
|
}
|
|
171
|
-
/** Update rows matching a WHERE clause. */
|
|
172
169
|
async update(table, data, where, whereParams) {
|
|
173
|
-
|
|
174
|
-
return this.query(`UPDATE "${table}" SET ${set} WHERE ${where}`, [...Object.values(data), ...whereParams || []]);
|
|
170
|
+
return this.query(`UPDATE "${table}" SET ${Object.keys(data).map((c) => `"${c}" = ?`).join(", ")} WHERE ${where}`, [...Object.values(data), ...whereParams || []]);
|
|
175
171
|
}
|
|
176
|
-
/** Delete rows matching a WHERE clause. */
|
|
177
172
|
async remove(table, where, whereParams) {
|
|
178
173
|
return this.query(`DELETE FROM "${table}" WHERE ${where}`, whereParams);
|
|
179
174
|
}
|
|
180
|
-
/** Find one row by ID. */
|
|
181
175
|
async find(table, id, idColumn = "id") {
|
|
182
176
|
const { results } = await this.query(`SELECT * FROM "${table}" WHERE "${idColumn}" = ? LIMIT 1`, [id]);
|
|
183
177
|
return results[0] || null;
|
|
184
178
|
}
|
|
185
|
-
/** Select rows with optional WHERE, ORDER BY, LIMIT, OFFSET. */
|
|
186
179
|
async select(table, where, params, opts) {
|
|
187
180
|
let sql = `SELECT * FROM "${table}"`;
|
|
188
181
|
if (where) sql += ` WHERE ${where}`;
|
|
@@ -192,7 +185,6 @@ var StitchDB = class {
|
|
|
192
185
|
const { results } = await this.query(sql, params);
|
|
193
186
|
return results;
|
|
194
187
|
}
|
|
195
|
-
/** Close the WebSocket connection. */
|
|
196
188
|
close() {
|
|
197
189
|
if (this.ws) {
|
|
198
190
|
this.ws.close();
|
package/dist/index.mjs
CHANGED
|
@@ -12,11 +12,13 @@ var StitchDB = class {
|
|
|
12
12
|
this.pending = /* @__PURE__ */ new Map();
|
|
13
13
|
this.msgId = 0;
|
|
14
14
|
this.connecting = null;
|
|
15
|
+
this.wsFailed = false;
|
|
15
16
|
this.url = (config.url || "https://db.stitchdb.com").replace(/\/$/, "");
|
|
16
17
|
this.wsUrl = this.url.replace("https://", "wss://").replace("http://", "ws://");
|
|
17
18
|
this.apiKey = config.apiKey;
|
|
18
|
-
this.
|
|
19
|
+
this.wsSupported = typeof WebSocket !== "undefined";
|
|
19
20
|
}
|
|
21
|
+
// ---- WebSocket ----
|
|
20
22
|
async connect() {
|
|
21
23
|
if (this.ws?.readyState === 1) return;
|
|
22
24
|
if (this.connecting) return this.connecting;
|
|
@@ -28,17 +30,13 @@ var StitchDB = class {
|
|
|
28
30
|
this.connecting = null;
|
|
29
31
|
resolve();
|
|
30
32
|
};
|
|
31
|
-
ws.onmessage = (
|
|
33
|
+
ws.onmessage = (e) => {
|
|
32
34
|
try {
|
|
33
|
-
const data = JSON.parse(typeof
|
|
34
|
-
const
|
|
35
|
-
if (
|
|
35
|
+
const data = JSON.parse(typeof e.data === "string" ? e.data : "");
|
|
36
|
+
const p = this.pending.get(data.id);
|
|
37
|
+
if (p) {
|
|
36
38
|
this.pending.delete(data.id);
|
|
37
|
-
|
|
38
|
-
pending.reject(new StitchDBError(data.error));
|
|
39
|
-
} else {
|
|
40
|
-
pending.resolve(data);
|
|
41
|
-
}
|
|
39
|
+
data.error ? p.reject(new StitchDBError(data.error)) : p.resolve(data);
|
|
42
40
|
}
|
|
43
41
|
} catch {
|
|
44
42
|
}
|
|
@@ -46,29 +44,29 @@ var StitchDB = class {
|
|
|
46
44
|
ws.onclose = () => {
|
|
47
45
|
this.ws = null;
|
|
48
46
|
this.connecting = null;
|
|
49
|
-
for (const [
|
|
50
|
-
|
|
51
|
-
this.pending.delete(id);
|
|
52
|
-
}
|
|
47
|
+
for (const [, p] of this.pending) p.reject(new StitchDBError("Connection closed"));
|
|
48
|
+
this.pending.clear();
|
|
53
49
|
};
|
|
54
50
|
ws.onerror = () => {
|
|
55
51
|
this.ws = null;
|
|
56
52
|
this.connecting = null;
|
|
57
|
-
|
|
53
|
+
this.wsFailed = true;
|
|
54
|
+
resolve();
|
|
58
55
|
};
|
|
59
56
|
} catch {
|
|
60
57
|
this.connecting = null;
|
|
61
|
-
this.
|
|
58
|
+
this.wsFailed = true;
|
|
62
59
|
resolve();
|
|
63
60
|
}
|
|
64
61
|
});
|
|
65
62
|
return this.connecting;
|
|
66
63
|
}
|
|
67
64
|
async wsSend(msg) {
|
|
65
|
+
if (this.wsFailed) return this.httpPost(msg);
|
|
68
66
|
await this.connect();
|
|
69
67
|
if (!this.ws || this.ws.readyState !== 1) {
|
|
70
|
-
this.
|
|
71
|
-
return this.
|
|
68
|
+
this.wsFailed = true;
|
|
69
|
+
return this.httpPost(msg);
|
|
72
70
|
}
|
|
73
71
|
const id = String(++this.msgId);
|
|
74
72
|
msg.id = id;
|
|
@@ -87,12 +85,19 @@ var StitchDB = class {
|
|
|
87
85
|
reject(e);
|
|
88
86
|
}
|
|
89
87
|
});
|
|
90
|
-
|
|
88
|
+
try {
|
|
89
|
+
this.ws.send(JSON.stringify(msg));
|
|
90
|
+
} catch {
|
|
91
|
+
clearTimeout(timeout);
|
|
92
|
+
this.pending.delete(id);
|
|
93
|
+
this.wsFailed = true;
|
|
94
|
+
this.httpPost(msg).then(resolve, reject);
|
|
95
|
+
}
|
|
91
96
|
});
|
|
92
97
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
let body = { sql: msg.sql, params: msg.params };
|
|
98
|
+
// ---- HTTP fallback ----
|
|
99
|
+
async httpPost(msg) {
|
|
100
|
+
let path = "/v1/query", body = { sql: msg.sql, params: msg.params };
|
|
96
101
|
if (msg.action === "batch") {
|
|
97
102
|
path = "/v1/batch";
|
|
98
103
|
body = { queries: msg.queries };
|
|
@@ -102,60 +107,48 @@ var StitchDB = class {
|
|
|
102
107
|
}
|
|
103
108
|
const res = await fetch(`${this.url}${path}`, {
|
|
104
109
|
method: "POST",
|
|
105
|
-
headers: {
|
|
106
|
-
"Authorization": `Bearer ${this.apiKey}`,
|
|
107
|
-
"Content-Type": "application/json"
|
|
108
|
-
},
|
|
110
|
+
headers: { "Authorization": `Bearer ${this.apiKey}`, "Content-Type": "application/json" },
|
|
109
111
|
body: JSON.stringify(body)
|
|
110
112
|
});
|
|
111
113
|
const data = await res.json();
|
|
112
|
-
if (!res.ok || data.error) {
|
|
113
|
-
throw new StitchDBError(data.error || `Request failed: ${res.status}`, res.status);
|
|
114
|
-
}
|
|
114
|
+
if (!res.ok || data.error) throw new StitchDBError(data.error || `HTTP ${res.status}`, res.status);
|
|
115
115
|
return data;
|
|
116
116
|
}
|
|
117
|
-
|
|
117
|
+
// ---- Public API ----
|
|
118
|
+
async send(action, data) {
|
|
119
|
+
const msg = { action, ...data };
|
|
120
|
+
if (this.wsSupported && !this.wsFailed) return this.wsSend(msg);
|
|
121
|
+
return this.httpPost(msg);
|
|
122
|
+
}
|
|
118
123
|
async query(sql, params) {
|
|
119
|
-
|
|
120
|
-
return this.wsSend({ action: "query", sql, params });
|
|
121
|
-
}
|
|
122
|
-
return this.httpQuery({ action: "query", sql, params });
|
|
124
|
+
return this.send("query", { sql, params });
|
|
123
125
|
}
|
|
124
|
-
/** Run multiple queries atomically in a single batch. */
|
|
125
126
|
async batch(queries) {
|
|
126
|
-
|
|
127
|
-
return this.wsSend({ action: "batch", queries });
|
|
128
|
-
}
|
|
129
|
-
return this.httpQuery({ action: "batch", queries });
|
|
127
|
+
return this.send("batch", { queries });
|
|
130
128
|
}
|
|
131
|
-
/** Run a DDL statement (CREATE TABLE, ALTER TABLE, DROP TABLE, etc.) */
|
|
132
129
|
async run(sql) {
|
|
133
|
-
|
|
134
|
-
return this.wsSend({ action: "exec", sql });
|
|
135
|
-
}
|
|
136
|
-
return this.httpQuery({ action: "exec", sql });
|
|
130
|
+
return this.send("exec", { sql });
|
|
137
131
|
}
|
|
138
|
-
/** Insert a row. */
|
|
139
132
|
async insert(table, data) {
|
|
140
133
|
const cols = Object.keys(data);
|
|
134
|
+
return this.query(`INSERT INTO "${table}" (${cols.map((c) => `"${c}"`).join(", ")}) VALUES (${cols.map(() => "?").join(", ")})`, Object.values(data));
|
|
135
|
+
}
|
|
136
|
+
async insertMany(table, rows) {
|
|
137
|
+
if (!rows.length) return { results: [], meta: { rows_read: 0, rows_written: 0, duration_ms: 0, queries_count: 0 } };
|
|
138
|
+
const cols = Object.keys(rows[0]);
|
|
141
139
|
const sql = `INSERT INTO "${table}" (${cols.map((c) => `"${c}"`).join(", ")}) VALUES (${cols.map(() => "?").join(", ")})`;
|
|
142
|
-
return this.
|
|
140
|
+
return this.batch(rows.map((row) => ({ sql, params: cols.map((c) => row[c]) })));
|
|
143
141
|
}
|
|
144
|
-
/** Update rows matching a WHERE clause. */
|
|
145
142
|
async update(table, data, where, whereParams) {
|
|
146
|
-
|
|
147
|
-
return this.query(`UPDATE "${table}" SET ${set} WHERE ${where}`, [...Object.values(data), ...whereParams || []]);
|
|
143
|
+
return this.query(`UPDATE "${table}" SET ${Object.keys(data).map((c) => `"${c}" = ?`).join(", ")} WHERE ${where}`, [...Object.values(data), ...whereParams || []]);
|
|
148
144
|
}
|
|
149
|
-
/** Delete rows matching a WHERE clause. */
|
|
150
145
|
async remove(table, where, whereParams) {
|
|
151
146
|
return this.query(`DELETE FROM "${table}" WHERE ${where}`, whereParams);
|
|
152
147
|
}
|
|
153
|
-
/** Find one row by ID. */
|
|
154
148
|
async find(table, id, idColumn = "id") {
|
|
155
149
|
const { results } = await this.query(`SELECT * FROM "${table}" WHERE "${idColumn}" = ? LIMIT 1`, [id]);
|
|
156
150
|
return results[0] || null;
|
|
157
151
|
}
|
|
158
|
-
/** Select rows with optional WHERE, ORDER BY, LIMIT, OFFSET. */
|
|
159
152
|
async select(table, where, params, opts) {
|
|
160
153
|
let sql = `SELECT * FROM "${table}"`;
|
|
161
154
|
if (where) sql += ` WHERE ${where}`;
|
|
@@ -165,7 +158,6 @@ var StitchDB = class {
|
|
|
165
158
|
const { results } = await this.query(sql, params);
|
|
166
159
|
return results;
|
|
167
160
|
}
|
|
168
|
-
/** Close the WebSocket connection. */
|
|
169
161
|
close() {
|
|
170
162
|
if (this.ws) {
|
|
171
163
|
this.ws.close();
|