@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.d.cts
CHANGED
package/dist/cli/index.d.ts
CHANGED
package/dist/cli/index.js
CHANGED
|
@@ -392,7 +392,7 @@ import { fileURLToPath } from "url";
|
|
|
392
392
|
// package.json
|
|
393
393
|
var package_default = {
|
|
394
394
|
name: "@aouda/client",
|
|
395
|
-
version: "0.1.
|
|
395
|
+
version: "0.1.9",
|
|
396
396
|
description: "Official TypeScript/JavaScript client library for Aouda",
|
|
397
397
|
type: "module",
|
|
398
398
|
main: "./dist/index.cjs",
|
|
@@ -507,12 +507,13 @@ var AoudaResponseError = class extends AoudaError {
|
|
|
507
507
|
}
|
|
508
508
|
};
|
|
509
509
|
var AoudaApiError = class extends AoudaError {
|
|
510
|
-
constructor(message, code, statusCode, details, requestId) {
|
|
510
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds) {
|
|
511
511
|
super(message);
|
|
512
512
|
this.code = code;
|
|
513
513
|
this.statusCode = statusCode;
|
|
514
514
|
this.details = details;
|
|
515
515
|
this.requestId = requestId;
|
|
516
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
516
517
|
this.name = "AoudaApiError";
|
|
517
518
|
}
|
|
518
519
|
};
|
|
@@ -535,8 +536,8 @@ var AoudaValidationError = class extends AoudaApiError {
|
|
|
535
536
|
}
|
|
536
537
|
};
|
|
537
538
|
var AoudaServerError = class extends AoudaApiError {
|
|
538
|
-
constructor(message, code, statusCode, details, requestId) {
|
|
539
|
-
super(message, code, statusCode, details, requestId);
|
|
539
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds) {
|
|
540
|
+
super(message, code, statusCode, details, requestId, retryAfterSeconds);
|
|
540
541
|
this.name = "AoudaServerError";
|
|
541
542
|
}
|
|
542
543
|
};
|
|
@@ -1475,6 +1476,8 @@ var ERROR_CODE_MAP = {
|
|
|
1475
1476
|
SERVICE_UNAVAILABLE: AoudaServerError,
|
|
1476
1477
|
TIMEOUT: AoudaServerError,
|
|
1477
1478
|
OVERLOADED: AoudaServerError,
|
|
1479
|
+
MEMORY_BUDGET_EXCEEDED: AoudaServerError,
|
|
1480
|
+
WAL_CAPACITY_EXCEEDED: AoudaServerError,
|
|
1478
1481
|
AUTH_TOKEN_MISSING: AoudaAuthenticationError,
|
|
1479
1482
|
AUTH_TOKEN_EXPIRED: AoudaAuthenticationError,
|
|
1480
1483
|
AUTH_TOKEN_INVALID: AoudaAuthenticationError,
|
|
@@ -1502,13 +1505,22 @@ function createComposedAbortController(...signals) {
|
|
|
1502
1505
|
}
|
|
1503
1506
|
return controller;
|
|
1504
1507
|
}
|
|
1505
|
-
function
|
|
1508
|
+
function parseRetryAfterSeconds(header) {
|
|
1509
|
+
if (header == null || header.trim() === "") return void 0;
|
|
1510
|
+
const trimmed = header.trim();
|
|
1511
|
+
if (!/^\d+$/.test(trimmed)) return void 0;
|
|
1512
|
+
const n = Number.parseInt(trimmed, 10);
|
|
1513
|
+
if (!Number.isFinite(n) || n < 0) return void 0;
|
|
1514
|
+
return n;
|
|
1515
|
+
}
|
|
1516
|
+
function createApiError(statusCode, statusText, body, retryAfterHeader) {
|
|
1506
1517
|
const message = body.error ?? `${statusCode} ${statusText}`;
|
|
1507
1518
|
const code = body.code ?? "UNKNOWN";
|
|
1508
1519
|
const details = body.details;
|
|
1509
1520
|
const requestId = body.requestId;
|
|
1521
|
+
const retryAfterSeconds = parseRetryAfterSeconds(retryAfterHeader ?? null);
|
|
1510
1522
|
const Ctor = ERROR_CODE_MAP[code] ?? AoudaApiError;
|
|
1511
|
-
return new Ctor(message, code, statusCode, details, requestId);
|
|
1523
|
+
return new Ctor(message, code, statusCode, details, requestId, retryAfterSeconds);
|
|
1512
1524
|
}
|
|
1513
1525
|
var HttpTransport = class {
|
|
1514
1526
|
constructor(options) {
|
|
@@ -1601,7 +1613,8 @@ var HttpTransport = class {
|
|
|
1601
1613
|
throw createApiError(
|
|
1602
1614
|
response.status,
|
|
1603
1615
|
response.statusText,
|
|
1604
|
-
errorBody
|
|
1616
|
+
errorBody,
|
|
1617
|
+
response.headers.get("Retry-After")
|
|
1605
1618
|
);
|
|
1606
1619
|
}
|
|
1607
1620
|
throw new AoudaResponseError(
|
|
@@ -1711,7 +1724,8 @@ var HttpTransport = class {
|
|
|
1711
1724
|
throw createApiError(
|
|
1712
1725
|
response.status,
|
|
1713
1726
|
response.statusText,
|
|
1714
|
-
errorBody
|
|
1727
|
+
errorBody,
|
|
1728
|
+
response.headers.get("Retry-After")
|
|
1715
1729
|
);
|
|
1716
1730
|
}
|
|
1717
1731
|
throw new AoudaResponseError(
|
|
@@ -2057,6 +2071,17 @@ var CIRCUIT_BREAKER_POLICY_DISABLED = {
|
|
|
2057
2071
|
|
|
2058
2072
|
// src/resilience/resilient-transport.ts
|
|
2059
2073
|
var REQUEST_ID_HEADER3 = "X-Request-Id";
|
|
2074
|
+
function isCapacityBackPressure(error) {
|
|
2075
|
+
return error instanceof AoudaApiError && (error.code === "MEMORY_BUDGET_EXCEEDED" || error.code === "WAL_CAPACITY_EXCEEDED");
|
|
2076
|
+
}
|
|
2077
|
+
function retryDelayMs(retryPolicy, attempt, error) {
|
|
2078
|
+
const backoff = calculateDelay(retryPolicy, attempt);
|
|
2079
|
+
if (!isCapacityBackPressure(error) || !(error instanceof AoudaApiError)) {
|
|
2080
|
+
return backoff;
|
|
2081
|
+
}
|
|
2082
|
+
const headerMs = error.retryAfterSeconds != null ? error.retryAfterSeconds * 1e3 : 0;
|
|
2083
|
+
return Math.max(backoff, headerMs);
|
|
2084
|
+
}
|
|
2060
2085
|
function delayMs(ms, signal) {
|
|
2061
2086
|
if (ms <= 0) return Promise.resolve();
|
|
2062
2087
|
return new Promise((resolve4, reject) => {
|
|
@@ -2111,7 +2136,7 @@ var ResilientTransport = class {
|
|
|
2111
2136
|
} catch (error) {
|
|
2112
2137
|
lastError = error;
|
|
2113
2138
|
const retryable = isRetryable(error);
|
|
2114
|
-
if (retryable) {
|
|
2139
|
+
if (retryable && !isCapacityBackPressure(error)) {
|
|
2115
2140
|
this.circuitBreaker.recordFailure(error);
|
|
2116
2141
|
}
|
|
2117
2142
|
if (!retryable) {
|
|
@@ -2121,7 +2146,7 @@ var ResilientTransport = class {
|
|
|
2121
2146
|
if (attempt > this.retryPolicy.maxRetries) {
|
|
2122
2147
|
throw error;
|
|
2123
2148
|
}
|
|
2124
|
-
const delay =
|
|
2149
|
+
const delay = retryDelayMs(this.retryPolicy, attempt, error);
|
|
2125
2150
|
try {
|
|
2126
2151
|
await delayMs(delay, config.signal);
|
|
2127
2152
|
} catch {
|
|
@@ -2157,7 +2182,7 @@ var ResilientTransport = class {
|
|
|
2157
2182
|
} catch (error) {
|
|
2158
2183
|
lastError = error;
|
|
2159
2184
|
const retryable = isRetryable(error);
|
|
2160
|
-
if (retryable) {
|
|
2185
|
+
if (retryable && !isCapacityBackPressure(error)) {
|
|
2161
2186
|
this.circuitBreaker.recordFailure(error);
|
|
2162
2187
|
}
|
|
2163
2188
|
if (!retryable) {
|
|
@@ -2167,7 +2192,7 @@ var ResilientTransport = class {
|
|
|
2167
2192
|
if (attempt > this.retryPolicy.maxRetries) {
|
|
2168
2193
|
throw error;
|
|
2169
2194
|
}
|
|
2170
|
-
const delay =
|
|
2195
|
+
const delay = retryDelayMs(this.retryPolicy, attempt, error);
|
|
2171
2196
|
try {
|
|
2172
2197
|
await delayMs(delay, config.signal);
|
|
2173
2198
|
} catch {
|
|
@@ -3924,23 +3949,68 @@ var TablesApi = class {
|
|
|
3924
3949
|
);
|
|
3925
3950
|
}
|
|
3926
3951
|
/**
|
|
3927
|
-
*
|
|
3952
|
+
* Alters a column (type, nullable, encoder, autoIncrement, references, and/or rename).
|
|
3953
|
+
* PATCH /api/databases/{db}/tables/{t}/columns/{c}.
|
|
3954
|
+
* Omit a property to leave it unchanged. For `references`, omit unchanged; `""` or `null` clears.
|
|
3928
3955
|
* @param tableName - Table name.
|
|
3929
3956
|
* @param columnName - Current column name.
|
|
3930
|
-
* @param body -
|
|
3931
|
-
* @returns
|
|
3932
|
-
* @throws AoudaNotFoundError if table or column does not exist; AoudaApiError for WRITE_NOT_ALLOWED, etc.
|
|
3957
|
+
* @param body - Fields to change. `database` is injected from the client scope when omitted.
|
|
3958
|
+
* @returns Updated column detail.
|
|
3933
3959
|
*/
|
|
3934
|
-
async
|
|
3960
|
+
async alterColumn(tableName, columnName, body) {
|
|
3935
3961
|
validateNonEmptyString(tableName, "Table name");
|
|
3936
3962
|
validateNonEmptyString(columnName, "Column name");
|
|
3937
|
-
|
|
3963
|
+
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;
|
|
3964
|
+
if (!hasField) {
|
|
3965
|
+
throw new Error(
|
|
3966
|
+
"AlterColumnRequest must set at least one of: newName, type, nullable, encoder, autoIncrement, references"
|
|
3967
|
+
);
|
|
3968
|
+
}
|
|
3938
3969
|
const prefix = databasePath2(this.database);
|
|
3939
3970
|
const encodedTable = encodeURIComponent(tableName);
|
|
3940
3971
|
const encodedColumn = encodeURIComponent(columnName);
|
|
3972
|
+
const requestBody = {
|
|
3973
|
+
database: this.database,
|
|
3974
|
+
...body
|
|
3975
|
+
};
|
|
3941
3976
|
return this.transport.patch(
|
|
3942
3977
|
`${prefix}/tables/${encodedTable}/columns/${encodedColumn}`,
|
|
3943
|
-
|
|
3978
|
+
requestBody
|
|
3979
|
+
);
|
|
3980
|
+
}
|
|
3981
|
+
/**
|
|
3982
|
+
* Renames a column (convenience wrapper over {@link alterColumn}).
|
|
3983
|
+
* @param tableName - Table name.
|
|
3984
|
+
* @param columnName - Current column name.
|
|
3985
|
+
* @param body - Request body with newName (database optional; injected when omitted).
|
|
3986
|
+
* @returns 200 response body (column detail).
|
|
3987
|
+
* @throws AoudaNotFoundError if table or column does not exist; AoudaApiError for WRITE_NOT_ALLOWED, etc.
|
|
3988
|
+
*/
|
|
3989
|
+
async renameColumn(tableName, columnName, body) {
|
|
3990
|
+
validateNonEmptyString(body.newName ?? "", "New column name");
|
|
3991
|
+
return this.alterColumn(tableName, columnName, { newName: body.newName });
|
|
3992
|
+
}
|
|
3993
|
+
/**
|
|
3994
|
+
* Reorders columns in a table.
|
|
3995
|
+
* PUT /api/databases/{db}/tables/{t}/columns:order (204 No Content).
|
|
3996
|
+
* @param tableName - Table name.
|
|
3997
|
+
* @param columnsOrBody - Ordered column names, or a request body with `columns`.
|
|
3998
|
+
*/
|
|
3999
|
+
async reorderColumns(tableName, columnsOrBody) {
|
|
4000
|
+
validateNonEmptyString(tableName, "Table name");
|
|
4001
|
+
const columns = Array.isArray(columnsOrBody) ? columnsOrBody : columnsOrBody.columns;
|
|
4002
|
+
if (!columns?.length) {
|
|
4003
|
+
throw new Error("columns array is required and must be non-empty");
|
|
4004
|
+
}
|
|
4005
|
+
const prefix = databasePath2(this.database);
|
|
4006
|
+
const encodedTable = encodeURIComponent(tableName);
|
|
4007
|
+
const requestBody = {
|
|
4008
|
+
database: this.database,
|
|
4009
|
+
columns
|
|
4010
|
+
};
|
|
4011
|
+
await this.transport.put(
|
|
4012
|
+
`${prefix}/tables/${encodedTable}/columns:order`,
|
|
4013
|
+
requestBody
|
|
3944
4014
|
);
|
|
3945
4015
|
}
|
|
3946
4016
|
/**
|
|
@@ -4180,6 +4250,37 @@ var BranchesApi = class {
|
|
|
4180
4250
|
}
|
|
4181
4251
|
};
|
|
4182
4252
|
|
|
4253
|
+
// src/jobs.ts
|
|
4254
|
+
function validateNonEmptyString2(value, name) {
|
|
4255
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
4256
|
+
throw new Error(`${name} must be a non-empty string`);
|
|
4257
|
+
}
|
|
4258
|
+
}
|
|
4259
|
+
var JobsApi = class {
|
|
4260
|
+
constructor(transport, database) {
|
|
4261
|
+
this.transport = transport;
|
|
4262
|
+
this.database = database;
|
|
4263
|
+
}
|
|
4264
|
+
get prefix() {
|
|
4265
|
+
return `${databasePath2(this.database)}/jobs`;
|
|
4266
|
+
}
|
|
4267
|
+
/**
|
|
4268
|
+
* Lists jobs whose params target this database.
|
|
4269
|
+
*/
|
|
4270
|
+
async list() {
|
|
4271
|
+
return this.transport.get(this.prefix);
|
|
4272
|
+
}
|
|
4273
|
+
/**
|
|
4274
|
+
* Gets a single job by id when it belongs to this database.
|
|
4275
|
+
* @param jobId - Job GUID string.
|
|
4276
|
+
*/
|
|
4277
|
+
async get(jobId) {
|
|
4278
|
+
validateNonEmptyString2(jobId, "Job id");
|
|
4279
|
+
const encoded = encodeURIComponent(jobId);
|
|
4280
|
+
return this.transport.get(`${this.prefix}/${encoded}`);
|
|
4281
|
+
}
|
|
4282
|
+
};
|
|
4283
|
+
|
|
4183
4284
|
// src/admin/server.ts
|
|
4184
4285
|
var ServerAdminApi = class {
|
|
4185
4286
|
constructor(transport) {
|
|
@@ -5457,7 +5558,7 @@ var DEFAULT_TIMEOUT_MS = 3e4;
|
|
|
5457
5558
|
function normalizeBaseUrl(url) {
|
|
5458
5559
|
return url.replace(/\/+$/, "");
|
|
5459
5560
|
}
|
|
5460
|
-
function
|
|
5561
|
+
function validateNonEmptyString3(value, name) {
|
|
5461
5562
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
5462
5563
|
throw new Error(`${name} must be a non-empty string`);
|
|
5463
5564
|
}
|
|
@@ -5472,8 +5573,8 @@ var AoudaClient = class {
|
|
|
5472
5573
|
constructor(options) {
|
|
5473
5574
|
this.connected = false;
|
|
5474
5575
|
this._wsTransport = null;
|
|
5475
|
-
|
|
5476
|
-
|
|
5576
|
+
validateNonEmptyString3(options.serverUrl, "serverUrl");
|
|
5577
|
+
validateNonEmptyString3(options.database, "database");
|
|
5477
5578
|
this.baseUrl = normalizeBaseUrl(options.serverUrl);
|
|
5478
5579
|
this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
5479
5580
|
this.database = options.database.trim();
|
|
@@ -5555,6 +5656,7 @@ var AoudaClient = class {
|
|
|
5555
5656
|
this._authHandler = null;
|
|
5556
5657
|
}
|
|
5557
5658
|
this._tables = new TablesApi(this.transport, this.database);
|
|
5659
|
+
this._jobs = new JobsApi(this.transport, this.database);
|
|
5558
5660
|
this._databases = new DatabasesApi(this.transport);
|
|
5559
5661
|
this._schema = new SchemaApi(this.transport, this.database);
|
|
5560
5662
|
this._branches = new BranchesApi(this.transport, this.database);
|
|
@@ -5648,7 +5750,7 @@ var AoudaClient = class {
|
|
|
5648
5750
|
* ```
|
|
5649
5751
|
*/
|
|
5650
5752
|
table(name) {
|
|
5651
|
-
|
|
5753
|
+
validateNonEmptyString3(name, "Table name");
|
|
5652
5754
|
return new TableQuery(
|
|
5653
5755
|
this.transport,
|
|
5654
5756
|
name,
|
|
@@ -5664,6 +5766,13 @@ var AoudaClient = class {
|
|
|
5664
5766
|
get tables() {
|
|
5665
5767
|
return this._tables;
|
|
5666
5768
|
}
|
|
5769
|
+
/**
|
|
5770
|
+
* Access pending/background jobs for the current database (e.g. ColumnRewrite).
|
|
5771
|
+
* @returns The jobs API.
|
|
5772
|
+
*/
|
|
5773
|
+
get jobs() {
|
|
5774
|
+
return this._jobs;
|
|
5775
|
+
}
|
|
5667
5776
|
/**
|
|
5668
5777
|
* Access server-level database operations (list, create, get, drop).
|
|
5669
5778
|
* @returns The databases API.
|
|
@@ -5760,7 +5869,7 @@ var AoudaClient = class {
|
|
|
5760
5869
|
* ```
|
|
5761
5870
|
*/
|
|
5762
5871
|
bulkLoad(tableName, rows, options) {
|
|
5763
|
-
|
|
5872
|
+
validateNonEmptyString3(tableName, "tableName");
|
|
5764
5873
|
return new BulkLoadCoordinator(this.transport, this.database).run(
|
|
5765
5874
|
[tableName],
|
|
5766
5875
|
rows,
|