@tinycloud/sdk-services 3.0.0 → 3.1.0-beta.2
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/encryption/index.cjs.map +1 -1
- package/dist/encryption/index.js.map +1 -1
- package/dist/index.cjs +181 -145
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -1
- package/dist/index.d.ts +53 -1
- package/dist/index.js +175 -145
- package/dist/index.js.map +1 -1
- package/dist/kv/index.cjs +94 -102
- package/dist/kv/index.cjs.map +1 -1
- package/dist/kv/index.d.cts +8 -1
- package/dist/kv/index.d.ts +8 -1
- package/dist/kv/index.js +94 -102
- package/dist/kv/index.js.map +1 -1
- package/dist/sql/index.cjs +44 -5
- package/dist/sql/index.cjs.map +1 -1
- package/dist/sql/index.js +44 -5
- package/dist/sql/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -993,6 +993,37 @@ function parseAuthError(responseText) {
|
|
|
993
993
|
function authUnauthorizedError(service, message, meta) {
|
|
994
994
|
return serviceError(ErrorCodes.AUTH_UNAUTHORIZED, message, service, { meta });
|
|
995
995
|
}
|
|
996
|
+
var MAX_CAUSE_DEPTH = 8;
|
|
997
|
+
function errorStatusOf(node) {
|
|
998
|
+
const meta = node.meta;
|
|
999
|
+
const candidates = [
|
|
1000
|
+
node.status,
|
|
1001
|
+
node.statusCode,
|
|
1002
|
+
typeof meta === "object" && meta !== null ? meta.status : void 0
|
|
1003
|
+
];
|
|
1004
|
+
for (const candidate of candidates) {
|
|
1005
|
+
if (typeof candidate === "number" && Number.isInteger(candidate) && candidate >= 400 && candidate <= 599) {
|
|
1006
|
+
return candidate;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
return void 0;
|
|
1010
|
+
}
|
|
1011
|
+
function authorizationVerdictOf(error) {
|
|
1012
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1013
|
+
let sawUnauthorizedCode = false;
|
|
1014
|
+
let node = error;
|
|
1015
|
+
for (let depth = 0; depth < MAX_CAUSE_DEPTH && typeof node === "object" && node !== null && !seen.has(node); depth += 1) {
|
|
1016
|
+
seen.add(node);
|
|
1017
|
+
const record = node;
|
|
1018
|
+
const status = errorStatusOf(record);
|
|
1019
|
+
if (status === 401) return "unauthenticated";
|
|
1020
|
+
if (status === 403) return "forbidden";
|
|
1021
|
+
if (status !== void 0) return "other";
|
|
1022
|
+
if (record.code === ErrorCodes.AUTH_UNAUTHORIZED) sawUnauthorizedCode = true;
|
|
1023
|
+
node = record.cause;
|
|
1024
|
+
}
|
|
1025
|
+
return sawUnauthorizedCode ? "forbidden" : void 0;
|
|
1026
|
+
}
|
|
996
1027
|
function storageQuotaExceededError(service, message, meta) {
|
|
997
1028
|
return {
|
|
998
1029
|
code: ErrorCodes.STORAGE_QUOTA_EXCEEDED,
|
|
@@ -1009,6 +1040,23 @@ function storageLimitReachedError(service, message, meta) {
|
|
|
1009
1040
|
meta
|
|
1010
1041
|
};
|
|
1011
1042
|
}
|
|
1043
|
+
var STORAGE_FULL_MESSAGE = "TinyCloud storage is full, so this change was not saved. Reading still works. Free up space or upgrade your plan to save again.";
|
|
1044
|
+
var STORAGE_WRITE_TOO_LARGE_MESSAGE = "This change is larger than the TinyCloud storage you have left, so it was not saved. Reading still works. Free up space or upgrade your plan to save it.";
|
|
1045
|
+
function parseStorageQuotaBytes(responseText) {
|
|
1046
|
+
const match = responseText.match(/Used:\s*(\d+)\s*bytes,\s*Limit:\s*(\d+)\s*bytes/i);
|
|
1047
|
+
if (!match) return void 0;
|
|
1048
|
+
return {
|
|
1049
|
+
usedBytes: parseInt(match[1], 10),
|
|
1050
|
+
limitBytes: parseInt(match[2], 10)
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
function storageRejectionError(service, status, meta, responseText) {
|
|
1054
|
+
const quotaMeta = { ...meta, ...parseStorageQuotaBytes(responseText) };
|
|
1055
|
+
return status === 402 ? storageQuotaExceededError(service, STORAGE_FULL_MESSAGE, quotaMeta) : storageLimitReachedError(service, STORAGE_WRITE_TOO_LARGE_MESSAGE, quotaMeta);
|
|
1056
|
+
}
|
|
1057
|
+
function isStorageFullError(error) {
|
|
1058
|
+
return error?.code === ErrorCodes.STORAGE_QUOTA_EXCEEDED || error?.code === ErrorCodes.STORAGE_LIMIT_REACHED;
|
|
1059
|
+
}
|
|
1012
1060
|
function wrapError(service, error, defaultCode = ErrorCodes.NETWORK_ERROR) {
|
|
1013
1061
|
if (error instanceof Error) {
|
|
1014
1062
|
if (error.name === "AbortError") {
|
|
@@ -1402,47 +1450,21 @@ var KVService = class extends BaseService {
|
|
|
1402
1450
|
get config() {
|
|
1403
1451
|
return this._config;
|
|
1404
1452
|
}
|
|
1405
|
-
// Parses "Used: X bytes, Limit: Y bytes" from tinycloud-node error responses
|
|
1406
|
-
parseQuotaInfo(errorText) {
|
|
1407
|
-
const match = errorText.match(
|
|
1408
|
-
/Used:\s*(\d+)\s*bytes,\s*Limit:\s*(\d+)\s*bytes/i
|
|
1409
|
-
);
|
|
1410
|
-
if (match) {
|
|
1411
|
-
return {
|
|
1412
|
-
usedBytes: parseInt(match[1], 10),
|
|
1413
|
-
limitBytes: parseInt(match[2], 10)
|
|
1414
|
-
};
|
|
1415
|
-
}
|
|
1416
|
-
return void 0;
|
|
1417
|
-
}
|
|
1418
1453
|
handleQuotaErrorResponse(response, errorText, key) {
|
|
1419
|
-
if (response.status
|
|
1420
|
-
|
|
1421
|
-
return err(
|
|
1422
|
-
storageQuotaExceededError(
|
|
1423
|
-
"kv",
|
|
1424
|
-
`Storage quota exceeded for key "${key}": ${errorText}`,
|
|
1425
|
-
{
|
|
1426
|
-
status: response.status,
|
|
1427
|
-
...quotaInfo ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes } : {}
|
|
1428
|
-
}
|
|
1429
|
-
)
|
|
1430
|
-
);
|
|
1454
|
+
if (response.status !== 402 && response.status !== 413) {
|
|
1455
|
+
return void 0;
|
|
1431
1456
|
}
|
|
1432
|
-
if (response.status === 413) {
|
|
1433
|
-
|
|
1434
|
-
return err(
|
|
1435
|
-
storageLimitReachedError(
|
|
1436
|
-
"kv",
|
|
1437
|
-
`Storage limit reached for key "${key}": ${errorText}`,
|
|
1438
|
-
{
|
|
1439
|
-
status: response.status,
|
|
1440
|
-
...quotaInfo ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes } : {}
|
|
1441
|
-
}
|
|
1442
|
-
)
|
|
1443
|
-
);
|
|
1457
|
+
if (response.status === 413 && !parseStorageQuotaBytes(errorText)) {
|
|
1458
|
+
return void 0;
|
|
1444
1459
|
}
|
|
1445
|
-
return
|
|
1460
|
+
return err(
|
|
1461
|
+
storageRejectionError(
|
|
1462
|
+
"kv",
|
|
1463
|
+
response.status,
|
|
1464
|
+
{ status: response.status, statusText: response.statusText, key },
|
|
1465
|
+
errorText
|
|
1466
|
+
)
|
|
1467
|
+
);
|
|
1446
1468
|
}
|
|
1447
1469
|
/**
|
|
1448
1470
|
* Classify a KV 404 by reading the response body once.
|
|
@@ -1720,12 +1742,11 @@ var KVService = class extends BaseService {
|
|
|
1720
1742
|
if (!response.ok) {
|
|
1721
1743
|
const errorText = await response.text();
|
|
1722
1744
|
if (response.status === 401 || response.status === 403) {
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
}));
|
|
1745
|
+
return this.authorizationFailure(
|
|
1746
|
+
`Failed to batch read ${keys.length} key(s)`,
|
|
1747
|
+
response,
|
|
1748
|
+
errorText
|
|
1749
|
+
);
|
|
1729
1750
|
}
|
|
1730
1751
|
if (response.status === 413) {
|
|
1731
1752
|
return err(serviceError(
|
|
@@ -1824,23 +1845,39 @@ var KVService = class extends BaseService {
|
|
|
1824
1845
|
} catch {
|
|
1825
1846
|
}
|
|
1826
1847
|
if (response.status === 401 || response.status === 403) {
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
}));
|
|
1848
|
+
return this.authorizationFailure(
|
|
1849
|
+
`Failed to create signed read URL for key ${JSON.stringify(key)}`,
|
|
1850
|
+
response,
|
|
1851
|
+
errorText
|
|
1852
|
+
);
|
|
1833
1853
|
}
|
|
1834
1854
|
const code = response.status === 400 ? ErrorCodes.INVALID_INPUT : ErrorCodes.NETWORK_ERROR;
|
|
1835
1855
|
return err(
|
|
1836
1856
|
serviceError(
|
|
1837
1857
|
code,
|
|
1838
|
-
`Failed to create signed read URL for key
|
|
1858
|
+
`Failed to create signed read URL for key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
1839
1859
|
"kv",
|
|
1840
1860
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1841
1861
|
)
|
|
1842
1862
|
);
|
|
1843
1863
|
}
|
|
1864
|
+
/**
|
|
1865
|
+
* AUTH_UNAUTHORIZED for a 401/403 response. The message keeps the HTTP
|
|
1866
|
+
* status and the server text (`<context>: <status> - <text>`, the same
|
|
1867
|
+
* shape as every other KV failure) so callers that rethrow only the message
|
|
1868
|
+
* still see the status; `meta.status` carries it for typed callers.
|
|
1869
|
+
* Resource/ability hints are parsed from the raw body, never the message.
|
|
1870
|
+
*/
|
|
1871
|
+
authorizationFailure(context, response, errorText, extraMeta = {}) {
|
|
1872
|
+
const { resource, action } = parseAuthError(errorText);
|
|
1873
|
+
const detail = errorText.trim().length > 0 ? errorText : response.statusText || "authorization failed";
|
|
1874
|
+
return err(authUnauthorizedError("kv", `${context}: ${response.status} - ${detail}`, {
|
|
1875
|
+
status: response.status,
|
|
1876
|
+
...action && { requiredAction: action },
|
|
1877
|
+
...resource && { resource },
|
|
1878
|
+
...extraMeta
|
|
1879
|
+
}));
|
|
1880
|
+
}
|
|
1844
1881
|
normalizeSignedReadUrlResponse(data) {
|
|
1845
1882
|
if (!data || typeof data !== "object") {
|
|
1846
1883
|
return void 0;
|
|
@@ -1883,14 +1920,13 @@ var KVService = class extends BaseService {
|
|
|
1883
1920
|
if (!response.ok) {
|
|
1884
1921
|
if (response.status === 401 || response.status === 403) {
|
|
1885
1922
|
const errorText2 = await response.text();
|
|
1886
|
-
const { resource, action } = parseAuthError(errorText2);
|
|
1887
1923
|
const permissionHint = parsePermissionHintFromErrorText(errorText2);
|
|
1888
|
-
return
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1924
|
+
return this.authorizationFailure(
|
|
1925
|
+
`Failed to get key ${JSON.stringify(key)}`,
|
|
1926
|
+
response,
|
|
1927
|
+
errorText2,
|
|
1928
|
+
permissionHint === void 0 ? {} : { permissionHint }
|
|
1929
|
+
);
|
|
1894
1930
|
}
|
|
1895
1931
|
if (response.status === 404) {
|
|
1896
1932
|
return this.classifyNotFound(response, key);
|
|
@@ -1899,7 +1935,7 @@ var KVService = class extends BaseService {
|
|
|
1899
1935
|
if (response.status === 413) {
|
|
1900
1936
|
return err(serviceError(
|
|
1901
1937
|
ErrorCodes.KV_RESPONSE_TOO_LARGE,
|
|
1902
|
-
`KV value at key
|
|
1938
|
+
`KV value at key ${JSON.stringify(key)} exceeds the requested response limit`,
|
|
1903
1939
|
"kv",
|
|
1904
1940
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1905
1941
|
));
|
|
@@ -1907,7 +1943,7 @@ var KVService = class extends BaseService {
|
|
|
1907
1943
|
return err(
|
|
1908
1944
|
serviceError(
|
|
1909
1945
|
ErrorCodes.NETWORK_ERROR,
|
|
1910
|
-
`Failed to get key
|
|
1946
|
+
`Failed to get key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
1911
1947
|
"kv",
|
|
1912
1948
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1913
1949
|
)
|
|
@@ -1963,21 +1999,18 @@ var KVService = class extends BaseService {
|
|
|
1963
1999
|
}
|
|
1964
2000
|
);
|
|
1965
2001
|
if (response.status === 401 || response.status === 403) {
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
...requiredAction && { requiredAction },
|
|
1972
|
-
...resource && { resource }
|
|
1973
|
-
}));
|
|
2002
|
+
return this.authorizationFailure(
|
|
2003
|
+
`Failed to put key ${JSON.stringify(key)}`,
|
|
2004
|
+
response,
|
|
2005
|
+
await response.text()
|
|
2006
|
+
);
|
|
1974
2007
|
}
|
|
1975
2008
|
if (!response.ok) {
|
|
1976
2009
|
const errorText = await response.text();
|
|
1977
2010
|
if (response.status === 412) {
|
|
1978
2011
|
return err(serviceError(
|
|
1979
2012
|
ErrorCodes.KV_PRECONDITION_FAILED,
|
|
1980
|
-
`KV precondition failed for key
|
|
2013
|
+
`KV precondition failed for key ${JSON.stringify(key)}`,
|
|
1981
2014
|
"kv",
|
|
1982
2015
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1983
2016
|
));
|
|
@@ -1985,7 +2018,7 @@ var KVService = class extends BaseService {
|
|
|
1985
2018
|
if (response.status === 503 && (options?.ifMatch !== void 0 || options?.ifNoneMatch !== void 0)) {
|
|
1986
2019
|
return err(serviceError(
|
|
1987
2020
|
ErrorCodes.KV_CONFLICT,
|
|
1988
|
-
`Concurrent KV update conflicted for key
|
|
2021
|
+
`Concurrent KV update conflicted for key ${JSON.stringify(key)}`,
|
|
1989
2022
|
"kv",
|
|
1990
2023
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1991
2024
|
));
|
|
@@ -2001,7 +2034,7 @@ var KVService = class extends BaseService {
|
|
|
2001
2034
|
return err(
|
|
2002
2035
|
serviceError(
|
|
2003
2036
|
ErrorCodes.KV_WRITE_FAILED,
|
|
2004
|
-
`Failed to put key
|
|
2037
|
+
`Failed to put key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
2005
2038
|
"kv",
|
|
2006
2039
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2007
2040
|
)
|
|
@@ -2095,12 +2128,11 @@ var KVService = class extends BaseService {
|
|
|
2095
2128
|
);
|
|
2096
2129
|
}
|
|
2097
2130
|
if (response.status === 401 || response.status === 403) {
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
}));
|
|
2131
|
+
return this.authorizationFailure(
|
|
2132
|
+
`Failed to batch put ${items.length} key(s)`,
|
|
2133
|
+
response,
|
|
2134
|
+
errorText
|
|
2135
|
+
);
|
|
2104
2136
|
}
|
|
2105
2137
|
const quotaError = this.handleQuotaErrorResponse(
|
|
2106
2138
|
response,
|
|
@@ -2221,13 +2253,11 @@ var KVService = class extends BaseService {
|
|
|
2221
2253
|
);
|
|
2222
2254
|
if (!response.ok) {
|
|
2223
2255
|
if (response.status === 401) {
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
...resource && { resource }
|
|
2230
|
-
}));
|
|
2256
|
+
return this.authorizationFailure(
|
|
2257
|
+
"Failed to list keys",
|
|
2258
|
+
response,
|
|
2259
|
+
await response.text()
|
|
2260
|
+
);
|
|
2231
2261
|
}
|
|
2232
2262
|
const errorText = await response.text();
|
|
2233
2263
|
return err(
|
|
@@ -2276,13 +2306,11 @@ var KVService = class extends BaseService {
|
|
|
2276
2306
|
);
|
|
2277
2307
|
if (!response.ok) {
|
|
2278
2308
|
if (response.status === 401) {
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
...resource && { resource }
|
|
2285
|
-
}));
|
|
2309
|
+
return this.authorizationFailure(
|
|
2310
|
+
`Failed to delete key ${JSON.stringify(key)}`,
|
|
2311
|
+
response,
|
|
2312
|
+
await response.text()
|
|
2313
|
+
);
|
|
2286
2314
|
}
|
|
2287
2315
|
if (response.status === 404) {
|
|
2288
2316
|
return this.classifyNotFound(response, key);
|
|
@@ -2291,7 +2319,7 @@ var KVService = class extends BaseService {
|
|
|
2291
2319
|
if (response.status === 412) {
|
|
2292
2320
|
return err(serviceError(
|
|
2293
2321
|
ErrorCodes.KV_PRECONDITION_FAILED,
|
|
2294
|
-
`KV precondition failed for key
|
|
2322
|
+
`KV precondition failed for key ${JSON.stringify(key)}`,
|
|
2295
2323
|
"kv",
|
|
2296
2324
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2297
2325
|
));
|
|
@@ -2299,7 +2327,7 @@ var KVService = class extends BaseService {
|
|
|
2299
2327
|
if (response.status === 503 && options?.ifMatch !== void 0) {
|
|
2300
2328
|
return err(serviceError(
|
|
2301
2329
|
ErrorCodes.KV_CONFLICT,
|
|
2302
|
-
`Concurrent KV delete conflicted for key
|
|
2330
|
+
`Concurrent KV delete conflicted for key ${JSON.stringify(key)}`,
|
|
2303
2331
|
"kv",
|
|
2304
2332
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2305
2333
|
));
|
|
@@ -2307,7 +2335,7 @@ var KVService = class extends BaseService {
|
|
|
2307
2335
|
return err(
|
|
2308
2336
|
serviceError(
|
|
2309
2337
|
ErrorCodes.NETWORK_ERROR,
|
|
2310
|
-
`Failed to delete key
|
|
2338
|
+
`Failed to delete key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
2311
2339
|
"kv",
|
|
2312
2340
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2313
2341
|
)
|
|
@@ -2340,13 +2368,11 @@ var KVService = class extends BaseService {
|
|
|
2340
2368
|
);
|
|
2341
2369
|
if (!response.ok) {
|
|
2342
2370
|
if (response.status === 401) {
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
...resource && { resource }
|
|
2349
|
-
}));
|
|
2371
|
+
return this.authorizationFailure(
|
|
2372
|
+
`Failed to get metadata for key ${JSON.stringify(key)}`,
|
|
2373
|
+
response,
|
|
2374
|
+
await response.text()
|
|
2375
|
+
);
|
|
2350
2376
|
}
|
|
2351
2377
|
if (response.status === 404) {
|
|
2352
2378
|
return this.classifyNotFound(response, key);
|
|
@@ -2355,7 +2381,7 @@ var KVService = class extends BaseService {
|
|
|
2355
2381
|
return err(
|
|
2356
2382
|
serviceError(
|
|
2357
2383
|
ErrorCodes.NETWORK_ERROR,
|
|
2358
|
-
`Failed to get metadata for key
|
|
2384
|
+
`Failed to get metadata for key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
2359
2385
|
"kv",
|
|
2360
2386
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
2361
2387
|
)
|
|
@@ -2775,21 +2801,24 @@ var SQLService = class extends BaseService {
|
|
|
2775
2801
|
}
|
|
2776
2802
|
async applyMigrationsOnDbUnlocked(dbName, options) {
|
|
2777
2803
|
return this.withTelemetry("migrations.apply", dbName, async () => {
|
|
2778
|
-
const created = await this.ensureMigrationsTable(dbName, options.signal);
|
|
2779
|
-
if (!created.ok) return created;
|
|
2780
2804
|
const listed = await this.queryOnDb(
|
|
2781
2805
|
dbName,
|
|
2782
2806
|
`SELECT id FROM ${MIGRATIONS_TABLE} WHERE namespace = ? ORDER BY applied_at, id`,
|
|
2783
2807
|
[options.namespace],
|
|
2784
2808
|
{ signal: options.signal }
|
|
2785
2809
|
);
|
|
2786
|
-
|
|
2810
|
+
const tableMissing = !listed.ok && (listed.error.code === ErrorCodes.SQL_DATABASE_NOT_FOUND || isMissingTableError(listed.error.message));
|
|
2811
|
+
if (!listed.ok && !tableMissing) return listed;
|
|
2787
2812
|
const appliedIds = new Set(
|
|
2788
|
-
listed.data.rows.map((row) => rowValue(row, 0)).filter((id) => typeof id === "string")
|
|
2813
|
+
(listed.ok ? listed.data.rows : []).map((row) => rowValue(row, 0)).filter((id) => typeof id === "string")
|
|
2789
2814
|
);
|
|
2790
2815
|
const skipped = options.migrations.filter((migration) => appliedIds.has(migration.id)).map((migration) => migration.id);
|
|
2791
2816
|
const pending = options.migrations.filter((migration) => !appliedIds.has(migration.id));
|
|
2792
2817
|
const applied = [];
|
|
2818
|
+
if (pending.length > 0 && tableMissing) {
|
|
2819
|
+
const created = await this.ensureMigrationsTable(dbName, options.signal);
|
|
2820
|
+
if (!created.ok) return created;
|
|
2821
|
+
}
|
|
2793
2822
|
for (const migration of pending) {
|
|
2794
2823
|
const result = await this.applyOneMigration(dbName, options.namespace, migration, options.signal);
|
|
2795
2824
|
if (!result.ok) return result;
|
|
@@ -2892,6 +2921,10 @@ var SQLService = class extends BaseService {
|
|
|
2892
2921
|
}
|
|
2893
2922
|
async handleErrorResponse(response, operation) {
|
|
2894
2923
|
const errorText = await response.text();
|
|
2924
|
+
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
2925
|
+
if (response.status === 402) {
|
|
2926
|
+
return err(storageRejectionError("sql", 402, meta, errorText));
|
|
2927
|
+
}
|
|
2895
2928
|
const errorBody = parseServiceErrorBody(errorText);
|
|
2896
2929
|
const errorCode = this.mapHttpStatusToErrorCode(
|
|
2897
2930
|
response.status,
|
|
@@ -2904,7 +2937,6 @@ var SQLService = class extends BaseService {
|
|
|
2904
2937
|
errorText,
|
|
2905
2938
|
errorBody
|
|
2906
2939
|
);
|
|
2907
|
-
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
2908
2940
|
if (response.status === 401) {
|
|
2909
2941
|
const { resource, action } = parseAuthError(errorText);
|
|
2910
2942
|
if (action) meta.requiredAction = action;
|
|
@@ -3005,6 +3037,9 @@ function serializeSqlValues(values) {
|
|
|
3005
3037
|
(value) => value instanceof Uint8Array ? Array.from(value) : value
|
|
3006
3038
|
);
|
|
3007
3039
|
}
|
|
3040
|
+
function isMissingTableError(message) {
|
|
3041
|
+
return /no such table/i.test(message);
|
|
3042
|
+
}
|
|
3008
3043
|
function migrationKey(namespace, id) {
|
|
3009
3044
|
return `${encodeURIComponent(namespace)}:${encodeURIComponent(id)}`;
|
|
3010
3045
|
}
|
|
@@ -3326,6 +3361,10 @@ var DuckDbService = class extends BaseService {
|
|
|
3326
3361
|
}
|
|
3327
3362
|
async handleErrorResponse(response, operation) {
|
|
3328
3363
|
const errorText = await response.text();
|
|
3364
|
+
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
3365
|
+
if (response.status === 402) {
|
|
3366
|
+
return err(storageRejectionError("duckdb", 402, meta, errorText));
|
|
3367
|
+
}
|
|
3329
3368
|
const errorBody = parseServiceErrorBody(errorText);
|
|
3330
3369
|
const errorCode = this.mapHttpStatusToErrorCode(
|
|
3331
3370
|
response.status,
|
|
@@ -3338,7 +3377,6 @@ var DuckDbService = class extends BaseService {
|
|
|
3338
3377
|
errorText,
|
|
3339
3378
|
errorBody
|
|
3340
3379
|
);
|
|
3341
|
-
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
3342
3380
|
if (response.status === 401) {
|
|
3343
3381
|
const { resource, action } = parseAuthError(errorText);
|
|
3344
3382
|
if (action) meta.requiredAction = action;
|
|
@@ -3837,10 +3875,14 @@ async function responseError(service, message, response) {
|
|
|
3837
3875
|
}
|
|
3838
3876
|
} catch {
|
|
3839
3877
|
}
|
|
3840
|
-
|
|
3878
|
+
const error = wrapError(
|
|
3841
3879
|
service,
|
|
3842
3880
|
new Error(`${message}: ${response.status} ${detail}`)
|
|
3843
3881
|
);
|
|
3882
|
+
return {
|
|
3883
|
+
...error,
|
|
3884
|
+
meta: { ...error.meta, status: response.status, statusText: response.statusText }
|
|
3885
|
+
};
|
|
3844
3886
|
}
|
|
3845
3887
|
function isAbortError(error) {
|
|
3846
3888
|
return error instanceof DOMException && error.name === "AbortError";
|
|
@@ -4306,6 +4348,9 @@ function defaultVaultMessage(input) {
|
|
|
4306
4348
|
return input.message ?? `Public key not found for ${input.did}`;
|
|
4307
4349
|
case "STORAGE_ERROR":
|
|
4308
4350
|
return input.message ?? input.cause.message;
|
|
4351
|
+
case "STORAGE_QUOTA_EXCEEDED":
|
|
4352
|
+
case "STORAGE_LIMIT_REACHED":
|
|
4353
|
+
return input.message;
|
|
4309
4354
|
}
|
|
4310
4355
|
}
|
|
4311
4356
|
function vaultError(input) {
|
|
@@ -4316,6 +4361,15 @@ function vaultError(input) {
|
|
|
4316
4361
|
};
|
|
4317
4362
|
return { ok: false, error };
|
|
4318
4363
|
}
|
|
4364
|
+
function kvWriteError(context, error) {
|
|
4365
|
+
if (error.code === ErrorCodes.STORAGE_QUOTA_EXCEEDED || error.code === ErrorCodes.STORAGE_LIMIT_REACHED) {
|
|
4366
|
+
return vaultError({ code: error.code, message: error.message, meta: error.meta });
|
|
4367
|
+
}
|
|
4368
|
+
return vaultError({
|
|
4369
|
+
code: "STORAGE_ERROR",
|
|
4370
|
+
cause: new Error(`${context}: ${error.message}`)
|
|
4371
|
+
});
|
|
4372
|
+
}
|
|
4319
4373
|
var DataVaultService = class extends BaseService {
|
|
4320
4374
|
/**
|
|
4321
4375
|
* Create a new DataVaultService instance.
|
|
@@ -4598,12 +4652,7 @@ var DataVaultService = class extends BaseService {
|
|
|
4598
4652
|
JSON.stringify(envelopeResult.data)
|
|
4599
4653
|
);
|
|
4600
4654
|
if (!valuePutResult.ok) {
|
|
4601
|
-
return
|
|
4602
|
-
code: "STORAGE_ERROR",
|
|
4603
|
-
cause: new Error(
|
|
4604
|
-
`Failed to store encrypted value: ${valuePutResult.error.message}`
|
|
4605
|
-
)
|
|
4606
|
-
});
|
|
4655
|
+
return kvWriteError("Failed to store encrypted value", valuePutResult.error);
|
|
4607
4656
|
}
|
|
4608
4657
|
return { ok: true, data: void 0 };
|
|
4609
4658
|
} catch (error) {
|
|
@@ -4821,12 +4870,7 @@ var DataVaultService = class extends BaseService {
|
|
|
4821
4870
|
keyPayload
|
|
4822
4871
|
);
|
|
4823
4872
|
if (!keyPutResult.ok) {
|
|
4824
|
-
return
|
|
4825
|
-
code: "STORAGE_ERROR",
|
|
4826
|
-
cause: new Error(
|
|
4827
|
-
`Failed to store key blob: ${keyPutResult.error.message}`
|
|
4828
|
-
)
|
|
4829
|
-
});
|
|
4873
|
+
return kvWriteError("Failed to store key blob", keyPutResult.error);
|
|
4830
4874
|
}
|
|
4831
4875
|
const valuePayload = JSON.stringify({
|
|
4832
4876
|
data: base64Encode(encrypted),
|
|
@@ -4837,12 +4881,7 @@ var DataVaultService = class extends BaseService {
|
|
|
4837
4881
|
valuePayload
|
|
4838
4882
|
);
|
|
4839
4883
|
if (!valuePutResult.ok) {
|
|
4840
|
-
return
|
|
4841
|
-
code: "STORAGE_ERROR",
|
|
4842
|
-
cause: new Error(
|
|
4843
|
-
`Failed to store encrypted value: ${valuePutResult.error.message}`
|
|
4844
|
-
)
|
|
4845
|
-
});
|
|
4884
|
+
return kvWriteError("Failed to store encrypted value", valuePutResult.error);
|
|
4846
4885
|
}
|
|
4847
4886
|
return ok(void 0);
|
|
4848
4887
|
} catch (error) {
|
|
@@ -5173,12 +5212,7 @@ var DataVaultService = class extends BaseService {
|
|
|
5173
5212
|
grantPayload
|
|
5174
5213
|
);
|
|
5175
5214
|
if (!grantPutResult.ok) {
|
|
5176
|
-
return
|
|
5177
|
-
code: "STORAGE_ERROR",
|
|
5178
|
-
cause: new Error(
|
|
5179
|
-
`Failed to store grant: ${grantPutResult.error.message}`
|
|
5180
|
-
)
|
|
5181
|
-
});
|
|
5215
|
+
return kvWriteError("Failed to store grant", grantPutResult.error);
|
|
5182
5216
|
}
|
|
5183
5217
|
return ok(void 0);
|
|
5184
5218
|
} catch (error) {
|
|
@@ -5523,12 +5557,7 @@ var DataVaultService = class extends BaseService {
|
|
|
5523
5557
|
keyPayload
|
|
5524
5558
|
);
|
|
5525
5559
|
if (!keyPutResult.ok) {
|
|
5526
|
-
return
|
|
5527
|
-
code: "STORAGE_ERROR",
|
|
5528
|
-
cause: new Error(
|
|
5529
|
-
`Failed to store rotated key blob: ${keyPutResult.error.message}`
|
|
5530
|
-
)
|
|
5531
|
-
});
|
|
5560
|
+
return kvWriteError("Failed to store rotated key blob", keyPutResult.error);
|
|
5532
5561
|
}
|
|
5533
5562
|
const valuePayload = JSON.stringify({
|
|
5534
5563
|
data: base64Encode(encrypted),
|
|
@@ -5539,12 +5568,7 @@ var DataVaultService = class extends BaseService {
|
|
|
5539
5568
|
valuePayload
|
|
5540
5569
|
);
|
|
5541
5570
|
if (!valuePutResult.ok) {
|
|
5542
|
-
return
|
|
5543
|
-
code: "STORAGE_ERROR",
|
|
5544
|
-
cause: new Error(
|
|
5545
|
-
`Failed to store re-encrypted value: ${valuePutResult.error.message}`
|
|
5546
|
-
)
|
|
5547
|
-
});
|
|
5571
|
+
return kvWriteError("Failed to store re-encrypted value", valuePutResult.error);
|
|
5548
5572
|
}
|
|
5549
5573
|
for (const did of remainingGrantees) {
|
|
5550
5574
|
const grantResult = await this.reencrypt(key, did);
|
|
@@ -6873,6 +6897,8 @@ export {
|
|
|
6873
6897
|
SQLAction,
|
|
6874
6898
|
SQLMigrations,
|
|
6875
6899
|
SQLService,
|
|
6900
|
+
STORAGE_FULL_MESSAGE,
|
|
6901
|
+
STORAGE_WRITE_TOO_LARGE_MESSAGE,
|
|
6876
6902
|
SecretsService,
|
|
6877
6903
|
ServiceContext,
|
|
6878
6904
|
ServiceErrorEventSchema,
|
|
@@ -6891,6 +6917,7 @@ export {
|
|
|
6891
6917
|
authExpiredError,
|
|
6892
6918
|
authRequiredError,
|
|
6893
6919
|
authUnauthorizedError,
|
|
6920
|
+
authorizationVerdictOf,
|
|
6894
6921
|
base64Decode2 as base64Decode,
|
|
6895
6922
|
base64Encode2 as base64Encode,
|
|
6896
6923
|
buildCanonicalDecryptRequest,
|
|
@@ -6924,6 +6951,7 @@ export {
|
|
|
6924
6951
|
hexEncode2 as hexEncode,
|
|
6925
6952
|
installTinyCloudDebugGlobals,
|
|
6926
6953
|
isNetworkId,
|
|
6954
|
+
isStorageFullError,
|
|
6927
6955
|
networkDiscoveryKey,
|
|
6928
6956
|
networkError,
|
|
6929
6957
|
notFoundError,
|
|
@@ -6934,12 +6962,14 @@ export {
|
|
|
6934
6962
|
parsePermissionHint,
|
|
6935
6963
|
parsePermissionHintFromErrorText,
|
|
6936
6964
|
parseSecretCatalogKey,
|
|
6965
|
+
parseStorageQuotaBytes,
|
|
6937
6966
|
permissionDeniedError,
|
|
6938
6967
|
resolveSecretListPrefix,
|
|
6939
6968
|
resolveSecretPath,
|
|
6940
6969
|
serviceError,
|
|
6941
6970
|
storageLimitReachedError,
|
|
6942
6971
|
storageQuotaExceededError,
|
|
6972
|
+
storageRejectionError,
|
|
6943
6973
|
timeoutError,
|
|
6944
6974
|
tinyCloudDebugLogger,
|
|
6945
6975
|
utf8Decode,
|