@an5/adapters 0.2.0 → 0.2.2
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 +226 -226
- package/package.json +46 -38
- package/typescript/an5Adapter.d.ts +4 -2
- package/typescript/an5Adapter.js +58 -21
- package/typescript/browser.d.ts +5 -0
- package/typescript/browser.js +12 -0
- package/typescript/googlesheets/adapter.d.ts +3 -2
- package/typescript/googlesheets/adapter.js +77 -7
- package/typescript/googlesheets/an5SheetsAdapter.d.ts +1 -1
- package/typescript/googlesheets/config.d.ts +11 -0
- package/typescript/googlesheets/config.js +7 -0
- package/typescript/googlesheets/helpers.js +1 -1
- package/typescript/googlesheets/index.d.ts +2 -1
- package/typescript/googlesheets/retry.js +21 -8
- package/typescript/googlesheets/tableClient.js +4 -3
- package/typescript/index.d.ts +4 -2
- package/typescript/{an5Adapter.ts → src/an5Adapter.ts} +505 -474
- package/typescript/{base → src/base}/index.ts +3 -3
- package/typescript/{base → src/base}/metadata.ts +28 -28
- package/typescript/{base → src/base}/sql.ts +98 -98
- package/typescript/{base → src/base}/types.ts +24 -24
- package/typescript/src/browser.ts +6 -0
- package/typescript/{config.ts → src/config.ts} +95 -95
- package/typescript/{googlesheets → src/googlesheets}/adapter.ts +242 -167
- package/typescript/{googlesheets → src/googlesheets}/an5SheetsAdapter.ts +3 -3
- package/typescript/{googlesheets → src/googlesheets}/config.ts +44 -33
- package/typescript/{googlesheets → src/googlesheets}/helpers.ts +124 -124
- package/typescript/{googlesheets → src/googlesheets}/index.ts +3 -2
- package/typescript/{googlesheets → src/googlesheets}/parseConnectionString.ts +44 -44
- package/typescript/src/googlesheets/retry.ts +32 -0
- package/typescript/{googlesheets → src/googlesheets}/sqlExecutor.ts +301 -301
- package/typescript/{googlesheets → src/googlesheets}/tableClient.ts +435 -434
- package/typescript/{googlesheets → src/googlesheets}/types.ts +6 -6
- package/typescript/{index.ts → src/index.ts} +19 -15
- package/typescript/{mssql → src/mssql}/engine.ts +132 -132
- package/typescript/{mysql → src/mssql}/index.ts +1 -1
- package/typescript/{mysql → src/mysql}/engine.ts +80 -80
- package/typescript/{postgres → src/mysql}/index.ts +1 -1
- package/typescript/{postgres → src/postgres}/engine.ts +87 -87
- package/typescript/{sqlite → src/postgres}/index.ts +1 -1
- package/typescript/{sqlite → src/sqlite}/engine.ts +55 -55
- package/typescript/{mssql → src/sqlite}/index.ts +1 -1
- package/typescript/googlesheets/retry.ts +0 -23
package/typescript/an5Adapter.js
CHANGED
|
@@ -7,10 +7,6 @@ const googlesheets_1 = require("./googlesheets");
|
|
|
7
7
|
const parseConnectionString_1 = require("./googlesheets/parseConnectionString");
|
|
8
8
|
const sql_1 = require("./base/sql");
|
|
9
9
|
const metadata_1 = require("./base/metadata");
|
|
10
|
-
const mssql_1 = require("./mssql");
|
|
11
|
-
const postgres_1 = require("./postgres");
|
|
12
|
-
const mysql_1 = require("./mysql");
|
|
13
|
-
const sqlite_1 = require("./sqlite");
|
|
14
10
|
var metadata_2 = require("./base/metadata");
|
|
15
11
|
Object.defineProperty(exports, "setAdapterMetadata", { enumerable: true, get: function () { return metadata_2.setAdapterMetadata; } });
|
|
16
12
|
function isSheetsConfig(config) {
|
|
@@ -18,9 +14,23 @@ function isSheetsConfig(config) {
|
|
|
18
14
|
}
|
|
19
15
|
// ─── An5Adapter ────────────────────────────────────────────────────────────────────
|
|
20
16
|
class An5Adapter {
|
|
21
|
-
get dialect() {
|
|
17
|
+
get dialect() {
|
|
18
|
+
if (this.sheetsAdapter)
|
|
19
|
+
return 'googlesheets';
|
|
20
|
+
if (this._engine)
|
|
21
|
+
return this._engine.dialect;
|
|
22
|
+
if (this._engineType === 'postgres')
|
|
23
|
+
return 'postgres';
|
|
24
|
+
if (this._engineType === 'mysql')
|
|
25
|
+
return 'mysql';
|
|
26
|
+
if (this._engineType === 'sqlite')
|
|
27
|
+
return 'sqlite';
|
|
28
|
+
return 'mssql';
|
|
29
|
+
}
|
|
22
30
|
constructor(adapterConfig) {
|
|
23
|
-
this.
|
|
31
|
+
this._engine = null;
|
|
32
|
+
this._engineType = null;
|
|
33
|
+
this._engineConfig = null;
|
|
24
34
|
this.sheetsAdapter = null;
|
|
25
35
|
if (isSheetsConfig(adapterConfig)) {
|
|
26
36
|
this.sheetsAdapter = new googlesheets_1.An5SheetsAdapter(adapterConfig);
|
|
@@ -31,23 +41,48 @@ class An5Adapter {
|
|
|
31
41
|
this.sheetsAdapter = new googlesheets_1.An5SheetsAdapter((0, parseConnectionString_1.parseSheetsConnectionString)(cs));
|
|
32
42
|
return;
|
|
33
43
|
}
|
|
44
|
+
this._engineConfig = adapterConfig;
|
|
34
45
|
if (cs.startsWith('postgres://') || cs.startsWith('postgresql://')) {
|
|
35
|
-
this.
|
|
46
|
+
this._engineType = 'postgres';
|
|
36
47
|
}
|
|
37
48
|
else if (cs.startsWith('mysql://') || cs.startsWith('mariadb://')) {
|
|
38
|
-
this.
|
|
49
|
+
this._engineType = 'mysql';
|
|
39
50
|
}
|
|
40
51
|
else if (cs.startsWith('sqlite://') || cs.endsWith('.sqlite') || cs.endsWith('.db')) {
|
|
41
|
-
this.
|
|
52
|
+
this._engineType = 'sqlite';
|
|
42
53
|
}
|
|
43
54
|
else {
|
|
44
|
-
this.
|
|
55
|
+
this._engineType = 'mssql';
|
|
45
56
|
}
|
|
46
57
|
}
|
|
47
|
-
requireEngine() {
|
|
48
|
-
if (!this.
|
|
58
|
+
async requireEngine() {
|
|
59
|
+
if (!this._engine && this._engineType) {
|
|
60
|
+
switch (this._engineType) {
|
|
61
|
+
case 'postgres': {
|
|
62
|
+
const { PostgresEngine } = require('./postgres.js');
|
|
63
|
+
this._engine = new PostgresEngine(this._engineConfig);
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
case 'mysql': {
|
|
67
|
+
const { MysqlEngine } = require('./mysql.js');
|
|
68
|
+
this._engine = new MysqlEngine(this._engineConfig);
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
case 'sqlite': {
|
|
72
|
+
const { SqliteEngine } = require('./sqlite.js');
|
|
73
|
+
this._engine = new SqliteEngine(this._engineConfig);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
case 'mssql': {
|
|
77
|
+
const { MssqlEngine } = require('./mssql.js');
|
|
78
|
+
this._engine = new MssqlEngine(this._engineConfig);
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (!this._engine)
|
|
49
84
|
throw new Error('SQL engine is not available for Google Sheets adapter');
|
|
50
|
-
return this.
|
|
85
|
+
return this._engine;
|
|
51
86
|
}
|
|
52
87
|
requireSheetsAdapter() {
|
|
53
88
|
if (!this.sheetsAdapter)
|
|
@@ -57,19 +92,19 @@ class An5Adapter {
|
|
|
57
92
|
async exec(query, params) {
|
|
58
93
|
if (this.sheetsAdapter)
|
|
59
94
|
return this.sheetsAdapter.exec(query, params);
|
|
60
|
-
return this.requireEngine().exec(query, params);
|
|
95
|
+
return (await this.requireEngine()).exec(query, params);
|
|
61
96
|
}
|
|
62
97
|
/** INTERNAL: used by AdapterTableClient for DML statements needing row count */
|
|
63
98
|
async _executeRaw(query, params) {
|
|
64
|
-
return this.requireEngine().executeRaw(query, params);
|
|
99
|
+
return (await this.requireEngine()).executeRaw(query, params);
|
|
65
100
|
}
|
|
66
101
|
/** Execute a raw query with positional values → @p_0, @p_1, ... per dialect */
|
|
67
102
|
async $queryRawUnsafe(query, ...values) {
|
|
68
103
|
if (this.sheetsAdapter)
|
|
69
104
|
return this.sheetsAdapter.$queryRawUnsafe(query, ...values);
|
|
105
|
+
const engine = await this.requireEngine();
|
|
70
106
|
const params = {};
|
|
71
107
|
values.forEach((v, i) => { params[`p_${i}`] = v; });
|
|
72
|
-
// Normalise external positional placeholders → @p_N so each engine can re-transform
|
|
73
108
|
let q = query;
|
|
74
109
|
if (this.dialect === 'postgres') {
|
|
75
110
|
let idx = 0;
|
|
@@ -79,11 +114,12 @@ class An5Adapter {
|
|
|
79
114
|
let idx = 0;
|
|
80
115
|
q = q.replace(/\?/g, () => `@p_${idx++}`);
|
|
81
116
|
}
|
|
82
|
-
return
|
|
117
|
+
return engine.exec(q, params);
|
|
83
118
|
}
|
|
84
119
|
async $executeRaw(query, ...values) {
|
|
85
120
|
if (this.sheetsAdapter)
|
|
86
121
|
return this.sheetsAdapter.$executeRaw(query, ...values);
|
|
122
|
+
const engine = await this.requireEngine();
|
|
87
123
|
const params = {};
|
|
88
124
|
values.forEach((v, i) => { params[`p_${i}`] = v; });
|
|
89
125
|
let q = query;
|
|
@@ -95,7 +131,7 @@ class An5Adapter {
|
|
|
95
131
|
let idx = 0;
|
|
96
132
|
q = q.replace(/\?/g, () => `@p_${idx++}`);
|
|
97
133
|
}
|
|
98
|
-
return
|
|
134
|
+
return engine.executeRaw(q, params);
|
|
99
135
|
}
|
|
100
136
|
async $executeRawUnsafe(query, ...values) {
|
|
101
137
|
return this.$executeRaw(query, ...values);
|
|
@@ -103,19 +139,20 @@ class An5Adapter {
|
|
|
103
139
|
async $connect() {
|
|
104
140
|
if (this.sheetsAdapter)
|
|
105
141
|
return this.sheetsAdapter.$connect();
|
|
106
|
-
await this.requireEngine().connect();
|
|
142
|
+
await (await this.requireEngine()).connect();
|
|
107
143
|
}
|
|
108
144
|
async $disconnect() {
|
|
109
145
|
if (this.sheetsAdapter)
|
|
110
146
|
return this.sheetsAdapter.$disconnect();
|
|
111
|
-
await this.requireEngine().disconnect();
|
|
147
|
+
await (await this.requireEngine()).disconnect();
|
|
112
148
|
}
|
|
113
149
|
async $transaction(fn, _options) {
|
|
114
150
|
if (this.sheetsAdapter)
|
|
115
151
|
return this.sheetsAdapter.$transaction(fn, _options);
|
|
116
152
|
if (Array.isArray(fn))
|
|
117
153
|
return Promise.all(fn);
|
|
118
|
-
const
|
|
154
|
+
const engine = await this.requireEngine();
|
|
155
|
+
const handle = await engine.beginTransaction();
|
|
119
156
|
const txAdapter = new An5AdapterTx(handle, this.dialect);
|
|
120
157
|
try {
|
|
121
158
|
const result = await fn(txAdapter);
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { An5SheetsAdapter, SheetsTableClient, createAn5SheetsAdapter } from './googlesheets';
|
|
2
|
+
export type { An5SheetsAdapterConfig } from './googlesheets';
|
|
3
|
+
export type { An5AdapterConfig, Dialect } from './base/types';
|
|
4
|
+
export { getFieldsForModel, getModelToTable, setAdapterMetadata } from './base/metadata';
|
|
5
|
+
export type { AdapterMetadata } from './base/metadata';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setAdapterMetadata = exports.getModelToTable = exports.getFieldsForModel = exports.createAn5SheetsAdapter = exports.SheetsTableClient = exports.An5SheetsAdapter = void 0;
|
|
4
|
+
// Browser-safe entry — no SQL engine imports
|
|
5
|
+
var googlesheets_1 = require("./googlesheets");
|
|
6
|
+
Object.defineProperty(exports, "An5SheetsAdapter", { enumerable: true, get: function () { return googlesheets_1.An5SheetsAdapter; } });
|
|
7
|
+
Object.defineProperty(exports, "SheetsTableClient", { enumerable: true, get: function () { return googlesheets_1.SheetsTableClient; } });
|
|
8
|
+
Object.defineProperty(exports, "createAn5SheetsAdapter", { enumerable: true, get: function () { return googlesheets_1.createAn5SheetsAdapter; } });
|
|
9
|
+
var metadata_1 = require("./base/metadata");
|
|
10
|
+
Object.defineProperty(exports, "getFieldsForModel", { enumerable: true, get: function () { return metadata_1.getFieldsForModel; } });
|
|
11
|
+
Object.defineProperty(exports, "getModelToTable", { enumerable: true, get: function () { return metadata_1.getModelToTable; } });
|
|
12
|
+
Object.defineProperty(exports, "setAdapterMetadata", { enumerable: true, get: function () { return metadata_1.setAdapterMetadata; } });
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { sheets_v4 } from 'googleapis';
|
|
2
1
|
import { An5SheetsAdapterConfig, resolveConfig } from './config';
|
|
3
2
|
import { SheetsTableClient } from './tableClient';
|
|
4
3
|
import { SheetMeta } from './types';
|
|
5
4
|
export declare class An5SheetsAdapter {
|
|
6
5
|
private sheets;
|
|
6
|
+
private fetchApi;
|
|
7
7
|
config: ReturnType<typeof resolveConfig>;
|
|
8
8
|
private sheetsCache;
|
|
9
9
|
constructor(config: An5SheetsAdapterConfig);
|
|
10
|
-
|
|
10
|
+
private get isOAuth();
|
|
11
|
+
getSheets(): Promise<any>;
|
|
11
12
|
private getApi;
|
|
12
13
|
invalidateCache(): void;
|
|
13
14
|
listSheets(): Promise<string[]>;
|
|
@@ -2,26 +2,95 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.An5SheetsAdapter = void 0;
|
|
4
4
|
exports.createAn5SheetsAdapter = createAn5SheetsAdapter;
|
|
5
|
-
const googleapis_1 = require("googleapis");
|
|
6
5
|
const config_1 = require("./config");
|
|
7
6
|
const sqlExecutor_1 = require("./sqlExecutor");
|
|
8
7
|
const tableClient_1 = require("./tableClient");
|
|
9
8
|
const retry_1 = require("./retry");
|
|
9
|
+
// ─── Fetch-based API proxy for OAuth Access Token (browser-compatible) ────────
|
|
10
|
+
function createFetchApi(spreadsheetId, accessToken) {
|
|
11
|
+
const base = `https://sheets.googleapis.com/v4/spreadsheets/${spreadsheetId}`;
|
|
12
|
+
const headers = { Authorization: `Bearer ${accessToken}`, 'Content-Type': 'application/json' };
|
|
13
|
+
async function request(method, path, body) {
|
|
14
|
+
const url = path.startsWith('http') ? path : `${base}${path}`;
|
|
15
|
+
const opts = { method, headers };
|
|
16
|
+
if (body)
|
|
17
|
+
opts.body = JSON.stringify(body);
|
|
18
|
+
const res = await fetch(url, opts);
|
|
19
|
+
if (!res.ok) {
|
|
20
|
+
const text = await res.text().catch(() => '');
|
|
21
|
+
const err = new Error(`Google Sheets API error (${res.status}): ${text}`);
|
|
22
|
+
err.status = res.status;
|
|
23
|
+
err.body = text;
|
|
24
|
+
const retryAfter = res.headers.get('Retry-After');
|
|
25
|
+
if (retryAfter)
|
|
26
|
+
err.retryAfter = parseInt(retryAfter, 10);
|
|
27
|
+
throw err;
|
|
28
|
+
}
|
|
29
|
+
const text = await res.text();
|
|
30
|
+
return text ? JSON.parse(text) : undefined;
|
|
31
|
+
}
|
|
32
|
+
function fmtRange(range) {
|
|
33
|
+
return `/${encodeURIComponent(range)}`;
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
spreadsheets: {
|
|
37
|
+
get: async (params) => {
|
|
38
|
+
const data = await request('GET', `?fields=${params.fields || ''}`);
|
|
39
|
+
return { data };
|
|
40
|
+
},
|
|
41
|
+
batchUpdate: async (params) => {
|
|
42
|
+
const data = await request('POST', ':batchUpdate', params.requestBody);
|
|
43
|
+
return { data };
|
|
44
|
+
},
|
|
45
|
+
values: {
|
|
46
|
+
get: async (params) => {
|
|
47
|
+
const data = await request('GET', fmtRange(params.range));
|
|
48
|
+
return { data };
|
|
49
|
+
},
|
|
50
|
+
update: async (params) => {
|
|
51
|
+
const qs = `?valueInputOption=${params.valueInputOption || 'RAW'}`;
|
|
52
|
+
const data = await request('PUT', `${fmtRange(params.range)}${qs}`, params.requestBody);
|
|
53
|
+
return { data };
|
|
54
|
+
},
|
|
55
|
+
append: async (params) => {
|
|
56
|
+
const qs = `?valueInputOption=${params.valueInputOption || 'RAW'}&insertDataOption=${params.insertDataOption || 'INSERT_ROWS'}`;
|
|
57
|
+
await request('POST', `${fmtRange(params.range)}:append${qs}`, params.requestBody);
|
|
58
|
+
return { data: { updates: { updatedRows: (params.requestBody?.values || []).length } } };
|
|
59
|
+
},
|
|
60
|
+
clear: async (params) => {
|
|
61
|
+
await request('POST', `${fmtRange(params.range)}:clear`);
|
|
62
|
+
return { data: {} };
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
10
68
|
// ─── Adapter ──────────────────────────────────────────────────────────────────
|
|
11
69
|
class An5SheetsAdapter {
|
|
12
70
|
constructor(config) {
|
|
13
71
|
this.sheets = null;
|
|
72
|
+
this.fetchApi = null;
|
|
14
73
|
this.sheetsCache = null;
|
|
15
74
|
this.config = (0, config_1.resolveConfig)(config);
|
|
16
75
|
}
|
|
76
|
+
get isOAuth() {
|
|
77
|
+
return !!this.config.accessToken;
|
|
78
|
+
}
|
|
17
79
|
async getSheets() {
|
|
80
|
+
if (this.isOAuth) {
|
|
81
|
+
if (!this.fetchApi) {
|
|
82
|
+
this.fetchApi = createFetchApi(this.config.spreadsheetId, this.config.accessToken);
|
|
83
|
+
}
|
|
84
|
+
return this.fetchApi;
|
|
85
|
+
}
|
|
18
86
|
if (!this.sheets) {
|
|
19
|
-
const
|
|
87
|
+
const { google } = await import('googleapis');
|
|
88
|
+
const auth = new google.auth.JWT({
|
|
20
89
|
email: this.config.clientEmail,
|
|
21
90
|
key: this.config.privateKey,
|
|
22
91
|
scopes: ['https://www.googleapis.com/auth/spreadsheets'],
|
|
23
92
|
});
|
|
24
|
-
this.sheets =
|
|
93
|
+
this.sheets = google.sheets({ version: 'v4', auth });
|
|
25
94
|
}
|
|
26
95
|
return this.sheets;
|
|
27
96
|
}
|
|
@@ -37,7 +106,7 @@ class An5SheetsAdapter {
|
|
|
37
106
|
spreadsheetId: this.config.spreadsheetId,
|
|
38
107
|
fields: 'sheets.properties.title',
|
|
39
108
|
}));
|
|
40
|
-
return (res.data.sheets || []).map(s => s.properties?.title || '');
|
|
109
|
+
return (res.data.sheets || []).map((s) => s.properties?.title || '');
|
|
41
110
|
}
|
|
42
111
|
async getSheetMeta(name) {
|
|
43
112
|
const api = await this.getApi();
|
|
@@ -47,14 +116,14 @@ class An5SheetsAdapter {
|
|
|
47
116
|
spreadsheetId: this.config.spreadsheetId,
|
|
48
117
|
fields: 'sheets.properties',
|
|
49
118
|
});
|
|
50
|
-
return (res.data.sheets || []).map(s => ({
|
|
119
|
+
return (res.data.sheets || []).map((s) => ({
|
|
51
120
|
sheetId: s.properties?.sheetId ?? -1,
|
|
52
121
|
title: s.properties?.title ?? '',
|
|
53
|
-
})).filter(m => m.sheetId >= 0);
|
|
122
|
+
})).filter((m) => m.sheetId >= 0);
|
|
54
123
|
});
|
|
55
124
|
}
|
|
56
125
|
const all = await this.sheetsCache;
|
|
57
|
-
return all.find(m => m.title === name) || null;
|
|
126
|
+
return all.find((m) => m.title === name) || null;
|
|
58
127
|
}
|
|
59
128
|
async deleteSheet(name) {
|
|
60
129
|
const meta = await this.getSheetMeta(name);
|
|
@@ -74,6 +143,7 @@ class An5SheetsAdapter {
|
|
|
74
143
|
}
|
|
75
144
|
async $disconnect() {
|
|
76
145
|
this.sheets = null;
|
|
146
|
+
this.fetchApi = null;
|
|
77
147
|
this.sheetsCache = null;
|
|
78
148
|
}
|
|
79
149
|
async exec(query, params) {
|
|
@@ -7,11 +7,22 @@ export interface An5SheetsAdapterConfig {
|
|
|
7
7
|
private_key: string;
|
|
8
8
|
};
|
|
9
9
|
sheetMapping?: Record<string, string>;
|
|
10
|
+
/** OAuth2 access token for browser-based authentication (e.g. from Firebase Auth Google sign-in).
|
|
11
|
+
* When provided, the adapter uses raw fetch() instead of googleapis JWT, making it compatible
|
|
12
|
+
* with browser environments. Mutually exclusive with clientEmail/privateKey/credentials. */
|
|
13
|
+
accessToken?: string;
|
|
10
14
|
}
|
|
11
15
|
export declare function normalizeKey(key: string): string;
|
|
12
16
|
export declare function resolveConfig(config: An5SheetsAdapterConfig): {
|
|
17
|
+
spreadsheetId: string;
|
|
18
|
+
accessToken: string;
|
|
19
|
+
sheetMapping: Record<string, string> | undefined;
|
|
20
|
+
clientEmail?: undefined;
|
|
21
|
+
privateKey?: undefined;
|
|
22
|
+
} | {
|
|
13
23
|
spreadsheetId: string;
|
|
14
24
|
clientEmail: string;
|
|
15
25
|
privateKey: string;
|
|
16
26
|
sheetMapping: Record<string, string> | undefined;
|
|
27
|
+
accessToken?: undefined;
|
|
17
28
|
};
|
|
@@ -12,6 +12,13 @@ function normalizeKey(key) {
|
|
|
12
12
|
return `-----BEGIN PRIVATE KEY-----\n${lines}\n-----END PRIVATE KEY-----`;
|
|
13
13
|
}
|
|
14
14
|
function resolveConfig(config) {
|
|
15
|
+
if (config.accessToken) {
|
|
16
|
+
return {
|
|
17
|
+
spreadsheetId: config.spreadsheetId,
|
|
18
|
+
accessToken: config.accessToken,
|
|
19
|
+
sheetMapping: config.sheetMapping,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
15
22
|
if (config.credentials) {
|
|
16
23
|
return {
|
|
17
24
|
spreadsheetId: config.spreadsheetId,
|
|
@@ -95,7 +95,7 @@ function buildOrderBy(orderBy) {
|
|
|
95
95
|
const parts = [];
|
|
96
96
|
for (const entry of entries) {
|
|
97
97
|
for (const [key, dir] of Object.entries(entry)) {
|
|
98
|
-
parts.push(`${key} ${dir.toUpperCase()}`);
|
|
98
|
+
parts.push(`${key} ${String(dir || 'asc').toUpperCase()}`);
|
|
99
99
|
}
|
|
100
100
|
}
|
|
101
101
|
return parts.join(', ');
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { An5SheetsAdapter, SheetsTableClient, createAn5SheetsAdapter
|
|
1
|
+
export { An5SheetsAdapter, SheetsTableClient, createAn5SheetsAdapter } from './an5SheetsAdapter';
|
|
2
|
+
export type { An5SheetsAdapterConfig } from './an5SheetsAdapter';
|
|
2
3
|
export { parseSheetsConnectionString } from './parseConnectionString';
|
|
@@ -5,19 +5,32 @@ exports.BASE_DELAY = exports.MAX_RETRIES = void 0;
|
|
|
5
5
|
exports.withRetry = withRetry;
|
|
6
6
|
exports.MAX_RETRIES = 3;
|
|
7
7
|
exports.BASE_DELAY = 1000;
|
|
8
|
+
function isRateLimitError(err) {
|
|
9
|
+
const code = err?.code || err?.status || err?.response?.status;
|
|
10
|
+
if (code === 429)
|
|
11
|
+
return true;
|
|
12
|
+
if (code === 500 || code === 503)
|
|
13
|
+
return true;
|
|
14
|
+
if (code === 403) {
|
|
15
|
+
const reason = err?.errors?.[0]?.reason || '';
|
|
16
|
+
if (reason === 'rateLimitExceeded')
|
|
17
|
+
return true;
|
|
18
|
+
if (typeof err?.body === 'string' && err.body.includes('rateLimitExceeded'))
|
|
19
|
+
return true;
|
|
20
|
+
if (typeof err?.message === 'string' && err.message.includes('rateLimitExceeded'))
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
8
25
|
async function withRetry(fn, attempt = 1) {
|
|
9
26
|
try {
|
|
10
27
|
return await fn();
|
|
11
28
|
}
|
|
12
29
|
catch (err) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return withRetry(fn, attempt + 1);
|
|
18
|
-
}
|
|
19
|
-
if (code === 403 && err?.errors?.[0]?.reason === 'rateLimitExceeded' && attempt <= exports.MAX_RETRIES) {
|
|
20
|
-
const delay = exports.BASE_DELAY * Math.pow(2, attempt - 1) + Math.random() * 500;
|
|
30
|
+
if (isRateLimitError(err) && attempt <= exports.MAX_RETRIES) {
|
|
31
|
+
const delay = err.retryAfter
|
|
32
|
+
? err.retryAfter * 1000
|
|
33
|
+
: exports.BASE_DELAY * Math.pow(2, attempt - 1) + Math.random() * 500;
|
|
21
34
|
await new Promise(r => setTimeout(r, delay));
|
|
22
35
|
return withRetry(fn, attempt + 1);
|
|
23
36
|
}
|
|
@@ -315,13 +315,14 @@ class SheetsTableClient {
|
|
|
315
315
|
result._count = rows.length;
|
|
316
316
|
if (args._sum) {
|
|
317
317
|
for (const f of Object.keys(args._sum)) {
|
|
318
|
-
|
|
318
|
+
const nums = rows.map((r) => Number(r[f])).filter(n => !isNaN(n));
|
|
319
|
+
result[`_sum_${f}`] = nums.length > 0 ? nums.reduce((s, n) => s + n, 0) : null;
|
|
319
320
|
}
|
|
320
321
|
}
|
|
321
322
|
if (args._avg) {
|
|
322
323
|
for (const f of Object.keys(args._avg)) {
|
|
323
|
-
const
|
|
324
|
-
result[`_avg_${f}`] =
|
|
324
|
+
const nums = rows.map((r) => Number(r[f])).filter(n => !isNaN(n));
|
|
325
|
+
result[`_avg_${f}`] = nums.length > 0 ? nums.reduce((s, n) => s + n, 0) / nums.length : null;
|
|
325
326
|
}
|
|
326
327
|
}
|
|
327
328
|
if (args._min) {
|
package/typescript/index.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
export { An5Adapter, AdapterTableClient, createAn5Adapter, setAdapterMetadata,
|
|
2
|
-
export {
|
|
1
|
+
export { An5Adapter, AdapterTableClient, createAn5Adapter, setAdapterMetadata, } from './an5Adapter';
|
|
2
|
+
export type { An5AdapterConfig, AdapterMetadata, Dialect, } from './an5Adapter';
|
|
3
|
+
export { getLlmConfig, setLlmConfig, getEmbeddingConfig, setEmbeddingConfig, resetAdapter, } from './config';
|
|
4
|
+
export type { LlmConfigData, EmbeddingConfigData, } from './config';
|