@an5/adapters 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.
Files changed (91) hide show
  1. package/README.md +263 -0
  2. package/dotnet/An5Adapter.cs +275 -0
  3. package/dotnet/Base/Core.cs +82 -0
  4. package/dotnet/Mssql/MssqlEngine.cs +144 -0
  5. package/dotnet/Postgres/PostgresEngine.cs +121 -0
  6. package/package.json +46 -0
  7. package/python/an5_adapter.py +97 -0
  8. package/python/base/__init__.py +3 -0
  9. package/python/base/dialects.py +8 -0
  10. package/python/base/metadata.py +9 -0
  11. package/python/base/sql.py +121 -0
  12. package/python/mssql/__init__.py +1 -0
  13. package/python/mssql/provider.py +62 -0
  14. package/python/postgres/__init__.py +1 -0
  15. package/python/postgres/provider.py +15 -0
  16. package/python/table_client.py +209 -0
  17. package/typescript/an5Adapter.d.ts +117 -0
  18. package/typescript/an5Adapter.js +447 -0
  19. package/typescript/an5Adapter.ts +474 -0
  20. package/typescript/base/index.d.ts +3 -0
  21. package/typescript/base/index.js +19 -0
  22. package/typescript/base/index.ts +3 -0
  23. package/typescript/base/metadata.d.ts +14 -0
  24. package/typescript/base/metadata.js +17 -0
  25. package/typescript/base/metadata.ts +28 -0
  26. package/typescript/base/sql.d.ts +4 -0
  27. package/typescript/base/sql.js +143 -0
  28. package/typescript/base/sql.ts +98 -0
  29. package/typescript/base/types.d.ts +21 -0
  30. package/typescript/base/types.js +2 -0
  31. package/typescript/base/types.ts +24 -0
  32. package/typescript/config.d.ts +17 -0
  33. package/typescript/config.js +92 -0
  34. package/typescript/config.ts +95 -0
  35. package/typescript/googlesheets/adapter.d.ts +31 -0
  36. package/typescript/googlesheets/adapter.js +138 -0
  37. package/typescript/googlesheets/adapter.ts +167 -0
  38. package/typescript/googlesheets/an5SheetsAdapter.d.ts +3 -0
  39. package/typescript/googlesheets/an5SheetsAdapter.js +8 -0
  40. package/typescript/googlesheets/an5SheetsAdapter.ts +3 -0
  41. package/typescript/googlesheets/config.d.ts +17 -0
  42. package/typescript/googlesheets/config.js +29 -0
  43. package/typescript/googlesheets/config.ts +33 -0
  44. package/typescript/googlesheets/helpers.d.ts +9 -0
  45. package/typescript/googlesheets/helpers.js +155 -0
  46. package/typescript/googlesheets/helpers.ts +124 -0
  47. package/typescript/googlesheets/index.d.ts +2 -0
  48. package/typescript/googlesheets/index.js +9 -0
  49. package/typescript/googlesheets/index.ts +2 -0
  50. package/typescript/googlesheets/parseConnectionString.d.ts +11 -0
  51. package/typescript/googlesheets/parseConnectionString.js +44 -0
  52. package/typescript/googlesheets/parseConnectionString.ts +44 -0
  53. package/typescript/googlesheets/retry.d.ts +3 -0
  54. package/typescript/googlesheets/retry.js +26 -0
  55. package/typescript/googlesheets/retry.ts +23 -0
  56. package/typescript/googlesheets/sqlExecutor.d.ts +12 -0
  57. package/typescript/googlesheets/sqlExecutor.js +306 -0
  58. package/typescript/googlesheets/sqlExecutor.ts +301 -0
  59. package/typescript/googlesheets/tableClient.d.ts +78 -0
  60. package/typescript/googlesheets/tableClient.js +394 -0
  61. package/typescript/googlesheets/tableClient.ts +434 -0
  62. package/typescript/googlesheets/types.d.ts +4 -0
  63. package/typescript/googlesheets/types.js +3 -0
  64. package/typescript/googlesheets/types.ts +6 -0
  65. package/typescript/index.d.ts +2 -0
  66. package/typescript/index.js +14 -0
  67. package/typescript/index.ts +15 -0
  68. package/typescript/mssql/engine.d.ts +16 -0
  69. package/typescript/mssql/engine.js +138 -0
  70. package/typescript/mssql/engine.ts +132 -0
  71. package/typescript/mssql/index.d.ts +1 -0
  72. package/typescript/mssql/index.js +17 -0
  73. package/typescript/mssql/index.ts +1 -0
  74. package/typescript/mysql/engine.d.ts +13 -0
  75. package/typescript/mysql/engine.js +77 -0
  76. package/typescript/mysql/engine.ts +80 -0
  77. package/typescript/mysql/index.d.ts +1 -0
  78. package/typescript/mysql/index.js +17 -0
  79. package/typescript/mysql/index.ts +1 -0
  80. package/typescript/postgres/engine.d.ts +13 -0
  81. package/typescript/postgres/engine.js +86 -0
  82. package/typescript/postgres/engine.ts +87 -0
  83. package/typescript/postgres/index.d.ts +1 -0
  84. package/typescript/postgres/index.js +17 -0
  85. package/typescript/postgres/index.ts +1 -0
  86. package/typescript/sqlite/engine.d.ts +13 -0
  87. package/typescript/sqlite/engine.js +58 -0
  88. package/typescript/sqlite/engine.ts +55 -0
  89. package/typescript/sqlite/index.d.ts +1 -0
  90. package/typescript/sqlite/index.js +17 -0
  91. package/typescript/sqlite/index.ts +1 -0
@@ -0,0 +1,434 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { getFieldsForModel } from '../base/metadata';
3
+ import type { An5SheetsAdapter } from './adapter';
4
+ import { buildOrderBy, coerceCell, esc, matchWhere, resolveSheetName, sortRows } from './helpers';
5
+ import { withRetry } from './retry';
6
+
7
+ // ─── Table Client ─────────────────────────────────────────────────────────────
8
+
9
+ export class SheetsTableClient<T = any> {
10
+ constructor(
11
+ private adapter: An5SheetsAdapter,
12
+ private modelName: string,
13
+ private sheetMapping?: Record<string, string>,
14
+ ) {}
15
+
16
+ private get sheetName(): string {
17
+ return resolveSheetName(this.modelName, this.sheetMapping);
18
+ }
19
+
20
+ private get escSheetName(): string {
21
+ return esc(this.sheetName);
22
+ }
23
+
24
+ private get fields(): Record<string, { ts: string; sql: string }> {
25
+ return getFieldsForModel(this.modelName);
26
+ }
27
+
28
+ private async ensureSheetExists(): Promise<void> {
29
+ const existing = await this.adapter.getSheetMeta(this.sheetName);
30
+ if (existing) return;
31
+
32
+ const api = await this.adapter.getSheets();
33
+ await withRetry(() =>
34
+ api.spreadsheets.batchUpdate({
35
+ spreadsheetId: this.adapter.config.spreadsheetId,
36
+ requestBody: {
37
+ requests: [{ addSheet: { properties: { title: this.sheetName } } }],
38
+ },
39
+ })
40
+ );
41
+ this.adapter.invalidateCache();
42
+ }
43
+
44
+ private async readAllRows(): Promise<{ headers: string[]; rows: Record<string, any>[] }> {
45
+ const api = await this.adapter.getSheets();
46
+ const res = await withRetry(() =>
47
+ api.spreadsheets.values.get({
48
+ spreadsheetId: this.adapter.config.spreadsheetId,
49
+ range: `${this.escSheetName}!A:ZZ`,
50
+ })
51
+ );
52
+ const values = res.data.values || [];
53
+ if (values.length < 1) return { headers: [], rows: [] };
54
+
55
+ const headers = values[0] as string[];
56
+ const rows: Record<string, any>[] = [];
57
+ for (let i = 1; i < values.length; i++) {
58
+ const row: Record<string, any> = { __row: i + 1 };
59
+ for (let j = 0; j < headers.length; j++) {
60
+ row[headers[j]] = coerceCell(values[i][j], this.fields[headers[j]]);
61
+ }
62
+ rows.push(row);
63
+ }
64
+ return { headers, rows };
65
+ }
66
+
67
+ private async getOrCreateHeaders(cols: string[]): Promise<string[]> {
68
+ const api = await this.adapter.getSheets();
69
+ await this.ensureSheetExists();
70
+
71
+ const res = await withRetry(() =>
72
+ api.spreadsheets.values.get({
73
+ spreadsheetId: this.adapter.config.spreadsheetId,
74
+ range: `${this.escSheetName}!A1:ZZ1`,
75
+ })
76
+ );
77
+ const existing = (res.data.values || [])[0] || [];
78
+ if (existing.length > 0) return existing as string[];
79
+
80
+ await withRetry(() =>
81
+ api.spreadsheets.values.update({
82
+ spreadsheetId: this.adapter.config.spreadsheetId,
83
+ range: `${this.escSheetName}!A1`,
84
+ valueInputOption: 'RAW',
85
+ requestBody: { values: [cols] },
86
+ })
87
+ );
88
+ return cols;
89
+ }
90
+
91
+ private rowToValues(data: Record<string, any>, headers: string[]): any[] {
92
+ return headers.map(h => {
93
+ const v = data[h];
94
+ if (v instanceof Date) return v.toISOString();
95
+ if (v === null || v === undefined) return '';
96
+ if (typeof v === 'boolean') return v ? 'TRUE' : 'FALSE';
97
+ if (typeof v === 'object') return JSON.stringify(v);
98
+ return String(v);
99
+ });
100
+ }
101
+
102
+ private async deleteRowByIndex(rowIdx: number, sheetIdVal: number): Promise<void> {
103
+ const api = await this.adapter.getSheets();
104
+ await withRetry(() =>
105
+ api.spreadsheets.batchUpdate({
106
+ spreadsheetId: this.adapter.config.spreadsheetId,
107
+ requestBody: {
108
+ requests: [{
109
+ deleteDimension: {
110
+ range: {
111
+ sheetId: sheetIdVal,
112
+ dimension: 'ROWS',
113
+ startIndex: rowIdx - 1,
114
+ endIndex: rowIdx,
115
+ },
116
+ },
117
+ }],
118
+ },
119
+ })
120
+ );
121
+ }
122
+
123
+ // ── CRUD ────────────────────────────────────────────────────────────────────
124
+
125
+ async findMany(args?: { where?: any; orderBy?: any; skip?: number; take?: number; select?: any }): Promise<T[]> {
126
+ const { headers, rows } = await this.readAllRows();
127
+ if (headers.length === 0) return [];
128
+
129
+ let filtered = rows.filter(r => matchWhere(r, args?.where));
130
+ const orderSql = buildOrderBy(args?.orderBy);
131
+ if (orderSql) filtered = sortRows(filtered, orderSql);
132
+
133
+ const skip = args?.skip ?? 0;
134
+ if (args?.take !== undefined) {
135
+ filtered = filtered.slice(skip, skip + args.take);
136
+ } else if (skip > 0) {
137
+ filtered = filtered.slice(skip);
138
+ }
139
+
140
+ const select = args?.select;
141
+ if (select) {
142
+ const selectedKeys = Object.keys(select).filter(k => select[k] === true);
143
+ return filtered.map(r => {
144
+ const obj: any = {};
145
+ for (const k of selectedKeys) obj[k] = r[k];
146
+ return obj as T;
147
+ });
148
+ }
149
+
150
+ return filtered.map(r => {
151
+ const { __row, ...rest } = r;
152
+ return rest as T;
153
+ });
154
+ }
155
+
156
+ async findFirst(args?: { where?: any; orderBy?: any; select?: any }): Promise<T | null> {
157
+ const rows = await this.findMany({ ...args, take: 1 });
158
+ return rows[0] ?? null;
159
+ }
160
+
161
+ async findUnique(args: { where: any }): Promise<T | null> {
162
+ return this.findFirst({ where: args.where });
163
+ }
164
+
165
+ async count(args?: { where?: any }): Promise<number> {
166
+ const rows = await this.findMany({ where: args?.where });
167
+ return rows.length;
168
+ }
169
+
170
+ async create(args: { data: Partial<T> }): Promise<T> {
171
+ const fields = this.fields;
172
+ const idFieldName = Object.prototype.hasOwnProperty.call(fields, 'id')
173
+ ? 'id'
174
+ : Object.keys(fields).find(name => name.endsWith('_id') || name.endsWith('Id') || name.toLowerCase() === 'id');
175
+
176
+ const data: any = { ...args.data } as any;
177
+ if (idFieldName) {
178
+ const fieldDef = fields[idFieldName];
179
+ const rawType = typeof fieldDef === 'string' ? fieldDef : (fieldDef?.ts || fieldDef?.sql || '');
180
+ const isStringType = ['string', 'uuid', 'uniqueidentifier', 'nvarchar', 'varchar', 'text'].includes(rawType.toLowerCase());
181
+ if (isStringType && !data[idFieldName]) {
182
+ data[idFieldName] = randomUUID();
183
+ }
184
+ }
185
+
186
+ const cols = Object.keys(data).filter(k => data[k] !== undefined);
187
+ const headers = await this.getOrCreateHeaders(cols);
188
+
189
+ for (const h of headers) {
190
+ if (data[h] === undefined) data[h] = null;
191
+ }
192
+
193
+ await this.adapter.appendRange(`${this.escSheetName}!A:A`, [
194
+ this.rowToValues(data, headers),
195
+ ]);
196
+
197
+ return data as T;
198
+ }
199
+
200
+ async createMany(args: { data: Partial<T>[]; skipDuplicates?: boolean }): Promise<{ count: number }> {
201
+ if (args.data.length === 0) return { count: 0 };
202
+
203
+ const allKeys = new Set<string>();
204
+ for (const row of args.data) {
205
+ Object.keys(row as any).forEach(k => allKeys.add(k));
206
+ }
207
+ const cols = [...allKeys];
208
+ const fields = this.fields;
209
+ const idFieldName = Object.prototype.hasOwnProperty.call(fields, 'id')
210
+ ? 'id'
211
+ : Object.keys(fields).find(name => name.endsWith('_id') || name.endsWith('Id') || name.toLowerCase() === 'id');
212
+
213
+ const prepared: Record<string, any>[] = [];
214
+ for (const item of args.data) {
215
+ const data: any = { ...item } as any;
216
+ if (idFieldName) {
217
+ const fieldDef = fields[idFieldName];
218
+ const rawType = typeof fieldDef === 'string' ? fieldDef : (fieldDef?.ts || fieldDef?.sql || '');
219
+ const isStringType = ['string', 'uuid', 'uniqueidentifier', 'nvarchar', 'varchar', 'text'].includes(rawType.toLowerCase());
220
+ if (isStringType && !data[idFieldName]) {
221
+ data[idFieldName] = randomUUID();
222
+ }
223
+ }
224
+ prepared.push(data);
225
+ }
226
+
227
+ const headers = await this.getOrCreateHeaders(cols);
228
+
229
+ const batchValues = prepared.map(data => {
230
+ for (const h of headers) {
231
+ if (data[h] === undefined) data[h] = null;
232
+ }
233
+ return this.rowToValues(data, headers);
234
+ });
235
+
236
+ try {
237
+ await this.adapter.appendRange(`${this.escSheetName}!A:A`, batchValues);
238
+ return { count: batchValues.length };
239
+ } catch (e) {
240
+ if (!args.skipDuplicates) throw e;
241
+ let count = 0;
242
+ for (const row of args.data) {
243
+ try { await this.create({ data: row }); count++; } catch { /* skip */ }
244
+ }
245
+ return { count };
246
+ }
247
+ }
248
+
249
+ async update(args: { where: any; data: Partial<T> }): Promise<T> {
250
+ const { headers, rows } = await this.readAllRows();
251
+ const matching = rows.filter(r => matchWhere(r, args.where));
252
+ if (matching.length === 0) throw new Error('No record found matching where clause');
253
+
254
+ const target = matching[0];
255
+ const updated = { ...target, ...args.data as any, __row: target.__row };
256
+ await this.adapter.writeRange(`${this.escSheetName}!A${target.__row}`, [
257
+ this.rowToValues(updated, headers),
258
+ ]);
259
+
260
+ const { __row, ...rest } = updated;
261
+ return rest as T;
262
+ }
263
+
264
+ async updateMany(args: { where?: any; data: Partial<T> }): Promise<{ count: number }> {
265
+ const { headers, rows } = await this.readAllRows();
266
+ const matching = rows.filter(r => matchWhere(r, args.where));
267
+
268
+ for (const target of matching) {
269
+ const updated = { ...target, ...args.data as any, __row: target.__row };
270
+ await this.adapter.writeRange(`${this.escSheetName}!A${target.__row}`, [
271
+ this.rowToValues(updated, headers),
272
+ ]);
273
+ }
274
+ return { count: matching.length };
275
+ }
276
+
277
+ async delete(args: { where: any }): Promise<T> {
278
+ const { headers, rows } = await this.readAllRows();
279
+ const matching = rows.filter(r => matchWhere(r, args.where));
280
+ if (matching.length === 0) throw new Error('No record found matching where clause');
281
+
282
+ const target = matching[0];
283
+ const meta = await this.adapter.getSheetMeta(this.sheetName);
284
+ if (!meta) throw new Error(`Sheet "${this.sheetName}" not found`);
285
+ await this.deleteRowByIndex(target.__row, meta.sheetId);
286
+
287
+ const { __row, ...rest } = target;
288
+ return rest as T;
289
+ }
290
+
291
+ async deleteMany(args?: { where?: any }): Promise<{ count: number }> {
292
+ const { headers, rows } = await this.readAllRows();
293
+ const matching = rows.filter(r => matchWhere(r, args?.where));
294
+ if (matching.length === 0) return { count: 0 };
295
+
296
+ const meta = await this.adapter.getSheetMeta(this.sheetName);
297
+ if (!meta) throw new Error(`Sheet "${this.sheetName}" not found`);
298
+
299
+ const sorted = [...matching].sort((a, b) => b.__row - a.__row);
300
+ for (const target of sorted) {
301
+ await this.deleteRowByIndex(target.__row, meta.sheetId);
302
+ }
303
+ return { count: matching.length };
304
+ }
305
+
306
+ async deleteAll(): Promise<void> {
307
+ const meta = await this.adapter.getSheetMeta(this.sheetName);
308
+ if (!meta) return;
309
+ const api = await this.adapter.getSheets();
310
+ await withRetry(() =>
311
+ api.spreadsheets.batchUpdate({
312
+ spreadsheetId: this.adapter.config.spreadsheetId,
313
+ requestBody: {
314
+ requests: [{
315
+ deleteDimension: {
316
+ range: {
317
+ sheetId: meta.sheetId,
318
+ dimension: 'ROWS',
319
+ startIndex: 1,
320
+ endIndex: 999999,
321
+ },
322
+ },
323
+ }],
324
+ },
325
+ })
326
+ );
327
+ }
328
+
329
+ async clear(): Promise<void> {
330
+ const api = await this.adapter.getSheets();
331
+ await withRetry(() =>
332
+ api.spreadsheets.values.clear({
333
+ spreadsheetId: this.adapter.config.spreadsheetId,
334
+ range: `${this.escSheetName}!A2:ZZ`,
335
+ })
336
+ );
337
+ }
338
+
339
+ async upsert(args: { where: any; create: Partial<T>; update: Partial<T> }): Promise<T> {
340
+ const existing = await this.findFirst({ where: args.where });
341
+ if (existing) {
342
+ return this.update({ where: args.where, data: args.update });
343
+ }
344
+ return this.create({ data: args.create });
345
+ }
346
+
347
+ async aggregate(args: any): Promise<any> {
348
+ const rows = await this.findMany({ where: args?.where });
349
+
350
+ const result: any = {};
351
+ if (args._count !== undefined) result._count = rows.length;
352
+ if (args._sum) {
353
+ for (const f of Object.keys(args._sum)) {
354
+ result[`_sum_${f}`] = rows.reduce((s, r: any) => s + (Number(r[f]) || 0), 0);
355
+ }
356
+ }
357
+ if (args._avg) {
358
+ for (const f of Object.keys(args._avg)) {
359
+ const sum = rows.reduce((s, r: any) => s + (Number(r[f]) || 0), 0);
360
+ result[`_avg_${f}`] = rows.length > 0 ? sum / rows.length : 0;
361
+ }
362
+ }
363
+ if (args._min) {
364
+ for (const f of Object.keys(args._min)) {
365
+ const nums = rows.map((r: any) => Number(r[f])).filter(n => !isNaN(n));
366
+ result[`_min_${f}`] = nums.length > 0 ? Math.min(...nums) : null;
367
+ }
368
+ }
369
+ if (args._max) {
370
+ for (const f of Object.keys(args._max)) {
371
+ const nums = rows.map((r: any) => Number(r[f])).filter(n => !isNaN(n));
372
+ result[`_max_${f}`] = nums.length > 0 ? Math.max(...nums) : null;
373
+ }
374
+ }
375
+ return result;
376
+ }
377
+
378
+ async groupBy(args: any): Promise<any[]> {
379
+ const rows = await this.findMany({ where: args?.where });
380
+ const byCols: string[] = args.by || [];
381
+
382
+ const groups: Record<string, any[]> = {};
383
+ for (const row of rows) {
384
+ const key = byCols.map(c => (row as any)[c]).join('|');
385
+ if (!groups[key]) groups[key] = [];
386
+ groups[key].push(row);
387
+ }
388
+
389
+ return Object.entries(groups).map(([key, group]) => {
390
+ const entry: any = {};
391
+ const parts = key.split('|');
392
+ byCols.forEach((c, i) => { entry[c] = parts[i]; });
393
+ entry._count = group.length;
394
+ return entry;
395
+ });
396
+ }
397
+
398
+ async vectorSearch(args: {
399
+ vector: number[];
400
+ take?: number;
401
+ where?: any;
402
+ vectorField?: string;
403
+ distanceMetric?: 'cosine' | 'euclidean' | 'dot';
404
+ }): Promise<(T & { distance: number })[]> {
405
+ const rows = await this.findMany({ where: args.where });
406
+ const vectorField = args.vectorField || 'embedding';
407
+ const metric = args.distanceMetric || 'cosine';
408
+
409
+ const scored: { row: any; dist: number }[] = [];
410
+ for (const raw of rows) {
411
+ const row = raw as any;
412
+ const rawVec = row[vectorField];
413
+ if (!rawVec) continue;
414
+ let vec: number[] = [];
415
+ try { vec = typeof rawVec === 'string' ? JSON.parse(rawVec) : rawVec; } catch { continue; }
416
+ if (!Array.isArray(vec) || vec.length !== args.vector.length) continue;
417
+
418
+ let dot = 0, m1 = 0, m2 = 0;
419
+ for (let i = 0; i < args.vector.length; i++) {
420
+ dot += args.vector[i] * vec[i];
421
+ m1 += args.vector[i] ** 2;
422
+ m2 += vec[i] ** 2;
423
+ }
424
+ const cosine = m1 && m2 ? dot / (Math.sqrt(m1) * Math.sqrt(m2)) : 0;
425
+ const dist = metric === 'cosine' ? 1 - cosine
426
+ : metric === 'dot' ? -dot
427
+ : Math.sqrt(args.vector.reduce((s, v, i) => s + (v - vec[i]) ** 2, 0));
428
+ scored.push({ row, dist });
429
+ }
430
+
431
+ scored.sort((a, b) => a.dist - b.dist);
432
+ return scored.slice(0, args.take ?? 10).map(s => ({ ...s.row, distance: s.dist }));
433
+ }
434
+ }
@@ -0,0 +1,4 @@
1
+ export interface SheetMeta {
2
+ sheetId: number;
3
+ title: string;
4
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ // ─── Cache ────────────────────────────────────────────────────────────────────
3
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ // ─── Cache ────────────────────────────────────────────────────────────────────
2
+
3
+ export interface SheetMeta {
4
+ sheetId: number;
5
+ title: string;
6
+ }
@@ -0,0 +1,2 @@
1
+ export { An5Adapter, AdapterTableClient, createAn5Adapter, setAdapterMetadata, An5AdapterConfig, AdapterMetadata, Dialect, } from './an5Adapter';
2
+ export { getLlmConfig, setLlmConfig, getEmbeddingConfig, setEmbeddingConfig, resetAdapter, LlmConfigData, EmbeddingConfigData, } from './config';
@@ -0,0 +1,14 @@
1
+ "use strict";
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;
4
+ var an5Adapter_1 = require("./an5Adapter");
5
+ Object.defineProperty(exports, "An5Adapter", { enumerable: true, get: function () { return an5Adapter_1.An5Adapter; } });
6
+ Object.defineProperty(exports, "AdapterTableClient", { enumerable: true, get: function () { return an5Adapter_1.AdapterTableClient; } });
7
+ Object.defineProperty(exports, "createAn5Adapter", { enumerable: true, get: function () { return an5Adapter_1.createAn5Adapter; } });
8
+ Object.defineProperty(exports, "setAdapterMetadata", { enumerable: true, get: function () { return an5Adapter_1.setAdapterMetadata; } });
9
+ var config_1 = require("./config");
10
+ Object.defineProperty(exports, "getLlmConfig", { enumerable: true, get: function () { return config_1.getLlmConfig; } });
11
+ Object.defineProperty(exports, "setLlmConfig", { enumerable: true, get: function () { return config_1.setLlmConfig; } });
12
+ Object.defineProperty(exports, "getEmbeddingConfig", { enumerable: true, get: function () { return config_1.getEmbeddingConfig; } });
13
+ Object.defineProperty(exports, "setEmbeddingConfig", { enumerable: true, get: function () { return config_1.setEmbeddingConfig; } });
14
+ Object.defineProperty(exports, "resetAdapter", { enumerable: true, get: function () { return config_1.resetAdapter; } });
@@ -0,0 +1,15 @@
1
+ export {
2
+ An5Adapter,
3
+ AdapterTableClient,
4
+ createAn5Adapter,
5
+ setAdapterMetadata,
6
+ An5AdapterConfig,
7
+ AdapterMetadata,
8
+ Dialect,
9
+ } from './an5Adapter';
10
+ export {
11
+ getLlmConfig, setLlmConfig,
12
+ getEmbeddingConfig, setEmbeddingConfig,
13
+ resetAdapter,
14
+ LlmConfigData, EmbeddingConfigData,
15
+ } from './config';
@@ -0,0 +1,16 @@
1
+ import sql from 'mssql';
2
+ import type { An5AdapterConfig, Dialect, QueryEngine, TransactionHandle } from '../base/types';
3
+ export declare function parseMssqlConnectionString(url: string): sql.config;
4
+ export declare class MssqlEngine implements QueryEngine {
5
+ dialect: Dialect;
6
+ private pool;
7
+ private config;
8
+ constructor(adapterConfig: An5AdapterConfig);
9
+ private getPool;
10
+ private attachParams;
11
+ exec<T = any>(query: string, params?: Record<string, any>): Promise<T[]>;
12
+ executeRaw(query: string, params?: Record<string, any>): Promise<number>;
13
+ connect(): Promise<void>;
14
+ disconnect(): Promise<void>;
15
+ beginTransaction(): Promise<TransactionHandle>;
16
+ }
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MssqlEngine = void 0;
7
+ exports.parseMssqlConnectionString = parseMssqlConnectionString;
8
+ const mssql_1 = __importDefault(require("mssql"));
9
+ // ─── MSSQL Connection Config ───────────────────────────────────────────────────────
10
+ function parseMssqlConnectionString(url) {
11
+ let cleanUrl = (url || '').trim();
12
+ // Strip scheme prefix
13
+ cleanUrl = cleanUrl.replace(/^(?:sqlserver|mssql):\/\//i, '');
14
+ const parts = cleanUrl.split(';');
15
+ const firstPart = parts[0].trim();
16
+ // host:port or host,port (SQL Server native style)
17
+ let server = firstPart;
18
+ let port = 1433;
19
+ const commaIdx = firstPart.lastIndexOf(',');
20
+ const colonIdx = firstPart.lastIndexOf(':');
21
+ if (commaIdx !== -1) {
22
+ server = firstPart.slice(0, commaIdx).trim();
23
+ port = parseInt(firstPart.slice(commaIdx + 1), 10) || 1433;
24
+ }
25
+ else if (colonIdx !== -1 && !firstPart.includes('=')) {
26
+ server = firstPart.slice(0, colonIdx).trim();
27
+ port = parseInt(firstPart.slice(colonIdx + 1), 10) || 1433;
28
+ }
29
+ const config = {
30
+ server,
31
+ port,
32
+ options: { encrypt: true, trustServerCertificate: true },
33
+ pool: { max: 10, min: 0, idleTimeoutMillis: 30000 },
34
+ requestTimeout: 60000,
35
+ connectionTimeout: 15000,
36
+ };
37
+ for (let i = 1; i < parts.length; i++) {
38
+ const part = parts[i].trim();
39
+ if (!part)
40
+ continue;
41
+ const eqIdx = part.indexOf('=');
42
+ if (eqIdx === -1)
43
+ continue;
44
+ const key = part.slice(0, eqIdx).trim().toLowerCase();
45
+ const value = decodeURIComponent(part.slice(eqIdx + 1).trim());
46
+ if (key === 'database' || key === 'initial catalog')
47
+ config.database = value;
48
+ else if (key === 'user' || key === 'uid' || key === 'user id')
49
+ config.user = value;
50
+ else if (key === 'password' || key === 'pwd')
51
+ config.password = value;
52
+ else if (key === 'server' || key === 'data source') {
53
+ // SERVER=host,port style (key-value form)
54
+ const [s, p] = value.split(',');
55
+ config.server = s.trim();
56
+ if (p)
57
+ config.port = parseInt(p.trim(), 10) || 1433;
58
+ }
59
+ else if (key === 'encrypt')
60
+ config.options.encrypt = value.toLowerCase() === 'true';
61
+ else if (key === 'trustservercertificate')
62
+ config.options.trustServerCertificate = value.toLowerCase() === 'true';
63
+ else if (key === 'connection timeout')
64
+ config.connectionTimeout = parseInt(value, 10) * 1000;
65
+ }
66
+ return config;
67
+ }
68
+ // ─── MSSQL Engine ──────────────────────────────────────────────────────────────────
69
+ class MssqlEngine {
70
+ constructor(adapterConfig) {
71
+ this.dialect = 'mssql';
72
+ this.pool = null;
73
+ this.config = parseMssqlConnectionString(adapterConfig.connectionString);
74
+ if (adapterConfig.poolMax)
75
+ this.config.pool = { ...this.config.pool, max: adapterConfig.poolMax };
76
+ if (adapterConfig.requestTimeout)
77
+ this.config.requestTimeout = adapterConfig.requestTimeout;
78
+ if (adapterConfig.connectionTimeout)
79
+ this.config.connectionTimeout = adapterConfig.connectionTimeout;
80
+ }
81
+ async getPool() {
82
+ if (!this.pool)
83
+ this.pool = new mssql_1.default.ConnectionPool(this.config).connect();
84
+ return this.pool;
85
+ }
86
+ attachParams(req, params) {
87
+ if (params)
88
+ for (const [k, v] of Object.entries(params))
89
+ req.input(k, v ?? null);
90
+ }
91
+ async exec(query, params) {
92
+ const pool = await this.getPool();
93
+ const req = new mssql_1.default.Request(pool);
94
+ this.attachParams(req, params);
95
+ const result = await req.query(query);
96
+ return (result.recordset || []);
97
+ }
98
+ async executeRaw(query, params) {
99
+ const pool = await this.getPool();
100
+ const req = new mssql_1.default.Request(pool);
101
+ this.attachParams(req, params);
102
+ const result = await req.query(query);
103
+ return result.rowsAffected[0] ?? 0;
104
+ }
105
+ async connect() { await this.getPool(); }
106
+ async disconnect() {
107
+ if (this.pool) {
108
+ const p = await this.pool;
109
+ await p.close();
110
+ this.pool = null;
111
+ }
112
+ }
113
+ async beginTransaction() {
114
+ const pool = await this.getPool();
115
+ const tx = new mssql_1.default.Transaction(pool);
116
+ await tx.begin();
117
+ const buildReq = (params) => {
118
+ const req = new mssql_1.default.Request(tx);
119
+ if (params)
120
+ for (const [k, v] of Object.entries(params))
121
+ req.input(k, v ?? null);
122
+ return req;
123
+ };
124
+ return {
125
+ exec: async (q, p) => {
126
+ const r = await buildReq(p).query(q);
127
+ return (r.recordset || []);
128
+ },
129
+ executeRaw: async (q, p) => {
130
+ const r = await buildReq(p).query(q);
131
+ return r.rowsAffected[0] ?? 0;
132
+ },
133
+ commit: () => tx.commit(),
134
+ rollback: () => tx.rollback(),
135
+ };
136
+ }
137
+ }
138
+ exports.MssqlEngine = MssqlEngine;