@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/kv/index.d.cts
CHANGED
|
@@ -850,7 +850,6 @@ declare class KVService extends BaseService implements IKVService {
|
|
|
850
850
|
* Get the service configuration.
|
|
851
851
|
*/
|
|
852
852
|
get config(): KVServiceConfig;
|
|
853
|
-
private parseQuotaInfo;
|
|
854
853
|
private handleQuotaErrorResponse;
|
|
855
854
|
/**
|
|
856
855
|
* Classify a KV 404 by reading the response body once.
|
|
@@ -919,6 +918,14 @@ declare class KVService extends BaseService implements IKVService {
|
|
|
919
918
|
*/
|
|
920
919
|
private parseResponse;
|
|
921
920
|
private createSignedReadUrlError;
|
|
921
|
+
/**
|
|
922
|
+
* AUTH_UNAUTHORIZED for a 401/403 response. The message keeps the HTTP
|
|
923
|
+
* status and the server text (`<context>: <status> - <text>`, the same
|
|
924
|
+
* shape as every other KV failure) so callers that rethrow only the message
|
|
925
|
+
* still see the status; `meta.status` carries it for typed callers.
|
|
926
|
+
* Resource/ability hints are parsed from the raw body, never the message.
|
|
927
|
+
*/
|
|
928
|
+
private authorizationFailure;
|
|
922
929
|
private normalizeSignedReadUrlResponse;
|
|
923
930
|
/**
|
|
924
931
|
* Get a value by key.
|
package/dist/kv/index.d.ts
CHANGED
|
@@ -850,7 +850,6 @@ declare class KVService extends BaseService implements IKVService {
|
|
|
850
850
|
* Get the service configuration.
|
|
851
851
|
*/
|
|
852
852
|
get config(): KVServiceConfig;
|
|
853
|
-
private parseQuotaInfo;
|
|
854
853
|
private handleQuotaErrorResponse;
|
|
855
854
|
/**
|
|
856
855
|
* Classify a KV 404 by reading the response body once.
|
|
@@ -919,6 +918,14 @@ declare class KVService extends BaseService implements IKVService {
|
|
|
919
918
|
*/
|
|
920
919
|
private parseResponse;
|
|
921
920
|
private createSignedReadUrlError;
|
|
921
|
+
/**
|
|
922
|
+
* AUTH_UNAUTHORIZED for a 401/403 response. The message keeps the HTTP
|
|
923
|
+
* status and the server text (`<context>: <status> - <text>`, the same
|
|
924
|
+
* shape as every other KV failure) so callers that rethrow only the message
|
|
925
|
+
* still see the status; `meta.status` carries it for typed callers.
|
|
926
|
+
* Resource/ability hints are parsed from the raw body, never the message.
|
|
927
|
+
*/
|
|
928
|
+
private authorizationFailure;
|
|
922
929
|
private normalizeSignedReadUrlResponse;
|
|
923
930
|
/**
|
|
924
931
|
* Get a value by key.
|
package/dist/kv/index.js
CHANGED
|
@@ -154,6 +154,20 @@ function storageLimitReachedError(service, message, meta) {
|
|
|
154
154
|
meta
|
|
155
155
|
};
|
|
156
156
|
}
|
|
157
|
+
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.";
|
|
158
|
+
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.";
|
|
159
|
+
function parseStorageQuotaBytes(responseText) {
|
|
160
|
+
const match = responseText.match(/Used:\s*(\d+)\s*bytes,\s*Limit:\s*(\d+)\s*bytes/i);
|
|
161
|
+
if (!match) return void 0;
|
|
162
|
+
return {
|
|
163
|
+
usedBytes: parseInt(match[1], 10),
|
|
164
|
+
limitBytes: parseInt(match[2], 10)
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function storageRejectionError(service, status, meta, responseText) {
|
|
168
|
+
const quotaMeta = { ...meta, ...parseStorageQuotaBytes(responseText) };
|
|
169
|
+
return status === 402 ? storageQuotaExceededError(service, STORAGE_FULL_MESSAGE, quotaMeta) : storageLimitReachedError(service, STORAGE_WRITE_TOO_LARGE_MESSAGE, quotaMeta);
|
|
170
|
+
}
|
|
157
171
|
function wrapError(service, error, defaultCode = ErrorCodes.NETWORK_ERROR) {
|
|
158
172
|
if (error instanceof Error) {
|
|
159
173
|
if (error.name === "AbortError") {
|
|
@@ -544,47 +558,21 @@ var KVService = class extends BaseService {
|
|
|
544
558
|
get config() {
|
|
545
559
|
return this._config;
|
|
546
560
|
}
|
|
547
|
-
// Parses "Used: X bytes, Limit: Y bytes" from tinycloud-node error responses
|
|
548
|
-
parseQuotaInfo(errorText) {
|
|
549
|
-
const match = errorText.match(
|
|
550
|
-
/Used:\s*(\d+)\s*bytes,\s*Limit:\s*(\d+)\s*bytes/i
|
|
551
|
-
);
|
|
552
|
-
if (match) {
|
|
553
|
-
return {
|
|
554
|
-
usedBytes: parseInt(match[1], 10),
|
|
555
|
-
limitBytes: parseInt(match[2], 10)
|
|
556
|
-
};
|
|
557
|
-
}
|
|
558
|
-
return void 0;
|
|
559
|
-
}
|
|
560
561
|
handleQuotaErrorResponse(response, errorText, key) {
|
|
561
|
-
if (response.status
|
|
562
|
-
|
|
563
|
-
return err(
|
|
564
|
-
storageQuotaExceededError(
|
|
565
|
-
"kv",
|
|
566
|
-
`Storage quota exceeded for key "${key}": ${errorText}`,
|
|
567
|
-
{
|
|
568
|
-
status: response.status,
|
|
569
|
-
...quotaInfo ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes } : {}
|
|
570
|
-
}
|
|
571
|
-
)
|
|
572
|
-
);
|
|
562
|
+
if (response.status !== 402 && response.status !== 413) {
|
|
563
|
+
return void 0;
|
|
573
564
|
}
|
|
574
|
-
if (response.status === 413) {
|
|
575
|
-
|
|
576
|
-
return err(
|
|
577
|
-
storageLimitReachedError(
|
|
578
|
-
"kv",
|
|
579
|
-
`Storage limit reached for key "${key}": ${errorText}`,
|
|
580
|
-
{
|
|
581
|
-
status: response.status,
|
|
582
|
-
...quotaInfo ? { usedBytes: quotaInfo.usedBytes, limitBytes: quotaInfo.limitBytes } : {}
|
|
583
|
-
}
|
|
584
|
-
)
|
|
585
|
-
);
|
|
565
|
+
if (response.status === 413 && !parseStorageQuotaBytes(errorText)) {
|
|
566
|
+
return void 0;
|
|
586
567
|
}
|
|
587
|
-
return
|
|
568
|
+
return err(
|
|
569
|
+
storageRejectionError(
|
|
570
|
+
"kv",
|
|
571
|
+
response.status,
|
|
572
|
+
{ status: response.status, statusText: response.statusText, key },
|
|
573
|
+
errorText
|
|
574
|
+
)
|
|
575
|
+
);
|
|
588
576
|
}
|
|
589
577
|
/**
|
|
590
578
|
* Classify a KV 404 by reading the response body once.
|
|
@@ -862,12 +850,11 @@ var KVService = class extends BaseService {
|
|
|
862
850
|
if (!response.ok) {
|
|
863
851
|
const errorText = await response.text();
|
|
864
852
|
if (response.status === 401 || response.status === 403) {
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
}));
|
|
853
|
+
return this.authorizationFailure(
|
|
854
|
+
`Failed to batch read ${keys.length} key(s)`,
|
|
855
|
+
response,
|
|
856
|
+
errorText
|
|
857
|
+
);
|
|
871
858
|
}
|
|
872
859
|
if (response.status === 413) {
|
|
873
860
|
return err(serviceError(
|
|
@@ -966,23 +953,39 @@ var KVService = class extends BaseService {
|
|
|
966
953
|
} catch {
|
|
967
954
|
}
|
|
968
955
|
if (response.status === 401 || response.status === 403) {
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
}));
|
|
956
|
+
return this.authorizationFailure(
|
|
957
|
+
`Failed to create signed read URL for key ${JSON.stringify(key)}`,
|
|
958
|
+
response,
|
|
959
|
+
errorText
|
|
960
|
+
);
|
|
975
961
|
}
|
|
976
962
|
const code = response.status === 400 ? ErrorCodes.INVALID_INPUT : ErrorCodes.NETWORK_ERROR;
|
|
977
963
|
return err(
|
|
978
964
|
serviceError(
|
|
979
965
|
code,
|
|
980
|
-
`Failed to create signed read URL for key
|
|
966
|
+
`Failed to create signed read URL for key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
981
967
|
"kv",
|
|
982
968
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
983
969
|
)
|
|
984
970
|
);
|
|
985
971
|
}
|
|
972
|
+
/**
|
|
973
|
+
* AUTH_UNAUTHORIZED for a 401/403 response. The message keeps the HTTP
|
|
974
|
+
* status and the server text (`<context>: <status> - <text>`, the same
|
|
975
|
+
* shape as every other KV failure) so callers that rethrow only the message
|
|
976
|
+
* still see the status; `meta.status` carries it for typed callers.
|
|
977
|
+
* Resource/ability hints are parsed from the raw body, never the message.
|
|
978
|
+
*/
|
|
979
|
+
authorizationFailure(context, response, errorText, extraMeta = {}) {
|
|
980
|
+
const { resource, action } = parseAuthError(errorText);
|
|
981
|
+
const detail = errorText.trim().length > 0 ? errorText : response.statusText || "authorization failed";
|
|
982
|
+
return err(authUnauthorizedError("kv", `${context}: ${response.status} - ${detail}`, {
|
|
983
|
+
status: response.status,
|
|
984
|
+
...action && { requiredAction: action },
|
|
985
|
+
...resource && { resource },
|
|
986
|
+
...extraMeta
|
|
987
|
+
}));
|
|
988
|
+
}
|
|
986
989
|
normalizeSignedReadUrlResponse(data) {
|
|
987
990
|
if (!data || typeof data !== "object") {
|
|
988
991
|
return void 0;
|
|
@@ -1025,14 +1028,13 @@ var KVService = class extends BaseService {
|
|
|
1025
1028
|
if (!response.ok) {
|
|
1026
1029
|
if (response.status === 401 || response.status === 403) {
|
|
1027
1030
|
const errorText2 = await response.text();
|
|
1028
|
-
const { resource, action } = parseAuthError(errorText2);
|
|
1029
1031
|
const permissionHint = parsePermissionHintFromErrorText(errorText2);
|
|
1030
|
-
return
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1032
|
+
return this.authorizationFailure(
|
|
1033
|
+
`Failed to get key ${JSON.stringify(key)}`,
|
|
1034
|
+
response,
|
|
1035
|
+
errorText2,
|
|
1036
|
+
permissionHint === void 0 ? {} : { permissionHint }
|
|
1037
|
+
);
|
|
1036
1038
|
}
|
|
1037
1039
|
if (response.status === 404) {
|
|
1038
1040
|
return this.classifyNotFound(response, key);
|
|
@@ -1041,7 +1043,7 @@ var KVService = class extends BaseService {
|
|
|
1041
1043
|
if (response.status === 413) {
|
|
1042
1044
|
return err(serviceError(
|
|
1043
1045
|
ErrorCodes.KV_RESPONSE_TOO_LARGE,
|
|
1044
|
-
`KV value at key
|
|
1046
|
+
`KV value at key ${JSON.stringify(key)} exceeds the requested response limit`,
|
|
1045
1047
|
"kv",
|
|
1046
1048
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1047
1049
|
));
|
|
@@ -1049,7 +1051,7 @@ var KVService = class extends BaseService {
|
|
|
1049
1051
|
return err(
|
|
1050
1052
|
serviceError(
|
|
1051
1053
|
ErrorCodes.NETWORK_ERROR,
|
|
1052
|
-
`Failed to get key
|
|
1054
|
+
`Failed to get key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
1053
1055
|
"kv",
|
|
1054
1056
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1055
1057
|
)
|
|
@@ -1105,21 +1107,18 @@ var KVService = class extends BaseService {
|
|
|
1105
1107
|
}
|
|
1106
1108
|
);
|
|
1107
1109
|
if (response.status === 401 || response.status === 403) {
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
...requiredAction && { requiredAction },
|
|
1114
|
-
...resource && { resource }
|
|
1115
|
-
}));
|
|
1110
|
+
return this.authorizationFailure(
|
|
1111
|
+
`Failed to put key ${JSON.stringify(key)}`,
|
|
1112
|
+
response,
|
|
1113
|
+
await response.text()
|
|
1114
|
+
);
|
|
1116
1115
|
}
|
|
1117
1116
|
if (!response.ok) {
|
|
1118
1117
|
const errorText = await response.text();
|
|
1119
1118
|
if (response.status === 412) {
|
|
1120
1119
|
return err(serviceError(
|
|
1121
1120
|
ErrorCodes.KV_PRECONDITION_FAILED,
|
|
1122
|
-
`KV precondition failed for key
|
|
1121
|
+
`KV precondition failed for key ${JSON.stringify(key)}`,
|
|
1123
1122
|
"kv",
|
|
1124
1123
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1125
1124
|
));
|
|
@@ -1127,7 +1126,7 @@ var KVService = class extends BaseService {
|
|
|
1127
1126
|
if (response.status === 503 && (options?.ifMatch !== void 0 || options?.ifNoneMatch !== void 0)) {
|
|
1128
1127
|
return err(serviceError(
|
|
1129
1128
|
ErrorCodes.KV_CONFLICT,
|
|
1130
|
-
`Concurrent KV update conflicted for key
|
|
1129
|
+
`Concurrent KV update conflicted for key ${JSON.stringify(key)}`,
|
|
1131
1130
|
"kv",
|
|
1132
1131
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1133
1132
|
));
|
|
@@ -1143,7 +1142,7 @@ var KVService = class extends BaseService {
|
|
|
1143
1142
|
return err(
|
|
1144
1143
|
serviceError(
|
|
1145
1144
|
ErrorCodes.KV_WRITE_FAILED,
|
|
1146
|
-
`Failed to put key
|
|
1145
|
+
`Failed to put key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
1147
1146
|
"kv",
|
|
1148
1147
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1149
1148
|
)
|
|
@@ -1237,12 +1236,11 @@ var KVService = class extends BaseService {
|
|
|
1237
1236
|
);
|
|
1238
1237
|
}
|
|
1239
1238
|
if (response.status === 401 || response.status === 403) {
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
}));
|
|
1239
|
+
return this.authorizationFailure(
|
|
1240
|
+
`Failed to batch put ${items.length} key(s)`,
|
|
1241
|
+
response,
|
|
1242
|
+
errorText
|
|
1243
|
+
);
|
|
1246
1244
|
}
|
|
1247
1245
|
const quotaError = this.handleQuotaErrorResponse(
|
|
1248
1246
|
response,
|
|
@@ -1363,13 +1361,11 @@ var KVService = class extends BaseService {
|
|
|
1363
1361
|
);
|
|
1364
1362
|
if (!response.ok) {
|
|
1365
1363
|
if (response.status === 401) {
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
...resource && { resource }
|
|
1372
|
-
}));
|
|
1364
|
+
return this.authorizationFailure(
|
|
1365
|
+
"Failed to list keys",
|
|
1366
|
+
response,
|
|
1367
|
+
await response.text()
|
|
1368
|
+
);
|
|
1373
1369
|
}
|
|
1374
1370
|
const errorText = await response.text();
|
|
1375
1371
|
return err(
|
|
@@ -1418,13 +1414,11 @@ var KVService = class extends BaseService {
|
|
|
1418
1414
|
);
|
|
1419
1415
|
if (!response.ok) {
|
|
1420
1416
|
if (response.status === 401) {
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
...resource && { resource }
|
|
1427
|
-
}));
|
|
1417
|
+
return this.authorizationFailure(
|
|
1418
|
+
`Failed to delete key ${JSON.stringify(key)}`,
|
|
1419
|
+
response,
|
|
1420
|
+
await response.text()
|
|
1421
|
+
);
|
|
1428
1422
|
}
|
|
1429
1423
|
if (response.status === 404) {
|
|
1430
1424
|
return this.classifyNotFound(response, key);
|
|
@@ -1433,7 +1427,7 @@ var KVService = class extends BaseService {
|
|
|
1433
1427
|
if (response.status === 412) {
|
|
1434
1428
|
return err(serviceError(
|
|
1435
1429
|
ErrorCodes.KV_PRECONDITION_FAILED,
|
|
1436
|
-
`KV precondition failed for key
|
|
1430
|
+
`KV precondition failed for key ${JSON.stringify(key)}`,
|
|
1437
1431
|
"kv",
|
|
1438
1432
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1439
1433
|
));
|
|
@@ -1441,7 +1435,7 @@ var KVService = class extends BaseService {
|
|
|
1441
1435
|
if (response.status === 503 && options?.ifMatch !== void 0) {
|
|
1442
1436
|
return err(serviceError(
|
|
1443
1437
|
ErrorCodes.KV_CONFLICT,
|
|
1444
|
-
`Concurrent KV delete conflicted for key
|
|
1438
|
+
`Concurrent KV delete conflicted for key ${JSON.stringify(key)}`,
|
|
1445
1439
|
"kv",
|
|
1446
1440
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1447
1441
|
));
|
|
@@ -1449,7 +1443,7 @@ var KVService = class extends BaseService {
|
|
|
1449
1443
|
return err(
|
|
1450
1444
|
serviceError(
|
|
1451
1445
|
ErrorCodes.NETWORK_ERROR,
|
|
1452
|
-
`Failed to delete key
|
|
1446
|
+
`Failed to delete key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
1453
1447
|
"kv",
|
|
1454
1448
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1455
1449
|
)
|
|
@@ -1482,13 +1476,11 @@ var KVService = class extends BaseService {
|
|
|
1482
1476
|
);
|
|
1483
1477
|
if (!response.ok) {
|
|
1484
1478
|
if (response.status === 401) {
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
...resource && { resource }
|
|
1491
|
-
}));
|
|
1479
|
+
return this.authorizationFailure(
|
|
1480
|
+
`Failed to get metadata for key ${JSON.stringify(key)}`,
|
|
1481
|
+
response,
|
|
1482
|
+
await response.text()
|
|
1483
|
+
);
|
|
1492
1484
|
}
|
|
1493
1485
|
if (response.status === 404) {
|
|
1494
1486
|
return this.classifyNotFound(response, key);
|
|
@@ -1497,7 +1489,7 @@ var KVService = class extends BaseService {
|
|
|
1497
1489
|
return err(
|
|
1498
1490
|
serviceError(
|
|
1499
1491
|
ErrorCodes.NETWORK_ERROR,
|
|
1500
|
-
`Failed to get metadata for key
|
|
1492
|
+
`Failed to get metadata for key ${JSON.stringify(key)}: ${response.status} - ${errorText}`,
|
|
1501
1493
|
"kv",
|
|
1502
1494
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1503
1495
|
)
|