get-db9 0.4.1 → 0.5.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.
- package/dist/{client-CXv2ZlbR.d.cts → client-UKXFQNll.d.cts} +49 -3
- package/dist/{client-CXv2ZlbR.d.ts → client-UKXFQNll.d.ts} +49 -3
- package/dist/client.cjs +309 -176
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/client.js +309 -176
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +313 -177
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +313 -177
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -92,6 +92,9 @@ var Db9ConflictError = class extends Db9Error {
|
|
|
92
92
|
};
|
|
93
93
|
|
|
94
94
|
// src/http.ts
|
|
95
|
+
function delay(ms) {
|
|
96
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
97
|
+
}
|
|
95
98
|
function createHttpClient(options) {
|
|
96
99
|
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
97
100
|
const baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
@@ -100,38 +103,61 @@ function createHttpClient(options) {
|
|
|
100
103
|
if (params) {
|
|
101
104
|
const searchParams = new URLSearchParams();
|
|
102
105
|
for (const [key, value] of Object.entries(params)) {
|
|
103
|
-
if (value !== void 0)
|
|
104
|
-
searchParams.set(key, value);
|
|
105
|
-
}
|
|
106
|
+
if (value !== void 0) searchParams.set(key, value);
|
|
106
107
|
}
|
|
107
108
|
const qs = searchParams.toString();
|
|
108
109
|
if (qs) url += `?${qs}`;
|
|
109
110
|
}
|
|
110
|
-
const
|
|
111
|
+
const reqHeaders = {
|
|
111
112
|
"Content-Type": "application/json",
|
|
112
113
|
...options.headers
|
|
113
114
|
};
|
|
114
|
-
const init = { method, headers };
|
|
115
|
+
const init = { method, headers: reqHeaders };
|
|
115
116
|
if (body !== void 0) {
|
|
116
117
|
init.body = JSON.stringify(body);
|
|
117
118
|
}
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
119
|
+
const maxAttempts = Math.min(options.maxRetries ?? 0, 3) + 1;
|
|
120
|
+
const baseDelay = options.retryDelay ?? 1e3;
|
|
121
|
+
let lastError;
|
|
122
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
123
|
+
let timeoutId;
|
|
124
|
+
try {
|
|
125
|
+
const fetchInit = { ...init };
|
|
126
|
+
if (options.timeout) {
|
|
127
|
+
const controller = new AbortController();
|
|
128
|
+
fetchInit.signal = controller.signal;
|
|
129
|
+
timeoutId = setTimeout(() => controller.abort(), options.timeout);
|
|
130
|
+
}
|
|
131
|
+
const response = await fetchFn(url, fetchInit);
|
|
132
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
133
|
+
if (!response.ok) {
|
|
134
|
+
if (response.status >= 500 && attempt < maxAttempts - 1) {
|
|
135
|
+
lastError = await Db9Error.fromResponse(response);
|
|
136
|
+
await delay(baseDelay * Math.pow(2, attempt));
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
throw await Db9Error.fromResponse(response);
|
|
140
|
+
}
|
|
141
|
+
if (response.status === 204) return void 0;
|
|
142
|
+
return response.json();
|
|
143
|
+
} catch (err) {
|
|
144
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
145
|
+
if (err instanceof TypeError && attempt < maxAttempts - 1) {
|
|
146
|
+
lastError = err;
|
|
147
|
+
await delay(baseDelay * Math.pow(2, attempt));
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
throw err;
|
|
151
|
+
}
|
|
124
152
|
}
|
|
125
|
-
|
|
153
|
+
throw lastError;
|
|
126
154
|
}
|
|
127
155
|
async function requestRaw(method, path, body, params, customHeaders) {
|
|
128
156
|
let url = `${baseUrl}${path}`;
|
|
129
157
|
if (params) {
|
|
130
158
|
const searchParams = new URLSearchParams();
|
|
131
159
|
for (const [key, value] of Object.entries(params)) {
|
|
132
|
-
if (value !== void 0)
|
|
133
|
-
searchParams.set(key, value);
|
|
134
|
-
}
|
|
160
|
+
if (value !== void 0) searchParams.set(key, value);
|
|
135
161
|
}
|
|
136
162
|
const qs = searchParams.toString();
|
|
137
163
|
if (qs) url += `?${qs}`;
|
|
@@ -140,15 +166,23 @@ function createHttpClient(options) {
|
|
|
140
166
|
...options.headers,
|
|
141
167
|
...customHeaders
|
|
142
168
|
};
|
|
143
|
-
const
|
|
144
|
-
if (body !== void 0)
|
|
145
|
-
|
|
169
|
+
const fetchInit = { method, headers };
|
|
170
|
+
if (body !== void 0) fetchInit.body = body;
|
|
171
|
+
let timeoutId;
|
|
172
|
+
if (options.timeout) {
|
|
173
|
+
const controller = new AbortController();
|
|
174
|
+
fetchInit.signal = controller.signal;
|
|
175
|
+
timeoutId = setTimeout(() => controller.abort(), options.timeout);
|
|
146
176
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
177
|
+
try {
|
|
178
|
+
const response = await fetchFn(url, fetchInit);
|
|
179
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
180
|
+
if (!response.ok) throw await Db9Error.fromResponse(response);
|
|
181
|
+
return response;
|
|
182
|
+
} catch (err) {
|
|
183
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
184
|
+
throw err;
|
|
150
185
|
}
|
|
151
|
-
return response;
|
|
152
186
|
}
|
|
153
187
|
return {
|
|
154
188
|
get: (path, params) => request("GET", path, void 0, params),
|
|
@@ -156,7 +190,9 @@ function createHttpClient(options) {
|
|
|
156
190
|
put: (path, body) => request("PUT", path, body),
|
|
157
191
|
del: (path) => request("DELETE", path),
|
|
158
192
|
getRaw: (path, params) => requestRaw("GET", path, void 0, params),
|
|
159
|
-
putRaw: (path, body, headers) => requestRaw("PUT", path, body, void 0, headers)
|
|
193
|
+
putRaw: (path, body, headers) => requestRaw("PUT", path, body, void 0, headers),
|
|
194
|
+
postRaw: (path, body, headers) => requestRaw("POST", path, body, void 0, headers),
|
|
195
|
+
delRaw: (path, params) => requestRaw("DELETE", path, void 0, params)
|
|
160
196
|
};
|
|
161
197
|
}
|
|
162
198
|
|
|
@@ -276,7 +312,10 @@ function createDb9Client(options = {}) {
|
|
|
276
312
|
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
277
313
|
const publicClient = createHttpClient({
|
|
278
314
|
baseUrl,
|
|
279
|
-
fetch: options.fetch
|
|
315
|
+
fetch: options.fetch,
|
|
316
|
+
timeout: options.timeout,
|
|
317
|
+
maxRetries: options.maxRetries,
|
|
318
|
+
retryDelay: options.retryDelay
|
|
280
319
|
});
|
|
281
320
|
async function getAuthClient() {
|
|
282
321
|
if (!token && !tokenLoaded) {
|
|
@@ -299,35 +338,118 @@ function createDb9Client(options = {}) {
|
|
|
299
338
|
return createHttpClient({
|
|
300
339
|
baseUrl,
|
|
301
340
|
fetch: options.fetch,
|
|
302
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
341
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
342
|
+
timeout: options.timeout,
|
|
343
|
+
maxRetries: options.maxRetries,
|
|
344
|
+
retryDelay: options.retryDelay
|
|
303
345
|
});
|
|
304
346
|
}
|
|
347
|
+
let refreshPromise = null;
|
|
348
|
+
async function refreshAnonymousToken() {
|
|
349
|
+
const creds = await store.load();
|
|
350
|
+
if (!creds?.anonymous_id || !creds?.anonymous_secret) {
|
|
351
|
+
throw new Error("Not an anonymous session");
|
|
352
|
+
}
|
|
353
|
+
const resp = await publicClient.post(
|
|
354
|
+
"/customer/anonymous-refresh",
|
|
355
|
+
{
|
|
356
|
+
anonymous_id: creds.anonymous_id,
|
|
357
|
+
anonymous_secret: creds.anonymous_secret
|
|
358
|
+
}
|
|
359
|
+
);
|
|
360
|
+
token = resp.token;
|
|
361
|
+
await store.save({ ...creds, token: resp.token });
|
|
362
|
+
}
|
|
363
|
+
async function withAuthRetry(operation) {
|
|
364
|
+
const client = await getAuthClient();
|
|
365
|
+
try {
|
|
366
|
+
return await operation(client);
|
|
367
|
+
} catch (err) {
|
|
368
|
+
if (!(err instanceof Db9Error) || err.statusCode !== 401) {
|
|
369
|
+
throw err;
|
|
370
|
+
}
|
|
371
|
+
try {
|
|
372
|
+
if (!refreshPromise) {
|
|
373
|
+
refreshPromise = refreshAnonymousToken();
|
|
374
|
+
}
|
|
375
|
+
await refreshPromise;
|
|
376
|
+
} catch {
|
|
377
|
+
throw err;
|
|
378
|
+
} finally {
|
|
379
|
+
refreshPromise = null;
|
|
380
|
+
}
|
|
381
|
+
const newClient = await getAuthClient();
|
|
382
|
+
return operation(newClient);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
305
385
|
function deriveFs9Url(dbId) {
|
|
306
386
|
const origin = baseUrl.replace(/\/api\/?$/, "");
|
|
307
387
|
return `${origin}/fs9/${dbId}`;
|
|
308
388
|
}
|
|
309
|
-
|
|
389
|
+
function getFsClient(dbId) {
|
|
390
|
+
const fs9Base = deriveFs9Url(dbId) + "/api/v1";
|
|
391
|
+
return createHttpClient({
|
|
392
|
+
baseUrl: fs9Base,
|
|
393
|
+
fetch: options.fetch,
|
|
394
|
+
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
|
395
|
+
timeout: options.timeout,
|
|
396
|
+
maxRetries: options.maxRetries,
|
|
397
|
+
retryDelay: options.retryDelay
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
async function withFsAuthRetry(dbId, operation) {
|
|
310
401
|
if (!token && !tokenLoaded) {
|
|
311
402
|
await getAuthClient();
|
|
312
403
|
}
|
|
313
|
-
const
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
404
|
+
const client = getFsClient(dbId);
|
|
405
|
+
try {
|
|
406
|
+
return await operation(client);
|
|
407
|
+
} catch (err) {
|
|
408
|
+
if (!(err instanceof Db9Error) || err.statusCode !== 401) {
|
|
409
|
+
throw err;
|
|
410
|
+
}
|
|
411
|
+
try {
|
|
412
|
+
if (!refreshPromise) {
|
|
413
|
+
refreshPromise = refreshAnonymousToken();
|
|
414
|
+
}
|
|
415
|
+
await refreshPromise;
|
|
416
|
+
} catch {
|
|
417
|
+
throw err;
|
|
418
|
+
} finally {
|
|
419
|
+
refreshPromise = null;
|
|
420
|
+
}
|
|
421
|
+
const newClient = getFsClient(dbId);
|
|
422
|
+
return operation(newClient);
|
|
321
423
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
424
|
+
}
|
|
425
|
+
function parseSqlError(raw) {
|
|
426
|
+
try {
|
|
427
|
+
const parsed = JSON.parse(raw);
|
|
428
|
+
if (typeof parsed === "object" && parsed !== null && typeof parsed.message === "string") {
|
|
429
|
+
return parsed;
|
|
430
|
+
}
|
|
431
|
+
} catch {
|
|
325
432
|
}
|
|
326
|
-
const
|
|
327
|
-
if (
|
|
328
|
-
|
|
433
|
+
const pgMatch = raw.match(/^(?:ERROR:\s*)?(.+?)(?:\s+DETAIL:\s+(.+?))?(?:\s+HINT:\s+(.+?))?(?:\s+\(SQLSTATE\s+(\w+)\))?$/s);
|
|
434
|
+
if (pgMatch && pgMatch[1]) {
|
|
435
|
+
const result = { message: pgMatch[1].trim() };
|
|
436
|
+
if (pgMatch[2]) result.detail = pgMatch[2].trim();
|
|
437
|
+
if (pgMatch[3]) result.hint = pgMatch[3].trim();
|
|
438
|
+
if (pgMatch[4]) result.code = pgMatch[4];
|
|
439
|
+
return result;
|
|
329
440
|
}
|
|
330
|
-
return
|
|
441
|
+
return { message: raw };
|
|
442
|
+
}
|
|
443
|
+
async function fsStat(dbId, path) {
|
|
444
|
+
return withFsAuthRetry(
|
|
445
|
+
dbId,
|
|
446
|
+
(client) => client.get("/stat", { path })
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
async function fetchAnonymousSecret() {
|
|
450
|
+
return withAuthRetry(
|
|
451
|
+
(client) => client.post("/customer/anonymous-secret", {})
|
|
452
|
+
);
|
|
331
453
|
}
|
|
332
454
|
return {
|
|
333
455
|
auth: {
|
|
@@ -342,195 +464,206 @@ function createDb9Client(options = {}) {
|
|
|
342
464
|
req
|
|
343
465
|
),
|
|
344
466
|
// Authenticated endpoints
|
|
345
|
-
me: async () =>
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
const client = await getAuthClient();
|
|
351
|
-
return client.get(
|
|
352
|
-
"/customer/anonymous-secret"
|
|
353
|
-
);
|
|
467
|
+
me: async () => withAuthRetry(
|
|
468
|
+
(client) => client.get("/customer/me")
|
|
469
|
+
),
|
|
470
|
+
getAnonymousSecret: () => {
|
|
471
|
+
return fetchAnonymousSecret();
|
|
354
472
|
},
|
|
355
|
-
claim: async (req) =>
|
|
356
|
-
|
|
357
|
-
|
|
473
|
+
claim: async (req) => withAuthRetry(
|
|
474
|
+
(client) => client.post("/customer/claim", req)
|
|
475
|
+
),
|
|
476
|
+
ensureAnonymousSecret: async () => {
|
|
477
|
+
const creds = await store.load();
|
|
478
|
+
if (!creds?.anonymous_id || creds.anonymous_secret) {
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
const resp = await fetchAnonymousSecret();
|
|
482
|
+
await store.save({
|
|
483
|
+
...creds,
|
|
484
|
+
anonymous_secret: resp.anonymous_secret
|
|
485
|
+
});
|
|
358
486
|
}
|
|
359
487
|
},
|
|
360
488
|
tokens: {
|
|
361
|
-
list: async () =>
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
489
|
+
list: async () => withAuthRetry(
|
|
490
|
+
(client) => client.get("/customer/tokens")
|
|
491
|
+
),
|
|
492
|
+
revoke: async (tokenId) => withAuthRetry(
|
|
493
|
+
(client) => client.del(`/customer/tokens/${tokenId}`)
|
|
494
|
+
),
|
|
495
|
+
create: async (req) => withAuthRetry(
|
|
496
|
+
(client) => client.post("/customer/tokens", req)
|
|
497
|
+
)
|
|
369
498
|
},
|
|
370
499
|
databases: {
|
|
371
500
|
// ── CRUD ──────────────────────────────────────────────────
|
|
372
|
-
create: async (req) =>
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
get: async (databaseId) => {
|
|
381
|
-
const client = await getAuthClient();
|
|
382
|
-
return client.get(
|
|
501
|
+
create: async (req) => withAuthRetry(
|
|
502
|
+
(client) => client.post("/customer/databases", req)
|
|
503
|
+
),
|
|
504
|
+
list: async () => withAuthRetry(
|
|
505
|
+
(client) => client.get("/customer/databases")
|
|
506
|
+
),
|
|
507
|
+
get: async (databaseId) => withAuthRetry(
|
|
508
|
+
(client) => client.get(
|
|
383
509
|
`/customer/databases/${databaseId}`
|
|
384
|
-
)
|
|
385
|
-
|
|
386
|
-
delete: async (databaseId) =>
|
|
387
|
-
|
|
388
|
-
return client.del(
|
|
510
|
+
)
|
|
511
|
+
),
|
|
512
|
+
delete: async (databaseId) => withAuthRetry(
|
|
513
|
+
(client) => client.del(
|
|
389
514
|
`/customer/databases/${databaseId}`
|
|
390
|
-
)
|
|
391
|
-
|
|
392
|
-
resetPassword: async (databaseId) =>
|
|
393
|
-
|
|
394
|
-
return client.post(
|
|
515
|
+
)
|
|
516
|
+
),
|
|
517
|
+
resetPassword: async (databaseId) => withAuthRetry(
|
|
518
|
+
(client) => client.post(
|
|
395
519
|
`/customer/databases/${databaseId}/reset-password`
|
|
396
|
-
)
|
|
397
|
-
|
|
398
|
-
observability: async (databaseId) =>
|
|
399
|
-
|
|
400
|
-
return client.get(
|
|
520
|
+
)
|
|
521
|
+
),
|
|
522
|
+
observability: async (databaseId) => withAuthRetry(
|
|
523
|
+
(client) => client.get(
|
|
401
524
|
`/customer/databases/${databaseId}/observability`
|
|
402
|
-
)
|
|
403
|
-
|
|
525
|
+
)
|
|
526
|
+
),
|
|
404
527
|
// ── SQL Execution ─────────────────────────────────────────
|
|
405
528
|
sql: async (databaseId, query) => {
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
529
|
+
const result = await withAuthRetry(
|
|
530
|
+
(client) => client.post(
|
|
531
|
+
`/customer/databases/${databaseId}/sql`,
|
|
532
|
+
{ query }
|
|
533
|
+
)
|
|
410
534
|
);
|
|
535
|
+
if (result.error && typeof result.error === "string") {
|
|
536
|
+
result.error = parseSqlError(result.error);
|
|
537
|
+
}
|
|
538
|
+
return result;
|
|
411
539
|
},
|
|
412
540
|
sqlFile: async (databaseId, fileContent) => {
|
|
413
|
-
const
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
541
|
+
const result = await withAuthRetry(
|
|
542
|
+
(client) => client.post(
|
|
543
|
+
`/customer/databases/${databaseId}/sql`,
|
|
544
|
+
{ file_content: fileContent }
|
|
545
|
+
)
|
|
417
546
|
);
|
|
547
|
+
if (result.error && typeof result.error === "string") {
|
|
548
|
+
result.error = parseSqlError(result.error);
|
|
549
|
+
}
|
|
550
|
+
return result;
|
|
418
551
|
},
|
|
419
552
|
// ── Schema & Dump ─────────────────────────────────────────
|
|
420
|
-
schema: async (databaseId) =>
|
|
421
|
-
|
|
422
|
-
return client.get(
|
|
553
|
+
schema: async (databaseId) => withAuthRetry(
|
|
554
|
+
(client) => client.get(
|
|
423
555
|
`/customer/databases/${databaseId}/schema`
|
|
424
|
-
)
|
|
425
|
-
|
|
426
|
-
dump: async (databaseId, req) =>
|
|
427
|
-
|
|
428
|
-
return client.post(
|
|
556
|
+
)
|
|
557
|
+
),
|
|
558
|
+
dump: async (databaseId, req) => withAuthRetry(
|
|
559
|
+
(client) => client.post(
|
|
429
560
|
`/customer/databases/${databaseId}/dump`,
|
|
430
561
|
req
|
|
431
|
-
)
|
|
432
|
-
|
|
562
|
+
)
|
|
563
|
+
),
|
|
433
564
|
// ── Migrations ────────────────────────────────────────────
|
|
434
|
-
applyMigration: async (databaseId, req) =>
|
|
435
|
-
|
|
436
|
-
return client.post(
|
|
565
|
+
applyMigration: async (databaseId, req) => withAuthRetry(
|
|
566
|
+
(client) => client.post(
|
|
437
567
|
`/customer/databases/${databaseId}/migrations`,
|
|
438
568
|
req
|
|
439
|
-
)
|
|
440
|
-
|
|
441
|
-
listMigrations: async (databaseId) =>
|
|
442
|
-
|
|
443
|
-
return client.get(
|
|
569
|
+
)
|
|
570
|
+
),
|
|
571
|
+
listMigrations: async (databaseId) => withAuthRetry(
|
|
572
|
+
(client) => client.get(
|
|
444
573
|
`/customer/databases/${databaseId}/migrations`
|
|
445
|
-
)
|
|
446
|
-
|
|
574
|
+
)
|
|
575
|
+
),
|
|
447
576
|
// ── Branching ─────────────────────────────────────────────
|
|
448
|
-
branch: async (databaseId, req) =>
|
|
449
|
-
|
|
450
|
-
return client.post(
|
|
577
|
+
branch: async (databaseId, req) => withAuthRetry(
|
|
578
|
+
(client) => client.post(
|
|
451
579
|
`/customer/databases/${databaseId}/branch`,
|
|
452
580
|
req
|
|
453
|
-
)
|
|
454
|
-
|
|
581
|
+
)
|
|
582
|
+
),
|
|
455
583
|
// ── User Management ───────────────────────────────────────
|
|
456
584
|
users: {
|
|
457
|
-
list: async (databaseId) =>
|
|
458
|
-
|
|
459
|
-
return client.get(
|
|
585
|
+
list: async (databaseId) => withAuthRetry(
|
|
586
|
+
(client) => client.get(
|
|
460
587
|
`/customer/databases/${databaseId}/users`
|
|
461
|
-
)
|
|
462
|
-
|
|
463
|
-
create: async (databaseId, req) =>
|
|
464
|
-
|
|
465
|
-
return client.post(
|
|
588
|
+
)
|
|
589
|
+
),
|
|
590
|
+
create: async (databaseId, req) => withAuthRetry(
|
|
591
|
+
(client) => client.post(
|
|
466
592
|
`/customer/databases/${databaseId}/users`,
|
|
467
593
|
req
|
|
468
|
-
)
|
|
469
|
-
|
|
470
|
-
delete: async (databaseId, username) =>
|
|
471
|
-
|
|
472
|
-
return client.del(
|
|
594
|
+
)
|
|
595
|
+
),
|
|
596
|
+
delete: async (databaseId, username) => withAuthRetry(
|
|
597
|
+
(client) => client.del(
|
|
473
598
|
`/customer/databases/${databaseId}/users/${username}`
|
|
474
|
-
)
|
|
475
|
-
|
|
599
|
+
)
|
|
600
|
+
)
|
|
476
601
|
}
|
|
477
602
|
},
|
|
478
603
|
fs: {
|
|
479
604
|
list: async (dbId, path, options2) => {
|
|
480
|
-
const params =
|
|
481
|
-
if (options2?.recursive) params.
|
|
482
|
-
|
|
483
|
-
"GET",
|
|
605
|
+
const params = { path };
|
|
606
|
+
if (options2?.recursive) params.recursive = "true";
|
|
607
|
+
return withFsAuthRetry(
|
|
484
608
|
dbId,
|
|
485
|
-
|
|
609
|
+
(client) => client.get("/readdir", params)
|
|
486
610
|
);
|
|
487
|
-
return response.json();
|
|
488
611
|
},
|
|
489
612
|
read: async (dbId, path) => {
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
`/download?${params.toString()}`
|
|
495
|
-
);
|
|
496
|
-
return response.text();
|
|
613
|
+
return withFsAuthRetry(dbId, async (client) => {
|
|
614
|
+
const resp = await client.getRaw("/download", { path });
|
|
615
|
+
return resp.text();
|
|
616
|
+
});
|
|
497
617
|
},
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
618
|
+
readBinary: async (dbId, path) => {
|
|
619
|
+
return withFsAuthRetry(dbId, async (client) => {
|
|
620
|
+
const resp = await client.getRaw("/download", { path });
|
|
621
|
+
return resp.arrayBuffer();
|
|
622
|
+
});
|
|
501
623
|
},
|
|
502
|
-
|
|
503
|
-
const
|
|
504
|
-
|
|
505
|
-
"GET",
|
|
624
|
+
write: async (dbId, path, content) => {
|
|
625
|
+
const contentType = typeof content === "string" ? "text/plain" : "application/octet-stream";
|
|
626
|
+
await withFsAuthRetry(
|
|
506
627
|
dbId,
|
|
507
|
-
`/
|
|
628
|
+
(client) => client.putRaw(`/upload?${new URLSearchParams({ path })}`, content, { "Content-Type": contentType })
|
|
508
629
|
);
|
|
509
|
-
|
|
630
|
+
},
|
|
631
|
+
stat: (dbId, path) => {
|
|
632
|
+
return fsStat(dbId, path);
|
|
633
|
+
},
|
|
634
|
+
exists: async (dbId, path) => {
|
|
635
|
+
try {
|
|
636
|
+
await fsStat(dbId, path);
|
|
637
|
+
return true;
|
|
638
|
+
} catch (err) {
|
|
639
|
+
if (err instanceof Db9Error && err.statusCode === 404) {
|
|
640
|
+
return false;
|
|
641
|
+
}
|
|
642
|
+
throw err;
|
|
643
|
+
}
|
|
510
644
|
},
|
|
511
645
|
mkdir: async (dbId, path) => {
|
|
512
|
-
|
|
513
|
-
"POST",
|
|
646
|
+
await withFsAuthRetry(
|
|
514
647
|
dbId,
|
|
515
|
-
"
|
|
516
|
-
JSON.stringify({
|
|
517
|
-
path,
|
|
518
|
-
flags: { create: true, directory: true }
|
|
519
|
-
}),
|
|
520
|
-
"application/json"
|
|
648
|
+
(client) => client.postRaw(`/mkdir?${new URLSearchParams({ path, recursive: "true" })}`)
|
|
521
649
|
);
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
650
|
+
},
|
|
651
|
+
remove: async (dbId, path) => {
|
|
652
|
+
await withFsAuthRetry(
|
|
525
653
|
dbId,
|
|
526
|
-
"/
|
|
527
|
-
JSON.stringify({ handle_id }),
|
|
528
|
-
"application/json"
|
|
654
|
+
(client) => client.delRaw("/remove", { path })
|
|
529
655
|
);
|
|
530
656
|
},
|
|
531
|
-
|
|
532
|
-
const params =
|
|
533
|
-
|
|
657
|
+
events: async (dbId, options2) => {
|
|
658
|
+
const params = {};
|
|
659
|
+
if (options2?.limit !== void 0) params.limit = String(options2.limit);
|
|
660
|
+
if (options2?.offset !== void 0) params.offset = String(options2.offset);
|
|
661
|
+
if (options2?.path) params.path = options2.path;
|
|
662
|
+
if (options2?.type) params.type = options2.type;
|
|
663
|
+
return withFsAuthRetry(
|
|
664
|
+
dbId,
|
|
665
|
+
(client) => client.get("/events", params)
|
|
666
|
+
);
|
|
534
667
|
}
|
|
535
668
|
}
|
|
536
669
|
};
|
|
@@ -542,7 +675,10 @@ async function instantDatabase(options = {}) {
|
|
|
542
675
|
const client = createDb9Client({
|
|
543
676
|
baseUrl: options.baseUrl,
|
|
544
677
|
fetch: options.fetch,
|
|
545
|
-
credentialStore: options.credentialStore
|
|
678
|
+
credentialStore: options.credentialStore,
|
|
679
|
+
timeout: options.timeout,
|
|
680
|
+
maxRetries: options.maxRetries,
|
|
681
|
+
retryDelay: options.retryDelay
|
|
546
682
|
});
|
|
547
683
|
const existing = await client.databases.list();
|
|
548
684
|
const found = existing.find((db) => db.name === dbName);
|