@an5/adapters 0.2.4 → 0.2.6
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 +189 -304
- package/dist/an5Adapter.d.ts +85 -7
- package/dist/an5Adapter.js +736 -64
- package/dist/base/metadata.d.ts +10 -0
- package/dist/base/metadata.js +107 -0
- package/dist/base/sql.d.ts +19 -1
- package/dist/base/sql.js +152 -24
- package/dist/base/types.d.ts +4 -1
- package/dist/browser.d.ts +5 -2
- package/dist/browser.js +10 -2
- package/dist/googlesheets/adapter.d.ts +1 -0
- package/dist/googlesheets/adapter.js +9 -2
- package/dist/googlesheets/config.d.ts +4 -4
- package/dist/googlesheets/helpers.js +2 -0
- package/dist/googlesheets/parseConnectionString.js +5 -2
- package/dist/googlesheets/sqlExecutor.js +29 -24
- package/dist/googlesheets/tableClient.js +14 -5
- package/dist/index.d.ts +5 -1
- package/dist/index.js +12 -1
- package/dist/mssql/engine.js +8 -4
- package/dist/mysql/engine.js +1 -1
- package/dist/postgres/engine.js +1 -1
- package/dist/sqlite/browserEngine.d.ts +27 -0
- package/dist/sqlite/browserEngine.js +161 -0
- package/dist/sqlite/engine.js +15 -3
- package/dist/sqlite/index.d.ts +1 -0
- package/dist/sqlite/index.js +1 -0
- package/dist/typed.d.ts +5 -0
- package/dist/typed.js +2 -0
- package/dotnet/An5Adapter.cs +1089 -275
- package/dotnet/Base/Core.cs +340 -82
- package/dotnet/Mssql/MssqlEngine.cs +145 -144
- package/dotnet/Postgres/PostgresEngine.cs +121 -121
- package/golang/an5_adapter.go +314 -0
- package/golang/base/base.go +100 -0
- package/golang/base/metadata.go +116 -0
- package/golang/base/where.go +311 -0
- package/golang/go.mod +3 -0
- package/golang/mssql/mssql.go +32 -0
- package/golang/postgres/postgres.go +37 -0
- package/golang/sqlite/sqlite.go +14 -0
- package/golang/sqlite_test.go +42 -0
- package/golang/table_client.go +1329 -0
- package/package.json +18 -8
- package/python/an5_adapter.py +119 -97
- package/python/base/__init__.py +3 -3
- package/python/base/dialects.py +11 -8
- package/python/base/metadata.py +35 -10
- package/python/base/sql.py +172 -121
- package/python/mssql/__init__.py +1 -1
- package/python/mssql/provider.py +62 -62
- package/python/postgres/__init__.py +1 -1
- package/python/postgres/provider.py +15 -15
- package/python/table_client.py +619 -216
- package/typescript/src/an5Adapter.ts +1220 -505
- package/typescript/src/base/index.ts +3 -3
- package/typescript/src/base/metadata.ts +148 -28
- package/typescript/src/base/sql.ts +264 -98
- package/typescript/src/base/types.ts +27 -24
- package/typescript/src/browser.ts +10 -6
- package/typescript/src/config.ts +95 -95
- package/typescript/src/googlesheets/adapter.ts +269 -259
- package/typescript/src/googlesheets/an5SheetsAdapter.ts +3 -3
- package/typescript/src/googlesheets/config.ts +47 -47
- package/typescript/src/googlesheets/helpers.ts +144 -143
- package/typescript/src/googlesheets/index.ts +3 -3
- package/typescript/src/googlesheets/parseConnectionString.ts +48 -46
- package/typescript/src/googlesheets/retry.ts +126 -126
- package/typescript/src/googlesheets/sqlExecutor.ts +304 -301
- package/typescript/src/googlesheets/tableClient.ts +461 -455
- package/typescript/src/googlesheets/types.ts +6 -6
- package/typescript/src/index.ts +32 -19
- package/typescript/src/mssql/engine.ts +134 -132
- package/typescript/src/mssql/index.ts +1 -1
- package/typescript/src/mysql/engine.ts +80 -80
- package/typescript/src/mysql/index.ts +1 -1
- package/typescript/src/postgres/engine.ts +87 -87
- package/typescript/src/postgres/index.ts +1 -1
- package/typescript/src/sqlite/browserEngine.ts +192 -0
- package/typescript/src/sqlite/engine.ts +66 -55
- package/typescript/src/sqlite/index.ts +3 -1
- package/typescript/src/typed.ts +52 -0
|
@@ -46,9 +46,9 @@ function matchRowSQL(row, whereText, values) {
|
|
|
46
46
|
const m = part.match(/^(.+?)\s*(=|!=|<>|>|<|>=|<=|LIKE|CONTAINS)\s*(.+)$/i);
|
|
47
47
|
if (!m)
|
|
48
48
|
continue;
|
|
49
|
-
const field = m[1].trim().replace(/[[\]]/g, '');
|
|
50
|
-
const op = m[2].toUpperCase();
|
|
51
|
-
const valRef = m[3].trim();
|
|
49
|
+
const field = (m[1] ?? '').trim().replace(/[[\]]/g, '');
|
|
50
|
+
const op = (m[2] ?? '').toUpperCase();
|
|
51
|
+
const valRef = (m[3] ?? '').trim();
|
|
52
52
|
const val = valRef.startsWith('?') ? values[parseInt(valRef.slice(1))] : valRef.replace(/^['"]|['"]$/g, '');
|
|
53
53
|
const cell = row[field];
|
|
54
54
|
switch (op) {
|
|
@@ -94,20 +94,26 @@ function extractColsAndVals(sql, params) {
|
|
|
94
94
|
const vals = [];
|
|
95
95
|
const colMatch = sql.match(/\(([^)]+)\)\s*VALUES/i);
|
|
96
96
|
if (colMatch) {
|
|
97
|
-
const rawCols = colMatch[1].split(',').map(c => c.trim().replace(/[[\]]/g, ''));
|
|
97
|
+
const rawCols = (colMatch[1] ?? '').split(',').map(c => c.trim().replace(/[[\]]/g, ''));
|
|
98
98
|
// Find actual values
|
|
99
|
-
const valMatch = sql.substring(colMatch.index + colMatch[0].length).match(/\(([^)]+)\)/);
|
|
99
|
+
const valMatch = sql.substring((colMatch.index ?? 0) + colMatch[0].length).match(/\(([^)]+)\)/);
|
|
100
100
|
if (valMatch) {
|
|
101
|
-
const rawVals = valMatch[1].split(',').map(v => v.trim());
|
|
101
|
+
const rawVals = (valMatch[1] ?? '').split(',').map(v => v.trim());
|
|
102
102
|
for (let i = 0; i < rawCols.length; i++) {
|
|
103
|
-
|
|
103
|
+
const col = rawCols[i];
|
|
104
|
+
if (col === undefined)
|
|
105
|
+
continue;
|
|
106
|
+
cols.push(col);
|
|
104
107
|
const rv = rawVals[i];
|
|
105
|
-
if (rv.startsWith('@') && params && params[rv.slice(1)] !== undefined) {
|
|
108
|
+
if (rv !== undefined && rv.startsWith('@') && params && params[rv.slice(1)] !== undefined) {
|
|
106
109
|
vals.push(params[rv.slice(1)]);
|
|
107
110
|
}
|
|
108
|
-
else {
|
|
111
|
+
else if (rv !== undefined) {
|
|
109
112
|
vals.push(rv.replace(/^['"]|['"]$/g, ''));
|
|
110
113
|
}
|
|
114
|
+
else {
|
|
115
|
+
vals.push(null);
|
|
116
|
+
}
|
|
111
117
|
}
|
|
112
118
|
}
|
|
113
119
|
}
|
|
@@ -125,13 +131,13 @@ async function execSelect(adapter, query, params) {
|
|
|
125
131
|
return obj;
|
|
126
132
|
});
|
|
127
133
|
}
|
|
128
|
-
const sheetName = m[2]
|
|
134
|
+
const sheetName = m[2] ?? m[3] ?? m[4] ?? '';
|
|
129
135
|
const whereClause = m[5];
|
|
130
136
|
const raw = await adapter.readRange((0, helpers_1.esc)(sheetName) + '!A:ZZ');
|
|
131
137
|
if (raw.length < 1)
|
|
132
138
|
return [];
|
|
133
139
|
const headers = raw[0];
|
|
134
|
-
const fieldList = m[1].trim();
|
|
140
|
+
const fieldList = (m[1] ?? '*').trim();
|
|
135
141
|
const selectAll = fieldList === '*';
|
|
136
142
|
const rows = raw.slice(1).map(row => {
|
|
137
143
|
const obj = {};
|
|
@@ -139,16 +145,15 @@ async function execSelect(adapter, query, params) {
|
|
|
139
145
|
return obj;
|
|
140
146
|
});
|
|
141
147
|
if (!whereClause)
|
|
142
|
-
return selectAll ? rows : rows.map(r => pickFields(r, fieldList
|
|
143
|
-
const { text, values } = substParams(query, params);
|
|
148
|
+
return selectAll ? rows : rows.map(r => pickFields(r, fieldList));
|
|
144
149
|
// Extract just the WHERE part
|
|
145
150
|
const whereParts = query.match(/WHERE\s+(.+)$/i);
|
|
146
|
-
const whereText = whereParts
|
|
151
|
+
const whereText = whereParts?.[1] ?? '';
|
|
147
152
|
const { text: whereSubst, values: whereVals } = substParams(whereText, params);
|
|
148
153
|
const result = rows.filter(r => matchRowSQL(r, whereSubst, whereVals));
|
|
149
|
-
return selectAll ? result : result.map(r => pickFields(r, fieldList
|
|
154
|
+
return selectAll ? result : result.map(r => pickFields(r, fieldList));
|
|
150
155
|
}
|
|
151
|
-
function pickFields(row, fieldList
|
|
156
|
+
function pickFields(row, fieldList) {
|
|
152
157
|
const fields = fieldList.split(',').map(f => f.trim().replace(/[[\]]/g, ''));
|
|
153
158
|
const obj = {};
|
|
154
159
|
fields.forEach(f => { obj[f] = row[f]; });
|
|
@@ -158,7 +163,7 @@ async function execInsert(adapter, query, params) {
|
|
|
158
163
|
const m = query.match(/INSERT\s+INTO\s+(?:'([^']+)'|"([^"]+)"|(\S+))\s*(.*)/i);
|
|
159
164
|
if (!m)
|
|
160
165
|
throw new Error('Invalid INSERT syntax');
|
|
161
|
-
const sheetName = m[1]
|
|
166
|
+
const sheetName = m[1] ?? m[2] ?? m[3] ?? '';
|
|
162
167
|
const { cols, vals } = extractColsAndVals(query, params);
|
|
163
168
|
if (cols.length === 0)
|
|
164
169
|
throw new Error('Cannot extract columns from INSERT');
|
|
@@ -198,8 +203,8 @@ async function execUpdate(adapter, query, params) {
|
|
|
198
203
|
const m = query.match(/UPDATE\s+(?:'([^']+)'|"([^"]+)"|(\S+))\s+SET\s+(.+?)(?:\s+WHERE\s+(.+))?$/i);
|
|
199
204
|
if (!m)
|
|
200
205
|
throw new Error('Invalid UPDATE syntax');
|
|
201
|
-
const sheetName = m[1]
|
|
202
|
-
const setClause = m[4];
|
|
206
|
+
const sheetName = m[1] ?? m[2] ?? m[3] ?? '';
|
|
207
|
+
const setClause = m[4] ?? '';
|
|
203
208
|
const whereClause = m[5];
|
|
204
209
|
// Parse SET clause
|
|
205
210
|
const setPairs = setClause.split(',').map(p => p.trim());
|
|
@@ -209,8 +214,8 @@ async function execUpdate(adapter, query, params) {
|
|
|
209
214
|
const sm = pair.match(/^(\w+)\s*=\s*(.+)$/i);
|
|
210
215
|
if (!sm)
|
|
211
216
|
continue;
|
|
212
|
-
setFields.push(sm[1].replace(/[[\]]/g, ''));
|
|
213
|
-
const rv = sm[2].trim();
|
|
217
|
+
setFields.push((sm[1] ?? '').replace(/[[\]]/g, ''));
|
|
218
|
+
const rv = (sm[2] ?? '').trim();
|
|
214
219
|
if (rv.startsWith('@') && params && params[rv.slice(1)] !== undefined) {
|
|
215
220
|
setVals.push(params[rv.slice(1)]);
|
|
216
221
|
}
|
|
@@ -230,7 +235,7 @@ async function execUpdate(adapter, query, params) {
|
|
|
230
235
|
let count = 0;
|
|
231
236
|
for (let i = 0; i < rows.length; i++) {
|
|
232
237
|
const row = {};
|
|
233
|
-
headers.forEach((h, j) => { row[h] = rows[i][j] ?? null; });
|
|
238
|
+
headers.forEach((h, j) => { row[h] = rows[i]?.[j] ?? null; });
|
|
234
239
|
row.__row = i + 2;
|
|
235
240
|
if (whereClause && !matchRowSQL(row, whereSubst, whereVals))
|
|
236
241
|
continue;
|
|
@@ -253,7 +258,7 @@ async function execDelete(adapter, query, params) {
|
|
|
253
258
|
const m = query.match(/DELETE\s+FROM\s+(?:'([^']+)'|"([^"]+)"|(\S+))\s*(?:WHERE\s+(.+))?$/i);
|
|
254
259
|
if (!m)
|
|
255
260
|
throw new Error('Invalid DELETE syntax');
|
|
256
|
-
const sheetName = m[1]
|
|
261
|
+
const sheetName = m[1] ?? m[2] ?? m[3] ?? '';
|
|
257
262
|
const whereClause = m[4];
|
|
258
263
|
const meta = await adapter.getSheetMeta(sheetName);
|
|
259
264
|
if (!meta)
|
|
@@ -282,7 +287,7 @@ async function execDelete(adapter, query, params) {
|
|
|
282
287
|
const toDelete = [];
|
|
283
288
|
for (let i = 1; i < raw.length; i++) {
|
|
284
289
|
const row = {};
|
|
285
|
-
headers.forEach((h, j) => { row[h] = raw[i][j] ?? null; });
|
|
290
|
+
headers.forEach((h, j) => { row[h] = raw[i]?.[j] ?? null; });
|
|
286
291
|
if (matchRowSQL(row, whereSubst, whereVals)) {
|
|
287
292
|
toDelete.push(i + 1);
|
|
288
293
|
}
|
|
@@ -54,7 +54,10 @@ class SheetsTableClient {
|
|
|
54
54
|
for (let i = 1; i < values.length; i++) {
|
|
55
55
|
const row = { __row: i + 1 };
|
|
56
56
|
for (let j = 0; j < headers.length; j++) {
|
|
57
|
-
|
|
57
|
+
const h = headers[j];
|
|
58
|
+
if (h === undefined)
|
|
59
|
+
continue;
|
|
60
|
+
row[h] = (0, helpers_1.coerceCell)(values[i]?.[j], this.fields[h]);
|
|
58
61
|
}
|
|
59
62
|
rows.push(row);
|
|
60
63
|
}
|
|
@@ -222,6 +225,8 @@ class SheetsTableClient {
|
|
|
222
225
|
if (matching.length === 0)
|
|
223
226
|
throw new Error('No record found matching where clause');
|
|
224
227
|
const target = matching[0];
|
|
228
|
+
if (target === undefined)
|
|
229
|
+
throw new Error('No record found matching where clause');
|
|
225
230
|
const updated = { ...target, ...args.data, __row: target.__row };
|
|
226
231
|
await this.adapter.writeRange(`${this.escSheetName}!A${target.__row}`, [
|
|
227
232
|
this.rowToValues(updated, headers),
|
|
@@ -256,6 +261,8 @@ class SheetsTableClient {
|
|
|
256
261
|
if (matching.length === 0)
|
|
257
262
|
throw new Error('No record found matching where clause');
|
|
258
263
|
const target = matching[0];
|
|
264
|
+
if (target === undefined)
|
|
265
|
+
throw new Error('No record found matching where clause');
|
|
259
266
|
const meta = await this.adapter.getSheetMeta(this.sheetName);
|
|
260
267
|
if (!meta)
|
|
261
268
|
throw new Error(`Sheet "${this.sheetName}" not found`);
|
|
@@ -395,14 +402,16 @@ class SheetsTableClient {
|
|
|
395
402
|
continue;
|
|
396
403
|
let dot = 0, m1 = 0, m2 = 0;
|
|
397
404
|
for (let i = 0; i < args.vector.length; i++) {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
405
|
+
const av = args.vector[i] ?? 0;
|
|
406
|
+
const bv = vec[i] ?? 0;
|
|
407
|
+
dot += av * bv;
|
|
408
|
+
m1 += av ** 2;
|
|
409
|
+
m2 += bv ** 2;
|
|
401
410
|
}
|
|
402
411
|
const cosine = m1 && m2 ? dot / (Math.sqrt(m1) * Math.sqrt(m2)) : 0;
|
|
403
412
|
const dist = metric === 'cosine' ? 1 - cosine
|
|
404
413
|
: metric === 'dot' ? -dot
|
|
405
|
-
: Math.sqrt(args.vector.reduce((s, v, i) => s + (v - vec[i]) ** 2, 0));
|
|
414
|
+
: Math.sqrt(args.vector.reduce((s, v, i) => s + (v - (vec[i] ?? 0)) ** 2, 0));
|
|
406
415
|
scored.push({ row, dist });
|
|
407
416
|
}
|
|
408
417
|
scored.sort((a, b) => a.dist - b.dist);
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
export { An5Adapter, AdapterTableClient, createAn5Adapter, setAdapterMetadata, } from './an5Adapter';
|
|
1
|
+
export { An5Adapter, AdapterTableClient, createAn5Adapter, createAdapterProxy, executorFromAdapter, setAdapterMetadata, } from './an5Adapter';
|
|
2
|
+
export { parseWhere, buildOrderBy, quote } from './base/sql';
|
|
2
3
|
export type { An5AdapterConfig, AdapterMetadata, Dialect, } from './an5Adapter';
|
|
4
|
+
export type { TypedAn5Adapter, AdapterAPI } from './typed';
|
|
3
5
|
export { getLlmConfig, setLlmConfig, getEmbeddingConfig, setEmbeddingConfig, resetAdapter, } from './config';
|
|
4
6
|
export type { LlmConfigData, EmbeddingConfigData, } from './config';
|
|
7
|
+
export { An5SheetsAdapter, SheetsTableClient, createAn5SheetsAdapter, parseSheetsConnectionString, } from './googlesheets';
|
|
8
|
+
export type { An5SheetsAdapterConfig, } from './googlesheets';
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.resetAdapter = exports.setEmbeddingConfig = exports.getEmbeddingConfig = exports.setLlmConfig = exports.getLlmConfig = exports.setAdapterMetadata = exports.createAn5Adapter = exports.AdapterTableClient = exports.An5Adapter = void 0;
|
|
3
|
+
exports.parseSheetsConnectionString = exports.createAn5SheetsAdapter = exports.SheetsTableClient = exports.An5SheetsAdapter = exports.resetAdapter = exports.setEmbeddingConfig = exports.getEmbeddingConfig = exports.setLlmConfig = exports.getLlmConfig = exports.quote = exports.buildOrderBy = exports.parseWhere = exports.setAdapterMetadata = exports.executorFromAdapter = exports.createAdapterProxy = exports.createAn5Adapter = exports.AdapterTableClient = exports.An5Adapter = void 0;
|
|
4
4
|
var an5Adapter_1 = require("./an5Adapter");
|
|
5
5
|
Object.defineProperty(exports, "An5Adapter", { enumerable: true, get: function () { return an5Adapter_1.An5Adapter; } });
|
|
6
6
|
Object.defineProperty(exports, "AdapterTableClient", { enumerable: true, get: function () { return an5Adapter_1.AdapterTableClient; } });
|
|
7
7
|
Object.defineProperty(exports, "createAn5Adapter", { enumerable: true, get: function () { return an5Adapter_1.createAn5Adapter; } });
|
|
8
|
+
Object.defineProperty(exports, "createAdapterProxy", { enumerable: true, get: function () { return an5Adapter_1.createAdapterProxy; } });
|
|
9
|
+
Object.defineProperty(exports, "executorFromAdapter", { enumerable: true, get: function () { return an5Adapter_1.executorFromAdapter; } });
|
|
8
10
|
Object.defineProperty(exports, "setAdapterMetadata", { enumerable: true, get: function () { return an5Adapter_1.setAdapterMetadata; } });
|
|
11
|
+
var sql_1 = require("./base/sql");
|
|
12
|
+
Object.defineProperty(exports, "parseWhere", { enumerable: true, get: function () { return sql_1.parseWhere; } });
|
|
13
|
+
Object.defineProperty(exports, "buildOrderBy", { enumerable: true, get: function () { return sql_1.buildOrderBy; } });
|
|
14
|
+
Object.defineProperty(exports, "quote", { enumerable: true, get: function () { return sql_1.quote; } });
|
|
9
15
|
var config_1 = require("./config");
|
|
10
16
|
Object.defineProperty(exports, "getLlmConfig", { enumerable: true, get: function () { return config_1.getLlmConfig; } });
|
|
11
17
|
Object.defineProperty(exports, "setLlmConfig", { enumerable: true, get: function () { return config_1.setLlmConfig; } });
|
|
12
18
|
Object.defineProperty(exports, "getEmbeddingConfig", { enumerable: true, get: function () { return config_1.getEmbeddingConfig; } });
|
|
13
19
|
Object.defineProperty(exports, "setEmbeddingConfig", { enumerable: true, get: function () { return config_1.setEmbeddingConfig; } });
|
|
14
20
|
Object.defineProperty(exports, "resetAdapter", { enumerable: true, get: function () { return config_1.resetAdapter; } });
|
|
21
|
+
var googlesheets_1 = require("./googlesheets");
|
|
22
|
+
Object.defineProperty(exports, "An5SheetsAdapter", { enumerable: true, get: function () { return googlesheets_1.An5SheetsAdapter; } });
|
|
23
|
+
Object.defineProperty(exports, "SheetsTableClient", { enumerable: true, get: function () { return googlesheets_1.SheetsTableClient; } });
|
|
24
|
+
Object.defineProperty(exports, "createAn5SheetsAdapter", { enumerable: true, get: function () { return googlesheets_1.createAn5SheetsAdapter; } });
|
|
25
|
+
Object.defineProperty(exports, "parseSheetsConnectionString", { enumerable: true, get: function () { return googlesheets_1.parseSheetsConnectionString; } });
|
package/dist/mssql/engine.js
CHANGED
|
@@ -12,7 +12,7 @@ function parseMssqlConnectionString(url) {
|
|
|
12
12
|
// Strip scheme prefix
|
|
13
13
|
cleanUrl = cleanUrl.replace(/^(?:sqlserver|mssql):\/\//i, '');
|
|
14
14
|
const parts = cleanUrl.split(';');
|
|
15
|
-
const firstPart = parts[0].trim();
|
|
15
|
+
const firstPart = (parts[0] ?? '').trim();
|
|
16
16
|
// host:port or host,port (SQL Server native style)
|
|
17
17
|
let server = firstPart;
|
|
18
18
|
let port = 1433;
|
|
@@ -35,7 +35,10 @@ function parseMssqlConnectionString(url) {
|
|
|
35
35
|
connectionTimeout: 15000,
|
|
36
36
|
};
|
|
37
37
|
for (let i = 1; i < parts.length; i++) {
|
|
38
|
-
const
|
|
38
|
+
const rawPart = parts[i];
|
|
39
|
+
if (rawPart === undefined)
|
|
40
|
+
continue;
|
|
41
|
+
const part = rawPart.trim();
|
|
39
42
|
if (!part)
|
|
40
43
|
continue;
|
|
41
44
|
const eqIdx = part.indexOf('=');
|
|
@@ -52,7 +55,8 @@ function parseMssqlConnectionString(url) {
|
|
|
52
55
|
else if (key === 'server' || key === 'data source') {
|
|
53
56
|
// SERVER=host,port style (key-value form)
|
|
54
57
|
const [s, p] = value.split(',');
|
|
55
|
-
|
|
58
|
+
if (s !== undefined)
|
|
59
|
+
config.server = s.trim();
|
|
56
60
|
if (p)
|
|
57
61
|
config.port = parseInt(p.trim(), 10) || 1433;
|
|
58
62
|
}
|
|
@@ -70,7 +74,7 @@ class MssqlEngine {
|
|
|
70
74
|
constructor(adapterConfig) {
|
|
71
75
|
this.dialect = 'mssql';
|
|
72
76
|
this.pool = null;
|
|
73
|
-
this.config = parseMssqlConnectionString(adapterConfig.connectionString);
|
|
77
|
+
this.config = parseMssqlConnectionString(adapterConfig.connectionString ?? '');
|
|
74
78
|
if (adapterConfig.poolMax)
|
|
75
79
|
this.config.pool = { ...this.config.pool, max: adapterConfig.poolMax };
|
|
76
80
|
if (adapterConfig.requestTimeout)
|
package/dist/mysql/engine.js
CHANGED
|
@@ -14,7 +14,7 @@ class MysqlEngine {
|
|
|
14
14
|
if (!Mysql2)
|
|
15
15
|
throw new Error('mysql2 package is required for MySQL support. Run: npm install mysql2');
|
|
16
16
|
this.pool = Mysql2.createPool({
|
|
17
|
-
uri: adapterConfig.connectionString,
|
|
17
|
+
uri: adapterConfig.connectionString ?? '',
|
|
18
18
|
connectionLimit: adapterConfig.poolMax ?? 10,
|
|
19
19
|
connectTimeout: adapterConfig.connectionTimeout ?? 15000,
|
|
20
20
|
});
|
package/dist/postgres/engine.js
CHANGED
|
@@ -14,7 +14,7 @@ class PostgresEngine {
|
|
|
14
14
|
if (!PgPool)
|
|
15
15
|
throw new Error('pg package is required for PostgreSQL support. Run: npm install pg');
|
|
16
16
|
this.pool = new PgPool({
|
|
17
|
-
connectionString: adapterConfig.connectionString,
|
|
17
|
+
connectionString: adapterConfig.connectionString ?? '',
|
|
18
18
|
max: adapterConfig.poolMax ?? 10,
|
|
19
19
|
});
|
|
20
20
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Dialect, QueryEngine, TransactionHandle } from '../base/types';
|
|
2
|
+
export interface SqliteDriver {
|
|
3
|
+
exec<T = any>(query: string, params?: Record<string, any>): Promise<T[]> | T[];
|
|
4
|
+
executeRaw?(query: string, params?: Record<string, any>): Promise<number> | number;
|
|
5
|
+
close?(): Promise<void> | void;
|
|
6
|
+
}
|
|
7
|
+
export interface SqliteBrowserConfig {
|
|
8
|
+
db?: any;
|
|
9
|
+
driver?: SqliteDriver;
|
|
10
|
+
exec?: <T = any>(query: string, params?: Record<string, any>) => Promise<T[]> | T[];
|
|
11
|
+
executeRaw?: (query: string, params?: Record<string, any>) => Promise<number> | number;
|
|
12
|
+
}
|
|
13
|
+
export declare class SqliteBrowserEngine implements QueryEngine {
|
|
14
|
+
dialect: Dialect;
|
|
15
|
+
private db;
|
|
16
|
+
private driver;
|
|
17
|
+
private customExec;
|
|
18
|
+
private customExecuteRaw;
|
|
19
|
+
constructor(config?: SqliteBrowserConfig | any);
|
|
20
|
+
private normalizeSqlJsParams;
|
|
21
|
+
exec<T = any>(query: string, params?: Record<string, any>): Promise<T[]>;
|
|
22
|
+
executeRaw(query: string, params?: Record<string, any>): Promise<number>;
|
|
23
|
+
connect(): Promise<void>;
|
|
24
|
+
disconnect(): Promise<void>;
|
|
25
|
+
beginTransaction(): Promise<TransactionHandle>;
|
|
26
|
+
}
|
|
27
|
+
export declare function createBrowserSqliteAdapter(config: SqliteBrowserConfig | any): any;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SqliteBrowserEngine = void 0;
|
|
4
|
+
exports.createBrowserSqliteAdapter = createBrowserSqliteAdapter;
|
|
5
|
+
// ─── Browser SQLite Engine ──────────────────────────────────────────────────────────
|
|
6
|
+
class SqliteBrowserEngine {
|
|
7
|
+
constructor(config) {
|
|
8
|
+
this.dialect = 'sqlite';
|
|
9
|
+
this.db = null;
|
|
10
|
+
this.driver = null;
|
|
11
|
+
this.customExec = null;
|
|
12
|
+
this.customExecuteRaw = null;
|
|
13
|
+
if (!config)
|
|
14
|
+
return;
|
|
15
|
+
if (config.exec && typeof config.exec === 'function') {
|
|
16
|
+
this.customExec = config.exec;
|
|
17
|
+
this.customExecuteRaw = config.executeRaw ?? null;
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (config.driver) {
|
|
21
|
+
this.driver = config.driver;
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
// Direct DB instance (e.g. sql.js Database or sqlite-wasm)
|
|
25
|
+
if (config.db) {
|
|
26
|
+
this.db = config.db;
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
// If config itself looks like a driver with exec()
|
|
30
|
+
if (typeof config.exec === 'function' && typeof config.run !== 'function' && typeof config.prepare !== 'function') {
|
|
31
|
+
this.driver = config;
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// If config itself is a Database instance (has prepare, exec, run)
|
|
35
|
+
if (typeof config.prepare === 'function' || typeof config.run === 'function' || typeof config.exec === 'function') {
|
|
36
|
+
this.db = config;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
normalizeSqlJsParams(params) {
|
|
40
|
+
if (!params || typeof params !== 'object')
|
|
41
|
+
return {};
|
|
42
|
+
const normalized = {};
|
|
43
|
+
for (const [k, v] of Object.entries(params)) {
|
|
44
|
+
const key = k.startsWith('@') || k.startsWith(':') || k.startsWith('$') ? k : `@${k}`;
|
|
45
|
+
normalized[key] = v;
|
|
46
|
+
}
|
|
47
|
+
return normalized;
|
|
48
|
+
}
|
|
49
|
+
async exec(query, params) {
|
|
50
|
+
if (this.customExec) {
|
|
51
|
+
return await this.customExec(query, params);
|
|
52
|
+
}
|
|
53
|
+
if (this.driver) {
|
|
54
|
+
return await this.driver.exec(query, params);
|
|
55
|
+
}
|
|
56
|
+
if (this.db) {
|
|
57
|
+
// sql.js Database with prepare()
|
|
58
|
+
if (typeof this.db.prepare === 'function') {
|
|
59
|
+
const stmt = this.db.prepare(query);
|
|
60
|
+
try {
|
|
61
|
+
if (params && Object.keys(params).length > 0) {
|
|
62
|
+
stmt.bind(this.normalizeSqlJsParams(params));
|
|
63
|
+
}
|
|
64
|
+
const results = [];
|
|
65
|
+
while (stmt.step()) {
|
|
66
|
+
results.push(stmt.getAsObject());
|
|
67
|
+
}
|
|
68
|
+
return results;
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
stmt.free();
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Fallback sql.js db.exec()
|
|
75
|
+
if (typeof this.db.exec === 'function') {
|
|
76
|
+
const res = this.db.exec(query);
|
|
77
|
+
if (!res || res.length === 0)
|
|
78
|
+
return [];
|
|
79
|
+
const { columns, values } = res[0];
|
|
80
|
+
return values.map((row) => {
|
|
81
|
+
const obj = {};
|
|
82
|
+
columns.forEach((col, i) => {
|
|
83
|
+
obj[col] = row[i];
|
|
84
|
+
});
|
|
85
|
+
return obj;
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
throw new Error('SqliteBrowserEngine: No SQLite database or driver provided. Pass a sql.js db instance or custom driver.');
|
|
90
|
+
}
|
|
91
|
+
async executeRaw(query, params) {
|
|
92
|
+
if (this.customExecuteRaw) {
|
|
93
|
+
return await this.customExecuteRaw(query, params);
|
|
94
|
+
}
|
|
95
|
+
if (this.driver && typeof this.driver.executeRaw === 'function') {
|
|
96
|
+
return await this.driver.executeRaw(query, params);
|
|
97
|
+
}
|
|
98
|
+
if (this.db) {
|
|
99
|
+
if (typeof this.db.prepare === 'function') {
|
|
100
|
+
const stmt = this.db.prepare(query);
|
|
101
|
+
try {
|
|
102
|
+
if (params && Object.keys(params).length > 0) {
|
|
103
|
+
stmt.bind(this.normalizeSqlJsParams(params));
|
|
104
|
+
}
|
|
105
|
+
stmt.step();
|
|
106
|
+
if (typeof this.db.getRowsModified === 'function') {
|
|
107
|
+
return this.db.getRowsModified();
|
|
108
|
+
}
|
|
109
|
+
return 1;
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
stmt.free();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (typeof this.db.run === 'function') {
|
|
116
|
+
this.db.run(query, this.normalizeSqlJsParams(params));
|
|
117
|
+
if (typeof this.db.getRowsModified === 'function') {
|
|
118
|
+
return this.db.getRowsModified();
|
|
119
|
+
}
|
|
120
|
+
return 1;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const rows = await this.exec(query, params);
|
|
124
|
+
return rows.length;
|
|
125
|
+
}
|
|
126
|
+
async connect() { }
|
|
127
|
+
async disconnect() {
|
|
128
|
+
if (this.driver && typeof this.driver.close === 'function') {
|
|
129
|
+
await this.driver.close();
|
|
130
|
+
}
|
|
131
|
+
else if (this.db && typeof this.db.close === 'function') {
|
|
132
|
+
this.db.close();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
async beginTransaction() {
|
|
136
|
+
await this.executeRaw('BEGIN');
|
|
137
|
+
let done = false;
|
|
138
|
+
return {
|
|
139
|
+
exec: async (q, p) => this.exec(q, p),
|
|
140
|
+
executeRaw: async (q, p) => this.executeRaw(q, p),
|
|
141
|
+
commit: async () => {
|
|
142
|
+
if (!done) {
|
|
143
|
+
await this.executeRaw('COMMIT');
|
|
144
|
+
done = true;
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
rollback: async () => {
|
|
148
|
+
if (!done) {
|
|
149
|
+
await this.executeRaw('ROLLBACK');
|
|
150
|
+
done = true;
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
exports.SqliteBrowserEngine = SqliteBrowserEngine;
|
|
157
|
+
// ─── Browser SQLite Adapter Factory ──────────────────────────────────────────────────
|
|
158
|
+
function createBrowserSqliteAdapter(config) {
|
|
159
|
+
const { An5Adapter } = require('../an5Adapter');
|
|
160
|
+
return new An5Adapter({ engine: new SqliteBrowserEngine(config) });
|
|
161
|
+
}
|
package/dist/sqlite/engine.js
CHANGED
|
@@ -13,7 +13,7 @@ class SqliteEngine {
|
|
|
13
13
|
this.db = null;
|
|
14
14
|
if (!BetterSqlite3)
|
|
15
15
|
throw new Error('better-sqlite3 package is required for SQLite support. Run: npm install better-sqlite3');
|
|
16
|
-
this.filePath = adapterConfig.connectionString
|
|
16
|
+
this.filePath = (adapterConfig.connectionString ?? '')
|
|
17
17
|
.replace(/^sqlite:\/\/\//i, '/')
|
|
18
18
|
.replace(/^sqlite:\/\//i, '');
|
|
19
19
|
}
|
|
@@ -24,7 +24,12 @@ class SqliteEngine {
|
|
|
24
24
|
}
|
|
25
25
|
// better-sqlite3 natively supports @name parameters
|
|
26
26
|
async exec(query, params) {
|
|
27
|
-
|
|
27
|
+
const stmt = this.getDb().prepare(query);
|
|
28
|
+
if (stmt.reader) {
|
|
29
|
+
return stmt.all(params ?? {});
|
|
30
|
+
}
|
|
31
|
+
stmt.run(params ?? {});
|
|
32
|
+
return [];
|
|
28
33
|
}
|
|
29
34
|
async executeRaw(query, params) {
|
|
30
35
|
const info = this.getDb().prepare(query).run(params ?? {});
|
|
@@ -42,7 +47,14 @@ class SqliteEngine {
|
|
|
42
47
|
db.prepare('BEGIN').run();
|
|
43
48
|
let done = false;
|
|
44
49
|
return {
|
|
45
|
-
exec: async (q, p) =>
|
|
50
|
+
exec: async (q, p) => {
|
|
51
|
+
const stmt = db.prepare(q);
|
|
52
|
+
if (stmt.reader) {
|
|
53
|
+
return stmt.all(p ?? {});
|
|
54
|
+
}
|
|
55
|
+
stmt.run(p ?? {});
|
|
56
|
+
return [];
|
|
57
|
+
},
|
|
46
58
|
executeRaw: async (q, p) => (db.prepare(q).run(p ?? {}).changes ?? 0),
|
|
47
59
|
commit: async () => { if (!done) {
|
|
48
60
|
db.prepare('COMMIT').run();
|
package/dist/sqlite/index.d.ts
CHANGED
package/dist/sqlite/index.js
CHANGED
package/dist/typed.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { AdapterTableClient, An5Adapter } from './an5Adapter';
|
|
2
|
+
type AdapterMethodKeys = 'dialect' | 'exec' | '$queryRawUnsafe' | '$executeRaw' | '$executeRawUnsafe' | '$connect' | '$disconnect' | '$transaction' | '$begin' | 'table' | '$on' | '$off' | '$emit' | '$use' | 'view' | '$queryProc' | '$executeProc' | 'readRange' | 'writeRange' | 'appendRange' | 'listSheets' | 'deleteSheet';
|
|
3
|
+
export type AdapterAPI = Pick<An5Adapter, AdapterMethodKeys>;
|
|
4
|
+
export type TypedAn5Adapter<TModels extends object = Record<string, AdapterTableClient<any>>> = AdapterAPI & TModels;
|
|
5
|
+
export {};
|
package/dist/typed.js
ADDED