@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/index.cjs
CHANGED
|
@@ -56,6 +56,7 @@ __export(index_exports, {
|
|
|
56
56
|
DatabasesApi: () => DatabasesApi,
|
|
57
57
|
FILTER_OPERATORS: () => FILTER_OPERATORS,
|
|
58
58
|
HealthAdminApi: () => HealthAdminApi,
|
|
59
|
+
JobsApi: () => JobsApi,
|
|
59
60
|
MaterializedQueriesApi: () => MaterializedQueriesApi,
|
|
60
61
|
MaterializedQueryState: () => MaterializedQueryState,
|
|
61
62
|
MaterializedQueryType: () => MaterializedQueryType,
|
|
@@ -82,7 +83,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
82
83
|
// package.json
|
|
83
84
|
var package_default = {
|
|
84
85
|
name: "@aouda/client",
|
|
85
|
-
version: "0.1.
|
|
86
|
+
version: "0.1.9",
|
|
86
87
|
description: "Official TypeScript/JavaScript client library for Aouda",
|
|
87
88
|
type: "module",
|
|
88
89
|
main: "./dist/index.cjs",
|
|
@@ -214,12 +215,13 @@ var AoudaResponseError = class extends AoudaError {
|
|
|
214
215
|
}
|
|
215
216
|
};
|
|
216
217
|
var AoudaApiError = class extends AoudaError {
|
|
217
|
-
constructor(message, code, statusCode, details, requestId) {
|
|
218
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds) {
|
|
218
219
|
super(message);
|
|
219
220
|
this.code = code;
|
|
220
221
|
this.statusCode = statusCode;
|
|
221
222
|
this.details = details;
|
|
222
223
|
this.requestId = requestId;
|
|
224
|
+
this.retryAfterSeconds = retryAfterSeconds;
|
|
223
225
|
this.name = "AoudaApiError";
|
|
224
226
|
}
|
|
225
227
|
};
|
|
@@ -242,8 +244,8 @@ var AoudaValidationError = class extends AoudaApiError {
|
|
|
242
244
|
}
|
|
243
245
|
};
|
|
244
246
|
var AoudaServerError = class extends AoudaApiError {
|
|
245
|
-
constructor(message, code, statusCode, details, requestId) {
|
|
246
|
-
super(message, code, statusCode, details, requestId);
|
|
247
|
+
constructor(message, code, statusCode, details, requestId, retryAfterSeconds) {
|
|
248
|
+
super(message, code, statusCode, details, requestId, retryAfterSeconds);
|
|
247
249
|
this.name = "AoudaServerError";
|
|
248
250
|
}
|
|
249
251
|
};
|
|
@@ -1198,6 +1200,8 @@ var ERROR_CODE_MAP = {
|
|
|
1198
1200
|
SERVICE_UNAVAILABLE: AoudaServerError,
|
|
1199
1201
|
TIMEOUT: AoudaServerError,
|
|
1200
1202
|
OVERLOADED: AoudaServerError,
|
|
1203
|
+
MEMORY_BUDGET_EXCEEDED: AoudaServerError,
|
|
1204
|
+
WAL_CAPACITY_EXCEEDED: AoudaServerError,
|
|
1201
1205
|
AUTH_TOKEN_MISSING: AoudaAuthenticationError,
|
|
1202
1206
|
AUTH_TOKEN_EXPIRED: AoudaAuthenticationError,
|
|
1203
1207
|
AUTH_TOKEN_INVALID: AoudaAuthenticationError,
|
|
@@ -1225,13 +1229,22 @@ function createComposedAbortController(...signals) {
|
|
|
1225
1229
|
}
|
|
1226
1230
|
return controller;
|
|
1227
1231
|
}
|
|
1228
|
-
function
|
|
1232
|
+
function parseRetryAfterSeconds(header) {
|
|
1233
|
+
if (header == null || header.trim() === "") return void 0;
|
|
1234
|
+
const trimmed = header.trim();
|
|
1235
|
+
if (!/^\d+$/.test(trimmed)) return void 0;
|
|
1236
|
+
const n = Number.parseInt(trimmed, 10);
|
|
1237
|
+
if (!Number.isFinite(n) || n < 0) return void 0;
|
|
1238
|
+
return n;
|
|
1239
|
+
}
|
|
1240
|
+
function createApiError(statusCode, statusText, body, retryAfterHeader) {
|
|
1229
1241
|
const message = body.error ?? `${statusCode} ${statusText}`;
|
|
1230
1242
|
const code = body.code ?? "UNKNOWN";
|
|
1231
1243
|
const details = body.details;
|
|
1232
1244
|
const requestId = body.requestId;
|
|
1245
|
+
const retryAfterSeconds = parseRetryAfterSeconds(retryAfterHeader ?? null);
|
|
1233
1246
|
const Ctor = ERROR_CODE_MAP[code] ?? AoudaApiError;
|
|
1234
|
-
return new Ctor(message, code, statusCode, details, requestId);
|
|
1247
|
+
return new Ctor(message, code, statusCode, details, requestId, retryAfterSeconds);
|
|
1235
1248
|
}
|
|
1236
1249
|
var HttpTransport = class {
|
|
1237
1250
|
constructor(options) {
|
|
@@ -1324,7 +1337,8 @@ var HttpTransport = class {
|
|
|
1324
1337
|
throw createApiError(
|
|
1325
1338
|
response.status,
|
|
1326
1339
|
response.statusText,
|
|
1327
|
-
errorBody
|
|
1340
|
+
errorBody,
|
|
1341
|
+
response.headers.get("Retry-After")
|
|
1328
1342
|
);
|
|
1329
1343
|
}
|
|
1330
1344
|
throw new AoudaResponseError(
|
|
@@ -1434,7 +1448,8 @@ var HttpTransport = class {
|
|
|
1434
1448
|
throw createApiError(
|
|
1435
1449
|
response.status,
|
|
1436
1450
|
response.statusText,
|
|
1437
|
-
errorBody
|
|
1451
|
+
errorBody,
|
|
1452
|
+
response.headers.get("Retry-After")
|
|
1438
1453
|
);
|
|
1439
1454
|
}
|
|
1440
1455
|
throw new AoudaResponseError(
|
|
@@ -1780,6 +1795,17 @@ var CIRCUIT_BREAKER_POLICY_DISABLED = {
|
|
|
1780
1795
|
|
|
1781
1796
|
// src/resilience/resilient-transport.ts
|
|
1782
1797
|
var REQUEST_ID_HEADER3 = "X-Request-Id";
|
|
1798
|
+
function isCapacityBackPressure(error) {
|
|
1799
|
+
return error instanceof AoudaApiError && (error.code === "MEMORY_BUDGET_EXCEEDED" || error.code === "WAL_CAPACITY_EXCEEDED");
|
|
1800
|
+
}
|
|
1801
|
+
function retryDelayMs(retryPolicy, attempt, error) {
|
|
1802
|
+
const backoff = calculateDelay(retryPolicy, attempt);
|
|
1803
|
+
if (!isCapacityBackPressure(error) || !(error instanceof AoudaApiError)) {
|
|
1804
|
+
return backoff;
|
|
1805
|
+
}
|
|
1806
|
+
const headerMs = error.retryAfterSeconds != null ? error.retryAfterSeconds * 1e3 : 0;
|
|
1807
|
+
return Math.max(backoff, headerMs);
|
|
1808
|
+
}
|
|
1783
1809
|
function delayMs(ms, signal) {
|
|
1784
1810
|
if (ms <= 0) return Promise.resolve();
|
|
1785
1811
|
return new Promise((resolve, reject) => {
|
|
@@ -1834,7 +1860,7 @@ var ResilientTransport = class {
|
|
|
1834
1860
|
} catch (error) {
|
|
1835
1861
|
lastError = error;
|
|
1836
1862
|
const retryable = isRetryable(error);
|
|
1837
|
-
if (retryable) {
|
|
1863
|
+
if (retryable && !isCapacityBackPressure(error)) {
|
|
1838
1864
|
this.circuitBreaker.recordFailure(error);
|
|
1839
1865
|
}
|
|
1840
1866
|
if (!retryable) {
|
|
@@ -1844,7 +1870,7 @@ var ResilientTransport = class {
|
|
|
1844
1870
|
if (attempt > this.retryPolicy.maxRetries) {
|
|
1845
1871
|
throw error;
|
|
1846
1872
|
}
|
|
1847
|
-
const delay =
|
|
1873
|
+
const delay = retryDelayMs(this.retryPolicy, attempt, error);
|
|
1848
1874
|
try {
|
|
1849
1875
|
await delayMs(delay, config.signal);
|
|
1850
1876
|
} catch {
|
|
@@ -1880,7 +1906,7 @@ var ResilientTransport = class {
|
|
|
1880
1906
|
} catch (error) {
|
|
1881
1907
|
lastError = error;
|
|
1882
1908
|
const retryable = isRetryable(error);
|
|
1883
|
-
if (retryable) {
|
|
1909
|
+
if (retryable && !isCapacityBackPressure(error)) {
|
|
1884
1910
|
this.circuitBreaker.recordFailure(error);
|
|
1885
1911
|
}
|
|
1886
1912
|
if (!retryable) {
|
|
@@ -1890,7 +1916,7 @@ var ResilientTransport = class {
|
|
|
1890
1916
|
if (attempt > this.retryPolicy.maxRetries) {
|
|
1891
1917
|
throw error;
|
|
1892
1918
|
}
|
|
1893
|
-
const delay =
|
|
1919
|
+
const delay = retryDelayMs(this.retryPolicy, attempt, error);
|
|
1894
1920
|
try {
|
|
1895
1921
|
await delayMs(delay, config.signal);
|
|
1896
1922
|
} catch {
|
|
@@ -3647,23 +3673,68 @@ var TablesApi = class {
|
|
|
3647
3673
|
);
|
|
3648
3674
|
}
|
|
3649
3675
|
/**
|
|
3650
|
-
*
|
|
3676
|
+
* Alters a column (type, nullable, encoder, autoIncrement, references, and/or rename).
|
|
3677
|
+
* PATCH /api/databases/{db}/tables/{t}/columns/{c}.
|
|
3678
|
+
* Omit a property to leave it unchanged. For `references`, omit unchanged; `""` or `null` clears.
|
|
3651
3679
|
* @param tableName - Table name.
|
|
3652
3680
|
* @param columnName - Current column name.
|
|
3653
|
-
* @param body -
|
|
3654
|
-
* @returns
|
|
3655
|
-
* @throws AoudaNotFoundError if table or column does not exist; AoudaApiError for WRITE_NOT_ALLOWED, etc.
|
|
3681
|
+
* @param body - Fields to change. `database` is injected from the client scope when omitted.
|
|
3682
|
+
* @returns Updated column detail.
|
|
3656
3683
|
*/
|
|
3657
|
-
async
|
|
3684
|
+
async alterColumn(tableName, columnName, body) {
|
|
3658
3685
|
validateNonEmptyString(tableName, "Table name");
|
|
3659
3686
|
validateNonEmptyString(columnName, "Column name");
|
|
3660
|
-
|
|
3687
|
+
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;
|
|
3688
|
+
if (!hasField) {
|
|
3689
|
+
throw new Error(
|
|
3690
|
+
"AlterColumnRequest must set at least one of: newName, type, nullable, encoder, autoIncrement, references"
|
|
3691
|
+
);
|
|
3692
|
+
}
|
|
3661
3693
|
const prefix = databasePath2(this.database);
|
|
3662
3694
|
const encodedTable = encodeURIComponent(tableName);
|
|
3663
3695
|
const encodedColumn = encodeURIComponent(columnName);
|
|
3696
|
+
const requestBody = {
|
|
3697
|
+
database: this.database,
|
|
3698
|
+
...body
|
|
3699
|
+
};
|
|
3664
3700
|
return this.transport.patch(
|
|
3665
3701
|
`${prefix}/tables/${encodedTable}/columns/${encodedColumn}`,
|
|
3666
|
-
|
|
3702
|
+
requestBody
|
|
3703
|
+
);
|
|
3704
|
+
}
|
|
3705
|
+
/**
|
|
3706
|
+
* Renames a column (convenience wrapper over {@link alterColumn}).
|
|
3707
|
+
* @param tableName - Table name.
|
|
3708
|
+
* @param columnName - Current column name.
|
|
3709
|
+
* @param body - Request body with newName (database optional; injected when omitted).
|
|
3710
|
+
* @returns 200 response body (column detail).
|
|
3711
|
+
* @throws AoudaNotFoundError if table or column does not exist; AoudaApiError for WRITE_NOT_ALLOWED, etc.
|
|
3712
|
+
*/
|
|
3713
|
+
async renameColumn(tableName, columnName, body) {
|
|
3714
|
+
validateNonEmptyString(body.newName ?? "", "New column name");
|
|
3715
|
+
return this.alterColumn(tableName, columnName, { newName: body.newName });
|
|
3716
|
+
}
|
|
3717
|
+
/**
|
|
3718
|
+
* Reorders columns in a table.
|
|
3719
|
+
* PUT /api/databases/{db}/tables/{t}/columns:order (204 No Content).
|
|
3720
|
+
* @param tableName - Table name.
|
|
3721
|
+
* @param columnsOrBody - Ordered column names, or a request body with `columns`.
|
|
3722
|
+
*/
|
|
3723
|
+
async reorderColumns(tableName, columnsOrBody) {
|
|
3724
|
+
validateNonEmptyString(tableName, "Table name");
|
|
3725
|
+
const columns = Array.isArray(columnsOrBody) ? columnsOrBody : columnsOrBody.columns;
|
|
3726
|
+
if (!columns?.length) {
|
|
3727
|
+
throw new Error("columns array is required and must be non-empty");
|
|
3728
|
+
}
|
|
3729
|
+
const prefix = databasePath2(this.database);
|
|
3730
|
+
const encodedTable = encodeURIComponent(tableName);
|
|
3731
|
+
const requestBody = {
|
|
3732
|
+
database: this.database,
|
|
3733
|
+
columns
|
|
3734
|
+
};
|
|
3735
|
+
await this.transport.put(
|
|
3736
|
+
`${prefix}/tables/${encodedTable}/columns:order`,
|
|
3737
|
+
requestBody
|
|
3667
3738
|
);
|
|
3668
3739
|
}
|
|
3669
3740
|
/**
|
|
@@ -3903,6 +3974,37 @@ var BranchesApi = class {
|
|
|
3903
3974
|
}
|
|
3904
3975
|
};
|
|
3905
3976
|
|
|
3977
|
+
// src/jobs.ts
|
|
3978
|
+
function validateNonEmptyString2(value, name) {
|
|
3979
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
3980
|
+
throw new Error(`${name} must be a non-empty string`);
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3983
|
+
var JobsApi = class {
|
|
3984
|
+
constructor(transport, database) {
|
|
3985
|
+
this.transport = transport;
|
|
3986
|
+
this.database = database;
|
|
3987
|
+
}
|
|
3988
|
+
get prefix() {
|
|
3989
|
+
return `${databasePath2(this.database)}/jobs`;
|
|
3990
|
+
}
|
|
3991
|
+
/**
|
|
3992
|
+
* Lists jobs whose params target this database.
|
|
3993
|
+
*/
|
|
3994
|
+
async list() {
|
|
3995
|
+
return this.transport.get(this.prefix);
|
|
3996
|
+
}
|
|
3997
|
+
/**
|
|
3998
|
+
* Gets a single job by id when it belongs to this database.
|
|
3999
|
+
* @param jobId - Job GUID string.
|
|
4000
|
+
*/
|
|
4001
|
+
async get(jobId) {
|
|
4002
|
+
validateNonEmptyString2(jobId, "Job id");
|
|
4003
|
+
const encoded = encodeURIComponent(jobId);
|
|
4004
|
+
return this.transport.get(`${this.prefix}/${encoded}`);
|
|
4005
|
+
}
|
|
4006
|
+
};
|
|
4007
|
+
|
|
3906
4008
|
// src/admin/server.ts
|
|
3907
4009
|
var ServerAdminApi = class {
|
|
3908
4010
|
constructor(transport) {
|
|
@@ -5211,7 +5313,7 @@ var DEFAULT_TIMEOUT_MS = 3e4;
|
|
|
5211
5313
|
function normalizeBaseUrl(url) {
|
|
5212
5314
|
return url.replace(/\/+$/, "");
|
|
5213
5315
|
}
|
|
5214
|
-
function
|
|
5316
|
+
function validateNonEmptyString3(value, name) {
|
|
5215
5317
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
5216
5318
|
throw new Error(`${name} must be a non-empty string`);
|
|
5217
5319
|
}
|
|
@@ -5226,8 +5328,8 @@ var AoudaClient = class {
|
|
|
5226
5328
|
constructor(options) {
|
|
5227
5329
|
this.connected = false;
|
|
5228
5330
|
this._wsTransport = null;
|
|
5229
|
-
|
|
5230
|
-
|
|
5331
|
+
validateNonEmptyString3(options.serverUrl, "serverUrl");
|
|
5332
|
+
validateNonEmptyString3(options.database, "database");
|
|
5231
5333
|
this.baseUrl = normalizeBaseUrl(options.serverUrl);
|
|
5232
5334
|
this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
5233
5335
|
this.database = options.database.trim();
|
|
@@ -5309,6 +5411,7 @@ var AoudaClient = class {
|
|
|
5309
5411
|
this._authHandler = null;
|
|
5310
5412
|
}
|
|
5311
5413
|
this._tables = new TablesApi(this.transport, this.database);
|
|
5414
|
+
this._jobs = new JobsApi(this.transport, this.database);
|
|
5312
5415
|
this._databases = new DatabasesApi(this.transport);
|
|
5313
5416
|
this._schema = new SchemaApi(this.transport, this.database);
|
|
5314
5417
|
this._branches = new BranchesApi(this.transport, this.database);
|
|
@@ -5402,7 +5505,7 @@ var AoudaClient = class {
|
|
|
5402
5505
|
* ```
|
|
5403
5506
|
*/
|
|
5404
5507
|
table(name) {
|
|
5405
|
-
|
|
5508
|
+
validateNonEmptyString3(name, "Table name");
|
|
5406
5509
|
return new TableQuery(
|
|
5407
5510
|
this.transport,
|
|
5408
5511
|
name,
|
|
@@ -5418,6 +5521,13 @@ var AoudaClient = class {
|
|
|
5418
5521
|
get tables() {
|
|
5419
5522
|
return this._tables;
|
|
5420
5523
|
}
|
|
5524
|
+
/**
|
|
5525
|
+
* Access pending/background jobs for the current database (e.g. ColumnRewrite).
|
|
5526
|
+
* @returns The jobs API.
|
|
5527
|
+
*/
|
|
5528
|
+
get jobs() {
|
|
5529
|
+
return this._jobs;
|
|
5530
|
+
}
|
|
5421
5531
|
/**
|
|
5422
5532
|
* Access server-level database operations (list, create, get, drop).
|
|
5423
5533
|
* @returns The databases API.
|
|
@@ -5514,7 +5624,7 @@ var AoudaClient = class {
|
|
|
5514
5624
|
* ```
|
|
5515
5625
|
*/
|
|
5516
5626
|
bulkLoad(tableName, rows, options) {
|
|
5517
|
-
|
|
5627
|
+
validateNonEmptyString3(tableName, "tableName");
|
|
5518
5628
|
return new BulkLoadCoordinator(this.transport, this.database).run(
|
|
5519
5629
|
[tableName],
|
|
5520
5630
|
rows,
|
|
@@ -5868,6 +5978,7 @@ var version = package_default.version;
|
|
|
5868
5978
|
DatabasesApi,
|
|
5869
5979
|
FILTER_OPERATORS,
|
|
5870
5980
|
HealthAdminApi,
|
|
5981
|
+
JobsApi,
|
|
5871
5982
|
MaterializedQueriesApi,
|
|
5872
5983
|
MaterializedQueryState,
|
|
5873
5984
|
MaterializedQueryType,
|