@moogodev/client 0.1.1 → 0.1.3
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/dist/client.d.ts +31 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +136 -21
- package/dist/esm/client.d.ts +31 -5
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +136 -21
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/types.d.ts +53 -4
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/types.d.ts +53 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +180 -25
- package/src/index.ts +9 -0
- package/src/types.ts +61 -4
package/src/client.ts
CHANGED
|
@@ -23,6 +23,13 @@ import type {
|
|
|
23
23
|
CreateCredentialResponse,
|
|
24
24
|
RotateCredentialResponse,
|
|
25
25
|
DeleteResponse,
|
|
26
|
+
// SQL types
|
|
27
|
+
QueryRequest,
|
|
28
|
+
QueryResponse,
|
|
29
|
+
ExecRequest,
|
|
30
|
+
ExecResponse,
|
|
31
|
+
TransactionRequest,
|
|
32
|
+
TransactionResponse,
|
|
26
33
|
} from './types.js';
|
|
27
34
|
|
|
28
35
|
import {
|
|
@@ -60,25 +67,44 @@ const DEFAULT_TIMEOUT = 30_000;
|
|
|
60
67
|
export class MoogoClient {
|
|
61
68
|
private readonly baseUrl: string;
|
|
62
69
|
private readonly projectId: string;
|
|
63
|
-
private readonly accessKeyId
|
|
64
|
-
private readonly secretKey
|
|
70
|
+
private readonly accessKeyId?: string;
|
|
71
|
+
private readonly secretKey?: string;
|
|
72
|
+
private readonly projectKey?: string;
|
|
65
73
|
private readonly fetchImpl: typeof fetch;
|
|
66
74
|
private readonly timeout: number;
|
|
67
75
|
|
|
68
76
|
constructor(config: ClientConfig) {
|
|
69
77
|
if (!config.baseUrl) throw new Error('baseUrl is required');
|
|
70
78
|
if (!config.projectId) throw new Error('projectId is required');
|
|
71
|
-
if (!config.accessKeyId
|
|
72
|
-
|
|
79
|
+
if (!config.accessKeyId && !config.projectKey) {
|
|
80
|
+
throw new Error('Either accessKeyId/secretKey (storage) or projectKey (SQL) is required');
|
|
81
|
+
}
|
|
82
|
+
if (config.accessKeyId && !config.secretKey) {
|
|
83
|
+
throw new Error('secretKey is required when accessKeyId is provided');
|
|
84
|
+
}
|
|
85
|
+
if (config.secretKey && !config.accessKeyId) {
|
|
86
|
+
throw new Error('accessKeyId is required when secretKey is provided');
|
|
87
|
+
}
|
|
73
88
|
|
|
74
89
|
this.baseUrl = config.baseUrl.replace(/\/+$/, '');
|
|
75
90
|
this.projectId = config.projectId;
|
|
76
91
|
this.accessKeyId = config.accessKeyId;
|
|
77
92
|
this.secretKey = config.secretKey;
|
|
93
|
+
this.projectKey = config.projectKey;
|
|
78
94
|
this.fetchImpl = config.fetch ?? fetch;
|
|
79
95
|
this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
|
|
80
96
|
}
|
|
81
97
|
|
|
98
|
+
/** Check if configured for SQL operations (project key) */
|
|
99
|
+
private hasProjectKey(): boolean {
|
|
100
|
+
return !!this.projectKey;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Check if configured for storage operations (access key) */
|
|
104
|
+
private hasStorageCredentials(): boolean {
|
|
105
|
+
return !!this.accessKeyId && !!this.secretKey;
|
|
106
|
+
}
|
|
107
|
+
|
|
82
108
|
/** Build the bucket catalog path */
|
|
83
109
|
private getCatalogPath(): string {
|
|
84
110
|
return `${this.baseUrl}/buckets/${this.projectId}`;
|
|
@@ -176,8 +202,8 @@ export class MoogoClient {
|
|
|
176
202
|
.join('');
|
|
177
203
|
}
|
|
178
204
|
|
|
179
|
-
/** Execute a request with auth and error handling */
|
|
180
|
-
private async
|
|
205
|
+
/** Execute a storage request with HMAC auth and error handling */
|
|
206
|
+
private async requestStorage<T>(
|
|
181
207
|
method: string,
|
|
182
208
|
path: string,
|
|
183
209
|
options: {
|
|
@@ -187,6 +213,10 @@ export class MoogoClient {
|
|
|
187
213
|
signal?: AbortSignal;
|
|
188
214
|
} = {}
|
|
189
215
|
): Promise<T> {
|
|
216
|
+
if (!this.hasStorageCredentials()) {
|
|
217
|
+
throw new Error('Storage operations require accessKeyId and secretKey');
|
|
218
|
+
}
|
|
219
|
+
|
|
190
220
|
const url = new URL(path, this.baseUrl);
|
|
191
221
|
if (options.query) {
|
|
192
222
|
Object.entries(options.query).forEach(([k, v]) => {
|
|
@@ -195,7 +225,7 @@ export class MoogoClient {
|
|
|
195
225
|
}
|
|
196
226
|
|
|
197
227
|
const requestHeaders: Record<string, string> = {
|
|
198
|
-
'X-Moogo-Access-Key-Id': this.accessKeyId
|
|
228
|
+
'X-Moogo-Access-Key-Id': this.accessKeyId!,
|
|
199
229
|
'Content-Type': 'application/json',
|
|
200
230
|
...options.headers,
|
|
201
231
|
};
|
|
@@ -250,17 +280,87 @@ export class MoogoClient {
|
|
|
250
280
|
}
|
|
251
281
|
}
|
|
252
282
|
|
|
283
|
+
/** Execute a SQL request with Bearer token auth and error handling */
|
|
284
|
+
private async requestSQL<T>(
|
|
285
|
+
method: string,
|
|
286
|
+
path: string,
|
|
287
|
+
options: {
|
|
288
|
+
headers?: Record<string, string>;
|
|
289
|
+
body?: BodyInit;
|
|
290
|
+
query?: Record<string, string>;
|
|
291
|
+
signal?: AbortSignal;
|
|
292
|
+
} = {}
|
|
293
|
+
): Promise<T> {
|
|
294
|
+
if (!this.hasProjectKey()) {
|
|
295
|
+
throw new Error('SQL operations require projectKey');
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
const url = new URL(path, this.baseUrl);
|
|
299
|
+
if (options.query) {
|
|
300
|
+
Object.entries(options.query).forEach(([k, v]) => {
|
|
301
|
+
if (v !== undefined && v !== null) url.searchParams.set(k, v);
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const requestHeaders: Record<string, string> = {
|
|
306
|
+
'Authorization': `Bearer ${this.projectKey}`,
|
|
307
|
+
'Content-Type': 'application/json',
|
|
308
|
+
...options.headers,
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
const controller = new AbortController();
|
|
312
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
313
|
+
|
|
314
|
+
const signal = options.signal
|
|
315
|
+
? AbortSignal.any([options.signal, controller.signal])
|
|
316
|
+
: controller.signal;
|
|
317
|
+
|
|
318
|
+
try {
|
|
319
|
+
const response = await this.fetchImpl(url.toString(), {
|
|
320
|
+
method,
|
|
321
|
+
headers: requestHeaders,
|
|
322
|
+
body: options.body,
|
|
323
|
+
signal,
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
clearTimeout(timeoutId);
|
|
327
|
+
|
|
328
|
+
const contentType = response.headers.get('Content-Type') || '';
|
|
329
|
+
const isJson = contentType.includes('application/json');
|
|
330
|
+
|
|
331
|
+
let data: any;
|
|
332
|
+
if (isJson) {
|
|
333
|
+
data = await response.json();
|
|
334
|
+
} else {
|
|
335
|
+
data = await response.text();
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (!response.ok) {
|
|
339
|
+
throw createErrorFromResponse(response, data);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return data as T;
|
|
343
|
+
} catch (error) {
|
|
344
|
+
clearTimeout(timeoutId);
|
|
345
|
+
if (error instanceof MoogoError) throw error;
|
|
346
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
347
|
+
throw new MoogoError('timeout', 'Request timed out', 408);
|
|
348
|
+
}
|
|
349
|
+
throw new MoogoError('network_error', `Network error: ${error}`, 0);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
253
353
|
// ==================== Bucket Operations ====================
|
|
254
354
|
|
|
255
355
|
/** List all buckets in the project */
|
|
256
356
|
async listBuckets(): Promise<Bucket[]> {
|
|
257
|
-
const response = await this.
|
|
357
|
+
const response = await this.requestStorage<ListBucketsResponse>('GET', this.getCatalogPath());
|
|
258
358
|
return response.buckets;
|
|
259
359
|
}
|
|
260
360
|
|
|
261
361
|
/** Get bucket info including usage stats */
|
|
262
362
|
async getBucketInfo(bucketId: string): Promise<BucketInfoResponse> {
|
|
263
|
-
const response = await this.
|
|
363
|
+
const response = await this.requestStorage<BucketInfoResponse>(
|
|
264
364
|
'GET',
|
|
265
365
|
`${this.getCatalogPath()}/${bucketId}`
|
|
266
366
|
);
|
|
@@ -269,7 +369,7 @@ export class MoogoClient {
|
|
|
269
369
|
|
|
270
370
|
/** Create a new bucket */
|
|
271
371
|
async createBucket(request: CreateBucketRequest): Promise<Bucket> {
|
|
272
|
-
const response = await this.
|
|
372
|
+
const response = await this.requestStorage<{ success: true; bucket: Bucket }>(
|
|
273
373
|
'POST',
|
|
274
374
|
this.getCatalogPath(),
|
|
275
375
|
{ body: JSON.stringify(request) }
|
|
@@ -279,7 +379,7 @@ export class MoogoClient {
|
|
|
279
379
|
|
|
280
380
|
/** Update bucket settings */
|
|
281
381
|
async updateBucket(bucketId: string, request: UpdateBucketRequest): Promise<Bucket> {
|
|
282
|
-
const response = await this.
|
|
382
|
+
const response = await this.requestStorage<{ success: true; bucket: Bucket }>(
|
|
283
383
|
'PATCH',
|
|
284
384
|
`${this.getCatalogPath()}/${bucketId}`,
|
|
285
385
|
{ body: JSON.stringify(request) }
|
|
@@ -289,12 +389,12 @@ export class MoogoClient {
|
|
|
289
389
|
|
|
290
390
|
/** Delete a bucket and all its objects */
|
|
291
391
|
async deleteBucket(bucketId: string): Promise<void> {
|
|
292
|
-
await this.
|
|
392
|
+
await this.requestStorage<DeleteResponse>('DELETE', `${this.getCatalogPath()}/${bucketId}`);
|
|
293
393
|
}
|
|
294
394
|
|
|
295
395
|
/** Toggle bucket public/private (fans out to all objects) */
|
|
296
396
|
async setBucketPublic(bucketId: string, isPublic: boolean): Promise<Bucket> {
|
|
297
|
-
const response = await this.
|
|
397
|
+
const response = await this.requestStorage<{ success: true; bucket: Bucket }>(
|
|
298
398
|
'POST',
|
|
299
399
|
`${this.getCatalogPath()}/${bucketId}/public`,
|
|
300
400
|
{ body: JSON.stringify({ is_public: isPublic }) }
|
|
@@ -328,6 +428,10 @@ export class MoogoClient {
|
|
|
328
428
|
const query: Record<string, string> = {};
|
|
329
429
|
if (bucket !== 'default') query.bucket = bucket;
|
|
330
430
|
|
|
431
|
+
if (!this.hasStorageCredentials()) {
|
|
432
|
+
throw new Error('Upload requires storage credentials (accessKeyId and secretKey)');
|
|
433
|
+
}
|
|
434
|
+
|
|
331
435
|
const requestHeaders: Record<string, string> = {};
|
|
332
436
|
if (contentType) requestHeaders['Content-Type'] = contentType;
|
|
333
437
|
if (cacheControl) requestHeaders['Cache-Control'] = cacheControl;
|
|
@@ -355,7 +459,7 @@ export class MoogoClient {
|
|
|
355
459
|
Object.entries(query).forEach(([k, v]) => url.searchParams.set(k, v));
|
|
356
460
|
|
|
357
461
|
const authHeaders: Record<string, string> = {
|
|
358
|
-
'X-Moogo-Access-Key-Id': this.accessKeyId
|
|
462
|
+
'X-Moogo-Access-Key-Id': this.accessKeyId!,
|
|
359
463
|
...requestHeaders,
|
|
360
464
|
};
|
|
361
465
|
|
|
@@ -436,8 +540,12 @@ export class MoogoClient {
|
|
|
436
540
|
const query: Record<string, string> = {};
|
|
437
541
|
if (bucket !== 'default') query.bucket = bucket;
|
|
438
542
|
|
|
543
|
+
if (!this.hasStorageCredentials()) {
|
|
544
|
+
throw new Error('Download requires storage credentials (accessKeyId and secretKey)');
|
|
545
|
+
}
|
|
546
|
+
|
|
439
547
|
const requestHeaders: Record<string, string> = {
|
|
440
|
-
'X-Moogo-Access-Key-Id': this.accessKeyId
|
|
548
|
+
'X-Moogo-Access-Key-Id': this.accessKeyId!,
|
|
441
549
|
};
|
|
442
550
|
if (range) {
|
|
443
551
|
const end = range.end !== undefined ? range.end : '';
|
|
@@ -508,11 +616,15 @@ export class MoogoClient {
|
|
|
508
616
|
const query: Record<string, string> = {};
|
|
509
617
|
if (bucket !== 'default') query.bucket = bucket;
|
|
510
618
|
|
|
619
|
+
if (!this.hasStorageCredentials()) {
|
|
620
|
+
throw new Error('HEAD requires storage credentials (accessKeyId and secretKey)');
|
|
621
|
+
}
|
|
622
|
+
|
|
511
623
|
const url = new URL(`${this.baseUrl}${path}`);
|
|
512
624
|
Object.entries(query).forEach(([k, v]) => url.searchParams.set(k, v));
|
|
513
625
|
|
|
514
626
|
const requestHeaders: Record<string, string> = {
|
|
515
|
-
'X-Moogo-Access-Key-Id': this.accessKeyId
|
|
627
|
+
'X-Moogo-Access-Key-Id': this.accessKeyId!,
|
|
516
628
|
};
|
|
517
629
|
|
|
518
630
|
const authHeader = await this.createAuthHeader('HEAD', url.pathname + url.search, requestHeaders);
|
|
@@ -559,7 +671,7 @@ export class MoogoClient {
|
|
|
559
671
|
const query: Record<string, string> = {};
|
|
560
672
|
if (bucket !== 'default') query.bucket = bucket;
|
|
561
673
|
|
|
562
|
-
await this.
|
|
674
|
+
await this.requestStorage('DELETE', path, { query, signal });
|
|
563
675
|
}
|
|
564
676
|
|
|
565
677
|
/** List objects in a bucket */
|
|
@@ -573,7 +685,7 @@ export class MoogoClient {
|
|
|
573
685
|
if (query.limit) params.limit = String(query.limit);
|
|
574
686
|
if (query.cursor) params.cursor = query.cursor;
|
|
575
687
|
|
|
576
|
-
return this.
|
|
688
|
+
return this.requestStorage<ListObjectsResponse>('GET', `/p/${this.projectId}/bucket`, { query: params });
|
|
577
689
|
}
|
|
578
690
|
|
|
579
691
|
/** Get a presigned URL for an object */
|
|
@@ -588,7 +700,7 @@ export class MoogoClient {
|
|
|
588
700
|
const query: Record<string, string> = {};
|
|
589
701
|
if (bucket !== 'default') query.bucket = bucket;
|
|
590
702
|
|
|
591
|
-
return this.
|
|
703
|
+
return this.requestStorage<PresignedUrlResponse>('POST', path, {
|
|
592
704
|
query,
|
|
593
705
|
body: JSON.stringify(request),
|
|
594
706
|
signal,
|
|
@@ -607,7 +719,7 @@ export class MoogoClient {
|
|
|
607
719
|
const query: Record<string, string> = {};
|
|
608
720
|
if (bucket !== 'default') query.bucket = bucket;
|
|
609
721
|
|
|
610
|
-
return this.
|
|
722
|
+
return this.requestStorage<SignedUploadResponse>('POST', path, {
|
|
611
723
|
query,
|
|
612
724
|
body: JSON.stringify(request),
|
|
613
725
|
signal,
|
|
@@ -626,7 +738,7 @@ export class MoogoClient {
|
|
|
626
738
|
const query: Record<string, string> = {};
|
|
627
739
|
if (bucket !== 'default') query.bucket = bucket;
|
|
628
740
|
|
|
629
|
-
const response = await this.
|
|
741
|
+
const response = await this.requestStorage<{ success: true; object: ObjectResponse }>(
|
|
630
742
|
'PATCH',
|
|
631
743
|
path,
|
|
632
744
|
{ query, body: JSON.stringify(updates), signal }
|
|
@@ -638,7 +750,7 @@ export class MoogoClient {
|
|
|
638
750
|
|
|
639
751
|
/** List storage credentials */
|
|
640
752
|
async listCredentials(): Promise<StorageCredential[]> {
|
|
641
|
-
const response = await this.
|
|
753
|
+
const response = await this.requestStorage<ListCredentialsResponse>(
|
|
642
754
|
'GET',
|
|
643
755
|
this.getCredentialsPath()
|
|
644
756
|
);
|
|
@@ -647,7 +759,7 @@ export class MoogoClient {
|
|
|
647
759
|
|
|
648
760
|
/** Create a new storage credential */
|
|
649
761
|
async createCredential(request: CreateCredentialRequest): Promise<CreateCredentialResponse> {
|
|
650
|
-
return this.
|
|
762
|
+
return this.requestStorage<CreateCredentialResponse>(
|
|
651
763
|
'POST',
|
|
652
764
|
this.getCredentialsPath(),
|
|
653
765
|
{ body: JSON.stringify(request) }
|
|
@@ -656,7 +768,7 @@ export class MoogoClient {
|
|
|
656
768
|
|
|
657
769
|
/** Rotate a credential (generates new secret) */
|
|
658
770
|
async rotateCredential(credentialId: string): Promise<RotateCredentialResponse> {
|
|
659
|
-
return this.
|
|
771
|
+
return this.requestStorage<RotateCredentialResponse>(
|
|
660
772
|
'POST',
|
|
661
773
|
`${this.getCredentialsPath()}/${credentialId}/rotate`
|
|
662
774
|
);
|
|
@@ -664,7 +776,7 @@ export class MoogoClient {
|
|
|
664
776
|
|
|
665
777
|
/** Revoke a credential */
|
|
666
778
|
async revokeCredential(credentialId: string): Promise<void> {
|
|
667
|
-
await this.
|
|
779
|
+
await this.requestStorage<DeleteResponse>(
|
|
668
780
|
'DELETE',
|
|
669
781
|
`${this.getCredentialsPath()}/${credentialId}`
|
|
670
782
|
);
|
|
@@ -706,11 +818,54 @@ export class MoogoClient {
|
|
|
706
818
|
if (!result.exists) return null;
|
|
707
819
|
return result.headers.get('ETag');
|
|
708
820
|
}
|
|
821
|
+
|
|
822
|
+
// ==================== SQL Operations ====================
|
|
823
|
+
|
|
824
|
+
/** Execute a SQL read query */
|
|
825
|
+
async query(request: QueryRequest, options: { signal?: AbortSignal } = {}): Promise<QueryResponse> {
|
|
826
|
+
return this.requestSQL<QueryResponse>('POST', `/p/${this.projectId}/query`, {
|
|
827
|
+
body: JSON.stringify(request),
|
|
828
|
+
signal: options.signal,
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
/** Execute a SQL write statement */
|
|
833
|
+
async exec(request: ExecRequest, options: { signal?: AbortSignal } = {}): Promise<ExecResponse> {
|
|
834
|
+
return this.requestSQL<ExecResponse>('POST', `/p/${this.projectId}/exec`, {
|
|
835
|
+
body: JSON.stringify(request),
|
|
836
|
+
signal: options.signal,
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
/** Execute multiple SQL statements in a transaction */
|
|
841
|
+
async transaction(request: TransactionRequest, options: { signal?: AbortSignal } = {}): Promise<TransactionResponse> {
|
|
842
|
+
return this.requestSQL<TransactionResponse>('POST', `/p/${this.projectId}/transaction`, {
|
|
843
|
+
body: JSON.stringify(request),
|
|
844
|
+
signal: options.signal,
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/** Run database maintenance (VACUUM, REINDEX, ANALYZE) */
|
|
849
|
+
async maintenance(options: { signal?: AbortSignal } = {}): Promise<{ success: true; reclaimed_bytes: number }> {
|
|
850
|
+
return this.requestSQL<{ success: true; reclaimed_bytes: number }>(
|
|
851
|
+
'POST',
|
|
852
|
+
`/p/${this.projectId}/maintenance`,
|
|
853
|
+
{ signal: options.signal }
|
|
854
|
+
);
|
|
855
|
+
}
|
|
709
856
|
}
|
|
710
857
|
|
|
711
858
|
/** Convenience function to create a client from environment variables */
|
|
712
859
|
export function createClientFromEnv(env?: Record<string, string | undefined>): MoogoClient {
|
|
713
860
|
const getEnv = (key: string) => env?.[key] ?? process.env[key];
|
|
861
|
+
const projectKey = getEnv('MOOGO_PROJECT_KEY');
|
|
862
|
+
if (projectKey) {
|
|
863
|
+
return new MoogoClient({
|
|
864
|
+
baseUrl: getEnv('MOOGO_API_URL') || 'https://api.moogo.dev',
|
|
865
|
+
projectId: getEnv('MOOGO_PROJECT_ID')!,
|
|
866
|
+
projectKey,
|
|
867
|
+
});
|
|
868
|
+
}
|
|
714
869
|
return new MoogoClient({
|
|
715
870
|
baseUrl: getEnv('MOOGO_API_URL') || 'https://api.moogo.dev',
|
|
716
871
|
projectId: getEnv('MOOGO_PROJECT_ID')!,
|
package/src/index.ts
CHANGED
|
@@ -58,6 +58,15 @@ export type {
|
|
|
58
58
|
CreateCredentialResponse,
|
|
59
59
|
RotateCredentialResponse,
|
|
60
60
|
DeleteResponse,
|
|
61
|
+
// SQL types
|
|
62
|
+
QueryRequest,
|
|
63
|
+
QueryRow,
|
|
64
|
+
QueryResponse,
|
|
65
|
+
ExecRequest,
|
|
66
|
+
ExecResponse,
|
|
67
|
+
TransactionRequest,
|
|
68
|
+
TransactionResponse,
|
|
69
|
+
TransactionResult,
|
|
61
70
|
} from './types.js';
|
|
62
71
|
|
|
63
72
|
// Errors
|
package/src/types.ts
CHANGED
|
@@ -187,10 +187,12 @@ export interface ClientConfig {
|
|
|
187
187
|
baseUrl: string;
|
|
188
188
|
/** Project ID */
|
|
189
189
|
projectId: string;
|
|
190
|
-
/** Access Key ID */
|
|
191
|
-
accessKeyId
|
|
192
|
-
/** Secret Key */
|
|
193
|
-
secretKey
|
|
190
|
+
/** Access Key ID (for storage operations) */
|
|
191
|
+
accessKeyId?: string;
|
|
192
|
+
/** Secret Key (for storage operations) */
|
|
193
|
+
secretKey?: string;
|
|
194
|
+
/** Project Key (for SQL operations) - used instead of accessKeyId/secretKey */
|
|
195
|
+
projectKey?: string;
|
|
194
196
|
/** Optional: custom fetch implementation */
|
|
195
197
|
fetch?: typeof fetch;
|
|
196
198
|
/** Optional: default timeout in ms */
|
|
@@ -203,4 +205,59 @@ export interface ParsedAuth {
|
|
|
203
205
|
signature: string;
|
|
204
206
|
timestamp: string;
|
|
205
207
|
signedHeaders: string;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/** SQL query request */
|
|
211
|
+
export interface QueryRequest {
|
|
212
|
+
sql: string;
|
|
213
|
+
args?: any[];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** SQL query response row */
|
|
217
|
+
export interface QueryRow {
|
|
218
|
+
[column: string]: any;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** SQL query response */
|
|
222
|
+
export interface QueryResponse {
|
|
223
|
+
success: true;
|
|
224
|
+
rows: QueryRow[];
|
|
225
|
+
row_count: number;
|
|
226
|
+
columns: string[];
|
|
227
|
+
truncated: boolean;
|
|
228
|
+
duration_ms: number;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** SQL exec request */
|
|
232
|
+
export interface ExecRequest {
|
|
233
|
+
sql: string;
|
|
234
|
+
args?: any[];
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** SQL exec response */
|
|
238
|
+
export interface ExecResponse {
|
|
239
|
+
success: true;
|
|
240
|
+
rows_affected: number;
|
|
241
|
+
duration_ms: number;
|
|
242
|
+
last_insert_id?: number;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** SQL transaction request */
|
|
246
|
+
export interface TransactionRequest {
|
|
247
|
+
statements: (string | QueryRequest)[];
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/** SQL transaction response */
|
|
251
|
+
export interface TransactionResponse {
|
|
252
|
+
success: true;
|
|
253
|
+
results: TransactionResult[];
|
|
254
|
+
duration_ms: number;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export interface TransactionResult {
|
|
258
|
+
rows?: QueryRow[];
|
|
259
|
+
row_count?: number;
|
|
260
|
+
rows_affected?: number;
|
|
261
|
+
columns?: string[];
|
|
262
|
+
truncated?: boolean;
|
|
206
263
|
}
|