get-db9 0.4.0 → 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-fUeI7kwU.d.cts → client-UKXFQNll.d.cts} +62 -17
- package/dist/{client-fUeI7kwU.d.ts → client-UKXFQNll.d.ts} +62 -17
- package/dist/client.cjs +314 -157
- 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 +314 -157
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +318 -158
- 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 +318 -158
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/client.js
CHANGED
|
@@ -48,6 +48,9 @@ var Db9ConflictError = class extends Db9Error {
|
|
|
48
48
|
};
|
|
49
49
|
|
|
50
50
|
// src/http.ts
|
|
51
|
+
function delay(ms) {
|
|
52
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
53
|
+
}
|
|
51
54
|
function createHttpClient(options) {
|
|
52
55
|
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
53
56
|
const baseUrl = options.baseUrl.replace(/\/$/, "");
|
|
@@ -56,38 +59,61 @@ function createHttpClient(options) {
|
|
|
56
59
|
if (params) {
|
|
57
60
|
const searchParams = new URLSearchParams();
|
|
58
61
|
for (const [key, value] of Object.entries(params)) {
|
|
59
|
-
if (value !== void 0)
|
|
60
|
-
searchParams.set(key, value);
|
|
61
|
-
}
|
|
62
|
+
if (value !== void 0) searchParams.set(key, value);
|
|
62
63
|
}
|
|
63
64
|
const qs = searchParams.toString();
|
|
64
65
|
if (qs) url += `?${qs}`;
|
|
65
66
|
}
|
|
66
|
-
const
|
|
67
|
+
const reqHeaders = {
|
|
67
68
|
"Content-Type": "application/json",
|
|
68
69
|
...options.headers
|
|
69
70
|
};
|
|
70
|
-
const init = { method, headers };
|
|
71
|
+
const init = { method, headers: reqHeaders };
|
|
71
72
|
if (body !== void 0) {
|
|
72
73
|
init.body = JSON.stringify(body);
|
|
73
74
|
}
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
const maxAttempts = Math.min(options.maxRetries ?? 0, 3) + 1;
|
|
76
|
+
const baseDelay = options.retryDelay ?? 1e3;
|
|
77
|
+
let lastError;
|
|
78
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
79
|
+
let timeoutId;
|
|
80
|
+
try {
|
|
81
|
+
const fetchInit = { ...init };
|
|
82
|
+
if (options.timeout) {
|
|
83
|
+
const controller = new AbortController();
|
|
84
|
+
fetchInit.signal = controller.signal;
|
|
85
|
+
timeoutId = setTimeout(() => controller.abort(), options.timeout);
|
|
86
|
+
}
|
|
87
|
+
const response = await fetchFn(url, fetchInit);
|
|
88
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
89
|
+
if (!response.ok) {
|
|
90
|
+
if (response.status >= 500 && attempt < maxAttempts - 1) {
|
|
91
|
+
lastError = await Db9Error.fromResponse(response);
|
|
92
|
+
await delay(baseDelay * Math.pow(2, attempt));
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
throw await Db9Error.fromResponse(response);
|
|
96
|
+
}
|
|
97
|
+
if (response.status === 204) return void 0;
|
|
98
|
+
return response.json();
|
|
99
|
+
} catch (err) {
|
|
100
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
101
|
+
if (err instanceof TypeError && attempt < maxAttempts - 1) {
|
|
102
|
+
lastError = err;
|
|
103
|
+
await delay(baseDelay * Math.pow(2, attempt));
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
throw err;
|
|
107
|
+
}
|
|
80
108
|
}
|
|
81
|
-
|
|
109
|
+
throw lastError;
|
|
82
110
|
}
|
|
83
111
|
async function requestRaw(method, path, body, params, customHeaders) {
|
|
84
112
|
let url = `${baseUrl}${path}`;
|
|
85
113
|
if (params) {
|
|
86
114
|
const searchParams = new URLSearchParams();
|
|
87
115
|
for (const [key, value] of Object.entries(params)) {
|
|
88
|
-
if (value !== void 0)
|
|
89
|
-
searchParams.set(key, value);
|
|
90
|
-
}
|
|
116
|
+
if (value !== void 0) searchParams.set(key, value);
|
|
91
117
|
}
|
|
92
118
|
const qs = searchParams.toString();
|
|
93
119
|
if (qs) url += `?${qs}`;
|
|
@@ -96,15 +122,23 @@ function createHttpClient(options) {
|
|
|
96
122
|
...options.headers,
|
|
97
123
|
...customHeaders
|
|
98
124
|
};
|
|
99
|
-
const
|
|
100
|
-
if (body !== void 0)
|
|
101
|
-
|
|
125
|
+
const fetchInit = { method, headers };
|
|
126
|
+
if (body !== void 0) fetchInit.body = body;
|
|
127
|
+
let timeoutId;
|
|
128
|
+
if (options.timeout) {
|
|
129
|
+
const controller = new AbortController();
|
|
130
|
+
fetchInit.signal = controller.signal;
|
|
131
|
+
timeoutId = setTimeout(() => controller.abort(), options.timeout);
|
|
102
132
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
133
|
+
try {
|
|
134
|
+
const response = await fetchFn(url, fetchInit);
|
|
135
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
136
|
+
if (!response.ok) throw await Db9Error.fromResponse(response);
|
|
137
|
+
return response;
|
|
138
|
+
} catch (err) {
|
|
139
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
140
|
+
throw err;
|
|
106
141
|
}
|
|
107
|
-
return response;
|
|
108
142
|
}
|
|
109
143
|
return {
|
|
110
144
|
get: (path, params) => request("GET", path, void 0, params),
|
|
@@ -112,7 +146,9 @@ function createHttpClient(options) {
|
|
|
112
146
|
put: (path, body) => request("PUT", path, body),
|
|
113
147
|
del: (path) => request("DELETE", path),
|
|
114
148
|
getRaw: (path, params) => requestRaw("GET", path, void 0, params),
|
|
115
|
-
putRaw: (path, body, headers) => requestRaw("PUT", path, body, void 0, headers)
|
|
149
|
+
putRaw: (path, body, headers) => requestRaw("PUT", path, body, void 0, headers),
|
|
150
|
+
postRaw: (path, body, headers) => requestRaw("POST", path, body, void 0, headers),
|
|
151
|
+
delRaw: (path, params) => requestRaw("DELETE", path, void 0, params)
|
|
116
152
|
};
|
|
117
153
|
}
|
|
118
154
|
|
|
@@ -215,7 +251,10 @@ function createDb9Client(options = {}) {
|
|
|
215
251
|
const fetchFn = options.fetch ?? globalThis.fetch;
|
|
216
252
|
const publicClient = createHttpClient({
|
|
217
253
|
baseUrl,
|
|
218
|
-
fetch: options.fetch
|
|
254
|
+
fetch: options.fetch,
|
|
255
|
+
timeout: options.timeout,
|
|
256
|
+
maxRetries: options.maxRetries,
|
|
257
|
+
retryDelay: options.retryDelay
|
|
219
258
|
});
|
|
220
259
|
async function getAuthClient() {
|
|
221
260
|
if (!token && !tokenLoaded) {
|
|
@@ -238,35 +277,118 @@ function createDb9Client(options = {}) {
|
|
|
238
277
|
return createHttpClient({
|
|
239
278
|
baseUrl,
|
|
240
279
|
fetch: options.fetch,
|
|
241
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
280
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
281
|
+
timeout: options.timeout,
|
|
282
|
+
maxRetries: options.maxRetries,
|
|
283
|
+
retryDelay: options.retryDelay
|
|
242
284
|
});
|
|
243
285
|
}
|
|
286
|
+
let refreshPromise = null;
|
|
287
|
+
async function refreshAnonymousToken() {
|
|
288
|
+
const creds = await store.load();
|
|
289
|
+
if (!creds?.anonymous_id || !creds?.anonymous_secret) {
|
|
290
|
+
throw new Error("Not an anonymous session");
|
|
291
|
+
}
|
|
292
|
+
const resp = await publicClient.post(
|
|
293
|
+
"/customer/anonymous-refresh",
|
|
294
|
+
{
|
|
295
|
+
anonymous_id: creds.anonymous_id,
|
|
296
|
+
anonymous_secret: creds.anonymous_secret
|
|
297
|
+
}
|
|
298
|
+
);
|
|
299
|
+
token = resp.token;
|
|
300
|
+
await store.save({ ...creds, token: resp.token });
|
|
301
|
+
}
|
|
302
|
+
async function withAuthRetry(operation) {
|
|
303
|
+
const client = await getAuthClient();
|
|
304
|
+
try {
|
|
305
|
+
return await operation(client);
|
|
306
|
+
} catch (err) {
|
|
307
|
+
if (!(err instanceof Db9Error) || err.statusCode !== 401) {
|
|
308
|
+
throw err;
|
|
309
|
+
}
|
|
310
|
+
try {
|
|
311
|
+
if (!refreshPromise) {
|
|
312
|
+
refreshPromise = refreshAnonymousToken();
|
|
313
|
+
}
|
|
314
|
+
await refreshPromise;
|
|
315
|
+
} catch {
|
|
316
|
+
throw err;
|
|
317
|
+
} finally {
|
|
318
|
+
refreshPromise = null;
|
|
319
|
+
}
|
|
320
|
+
const newClient = await getAuthClient();
|
|
321
|
+
return operation(newClient);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
244
324
|
function deriveFs9Url(dbId) {
|
|
245
325
|
const origin = baseUrl.replace(/\/api\/?$/, "");
|
|
246
326
|
return `${origin}/fs9/${dbId}`;
|
|
247
327
|
}
|
|
248
|
-
|
|
328
|
+
function getFsClient(dbId) {
|
|
329
|
+
const fs9Base = deriveFs9Url(dbId) + "/api/v1";
|
|
330
|
+
return createHttpClient({
|
|
331
|
+
baseUrl: fs9Base,
|
|
332
|
+
fetch: options.fetch,
|
|
333
|
+
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
|
334
|
+
timeout: options.timeout,
|
|
335
|
+
maxRetries: options.maxRetries,
|
|
336
|
+
retryDelay: options.retryDelay
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
async function withFsAuthRetry(dbId, operation) {
|
|
249
340
|
if (!token && !tokenLoaded) {
|
|
250
341
|
await getAuthClient();
|
|
251
342
|
}
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
343
|
+
const client = getFsClient(dbId);
|
|
344
|
+
try {
|
|
345
|
+
return await operation(client);
|
|
346
|
+
} catch (err) {
|
|
347
|
+
if (!(err instanceof Db9Error) || err.statusCode !== 401) {
|
|
348
|
+
throw err;
|
|
349
|
+
}
|
|
350
|
+
try {
|
|
351
|
+
if (!refreshPromise) {
|
|
352
|
+
refreshPromise = refreshAnonymousToken();
|
|
353
|
+
}
|
|
354
|
+
await refreshPromise;
|
|
355
|
+
} catch {
|
|
356
|
+
throw err;
|
|
357
|
+
} finally {
|
|
358
|
+
refreshPromise = null;
|
|
359
|
+
}
|
|
360
|
+
const newClient = getFsClient(dbId);
|
|
361
|
+
return operation(newClient);
|
|
260
362
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
363
|
+
}
|
|
364
|
+
function parseSqlError(raw) {
|
|
365
|
+
try {
|
|
366
|
+
const parsed = JSON.parse(raw);
|
|
367
|
+
if (typeof parsed === "object" && parsed !== null && typeof parsed.message === "string") {
|
|
368
|
+
return parsed;
|
|
369
|
+
}
|
|
370
|
+
} catch {
|
|
264
371
|
}
|
|
265
|
-
const
|
|
266
|
-
if (
|
|
267
|
-
|
|
372
|
+
const pgMatch = raw.match(/^(?:ERROR:\s*)?(.+?)(?:\s+DETAIL:\s+(.+?))?(?:\s+HINT:\s+(.+?))?(?:\s+\(SQLSTATE\s+(\w+)\))?$/s);
|
|
373
|
+
if (pgMatch && pgMatch[1]) {
|
|
374
|
+
const result = { message: pgMatch[1].trim() };
|
|
375
|
+
if (pgMatch[2]) result.detail = pgMatch[2].trim();
|
|
376
|
+
if (pgMatch[3]) result.hint = pgMatch[3].trim();
|
|
377
|
+
if (pgMatch[4]) result.code = pgMatch[4];
|
|
378
|
+
return result;
|
|
268
379
|
}
|
|
269
|
-
return
|
|
380
|
+
return { message: raw };
|
|
381
|
+
}
|
|
382
|
+
async function fsStat(dbId, path) {
|
|
383
|
+
return withFsAuthRetry(
|
|
384
|
+
dbId,
|
|
385
|
+
(client) => client.get("/stat", { path })
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
async function fetchAnonymousSecret() {
|
|
389
|
+
return withAuthRetry(
|
|
390
|
+
(client) => client.post("/customer/anonymous-secret", {})
|
|
391
|
+
);
|
|
270
392
|
}
|
|
271
393
|
return {
|
|
272
394
|
auth: {
|
|
@@ -281,171 +403,206 @@ function createDb9Client(options = {}) {
|
|
|
281
403
|
req
|
|
282
404
|
),
|
|
283
405
|
// Authenticated endpoints
|
|
284
|
-
me: async () =>
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
const client = await getAuthClient();
|
|
290
|
-
return client.get(
|
|
291
|
-
"/customer/anonymous-secret"
|
|
292
|
-
);
|
|
406
|
+
me: async () => withAuthRetry(
|
|
407
|
+
(client) => client.get("/customer/me")
|
|
408
|
+
),
|
|
409
|
+
getAnonymousSecret: () => {
|
|
410
|
+
return fetchAnonymousSecret();
|
|
293
411
|
},
|
|
294
|
-
claim: async (req) =>
|
|
295
|
-
|
|
296
|
-
|
|
412
|
+
claim: async (req) => withAuthRetry(
|
|
413
|
+
(client) => client.post("/customer/claim", req)
|
|
414
|
+
),
|
|
415
|
+
ensureAnonymousSecret: async () => {
|
|
416
|
+
const creds = await store.load();
|
|
417
|
+
if (!creds?.anonymous_id || creds.anonymous_secret) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
const resp = await fetchAnonymousSecret();
|
|
421
|
+
await store.save({
|
|
422
|
+
...creds,
|
|
423
|
+
anonymous_secret: resp.anonymous_secret
|
|
424
|
+
});
|
|
297
425
|
}
|
|
298
426
|
},
|
|
299
427
|
tokens: {
|
|
300
|
-
list: async () =>
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
428
|
+
list: async () => withAuthRetry(
|
|
429
|
+
(client) => client.get("/customer/tokens")
|
|
430
|
+
),
|
|
431
|
+
revoke: async (tokenId) => withAuthRetry(
|
|
432
|
+
(client) => client.del(`/customer/tokens/${tokenId}`)
|
|
433
|
+
),
|
|
434
|
+
create: async (req) => withAuthRetry(
|
|
435
|
+
(client) => client.post("/customer/tokens", req)
|
|
436
|
+
)
|
|
308
437
|
},
|
|
309
438
|
databases: {
|
|
310
439
|
// ── CRUD ──────────────────────────────────────────────────
|
|
311
|
-
create: async (req) =>
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
get: async (databaseId) => {
|
|
320
|
-
const client = await getAuthClient();
|
|
321
|
-
return client.get(
|
|
440
|
+
create: async (req) => withAuthRetry(
|
|
441
|
+
(client) => client.post("/customer/databases", req)
|
|
442
|
+
),
|
|
443
|
+
list: async () => withAuthRetry(
|
|
444
|
+
(client) => client.get("/customer/databases")
|
|
445
|
+
),
|
|
446
|
+
get: async (databaseId) => withAuthRetry(
|
|
447
|
+
(client) => client.get(
|
|
322
448
|
`/customer/databases/${databaseId}`
|
|
323
|
-
)
|
|
324
|
-
|
|
325
|
-
delete: async (databaseId) =>
|
|
326
|
-
|
|
327
|
-
return client.del(
|
|
449
|
+
)
|
|
450
|
+
),
|
|
451
|
+
delete: async (databaseId) => withAuthRetry(
|
|
452
|
+
(client) => client.del(
|
|
328
453
|
`/customer/databases/${databaseId}`
|
|
329
|
-
)
|
|
330
|
-
|
|
331
|
-
resetPassword: async (databaseId) =>
|
|
332
|
-
|
|
333
|
-
return client.post(
|
|
454
|
+
)
|
|
455
|
+
),
|
|
456
|
+
resetPassword: async (databaseId) => withAuthRetry(
|
|
457
|
+
(client) => client.post(
|
|
334
458
|
`/customer/databases/${databaseId}/reset-password`
|
|
335
|
-
)
|
|
336
|
-
|
|
337
|
-
observability: async (databaseId) =>
|
|
338
|
-
|
|
339
|
-
return client.get(
|
|
459
|
+
)
|
|
460
|
+
),
|
|
461
|
+
observability: async (databaseId) => withAuthRetry(
|
|
462
|
+
(client) => client.get(
|
|
340
463
|
`/customer/databases/${databaseId}/observability`
|
|
341
|
-
)
|
|
342
|
-
|
|
464
|
+
)
|
|
465
|
+
),
|
|
343
466
|
// ── SQL Execution ─────────────────────────────────────────
|
|
344
467
|
sql: async (databaseId, query) => {
|
|
345
|
-
const
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
468
|
+
const result = await withAuthRetry(
|
|
469
|
+
(client) => client.post(
|
|
470
|
+
`/customer/databases/${databaseId}/sql`,
|
|
471
|
+
{ query }
|
|
472
|
+
)
|
|
349
473
|
);
|
|
474
|
+
if (result.error && typeof result.error === "string") {
|
|
475
|
+
result.error = parseSqlError(result.error);
|
|
476
|
+
}
|
|
477
|
+
return result;
|
|
350
478
|
},
|
|
351
479
|
sqlFile: async (databaseId, fileContent) => {
|
|
352
|
-
const
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
480
|
+
const result = await withAuthRetry(
|
|
481
|
+
(client) => client.post(
|
|
482
|
+
`/customer/databases/${databaseId}/sql`,
|
|
483
|
+
{ file_content: fileContent }
|
|
484
|
+
)
|
|
356
485
|
);
|
|
486
|
+
if (result.error && typeof result.error === "string") {
|
|
487
|
+
result.error = parseSqlError(result.error);
|
|
488
|
+
}
|
|
489
|
+
return result;
|
|
357
490
|
},
|
|
358
491
|
// ── Schema & Dump ─────────────────────────────────────────
|
|
359
|
-
schema: async (databaseId) =>
|
|
360
|
-
|
|
361
|
-
return client.get(
|
|
492
|
+
schema: async (databaseId) => withAuthRetry(
|
|
493
|
+
(client) => client.get(
|
|
362
494
|
`/customer/databases/${databaseId}/schema`
|
|
363
|
-
)
|
|
364
|
-
|
|
365
|
-
dump: async (databaseId, req) =>
|
|
366
|
-
|
|
367
|
-
return client.post(
|
|
495
|
+
)
|
|
496
|
+
),
|
|
497
|
+
dump: async (databaseId, req) => withAuthRetry(
|
|
498
|
+
(client) => client.post(
|
|
368
499
|
`/customer/databases/${databaseId}/dump`,
|
|
369
500
|
req
|
|
370
|
-
)
|
|
371
|
-
|
|
501
|
+
)
|
|
502
|
+
),
|
|
372
503
|
// ── Migrations ────────────────────────────────────────────
|
|
373
|
-
applyMigration: async (databaseId, req) =>
|
|
374
|
-
|
|
375
|
-
return client.post(
|
|
504
|
+
applyMigration: async (databaseId, req) => withAuthRetry(
|
|
505
|
+
(client) => client.post(
|
|
376
506
|
`/customer/databases/${databaseId}/migrations`,
|
|
377
507
|
req
|
|
378
|
-
)
|
|
379
|
-
|
|
380
|
-
listMigrations: async (databaseId) =>
|
|
381
|
-
|
|
382
|
-
return client.get(
|
|
508
|
+
)
|
|
509
|
+
),
|
|
510
|
+
listMigrations: async (databaseId) => withAuthRetry(
|
|
511
|
+
(client) => client.get(
|
|
383
512
|
`/customer/databases/${databaseId}/migrations`
|
|
384
|
-
)
|
|
385
|
-
|
|
513
|
+
)
|
|
514
|
+
),
|
|
386
515
|
// ── Branching ─────────────────────────────────────────────
|
|
387
|
-
branch: async (databaseId, req) =>
|
|
388
|
-
|
|
389
|
-
return client.post(
|
|
516
|
+
branch: async (databaseId, req) => withAuthRetry(
|
|
517
|
+
(client) => client.post(
|
|
390
518
|
`/customer/databases/${databaseId}/branch`,
|
|
391
519
|
req
|
|
392
|
-
)
|
|
393
|
-
|
|
520
|
+
)
|
|
521
|
+
),
|
|
394
522
|
// ── User Management ───────────────────────────────────────
|
|
395
523
|
users: {
|
|
396
|
-
list: async (databaseId) =>
|
|
397
|
-
|
|
398
|
-
return client.get(
|
|
524
|
+
list: async (databaseId) => withAuthRetry(
|
|
525
|
+
(client) => client.get(
|
|
399
526
|
`/customer/databases/${databaseId}/users`
|
|
400
|
-
)
|
|
401
|
-
|
|
402
|
-
create: async (databaseId, req) =>
|
|
403
|
-
|
|
404
|
-
return client.post(
|
|
527
|
+
)
|
|
528
|
+
),
|
|
529
|
+
create: async (databaseId, req) => withAuthRetry(
|
|
530
|
+
(client) => client.post(
|
|
405
531
|
`/customer/databases/${databaseId}/users`,
|
|
406
532
|
req
|
|
407
|
-
)
|
|
408
|
-
|
|
409
|
-
delete: async (databaseId, username) =>
|
|
410
|
-
|
|
411
|
-
return client.del(
|
|
533
|
+
)
|
|
534
|
+
),
|
|
535
|
+
delete: async (databaseId, username) => withAuthRetry(
|
|
536
|
+
(client) => client.del(
|
|
412
537
|
`/customer/databases/${databaseId}/users/${username}`
|
|
413
|
-
)
|
|
414
|
-
|
|
538
|
+
)
|
|
539
|
+
)
|
|
415
540
|
}
|
|
416
541
|
},
|
|
417
542
|
fs: {
|
|
418
543
|
list: async (dbId, path, options2) => {
|
|
419
|
-
const params =
|
|
420
|
-
if (options2?.recursive) params.
|
|
421
|
-
|
|
422
|
-
"GET",
|
|
544
|
+
const params = { path };
|
|
545
|
+
if (options2?.recursive) params.recursive = "true";
|
|
546
|
+
return withFsAuthRetry(
|
|
423
547
|
dbId,
|
|
424
|
-
|
|
548
|
+
(client) => client.get("/readdir", params)
|
|
425
549
|
);
|
|
426
|
-
return response.json();
|
|
427
550
|
},
|
|
428
551
|
read: async (dbId, path) => {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
552
|
+
return withFsAuthRetry(dbId, async (client) => {
|
|
553
|
+
const resp = await client.getRaw("/download", { path });
|
|
554
|
+
return resp.text();
|
|
555
|
+
});
|
|
556
|
+
},
|
|
557
|
+
readBinary: async (dbId, path) => {
|
|
558
|
+
return withFsAuthRetry(dbId, async (client) => {
|
|
559
|
+
const resp = await client.getRaw("/download", { path });
|
|
560
|
+
return resp.arrayBuffer();
|
|
561
|
+
});
|
|
562
|
+
},
|
|
563
|
+
write: async (dbId, path, content) => {
|
|
564
|
+
const contentType = typeof content === "string" ? "text/plain" : "application/octet-stream";
|
|
565
|
+
await withFsAuthRetry(
|
|
432
566
|
dbId,
|
|
433
|
-
`/
|
|
567
|
+
(client) => client.putRaw(`/upload?${new URLSearchParams({ path })}`, content, { "Content-Type": contentType })
|
|
434
568
|
);
|
|
435
|
-
return response.text();
|
|
436
569
|
},
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
await fsRequest("PUT", dbId, `/upload?${params.toString()}`, content);
|
|
570
|
+
stat: (dbId, path) => {
|
|
571
|
+
return fsStat(dbId, path);
|
|
440
572
|
},
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
573
|
+
exists: async (dbId, path) => {
|
|
574
|
+
try {
|
|
575
|
+
await fsStat(dbId, path);
|
|
576
|
+
return true;
|
|
577
|
+
} catch (err) {
|
|
578
|
+
if (err instanceof Db9Error && err.statusCode === 404) {
|
|
579
|
+
return false;
|
|
580
|
+
}
|
|
581
|
+
throw err;
|
|
582
|
+
}
|
|
583
|
+
},
|
|
584
|
+
mkdir: async (dbId, path) => {
|
|
585
|
+
await withFsAuthRetry(
|
|
445
586
|
dbId,
|
|
446
|
-
`/
|
|
587
|
+
(client) => client.postRaw(`/mkdir?${new URLSearchParams({ path, recursive: "true" })}`)
|
|
588
|
+
);
|
|
589
|
+
},
|
|
590
|
+
remove: async (dbId, path) => {
|
|
591
|
+
await withFsAuthRetry(
|
|
592
|
+
dbId,
|
|
593
|
+
(client) => client.delRaw("/remove", { path })
|
|
594
|
+
);
|
|
595
|
+
},
|
|
596
|
+
events: async (dbId, options2) => {
|
|
597
|
+
const params = {};
|
|
598
|
+
if (options2?.limit !== void 0) params.limit = String(options2.limit);
|
|
599
|
+
if (options2?.offset !== void 0) params.offset = String(options2.offset);
|
|
600
|
+
if (options2?.path) params.path = options2.path;
|
|
601
|
+
if (options2?.type) params.type = options2.type;
|
|
602
|
+
return withFsAuthRetry(
|
|
603
|
+
dbId,
|
|
604
|
+
(client) => client.get("/events", params)
|
|
447
605
|
);
|
|
448
|
-
return response.json();
|
|
449
606
|
}
|
|
450
607
|
}
|
|
451
608
|
};
|