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