@an5/adapters 0.2.5 → 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 -305
  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 +4 -1
  10. package/dist/browser.js +9 -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 +3 -1
  19. package/dist/index.js +7 -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 +17 -7
  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 +31 -27
  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
@@ -1,87 +1,87 @@
1
- import type { An5AdapterConfig, Dialect, QueryEngine, TransactionHandle } from '../base/types';
2
-
3
- // ─── PostgreSQL Engine ─────────────────────────────────────────────────────────────
4
-
5
- let PgPool: any = null;
6
- try { PgPool = require('pg').Pool; } catch { }
7
-
8
- export class PostgresEngine implements QueryEngine {
9
- dialect: Dialect = 'postgres';
10
- private pool: any = null;
11
-
12
- constructor(adapterConfig: An5AdapterConfig) {
13
- if (!PgPool) throw new Error('pg package is required for PostgreSQL support. Run: npm install pg');
14
- this.pool = new PgPool({
15
- connectionString: adapterConfig.connectionString,
16
- max: adapterConfig.poolMax ?? 10,
17
- });
18
- }
19
-
20
- /** Convert @name → $N; identical names reuse the same $N */
21
- private transform(query: string, params?: Record<string, any>): { text: string; values: any[] } {
22
- if (!params || Object.keys(params).length === 0) return { text: query, values: [] };
23
- const values: any[] = [];
24
- const seen: Record<string, number> = {};
25
- const text = query.replace(/@(\w+)/g, (_, name: string) => {
26
- if (seen[name] !== undefined) return `$${seen[name]}`;
27
- const idx = values.length + 1;
28
- seen[name] = idx;
29
- values.push(params[name] ?? null);
30
- return `$${idx}`;
31
- });
32
- return { text, values };
33
- }
34
-
35
- async exec<T = any>(query: string, params?: Record<string, any>): Promise<T[]> {
36
- const { text, values } = this.transform(query, params);
37
- const result = await this.pool.query(text, values);
38
- return result.rows as T[];
39
- }
40
-
41
- async executeRaw(query: string, params?: Record<string, any>): Promise<number> {
42
- const { text, values } = this.transform(query, params);
43
- const result = await this.pool.query(text, values);
44
- return result.rowCount ?? 0;
45
- }
46
-
47
- async connect(): Promise<void> {
48
- const client = await this.pool.connect();
49
- client.release();
50
- }
51
-
52
- async disconnect(): Promise<void> { await this.pool.end(); }
53
-
54
- async beginTransaction(): Promise<TransactionHandle> {
55
- const client = await this.pool.connect();
56
- await client.query('BEGIN');
57
-
58
- const transform = (query: string, params?: Record<string, any>) => {
59
- if (!params || Object.keys(params).length === 0) return { text: query, values: [] };
60
- const values: any[] = [];
61
- const seen: Record<string, number> = {};
62
- const text = query.replace(/@(\w+)/g, (_, name: string) => {
63
- if (seen[name] !== undefined) return `$${seen[name]}`;
64
- const idx = values.length + 1;
65
- seen[name] = idx;
66
- values.push(params[name] ?? null);
67
- return `$${idx}`;
68
- });
69
- return { text, values };
70
- };
71
-
72
- return {
73
- exec: async <T>(q: string, p?: Record<string, any>) => {
74
- const { text, values } = transform(q, p);
75
- const r = await client.query(text, values);
76
- return (r.rows || []) as T[];
77
- },
78
- executeRaw: async (q: string, p?: Record<string, any>) => {
79
- const { text, values } = transform(q, p);
80
- const r = await client.query(text, values);
81
- return r.rowCount ?? 0;
82
- },
83
- commit: async () => { await client.query('COMMIT'); client.release(); },
84
- rollback: async () => { await client.query('ROLLBACK'); client.release(); },
85
- };
86
- }
87
- }
1
+ import type { An5AdapterConfig, Dialect, QueryEngine, TransactionHandle } from '../base/types';
2
+
3
+ // ─── PostgreSQL Engine ─────────────────────────────────────────────────────────────
4
+
5
+ let PgPool: any = null;
6
+ try { PgPool = require('pg').Pool; } catch { }
7
+
8
+ export class PostgresEngine implements QueryEngine {
9
+ dialect: Dialect = 'postgres';
10
+ private pool: any = null;
11
+
12
+ constructor(adapterConfig: An5AdapterConfig) {
13
+ if (!PgPool) throw new Error('pg package is required for PostgreSQL support. Run: npm install pg');
14
+ this.pool = new PgPool({
15
+ connectionString: adapterConfig.connectionString ?? '',
16
+ max: adapterConfig.poolMax ?? 10,
17
+ });
18
+ }
19
+
20
+ /** Convert @name → $N; identical names reuse the same $N */
21
+ private transform(query: string, params?: Record<string, any>): { text: string; values: any[] } {
22
+ if (!params || Object.keys(params).length === 0) return { text: query, values: [] };
23
+ const values: any[] = [];
24
+ const seen: Record<string, number> = {};
25
+ const text = query.replace(/@(\w+)/g, (_, name: string) => {
26
+ if (seen[name] !== undefined) return `$${seen[name]}`;
27
+ const idx = values.length + 1;
28
+ seen[name] = idx;
29
+ values.push(params[name] ?? null);
30
+ return `$${idx}`;
31
+ });
32
+ return { text, values };
33
+ }
34
+
35
+ async exec<T = any>(query: string, params?: Record<string, any>): Promise<T[]> {
36
+ const { text, values } = this.transform(query, params);
37
+ const result = await this.pool.query(text, values);
38
+ return result.rows as T[];
39
+ }
40
+
41
+ async executeRaw(query: string, params?: Record<string, any>): Promise<number> {
42
+ const { text, values } = this.transform(query, params);
43
+ const result = await this.pool.query(text, values);
44
+ return result.rowCount ?? 0;
45
+ }
46
+
47
+ async connect(): Promise<void> {
48
+ const client = await this.pool.connect();
49
+ client.release();
50
+ }
51
+
52
+ async disconnect(): Promise<void> { await this.pool.end(); }
53
+
54
+ async beginTransaction(): Promise<TransactionHandle> {
55
+ const client = await this.pool.connect();
56
+ await client.query('BEGIN');
57
+
58
+ const transform = (query: string, params?: Record<string, any>) => {
59
+ if (!params || Object.keys(params).length === 0) return { text: query, values: [] };
60
+ const values: any[] = [];
61
+ const seen: Record<string, number> = {};
62
+ const text = query.replace(/@(\w+)/g, (_, name: string) => {
63
+ if (seen[name] !== undefined) return `$${seen[name]}`;
64
+ const idx = values.length + 1;
65
+ seen[name] = idx;
66
+ values.push(params[name] ?? null);
67
+ return `$${idx}`;
68
+ });
69
+ return { text, values };
70
+ };
71
+
72
+ return {
73
+ exec: async <T>(q: string, p?: Record<string, any>) => {
74
+ const { text, values } = transform(q, p);
75
+ const r = await client.query(text, values);
76
+ return (r.rows || []) as T[];
77
+ },
78
+ executeRaw: async (q: string, p?: Record<string, any>) => {
79
+ const { text, values } = transform(q, p);
80
+ const r = await client.query(text, values);
81
+ return r.rowCount ?? 0;
82
+ },
83
+ commit: async () => { await client.query('COMMIT'); client.release(); },
84
+ rollback: async () => { await client.query('ROLLBACK'); client.release(); },
85
+ };
86
+ }
87
+ }
@@ -1 +1 @@
1
- export * from './engine';
1
+ export * from './engine';
@@ -0,0 +1,192 @@
1
+ import type { Dialect, QueryEngine, TransactionHandle } from '../base/types';
2
+
3
+ // ─── Browser SQLite Driver & Config ──────────────────────────────────────────────────
4
+
5
+ export interface SqliteDriver {
6
+ exec<T = any>(query: string, params?: Record<string, any>): Promise<T[]> | T[];
7
+ executeRaw?(query: string, params?: Record<string, any>): Promise<number> | number;
8
+ close?(): Promise<void> | void;
9
+ }
10
+
11
+ export interface SqliteBrowserConfig {
12
+ db?: any; // sql.js Database instance or SQLite WASM DB
13
+ driver?: SqliteDriver;
14
+ exec?: <T = any>(query: string, params?: Record<string, any>) => Promise<T[]> | T[];
15
+ executeRaw?: (query: string, params?: Record<string, any>) => Promise<number> | number;
16
+ }
17
+
18
+ // ─── Browser SQLite Engine ──────────────────────────────────────────────────────────
19
+
20
+ export class SqliteBrowserEngine implements QueryEngine {
21
+ dialect: Dialect = 'sqlite';
22
+ private db: any = null;
23
+ private driver: SqliteDriver | null = null;
24
+ private customExec: ((query: string, params?: Record<string, any>) => Promise<any[]> | any[]) | null = null;
25
+ private customExecuteRaw: ((query: string, params?: Record<string, any>) => Promise<number> | number) | null = null;
26
+
27
+ constructor(config?: SqliteBrowserConfig | any) {
28
+ if (!config) return;
29
+
30
+ if (config.exec && typeof config.exec === 'function') {
31
+ this.customExec = config.exec;
32
+ this.customExecuteRaw = config.executeRaw ?? null;
33
+ return;
34
+ }
35
+
36
+ if (config.driver) {
37
+ this.driver = config.driver;
38
+ return;
39
+ }
40
+
41
+ // Direct DB instance (e.g. sql.js Database or sqlite-wasm)
42
+ if (config.db) {
43
+ this.db = config.db;
44
+ return;
45
+ }
46
+
47
+ // If config itself looks like a driver with exec()
48
+ if (typeof config.exec === 'function' && typeof config.run !== 'function' && typeof config.prepare !== 'function') {
49
+ this.driver = config as SqliteDriver;
50
+ return;
51
+ }
52
+
53
+ // If config itself is a Database instance (has prepare, exec, run)
54
+ if (typeof config.prepare === 'function' || typeof config.run === 'function' || typeof config.exec === 'function') {
55
+ this.db = config;
56
+ }
57
+ }
58
+
59
+ private normalizeSqlJsParams(params?: Record<string, any>): Record<string, any> {
60
+ if (!params || typeof params !== 'object') return {};
61
+ const normalized: Record<string, any> = {};
62
+ for (const [k, v] of Object.entries(params)) {
63
+ const key = k.startsWith('@') || k.startsWith(':') || k.startsWith('$') ? k : `@${k}`;
64
+ normalized[key] = v;
65
+ }
66
+ return normalized;
67
+ }
68
+
69
+ async exec<T = any>(query: string, params?: Record<string, any>): Promise<T[]> {
70
+ if (this.customExec) {
71
+ return await this.customExec(query, params);
72
+ }
73
+
74
+ if (this.driver) {
75
+ return await this.driver.exec<T>(query, params);
76
+ }
77
+
78
+ if (this.db) {
79
+ // sql.js Database with prepare()
80
+ if (typeof this.db.prepare === 'function') {
81
+ const stmt = this.db.prepare(query);
82
+ try {
83
+ if (params && Object.keys(params).length > 0) {
84
+ stmt.bind(this.normalizeSqlJsParams(params));
85
+ }
86
+ const results: T[] = [];
87
+ while (stmt.step()) {
88
+ results.push(stmt.getAsObject() as T);
89
+ }
90
+ return results;
91
+ } finally {
92
+ stmt.free();
93
+ }
94
+ }
95
+
96
+ // Fallback sql.js db.exec()
97
+ if (typeof this.db.exec === 'function') {
98
+ const res = this.db.exec(query);
99
+ if (!res || res.length === 0) return [];
100
+ const { columns, values } = res[0];
101
+ return values.map((row: any[]) => {
102
+ const obj: any = {};
103
+ columns.forEach((col: string, i: number) => {
104
+ obj[col] = row[i];
105
+ });
106
+ return obj as T;
107
+ });
108
+ }
109
+ }
110
+
111
+ throw new Error('SqliteBrowserEngine: No SQLite database or driver provided. Pass a sql.js db instance or custom driver.');
112
+ }
113
+
114
+ async executeRaw(query: string, params?: Record<string, any>): Promise<number> {
115
+ if (this.customExecuteRaw) {
116
+ return await this.customExecuteRaw(query, params);
117
+ }
118
+
119
+ if (this.driver && typeof this.driver.executeRaw === 'function') {
120
+ return await this.driver.executeRaw(query, params);
121
+ }
122
+
123
+ if (this.db) {
124
+ if (typeof this.db.prepare === 'function') {
125
+ const stmt = this.db.prepare(query);
126
+ try {
127
+ if (params && Object.keys(params).length > 0) {
128
+ stmt.bind(this.normalizeSqlJsParams(params));
129
+ }
130
+ stmt.step();
131
+ if (typeof this.db.getRowsModified === 'function') {
132
+ return this.db.getRowsModified();
133
+ }
134
+ return 1;
135
+ } finally {
136
+ stmt.free();
137
+ }
138
+ }
139
+
140
+ if (typeof this.db.run === 'function') {
141
+ this.db.run(query, this.normalizeSqlJsParams(params));
142
+ if (typeof this.db.getRowsModified === 'function') {
143
+ return this.db.getRowsModified();
144
+ }
145
+ return 1;
146
+ }
147
+ }
148
+
149
+ const rows = await this.exec(query, params);
150
+ return rows.length;
151
+ }
152
+
153
+ async connect(): Promise<void> {}
154
+
155
+ async disconnect(): Promise<void> {
156
+ if (this.driver && typeof this.driver.close === 'function') {
157
+ await this.driver.close();
158
+ } else if (this.db && typeof this.db.close === 'function') {
159
+ this.db.close();
160
+ }
161
+ }
162
+
163
+ async beginTransaction(): Promise<TransactionHandle> {
164
+ await this.executeRaw('BEGIN');
165
+ let done = false;
166
+
167
+ return {
168
+ exec: async <T>(q: string, p?: Record<string, any>) => this.exec<T>(q, p),
169
+ executeRaw: async (q: string, p?: Record<string, any>) => this.executeRaw(q, p),
170
+ commit: async () => {
171
+ if (!done) {
172
+ await this.executeRaw('COMMIT');
173
+ done = true;
174
+ }
175
+ },
176
+ rollback: async () => {
177
+ if (!done) {
178
+ await this.executeRaw('ROLLBACK');
179
+ done = true;
180
+ }
181
+ },
182
+ };
183
+ }
184
+ }
185
+
186
+ // ─── Browser SQLite Adapter Factory ──────────────────────────────────────────────────
187
+
188
+ export function createBrowserSqliteAdapter(config: SqliteBrowserConfig | any): any {
189
+ const { An5Adapter } = require('../an5Adapter');
190
+ return new An5Adapter({ engine: new SqliteBrowserEngine(config) });
191
+ }
192
+
@@ -1,55 +1,66 @@
1
- import type { An5AdapterConfig, Dialect, QueryEngine, TransactionHandle } from '../base/types';
2
-
3
- // ─── SQLite Engine ─────────────────────────────────────────────────────────────────
4
-
5
- let BetterSqlite3: any = null;
6
- try { BetterSqlite3 = require('better-sqlite3'); } catch { }
7
-
8
- export class SqliteEngine implements QueryEngine {
9
- dialect: Dialect = 'sqlite';
10
- private db: any = null;
11
- private readonly filePath: string;
12
-
13
- constructor(adapterConfig: An5AdapterConfig) {
14
- if (!BetterSqlite3) throw new Error('better-sqlite3 package is required for SQLite support. Run: npm install better-sqlite3');
15
- this.filePath = adapterConfig.connectionString
16
- .replace(/^sqlite:\/\/\//i, '/')
17
- .replace(/^sqlite:\/\//i, '');
18
- }
19
-
20
- private getDb(): any {
21
- if (!this.db) this.db = new BetterSqlite3(this.filePath);
22
- return this.db;
23
- }
24
-
25
- // better-sqlite3 natively supports @name parameters
26
- async exec<T = any>(query: string, params?: Record<string, any>): Promise<T[]> {
27
- return this.getDb().prepare(query).all(params ?? {}) as T[];
28
- }
29
-
30
- async executeRaw(query: string, params?: Record<string, any>): Promise<number> {
31
- const info = this.getDb().prepare(query).run(params ?? {});
32
- return info.changes ?? 0;
33
- }
34
-
35
- async connect(): Promise<void> { this.getDb(); }
36
-
37
- async disconnect(): Promise<void> {
38
- if (this.db) { this.db.close(); this.db = null; }
39
- }
40
-
41
- async beginTransaction(): Promise<TransactionHandle> {
42
- const db = this.getDb();
43
- db.prepare('BEGIN').run();
44
- let done = false;
45
-
46
- return {
47
- exec: async <T>(q: string, p?: Record<string, any>) =>
48
- db.prepare(q).all(p ?? {}) as T[],
49
- executeRaw: async (q: string, p?: Record<string, any>) =>
50
- (db.prepare(q).run(p ?? {}).changes ?? 0),
51
- commit: async () => { if (!done) { db.prepare('COMMIT').run(); done = true; } },
52
- rollback: async () => { if (!done) { db.prepare('ROLLBACK').run(); done = true; } },
53
- };
54
- }
55
- }
1
+ import type { An5AdapterConfig, Dialect, QueryEngine, TransactionHandle } from '../base/types';
2
+
3
+ // ─── SQLite Engine ─────────────────────────────────────────────────────────────────
4
+
5
+ let BetterSqlite3: any = null;
6
+ try { BetterSqlite3 = require('better-sqlite3'); } catch { }
7
+
8
+ export class SqliteEngine implements QueryEngine {
9
+ dialect: Dialect = 'sqlite';
10
+ private db: any = null;
11
+ private readonly filePath: string;
12
+
13
+ constructor(adapterConfig: An5AdapterConfig) {
14
+ if (!BetterSqlite3) throw new Error('better-sqlite3 package is required for SQLite support. Run: npm install better-sqlite3');
15
+ this.filePath = (adapterConfig.connectionString ?? '')
16
+ .replace(/^sqlite:\/\/\//i, '/')
17
+ .replace(/^sqlite:\/\//i, '');
18
+ }
19
+
20
+ private getDb(): any {
21
+ if (!this.db) this.db = new BetterSqlite3(this.filePath);
22
+ return this.db;
23
+ }
24
+
25
+ // better-sqlite3 natively supports @name parameters
26
+ async exec<T = any>(query: string, params?: Record<string, any>): Promise<T[]> {
27
+ const stmt = this.getDb().prepare(query);
28
+ if (stmt.reader) {
29
+ return stmt.all(params ?? {}) as T[];
30
+ }
31
+ stmt.run(params ?? {});
32
+ return [] as T[];
33
+ }
34
+
35
+ async executeRaw(query: string, params?: Record<string, any>): Promise<number> {
36
+ const info = this.getDb().prepare(query).run(params ?? {});
37
+ return info.changes ?? 0;
38
+ }
39
+
40
+ async connect(): Promise<void> { this.getDb(); }
41
+
42
+ async disconnect(): Promise<void> {
43
+ if (this.db) { this.db.close(); this.db = null; }
44
+ }
45
+
46
+ async beginTransaction(): Promise<TransactionHandle> {
47
+ const db = this.getDb();
48
+ db.prepare('BEGIN').run();
49
+ let done = false;
50
+
51
+ return {
52
+ exec: async <T>(q: string, p?: Record<string, any>) => {
53
+ const stmt = db.prepare(q);
54
+ if (stmt.reader) {
55
+ return stmt.all(p ?? {}) as T[];
56
+ }
57
+ stmt.run(p ?? {});
58
+ return [] as T[];
59
+ },
60
+ executeRaw: async (q: string, p?: Record<string, any>) =>
61
+ (db.prepare(q).run(p ?? {}).changes ?? 0),
62
+ commit: async () => { if (!done) { db.prepare('COMMIT').run(); done = true; } },
63
+ rollback: async () => { if (!done) { db.prepare('ROLLBACK').run(); done = true; } },
64
+ };
65
+ }
66
+ }
@@ -1 +1,3 @@
1
- export * from './engine';
1
+ export * from './engine';
2
+ export * from './browserEngine';
3
+
@@ -0,0 +1,52 @@
1
+ import type { AdapterTableClient, An5Adapter } from './an5Adapter';
2
+
3
+ // ─── Typed model access ──────────────────────────────────────────────────────
4
+ // The runtime adapter resolves `db.user` / `db.User` dynamically through a
5
+ // Proxy, which TypeScript normally types as `any` (An5Adapter declares
6
+ // `[key: string]: any`). These helpers let app code bind generated model
7
+ // delegate types (e.g. `UserTableClient` emitted by the schema generator) so
8
+ // `db.user` gets full autocomplete and compile-time argument checking — the
9
+ // standard ORM experience — without changing any runtime behavior.
10
+ //
11
+ // Usage:
12
+ // import { createAn5Adapter } from '@an5/adapters';
13
+ // import type { UserTableClient } from './generated/typescript/User';
14
+ // import type { OrderTableClient } from './generated/typescript/Order';
15
+ // const db = createAn5Adapter<{
16
+ // user: UserTableClient;
17
+ // order: OrderTableClient;
18
+ // }>({ connectionString: process.env.DATABASE_URL! });
19
+ // await db.user.findMany({ where: { email: { contains: '@example.com' } } });
20
+
21
+ // Public adapter surface (methods/getters) without the open-ended index
22
+ // signature, so explicit model props in TModels take effect instead of `any`.
23
+ type AdapterMethodKeys =
24
+ | 'dialect'
25
+ | 'exec'
26
+ | '$queryRawUnsafe'
27
+ | '$executeRaw'
28
+ | '$executeRawUnsafe'
29
+ | '$connect'
30
+ | '$disconnect'
31
+ | '$transaction'
32
+ | '$begin'
33
+ | 'table'
34
+ | '$on'
35
+ | '$off'
36
+ | '$emit'
37
+ | '$use'
38
+ | 'view'
39
+ | '$queryProc'
40
+ | '$executeProc'
41
+ | 'readRange'
42
+ | 'writeRange'
43
+ | 'appendRange'
44
+ | 'listSheets'
45
+ | 'deleteSheet';
46
+
47
+ export type AdapterAPI = Pick<An5Adapter, AdapterMethodKeys>;
48
+
49
+ // An5Adapter with dynamically-resolved model delegates typed as TModels.
50
+ // NOTE: keep AdapterMethodKeys in sync when adding public An5Adapter methods.
51
+ export type TypedAn5Adapter<TModels extends object = Record<string, AdapterTableClient<any>>> =
52
+ AdapterAPI & TModels;