@aouda/client 0.1.7 → 0.1.9
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/cli/index.cjs +133 -24
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +133 -24
- package/dist/cli/index.js.map +1 -1
- package/dist/{client-BbyXG5AL.d.cts → client-CxP9Vnc8.d.cts} +154 -8
- package/dist/{client-BbyXG5AL.d.ts → client-CxP9Vnc8.d.ts} +154 -8
- package/dist/index.cjs +135 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +134 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.cjs
CHANGED
|
@@ -421,7 +421,7 @@ var import_node_url = require("url");
|
|
|
421
421
|
// package.json
|
|
422
422
|
var package_default = {
|
|
423
423
|
name: "@aouda/client",
|
|
424
|
-
version: "0.1.
|
|
424
|
+
version: "0.1.9",
|
|
425
425
|
description: "Official TypeScript/JavaScript client library for Aouda",
|
|
426
426
|
type: "module",
|
|
427
427
|
main: "./dist/index.cjs",
|
|
@@ -536,12 +536,13 @@ var AoudaResponseError = class extends AoudaError {
|
|
|
536
536
|
}
|
|
537
537
|
};
|
|
538
538
|
var AoudaApiError = class extends AoudaError {
|
|
539
|
-
constructor(message, code, statusCode, details, requestId) {
|
|
539
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds) {
|
|
540
540
|
super(message);
|
|
541
541
|
this.code = code;
|
|
542
542
|
this.statusCode = statusCode;
|
|
543
543
|
this.details = details;
|
|
544
544
|
this.requestId = requestId;
|
|
545
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
545
546
|
this.name = "AoudaApiError";
|
|
546
547
|
}
|
|
547
548
|
};
|
|
@@ -564,8 +565,8 @@ var AoudaValidationError = class extends AoudaApiError {
|
|
|
564
565
|
}
|
|
565
566
|
};
|
|
566
567
|
var AoudaServerError = class extends AoudaApiError {
|
|
567
|
-
constructor(message, code, statusCode, details, requestId) {
|
|
568
|
-
super(message, code, statusCode, details, requestId);
|
|
568
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds) {
|
|
569
|
+
super(message, code, statusCode, details, requestId, retryAfterSeconds);
|
|
569
570
|
this.name = "AoudaServerError";
|
|
570
571
|
}
|
|
571
572
|
};
|
|
@@ -1504,6 +1505,8 @@ var ERROR_CODE_MAP = {
|
|
|
1504
1505
|
SERVICE_UNAVAILABLE: AoudaServerError,
|
|
1505
1506
|
TIMEOUT: AoudaServerError,
|
|
1506
1507
|
OVERLOADED: AoudaServerError,
|
|
1508
|
+
MEMORY_BUDGET_EXCEEDED: AoudaServerError,
|
|
1509
|
+
WAL_CAPACITY_EXCEEDED: AoudaServerError,
|
|
1507
1510
|
AUTH_TOKEN_MISSING: AoudaAuthenticationError,
|
|
1508
1511
|
AUTH_TOKEN_EXPIRED: AoudaAuthenticationError,
|
|
1509
1512
|
AUTH_TOKEN_INVALID: AoudaAuthenticationError,
|
|
@@ -1531,13 +1534,22 @@ function createComposedAbortController(...signals) {
|
|
|
1531
1534
|
}
|
|
1532
1535
|
return controller;
|
|
1533
1536
|
}
|
|
1534
|
-
function
|
|
1537
|
+
function parseRetryAfterSeconds(header) {
|
|
1538
|
+
if (header == null || header.trim() === "") return void 0;
|
|
1539
|
+
const trimmed = header.trim();
|
|
1540
|
+
if (!/^\d+$/.test(trimmed)) return void 0;
|
|
1541
|
+
const n = Number.parseInt(trimmed, 10);
|
|
1542
|
+
if (!Number.isFinite(n) || n < 0) return void 0;
|
|
1543
|
+
return n;
|
|
1544
|
+
}
|
|
1545
|
+
function createApiError(statusCode, statusText, body, retryAfterHeader) {
|
|
1535
1546
|
const message = body.error ?? `${statusCode} ${statusText}`;
|
|
1536
1547
|
const code = body.code ?? "UNKNOWN";
|
|
1537
1548
|
const details = body.details;
|
|
1538
1549
|
const requestId = body.requestId;
|
|
1550
|
+
const retryAfterSeconds = parseRetryAfterSeconds(retryAfterHeader ?? null);
|
|
1539
1551
|
const Ctor = ERROR_CODE_MAP[code] ?? AoudaApiError;
|
|
1540
|
-
return new Ctor(message, code, statusCode, details, requestId);
|
|
1552
|
+
return new Ctor(message, code, statusCode, details, requestId, retryAfterSeconds);
|
|
1541
1553
|
}
|
|
1542
1554
|
var HttpTransport = class {
|
|
1543
1555
|
constructor(options) {
|
|
@@ -1630,7 +1642,8 @@ var HttpTransport = class {
|
|
|
1630
1642
|
throw createApiError(
|
|
1631
1643
|
response.status,
|
|
1632
1644
|
response.statusText,
|
|
1633
|
-
errorBody
|
|
1645
|
+
errorBody,
|
|
1646
|
+
response.headers.get("Retry-After")
|
|
1634
1647
|
);
|
|
1635
1648
|
}
|
|
1636
1649
|
throw new AoudaResponseError(
|
|
@@ -1740,7 +1753,8 @@ var HttpTransport = class {
|
|
|
1740
1753
|
throw createApiError(
|
|
1741
1754
|
response.status,
|
|
1742
1755
|
response.statusText,
|
|
1743
|
-
errorBody
|
|
1756
|
+
errorBody,
|
|
1757
|
+
response.headers.get("Retry-After")
|
|
1744
1758
|
);
|
|
1745
1759
|
}
|
|
1746
1760
|
throw new AoudaResponseError(
|
|
@@ -2086,6 +2100,17 @@ var CIRCUIT_BREAKER_POLICY_DISABLED = {
|
|
|
2086
2100
|
|
|
2087
2101
|
// src/resilience/resilient-transport.ts
|
|
2088
2102
|
var REQUEST_ID_HEADER3 = "X-Request-Id";
|
|
2103
|
+
function isCapacityBackPressure(error) {
|
|
2104
|
+
return error instanceof AoudaApiError && (error.code === "MEMORY_BUDGET_EXCEEDED" || error.code === "WAL_CAPACITY_EXCEEDED");
|
|
2105
|
+
}
|
|
2106
|
+
function retryDelayMs(retryPolicy, attempt, error) {
|
|
2107
|
+
const backoff = calculateDelay(retryPolicy, attempt);
|
|
2108
|
+
if (!isCapacityBackPressure(error) || !(error instanceof AoudaApiError)) {
|
|
2109
|
+
return backoff;
|
|
2110
|
+
}
|
|
2111
|
+
const headerMs = error.retryAfterSeconds != null ? error.retryAfterSeconds * 1e3 : 0;
|
|
2112
|
+
return Math.max(backoff, headerMs);
|
|
2113
|
+
}
|
|
2089
2114
|
function delayMs(ms, signal) {
|
|
2090
2115
|
if (ms <= 0) return Promise.resolve();
|
|
2091
2116
|
return new Promise((resolve4, reject) => {
|
|
@@ -2140,7 +2165,7 @@ var ResilientTransport = class {
|
|
|
2140
2165
|
} catch (error) {
|
|
2141
2166
|
lastError = error;
|
|
2142
2167
|
const retryable = isRetryable(error);
|
|
2143
|
-
if (retryable) {
|
|
2168
|
+
if (retryable && !isCapacityBackPressure(error)) {
|
|
2144
2169
|
this.circuitBreaker.recordFailure(error);
|
|
2145
2170
|
}
|
|
2146
2171
|
if (!retryable) {
|
|
@@ -2150,7 +2175,7 @@ var ResilientTransport = class {
|
|
|
2150
2175
|
if (attempt > this.retryPolicy.maxRetries) {
|
|
2151
2176
|
throw error;
|
|
2152
2177
|
}
|
|
2153
|
-
const delay =
|
|
2178
|
+
const delay = retryDelayMs(this.retryPolicy, attempt, error);
|
|
2154
2179
|
try {
|
|
2155
2180
|
await delayMs(delay, config.signal);
|
|
2156
2181
|
} catch {
|
|
@@ -2186,7 +2211,7 @@ var ResilientTransport = class {
|
|
|
2186
2211
|
} catch (error) {
|
|
2187
2212
|
lastError = error;
|
|
2188
2213
|
const retryable = isRetryable(error);
|
|
2189
|
-
if (retryable) {
|
|
2214
|
+
if (retryable && !isCapacityBackPressure(error)) {
|
|
2190
2215
|
this.circuitBreaker.recordFailure(error);
|
|
2191
2216
|
}
|
|
2192
2217
|
if (!retryable) {
|
|
@@ -2196,7 +2221,7 @@ var ResilientTransport = class {
|
|
|
2196
2221
|
if (attempt > this.retryPolicy.maxRetries) {
|
|
2197
2222
|
throw error;
|
|
2198
2223
|
}
|
|
2199
|
-
const delay =
|
|
2224
|
+
const delay = retryDelayMs(this.retryPolicy, attempt, error);
|
|
2200
2225
|
try {
|
|
2201
2226
|
await delayMs(delay, config.signal);
|
|
2202
2227
|
} catch {
|
|
@@ -3953,23 +3978,68 @@ var TablesApi = class {
|
|
|
3953
3978
|
);
|
|
3954
3979
|
}
|
|
3955
3980
|
/**
|
|
3956
|
-
*
|
|
3981
|
+
* Alters a column (type, nullable, encoder, autoIncrement, references, and/or rename).
|
|
3982
|
+
* PATCH /api/databases/{db}/tables/{t}/columns/{c}.
|
|
3983
|
+
* Omit a property to leave it unchanged. For `references`, omit unchanged; `""` or `null` clears.
|
|
3957
3984
|
* @param tableName - Table name.
|
|
3958
3985
|
* @param columnName - Current column name.
|
|
3959
|
-
* @param body -
|
|
3960
|
-
* @returns
|
|
3961
|
-
* @throws AoudaNotFoundError if table or column does not exist; AoudaApiError for WRITE_NOT_ALLOWED, etc.
|
|
3986
|
+
* @param body - Fields to change. `database` is injected from the client scope when omitted.
|
|
3987
|
+
* @returns Updated column detail.
|
|
3962
3988
|
*/
|
|
3963
|
-
async
|
|
3989
|
+
async alterColumn(tableName, columnName, body) {
|
|
3964
3990
|
validateNonEmptyString(tableName, "Table name");
|
|
3965
3991
|
validateNonEmptyString(columnName, "Column name");
|
|
3966
|
-
|
|
3992
|
+
const hasField = body.newName !== void 0 || body.type !== void 0 || body.nullable !== void 0 || body.encoder !== void 0 || body.autoIncrement !== void 0 || body.references !== void 0;
|
|
3993
|
+
if (!hasField) {
|
|
3994
|
+
throw new Error(
|
|
3995
|
+
"AlterColumnRequest must set at least one of: newName, type, nullable, encoder, autoIncrement, references"
|
|
3996
|
+
);
|
|
3997
|
+
}
|
|
3967
3998
|
const prefix = databasePath2(this.database);
|
|
3968
3999
|
const encodedTable = encodeURIComponent(tableName);
|
|
3969
4000
|
const encodedColumn = encodeURIComponent(columnName);
|
|
4001
|
+
const requestBody = {
|
|
4002
|
+
database: this.database,
|
|
4003
|
+
...body
|
|
4004
|
+
};
|
|
3970
4005
|
return this.transport.patch(
|
|
3971
4006
|
`${prefix}/tables/${encodedTable}/columns/${encodedColumn}`,
|
|
3972
|
-
|
|
4007
|
+
requestBody
|
|
4008
|
+
);
|
|
4009
|
+
}
|
|
4010
|
+
/**
|
|
4011
|
+
* Renames a column (convenience wrapper over {@link alterColumn}).
|
|
4012
|
+
* @param tableName - Table name.
|
|
4013
|
+
* @param columnName - Current column name.
|
|
4014
|
+
* @param body - Request body with newName (database optional; injected when omitted).
|
|
4015
|
+
* @returns 200 response body (column detail).
|
|
4016
|
+
* @throws AoudaNotFoundError if table or column does not exist; AoudaApiError for WRITE_NOT_ALLOWED, etc.
|
|
4017
|
+
*/
|
|
4018
|
+
async renameColumn(tableName, columnName, body) {
|
|
4019
|
+
validateNonEmptyString(body.newName ?? "", "New column name");
|
|
4020
|
+
return this.alterColumn(tableName, columnName, { newName: body.newName });
|
|
4021
|
+
}
|
|
4022
|
+
/**
|
|
4023
|
+
* Reorders columns in a table.
|
|
4024
|
+
* PUT /api/databases/{db}/tables/{t}/columns:order (204 No Content).
|
|
4025
|
+
* @param tableName - Table name.
|
|
4026
|
+
* @param columnsOrBody - Ordered column names, or a request body with `columns`.
|
|
4027
|
+
*/
|
|
4028
|
+
async reorderColumns(tableName, columnsOrBody) {
|
|
4029
|
+
validateNonEmptyString(tableName, "Table name");
|
|
4030
|
+
const columns = Array.isArray(columnsOrBody) ? columnsOrBody : columnsOrBody.columns;
|
|
4031
|
+
if (!columns?.length) {
|
|
4032
|
+
throw new Error("columns array is required and must be non-empty");
|
|
4033
|
+
}
|
|
4034
|
+
const prefix = databasePath2(this.database);
|
|
4035
|
+
const encodedTable = encodeURIComponent(tableName);
|
|
4036
|
+
const requestBody = {
|
|
4037
|
+
database: this.database,
|
|
4038
|
+
columns
|
|
4039
|
+
};
|
|
4040
|
+
await this.transport.put(
|
|
4041
|
+
`${prefix}/tables/${encodedTable}/columns:order`,
|
|
4042
|
+
requestBody
|
|
3973
4043
|
);
|
|
3974
4044
|
}
|
|
3975
4045
|
/**
|
|
@@ -4209,6 +4279,37 @@ var BranchesApi = class {
|
|
|
4209
4279
|
}
|
|
4210
4280
|
};
|
|
4211
4281
|
|
|
4282
|
+
// src/jobs.ts
|
|
4283
|
+
function validateNonEmptyString2(value, name) {
|
|
4284
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
4285
|
+
throw new Error(`${name} must be a non-empty string`);
|
|
4286
|
+
}
|
|
4287
|
+
}
|
|
4288
|
+
var JobsApi = class {
|
|
4289
|
+
constructor(transport, database) {
|
|
4290
|
+
this.transport = transport;
|
|
4291
|
+
this.database = database;
|
|
4292
|
+
}
|
|
4293
|
+
get prefix() {
|
|
4294
|
+
return `${databasePath2(this.database)}/jobs`;
|
|
4295
|
+
}
|
|
4296
|
+
/**
|
|
4297
|
+
* Lists jobs whose params target this database.
|
|
4298
|
+
*/
|
|
4299
|
+
async list() {
|
|
4300
|
+
return this.transport.get(this.prefix);
|
|
4301
|
+
}
|
|
4302
|
+
/**
|
|
4303
|
+
* Gets a single job by id when it belongs to this database.
|
|
4304
|
+
* @param jobId - Job GUID string.
|
|
4305
|
+
*/
|
|
4306
|
+
async get(jobId) {
|
|
4307
|
+
validateNonEmptyString2(jobId, "Job id");
|
|
4308
|
+
const encoded = encodeURIComponent(jobId);
|
|
4309
|
+
return this.transport.get(`${this.prefix}/${encoded}`);
|
|
4310
|
+
}
|
|
4311
|
+
};
|
|
4312
|
+
|
|
4212
4313
|
// src/admin/server.ts
|
|
4213
4314
|
var ServerAdminApi = class {
|
|
4214
4315
|
constructor(transport) {
|
|
@@ -5486,7 +5587,7 @@ var DEFAULT_TIMEOUT_MS = 3e4;
|
|
|
5486
5587
|
function normalizeBaseUrl(url) {
|
|
5487
5588
|
return url.replace(/\/+$/, "");
|
|
5488
5589
|
}
|
|
5489
|
-
function
|
|
5590
|
+
function validateNonEmptyString3(value, name) {
|
|
5490
5591
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
5491
5592
|
throw new Error(`${name} must be a non-empty string`);
|
|
5492
5593
|
}
|
|
@@ -5501,8 +5602,8 @@ var AoudaClient = class {
|
|
|
5501
5602
|
constructor(options) {
|
|
5502
5603
|
this.connected = false;
|
|
5503
5604
|
this._wsTransport = null;
|
|
5504
|
-
|
|
5505
|
-
|
|
5605
|
+
validateNonEmptyString3(options.serverUrl, "serverUrl");
|
|
5606
|
+
validateNonEmptyString3(options.database, "database");
|
|
5506
5607
|
this.baseUrl = normalizeBaseUrl(options.serverUrl);
|
|
5507
5608
|
this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
5508
5609
|
this.database = options.database.trim();
|
|
@@ -5584,6 +5685,7 @@ var AoudaClient = class {
|
|
|
5584
5685
|
this._authHandler = null;
|
|
5585
5686
|
}
|
|
5586
5687
|
this._tables = new TablesApi(this.transport, this.database);
|
|
5688
|
+
this._jobs = new JobsApi(this.transport, this.database);
|
|
5587
5689
|
this._databases = new DatabasesApi(this.transport);
|
|
5588
5690
|
this._schema = new SchemaApi(this.transport, this.database);
|
|
5589
5691
|
this._branches = new BranchesApi(this.transport, this.database);
|
|
@@ -5677,7 +5779,7 @@ var AoudaClient = class {
|
|
|
5677
5779
|
* ```
|
|
5678
5780
|
*/
|
|
5679
5781
|
table(name) {
|
|
5680
|
-
|
|
5782
|
+
validateNonEmptyString3(name, "Table name");
|
|
5681
5783
|
return new TableQuery(
|
|
5682
5784
|
this.transport,
|
|
5683
5785
|
name,
|
|
@@ -5693,6 +5795,13 @@ var AoudaClient = class {
|
|
|
5693
5795
|
get tables() {
|
|
5694
5796
|
return this._tables;
|
|
5695
5797
|
}
|
|
5798
|
+
/**
|
|
5799
|
+
* Access pending/background jobs for the current database (e.g. ColumnRewrite).
|
|
5800
|
+
* @returns The jobs API.
|
|
5801
|
+
*/
|
|
5802
|
+
get jobs() {
|
|
5803
|
+
return this._jobs;
|
|
5804
|
+
}
|
|
5696
5805
|
/**
|
|
5697
5806
|
* Access server-level database operations (list, create, get, drop).
|
|
5698
5807
|
* @returns The databases API.
|
|
@@ -5789,7 +5898,7 @@ var AoudaClient = class {
|
|
|
5789
5898
|
* ```
|
|
5790
5899
|
*/
|
|
5791
5900
|
bulkLoad(tableName, rows, options) {
|
|
5792
|
-
|
|
5901
|
+
validateNonEmptyString3(tableName, "tableName");
|
|
5793
5902
|
return new BulkLoadCoordinator(this.transport, this.database).run(
|
|
5794
5903
|
[tableName],
|
|
5795
5904
|
rows,
|