@tinycloud/sdk-services 3.1.0-beta.9 → 3.1.0
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/index.cjs +551 -171
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +103 -12
- package/dist/index.d.ts +103 -12
- package/dist/index.js +551 -171
- package/dist/index.js.map +1 -1
- package/dist/kv/index.cjs +56 -11
- package/dist/kv/index.cjs.map +1 -1
- package/dist/kv/index.d.cts +12 -2
- package/dist/kv/index.d.ts +12 -2
- package/dist/kv/index.js +56 -11
- package/dist/kv/index.js.map +1 -1
- package/package.json +3 -3
package/dist/kv/index.cjs
CHANGED
|
@@ -830,6 +830,24 @@ var MAX_KV_BATCH_READ_ITEMS = 100;
|
|
|
830
830
|
function isJsonObject(value) {
|
|
831
831
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
832
832
|
}
|
|
833
|
+
var pathByteEncoder = new TextEncoder();
|
|
834
|
+
function comparePathsByBytes(a, b) {
|
|
835
|
+
const left = pathByteEncoder.encode(a);
|
|
836
|
+
const right = pathByteEncoder.encode(b);
|
|
837
|
+
const length = Math.min(left.length, right.length);
|
|
838
|
+
for (let index = 0; index < length; index++) {
|
|
839
|
+
if (left[index] !== right[index]) {
|
|
840
|
+
return left[index] - right[index];
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
return left.length - right.length;
|
|
844
|
+
}
|
|
845
|
+
var REVOKED_BODY = /^(?:Invalid invocation: )?delegation-(?:(revoked): [A-Za-z0-9]+|(ancestor-revoked): ancestor=[A-Za-z0-9]+ invoked=[A-Za-z0-9]+)$/;
|
|
846
|
+
function revocationCodeOf(body) {
|
|
847
|
+
const match = REVOKED_BODY.exec(body.trim());
|
|
848
|
+
if (match === null) return void 0;
|
|
849
|
+
return match[1] !== void 0 ? ErrorCodes.AUTH_DELEGATION_REVOKED : ErrorCodes.AUTH_DELEGATION_ANCESTOR_REVOKED;
|
|
850
|
+
}
|
|
833
851
|
function encodeKvBatchPartName(path) {
|
|
834
852
|
return encodeURIComponent(path).replace(
|
|
835
853
|
/[!'()*]/g,
|
|
@@ -1057,15 +1075,25 @@ var KVService = class extends BaseService {
|
|
|
1057
1075
|
)?.[1];
|
|
1058
1076
|
return contentType?.includes("application/json") ? JSON.parse(text) : text;
|
|
1059
1077
|
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Validate a batch read response and return its items in the caller's
|
|
1080
|
+
* request order. The node flattens invocation abilities from a `BTreeMap`,
|
|
1081
|
+
* so results arrive sorted by UTF-8 byte order of the path, not in request
|
|
1082
|
+
* order. Items that carry their path in `key` are matched by path; if no
|
|
1083
|
+
* item carries a key, items are assumed to be in the node's byte-sorted
|
|
1084
|
+
* order and the request is aligned the same way. Any mix of keyed and
|
|
1085
|
+
* keyless items, a missing requested path, an unrequested path, or a
|
|
1086
|
+
* malformed item fails closed (returns undefined).
|
|
1087
|
+
*/
|
|
1060
1088
|
normalizeBatchReadResponse(data, paths, requireData) {
|
|
1061
1089
|
if (!data || typeof data !== "object") return void 0;
|
|
1062
1090
|
const response = data;
|
|
1063
|
-
|
|
1091
|
+
const items = response.results;
|
|
1092
|
+
if (!Array.isArray(items) || items.length !== paths.length) {
|
|
1064
1093
|
return void 0;
|
|
1065
1094
|
}
|
|
1066
|
-
for (
|
|
1067
|
-
|
|
1068
|
-
if (!item || typeof item !== "object" || item.key !== paths[index] || typeof item.ok !== "boolean") {
|
|
1095
|
+
for (const item of items) {
|
|
1096
|
+
if (!item || typeof item !== "object" || typeof item.ok !== "boolean") {
|
|
1069
1097
|
return void 0;
|
|
1070
1098
|
}
|
|
1071
1099
|
if (item.ok && (!item.headers || typeof item.headers !== "object" || Object.values(item.headers).some((value) => typeof value !== "string") || requireData && typeof item.dataBase64 !== "string")) {
|
|
@@ -1075,7 +1103,24 @@ var KVService = class extends BaseService {
|
|
|
1075
1103
|
return void 0;
|
|
1076
1104
|
}
|
|
1077
1105
|
}
|
|
1078
|
-
|
|
1106
|
+
if (items.every((item) => typeof item.key === "string")) {
|
|
1107
|
+
const byPath = new Map(items.map((item) => [item.key, item]));
|
|
1108
|
+
if (byPath.size !== items.length) return void 0;
|
|
1109
|
+
const aligned2 = [];
|
|
1110
|
+
for (const path of paths) {
|
|
1111
|
+
const item = byPath.get(path);
|
|
1112
|
+
if (!item) return void 0;
|
|
1113
|
+
aligned2.push(item);
|
|
1114
|
+
}
|
|
1115
|
+
return aligned2;
|
|
1116
|
+
}
|
|
1117
|
+
if (items.some((item) => item.key !== void 0)) return void 0;
|
|
1118
|
+
const requestOrder = paths.map((_, index) => index).sort((a, b) => comparePathsByBytes(paths[a], paths[b]));
|
|
1119
|
+
const aligned = new Array(items.length);
|
|
1120
|
+
for (let position = 0; position < requestOrder.length; position++) {
|
|
1121
|
+
aligned[requestOrder[position]] = items[position];
|
|
1122
|
+
}
|
|
1123
|
+
return aligned;
|
|
1079
1124
|
}
|
|
1080
1125
|
async batchRead(keys, action, options) {
|
|
1081
1126
|
if (!this.requireAuth()) return err(authRequiredError("kv"));
|
|
@@ -1168,19 +1213,19 @@ var KVService = class extends BaseService {
|
|
|
1168
1213
|
{ meta: { status: response.status, statusText: response.statusText } }
|
|
1169
1214
|
));
|
|
1170
1215
|
}
|
|
1171
|
-
const
|
|
1216
|
+
const items = this.normalizeBatchReadResponse(
|
|
1172
1217
|
await response.json(),
|
|
1173
1218
|
paths,
|
|
1174
1219
|
action === KVAction.GET
|
|
1175
1220
|
);
|
|
1176
|
-
if (!
|
|
1221
|
+
if (!items) {
|
|
1177
1222
|
return err(serviceError(
|
|
1178
1223
|
ErrorCodes.NETWORK_ERROR,
|
|
1179
1224
|
"KV batch read response did not match the requested keys",
|
|
1180
1225
|
"kv"
|
|
1181
1226
|
));
|
|
1182
1227
|
}
|
|
1183
|
-
const results =
|
|
1228
|
+
const results = items.map((item, index) => {
|
|
1184
1229
|
if (!item.ok) {
|
|
1185
1230
|
return {
|
|
1186
1231
|
key: keys[index],
|
|
@@ -1814,8 +1859,8 @@ var KVService = class extends BaseService {
|
|
|
1814
1859
|
}
|
|
1815
1860
|
/**
|
|
1816
1861
|
* Map a failed `kv/sync` response. 410 and the retention 403 carry
|
|
1817
|
-
* `{"error":{"code","reason"}}`; a revoked grant is a 401 whose
|
|
1818
|
-
*
|
|
1862
|
+
* `{"error":{"code","reason"}}`; a revoked grant is a 401 whose whole body
|
|
1863
|
+
* is the node's revocation error (see REVOKED_BODY). A body read that
|
|
1819
1864
|
* fails because the request was cancelled or timed out rethrows, so the
|
|
1820
1865
|
* caller sees `ABORTED`/`TIMEOUT` rather than a mapped status.
|
|
1821
1866
|
*/
|
|
@@ -1860,7 +1905,7 @@ var KVService = class extends BaseService {
|
|
|
1860
1905
|
));
|
|
1861
1906
|
}
|
|
1862
1907
|
if (response.status === 401) {
|
|
1863
|
-
const revoked =
|
|
1908
|
+
const revoked = revocationCodeOf(errorText);
|
|
1864
1909
|
if (revoked !== void 0) {
|
|
1865
1910
|
return err(serviceError(revoked, `${context}: 401 - ${errorText}`, "kv", { meta }));
|
|
1866
1911
|
}
|