@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.
Files changed (82) hide show
  1. package/README.md +189 -304
  2. package/dist/an5Adapter.d.ts +85 -7
  3. package/dist/an5Adapter.js +736 -64
  4. package/dist/base/metadata.d.ts +10 -0
  5. package/dist/base/metadata.js +107 -0
  6. package/dist/base/sql.d.ts +19 -1
  7. package/dist/base/sql.js +152 -24
  8. package/dist/base/types.d.ts +4 -1
  9. package/dist/browser.d.ts +5 -2
  10. package/dist/browser.js +10 -2
  11. package/dist/googlesheets/adapter.d.ts +1 -0
  12. package/dist/googlesheets/adapter.js +9 -2
  13. package/dist/googlesheets/config.d.ts +4 -4
  14. package/dist/googlesheets/helpers.js +2 -0
  15. package/dist/googlesheets/parseConnectionString.js +5 -2
  16. package/dist/googlesheets/sqlExecutor.js +29 -24
  17. package/dist/googlesheets/tableClient.js +14 -5
  18. package/dist/index.d.ts +5 -1
  19. package/dist/index.js +12 -1
  20. package/dist/mssql/engine.js +8 -4
  21. package/dist/mysql/engine.js +1 -1
  22. package/dist/postgres/engine.js +1 -1
  23. package/dist/sqlite/browserEngine.d.ts +27 -0
  24. package/dist/sqlite/browserEngine.js +161 -0
  25. package/dist/sqlite/engine.js +15 -3
  26. package/dist/sqlite/index.d.ts +1 -0
  27. package/dist/sqlite/index.js +1 -0
  28. package/dist/typed.d.ts +5 -0
  29. package/dist/typed.js +2 -0
  30. package/dotnet/An5Adapter.cs +1089 -275
  31. package/dotnet/Base/Core.cs +340 -82
  32. package/dotnet/Mssql/MssqlEngine.cs +145 -144
  33. package/dotnet/Postgres/PostgresEngine.cs +121 -121
  34. package/golang/an5_adapter.go +314 -0
  35. package/golang/base/base.go +100 -0
  36. package/golang/base/metadata.go +116 -0
  37. package/golang/base/where.go +311 -0
  38. package/golang/go.mod +3 -0
  39. package/golang/mssql/mssql.go +32 -0
  40. package/golang/postgres/postgres.go +37 -0
  41. package/golang/sqlite/sqlite.go +14 -0
  42. package/golang/sqlite_test.go +42 -0
  43. package/golang/table_client.go +1329 -0
  44. package/package.json +18 -8
  45. package/python/an5_adapter.py +119 -97
  46. package/python/base/__init__.py +3 -3
  47. package/python/base/dialects.py +11 -8
  48. package/python/base/metadata.py +35 -10
  49. package/python/base/sql.py +172 -121
  50. package/python/mssql/__init__.py +1 -1
  51. package/python/mssql/provider.py +62 -62
  52. package/python/postgres/__init__.py +1 -1
  53. package/python/postgres/provider.py +15 -15
  54. package/python/table_client.py +619 -216
  55. package/typescript/src/an5Adapter.ts +1220 -505
  56. package/typescript/src/base/index.ts +3 -3
  57. package/typescript/src/base/metadata.ts +148 -28
  58. package/typescript/src/base/sql.ts +264 -98
  59. package/typescript/src/base/types.ts +27 -24
  60. package/typescript/src/browser.ts +10 -6
  61. package/typescript/src/config.ts +95 -95
  62. package/typescript/src/googlesheets/adapter.ts +269 -259
  63. package/typescript/src/googlesheets/an5SheetsAdapter.ts +3 -3
  64. package/typescript/src/googlesheets/config.ts +47 -47
  65. package/typescript/src/googlesheets/helpers.ts +144 -143
  66. package/typescript/src/googlesheets/index.ts +3 -3
  67. package/typescript/src/googlesheets/parseConnectionString.ts +48 -46
  68. package/typescript/src/googlesheets/retry.ts +126 -126
  69. package/typescript/src/googlesheets/sqlExecutor.ts +304 -301
  70. package/typescript/src/googlesheets/tableClient.ts +461 -455
  71. package/typescript/src/googlesheets/types.ts +6 -6
  72. package/typescript/src/index.ts +32 -19
  73. package/typescript/src/mssql/engine.ts +134 -132
  74. package/typescript/src/mssql/index.ts +1 -1
  75. package/typescript/src/mysql/engine.ts +80 -80
  76. package/typescript/src/mysql/index.ts +1 -1
  77. package/typescript/src/postgres/engine.ts +87 -87
  78. package/typescript/src/postgres/index.ts +1 -1
  79. package/typescript/src/sqlite/browserEngine.ts +192 -0
  80. package/typescript/src/sqlite/engine.ts +66 -55
  81. package/typescript/src/sqlite/index.ts +3 -1
  82. 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
- cols.push(rawCols[i]);
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] || m[3] || m[4];
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, headers));
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 ? whereParts[1] : '';
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, headers));
154
+ return selectAll ? result : result.map(r => pickFields(r, fieldList));
150
155
  }
151
- function pickFields(row, fieldList, headers) {
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] || m[2] || m[3];
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] || m[2] || m[3];
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] || m[2] || m[3];
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
- row[headers[j]] = (0, helpers_1.coerceCell)(values[i][j], this.fields[headers[j]]);
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
- dot += args.vector[i] * vec[i];
399
- m1 += args.vector[i] ** 2;
400
- m2 += vec[i] ** 2;
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; } });
@@ -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 part = parts[i].trim();
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
- config.server = s.trim();
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)
@@ -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
  });
@@ -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
+ }
@@ -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
- return this.getDb().prepare(query).all(params ?? {});
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) => db.prepare(q).all(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();
@@ -1 +1,2 @@
1
1
  export * from './engine';
2
+ export * from './browserEngine';
@@ -15,3 +15,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./engine"), exports);
18
+ __exportStar(require("./browserEngine"), exports);
@@ -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
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });