@tinycloud/sdk-services 3.1.0-beta.2 → 3.1.0-beta.7
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/{BaseService-BhpVpA9b.d.cts → BaseService-C8zRy0ww.d.cts} +73 -1
- package/dist/{BaseService-CuV-ZVPs.d.ts → BaseService-DU-lE-Qx.d.ts} +73 -1
- package/dist/encryption/index.cjs +191 -100
- package/dist/encryption/index.cjs.map +1 -1
- package/dist/encryption/index.d.cts +1 -1
- package/dist/encryption/index.d.ts +1 -1
- package/dist/encryption/index.js +191 -100
- package/dist/encryption/index.js.map +1 -1
- package/dist/index.cjs +446 -177
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -39
- package/dist/index.d.ts +29 -39
- package/dist/index.js +426 -159
- package/dist/index.js.map +1 -1
- package/dist/kv/index.cjs +333 -35
- package/dist/kv/index.cjs.map +1 -1
- package/dist/kv/index.d.cts +26 -12
- package/dist/kv/index.d.ts +26 -12
- package/dist/kv/index.js +333 -35
- package/dist/kv/index.js.map +1 -1
- package/dist/sql/index.cjs +139 -30
- package/dist/sql/index.cjs.map +1 -1
- package/dist/sql/index.d.cts +5 -2
- package/dist/sql/index.d.ts +5 -2
- package/dist/sql/index.js +130 -21
- package/dist/sql/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -116,6 +116,7 @@ __export(src_exports, {
|
|
|
116
116
|
ok: () => ok,
|
|
117
117
|
openWrappedKey: () => openWrappedKey,
|
|
118
118
|
parseAuthError: () => parseAuthError,
|
|
119
|
+
parseCapabilityResource: () => parseCapabilityResource,
|
|
119
120
|
parseNetworkId: () => parseNetworkId,
|
|
120
121
|
parsePermissionHint: () => parsePermissionHint,
|
|
121
122
|
parsePermissionHintFromErrorText: () => parsePermissionHintFromErrorText,
|
|
@@ -141,6 +142,7 @@ __export(src_exports, {
|
|
|
141
142
|
validateServiceResponseEvent: () => validateServiceResponseEvent,
|
|
142
143
|
validateServiceSession: () => validateServiceSession,
|
|
143
144
|
validateTelemetrySpanEvent: () => validateTelemetrySpanEvent,
|
|
145
|
+
validatedCapabilityOf: () => validatedCapabilityOf,
|
|
144
146
|
verifyDecryptResponse: () => verifyDecryptResponse,
|
|
145
147
|
wrapError: () => wrapError
|
|
146
148
|
});
|
|
@@ -1044,6 +1046,106 @@ var ServiceContext = class {
|
|
|
1044
1046
|
}
|
|
1045
1047
|
};
|
|
1046
1048
|
|
|
1049
|
+
// src/errors.ts
|
|
1050
|
+
var import_bootstrap = require("@tinycloud/bootstrap");
|
|
1051
|
+
|
|
1052
|
+
// src/encryption/networkId.ts
|
|
1053
|
+
var URN_PREFIX = "urn:tinycloud:encryption:";
|
|
1054
|
+
var NETWORK_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
1055
|
+
var PKH_EIP155_DID_RE = /^did:pkh:eip155:(\d+):(0x[a-fA-F0-9]{40})$/;
|
|
1056
|
+
var NetworkIdError = class extends Error {
|
|
1057
|
+
constructor(message) {
|
|
1058
|
+
super(message);
|
|
1059
|
+
this.name = "NetworkIdError";
|
|
1060
|
+
}
|
|
1061
|
+
};
|
|
1062
|
+
function parseNetworkId(networkId) {
|
|
1063
|
+
if (typeof networkId !== "string" || networkId.length === 0) {
|
|
1064
|
+
throw new NetworkIdError("networkId must be a non-empty string");
|
|
1065
|
+
}
|
|
1066
|
+
if (!networkId.startsWith(URN_PREFIX)) {
|
|
1067
|
+
throw new NetworkIdError(
|
|
1068
|
+
`networkId must start with ${URN_PREFIX} (got ${JSON.stringify(networkId)})`
|
|
1069
|
+
);
|
|
1070
|
+
}
|
|
1071
|
+
const body = networkId.slice(URN_PREFIX.length);
|
|
1072
|
+
const lastColon = body.lastIndexOf(":");
|
|
1073
|
+
if (lastColon <= 0 || lastColon === body.length - 1) {
|
|
1074
|
+
throw new NetworkIdError(
|
|
1075
|
+
`networkId missing ownerDid or name segment (got ${JSON.stringify(networkId)})`
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
1078
|
+
const ownerDid = body.slice(0, lastColon);
|
|
1079
|
+
const name = body.slice(lastColon + 1);
|
|
1080
|
+
if (!ownerDid.startsWith("did:")) {
|
|
1081
|
+
throw new NetworkIdError(
|
|
1082
|
+
`networkId ownerDid must be a DID (got ${JSON.stringify(ownerDid)})`
|
|
1083
|
+
);
|
|
1084
|
+
}
|
|
1085
|
+
const didParts = ownerDid.split(":");
|
|
1086
|
+
if (didParts.length < 3 || didParts.some((p) => p.length === 0)) {
|
|
1087
|
+
throw new NetworkIdError(
|
|
1088
|
+
`networkId ownerDid is not a well-formed DID (got ${JSON.stringify(ownerDid)})`
|
|
1089
|
+
);
|
|
1090
|
+
}
|
|
1091
|
+
if (!NETWORK_NAME_RE.test(name)) {
|
|
1092
|
+
throw new NetworkIdError(
|
|
1093
|
+
`networkId name ${JSON.stringify(name)} must match ${NETWORK_NAME_RE.source}`
|
|
1094
|
+
);
|
|
1095
|
+
}
|
|
1096
|
+
return { networkId, ownerDid, name };
|
|
1097
|
+
}
|
|
1098
|
+
function buildNetworkId(ownerDid, name) {
|
|
1099
|
+
if (typeof ownerDid !== "string" || !ownerDid.startsWith("did:")) {
|
|
1100
|
+
throw new NetworkIdError("ownerDid must be a DID");
|
|
1101
|
+
}
|
|
1102
|
+
if (typeof name !== "string" || !NETWORK_NAME_RE.test(name)) {
|
|
1103
|
+
throw new NetworkIdError(
|
|
1104
|
+
`network name ${JSON.stringify(name)} must match ${NETWORK_NAME_RE.source}`
|
|
1105
|
+
);
|
|
1106
|
+
}
|
|
1107
|
+
const networkId = `${URN_PREFIX}${ownerDid}:${name}`;
|
|
1108
|
+
parseNetworkId(networkId);
|
|
1109
|
+
return networkId;
|
|
1110
|
+
}
|
|
1111
|
+
function isNetworkId(networkId) {
|
|
1112
|
+
if (typeof networkId !== "string") {
|
|
1113
|
+
return false;
|
|
1114
|
+
}
|
|
1115
|
+
try {
|
|
1116
|
+
parseNetworkId(networkId);
|
|
1117
|
+
return true;
|
|
1118
|
+
} catch {
|
|
1119
|
+
return false;
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
function parsePkhOwnerDid(ownerDid) {
|
|
1123
|
+
const match = ownerDid.match(PKH_EIP155_DID_RE);
|
|
1124
|
+
if (!match) return null;
|
|
1125
|
+
return {
|
|
1126
|
+
chainId: match[1],
|
|
1127
|
+
address: match[2].toLowerCase()
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
function ownerDidMatches(a, b) {
|
|
1131
|
+
const aPkh = parsePkhOwnerDid(a);
|
|
1132
|
+
const bPkh = parsePkhOwnerDid(b);
|
|
1133
|
+
if (aPkh && bPkh) {
|
|
1134
|
+
return aPkh.chainId === bPkh.chainId && aPkh.address === bPkh.address;
|
|
1135
|
+
}
|
|
1136
|
+
return a === b;
|
|
1137
|
+
}
|
|
1138
|
+
function networkDiscoveryKey(name) {
|
|
1139
|
+
if (!NETWORK_NAME_RE.test(name)) {
|
|
1140
|
+
throw new NetworkIdError(
|
|
1141
|
+
`network name ${JSON.stringify(name)} must match ${NETWORK_NAME_RE.source}`
|
|
1142
|
+
);
|
|
1143
|
+
}
|
|
1144
|
+
return `.well-known/encryption/network/${name}`;
|
|
1145
|
+
}
|
|
1146
|
+
var ENCRYPTION_NETWORK_URN_PREFIX = URN_PREFIX;
|
|
1147
|
+
var NETWORK_NAME_PATTERN = NETWORK_NAME_RE;
|
|
1148
|
+
|
|
1047
1149
|
// src/errors.ts
|
|
1048
1150
|
function parsePermissionHint(value) {
|
|
1049
1151
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
@@ -1103,11 +1205,31 @@ function networkError(service, message, cause) {
|
|
|
1103
1205
|
cause
|
|
1104
1206
|
};
|
|
1105
1207
|
}
|
|
1106
|
-
|
|
1208
|
+
var RequestTimeoutError = class extends Error {
|
|
1209
|
+
constructor(timeoutMs) {
|
|
1210
|
+
super(`Request timed out after ${timeoutMs}ms.`);
|
|
1211
|
+
this.name = "TimeoutError";
|
|
1212
|
+
this.timeoutMs = timeoutMs;
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
function isRequestTimeoutError(error) {
|
|
1216
|
+
return error instanceof RequestTimeoutError || error instanceof Error && error.name === "TimeoutError" && typeof error.timeoutMs === "number";
|
|
1217
|
+
}
|
|
1218
|
+
function timeoutError(service, timeoutMs, cause) {
|
|
1219
|
+
if (timeoutMs === void 0) {
|
|
1220
|
+
return {
|
|
1221
|
+
code: ErrorCodes.TIMEOUT,
|
|
1222
|
+
message: "Request timed out.",
|
|
1223
|
+
service,
|
|
1224
|
+
...cause === void 0 ? {} : { cause }
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1107
1227
|
return {
|
|
1108
1228
|
code: ErrorCodes.TIMEOUT,
|
|
1109
|
-
message:
|
|
1110
|
-
service
|
|
1229
|
+
message: `Request timed out after ${timeoutMs}ms.`,
|
|
1230
|
+
service,
|
|
1231
|
+
...cause === void 0 ? {} : { cause },
|
|
1232
|
+
meta: { timeoutMs }
|
|
1111
1233
|
};
|
|
1112
1234
|
}
|
|
1113
1235
|
function abortedError(service) {
|
|
@@ -1141,6 +1263,70 @@ function parseAuthError(responseText) {
|
|
|
1141
1263
|
function authUnauthorizedError(service, message, meta) {
|
|
1142
1264
|
return serviceError(ErrorCodes.AUTH_UNAUTHORIZED, message, service, { meta });
|
|
1143
1265
|
}
|
|
1266
|
+
var grantableActions = new Set(
|
|
1267
|
+
import_bootstrap.CAPABILITY_REGISTRY.map(({ urn }) => urn).filter((urn) => !urn.endsWith("/*"))
|
|
1268
|
+
);
|
|
1269
|
+
var capabilityServices = new Set(
|
|
1270
|
+
import_bootstrap.CAPABILITY_REGISTRY.map(({ service }) => service.slice("tinycloud.".length))
|
|
1271
|
+
);
|
|
1272
|
+
function parseCapabilityResource(resource, service) {
|
|
1273
|
+
if (resource.length === 0 || resource.length > 1024 || !capabilityServices.has(service) || /[\s\p{C}*#]/u.test(resource) || resource.includes("://")) return void 0;
|
|
1274
|
+
const segments = resource.split("/");
|
|
1275
|
+
if (!/^tinycloud:[A-Za-z0-9][A-Za-z0-9:._-]*$/.test(segments[0])) return void 0;
|
|
1276
|
+
const serviceIndex = segments.findIndex(
|
|
1277
|
+
(segment, index) => index > 0 && capabilityServices.has(segment)
|
|
1278
|
+
);
|
|
1279
|
+
if (serviceIndex < 1 || segments[serviceIndex] !== service) return void 0;
|
|
1280
|
+
if (segments.slice(1, serviceIndex).some(
|
|
1281
|
+
(segment) => segment.length === 0 || segment === "." || segment === ".."
|
|
1282
|
+
)) return void 0;
|
|
1283
|
+
const pathSegments = segments.slice(serviceIndex + 1);
|
|
1284
|
+
if (pathSegments.some((segment) => segment === "." || segment === "..")) return void 0;
|
|
1285
|
+
if (service !== "kv" && (pathSegments.length === 0 || pathSegments[pathSegments.length - 1] === "")) return void 0;
|
|
1286
|
+
return {
|
|
1287
|
+
space: segments.slice(0, serviceIndex).join("/"),
|
|
1288
|
+
path: pathSegments.join("/")
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
function safeCapabilityResource(value, service, action) {
|
|
1292
|
+
if (typeof value !== "string" || value.length === 0 || value.length > 1024) return false;
|
|
1293
|
+
if (service === "encryption" && value.startsWith("urn:tinycloud:encryption:")) {
|
|
1294
|
+
if (!/^[A-Za-z0-9_][A-Za-z0-9_.:/-]*$/.test(value) || value.includes("//") || value.split("/").some((segment) => segment === "." || segment === "..")) return false;
|
|
1295
|
+
try {
|
|
1296
|
+
parseNetworkId(value);
|
|
1297
|
+
return true;
|
|
1298
|
+
} catch {
|
|
1299
|
+
return false;
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
const parsed = parseCapabilityResource(value, service);
|
|
1303
|
+
return parsed !== void 0 && (!parsed.path.endsWith("/") || service === "kv" && action === "tinycloud.kv/list") && (parsed.path !== "" || service === "kv" && action === "tinycloud.kv/list");
|
|
1304
|
+
}
|
|
1305
|
+
function validatedCapabilityOf(error) {
|
|
1306
|
+
const verdict = authorizationVerdictOf(error);
|
|
1307
|
+
if (verdict !== "unauthenticated" && verdict !== "forbidden") return void 0;
|
|
1308
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1309
|
+
let node = error;
|
|
1310
|
+
for (let depth = 0; depth < MAX_CAUSE_DEPTH && typeof node === "object" && node !== null && !seen.has(node); depth += 1) {
|
|
1311
|
+
seen.add(node);
|
|
1312
|
+
const record = node;
|
|
1313
|
+
const status = errorStatusOf(record);
|
|
1314
|
+
const meta = record.meta;
|
|
1315
|
+
if ((status === 401 || status === 403 || status === void 0 && record.code === ErrorCodes.AUTH_UNAUTHORIZED) && typeof meta === "object" && meta !== null && !Array.isArray(meta)) {
|
|
1316
|
+
const metadata = meta;
|
|
1317
|
+
const { resource, requiredAction } = metadata;
|
|
1318
|
+
if (typeof requiredAction === "string" && grantableActions.has(requiredAction)) {
|
|
1319
|
+
const actionService = requiredAction.slice("tinycloud.".length, requiredAction.indexOf("/"));
|
|
1320
|
+
const explicitService = record.service === void 0 ? metadata.service : record.service;
|
|
1321
|
+
if (safeCapabilityResource(resource, actionService, requiredAction) && (explicitService === void 0 || explicitService === actionService || explicitService === `tinycloud.${actionService}`)) {
|
|
1322
|
+
return { resource, requiredAction };
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
node = record.cause;
|
|
1327
|
+
}
|
|
1328
|
+
return void 0;
|
|
1329
|
+
}
|
|
1144
1330
|
var MAX_CAUSE_DEPTH = 8;
|
|
1145
1331
|
function errorStatusOf(node) {
|
|
1146
1332
|
const meta = node.meta;
|
|
@@ -1207,6 +1393,9 @@ function isStorageFullError(error) {
|
|
|
1207
1393
|
}
|
|
1208
1394
|
function wrapError(service, error, defaultCode = ErrorCodes.NETWORK_ERROR) {
|
|
1209
1395
|
if (error instanceof Error) {
|
|
1396
|
+
if (isRequestTimeoutError(error)) {
|
|
1397
|
+
return timeoutError(service, error.timeoutMs, error);
|
|
1398
|
+
}
|
|
1210
1399
|
if (error.name === "AbortError") {
|
|
1211
1400
|
return abortedError(service);
|
|
1212
1401
|
}
|
|
@@ -1231,6 +1420,7 @@ function errorResult(error) {
|
|
|
1231
1420
|
}
|
|
1232
1421
|
|
|
1233
1422
|
// src/base/BaseService.ts
|
|
1423
|
+
var MAX_TIMER_DELAY_MS = 2147483647;
|
|
1234
1424
|
var BaseService = class {
|
|
1235
1425
|
constructor() {
|
|
1236
1426
|
/**
|
|
@@ -1411,6 +1601,64 @@ var BaseService = class {
|
|
|
1411
1601
|
}
|
|
1412
1602
|
return controller.signal;
|
|
1413
1603
|
}
|
|
1604
|
+
/**
|
|
1605
|
+
* Create the abort signal for one request, bounded by the request timeout.
|
|
1606
|
+
*
|
|
1607
|
+
* The signal aborts when the service signs out, the context aborts, the
|
|
1608
|
+
* caller's `signal` aborts, or the timeout elapses, whichever comes first.
|
|
1609
|
+
* A timeout aborts with a {@link RequestTimeoutError} (`TimeoutError`), which
|
|
1610
|
+
* `wrapError` maps to `ErrorCodes.TIMEOUT`; the other sources keep their own
|
|
1611
|
+
* reason (normally `AbortError`, mapped to `ErrorCodes.ABORTED`).
|
|
1612
|
+
*
|
|
1613
|
+
* The timeout is `timeoutMs` when given, otherwise `config.timeout`. Only a
|
|
1614
|
+
* positive, finite value (at most 2^31-1 ms) applies; `undefined`, `0`, and
|
|
1615
|
+
* `Infinity` mean no timeout, so a per-call `0` opts out of a configured one.
|
|
1616
|
+
*
|
|
1617
|
+
* Callers must call `dispose()` once the response body has been consumed,
|
|
1618
|
+
* which clears the timer and removes the listeners this adds to the
|
|
1619
|
+
* long-lived service and context signals.
|
|
1620
|
+
*
|
|
1621
|
+
* @param signal - The caller's abort signal for this request
|
|
1622
|
+
* @param timeoutMs - Per-request timeout override in milliseconds
|
|
1623
|
+
*/
|
|
1624
|
+
createRequestSignal(signal, timeoutMs) {
|
|
1625
|
+
const controller = new AbortController();
|
|
1626
|
+
const detachers = [];
|
|
1627
|
+
let timer;
|
|
1628
|
+
const dispose = () => {
|
|
1629
|
+
if (timer !== void 0) {
|
|
1630
|
+
clearTimeout(timer);
|
|
1631
|
+
timer = void 0;
|
|
1632
|
+
}
|
|
1633
|
+
for (const detach of detachers.splice(0)) {
|
|
1634
|
+
detach();
|
|
1635
|
+
}
|
|
1636
|
+
};
|
|
1637
|
+
const abort = (reason) => {
|
|
1638
|
+
dispose();
|
|
1639
|
+
controller.abort(reason);
|
|
1640
|
+
};
|
|
1641
|
+
const requestSignal = { signal: controller.signal, dispose };
|
|
1642
|
+
const parents = [
|
|
1643
|
+
this.abortController.signal,
|
|
1644
|
+
this.context?.abortSignal,
|
|
1645
|
+
signal
|
|
1646
|
+
].filter((parent) => parent !== void 0);
|
|
1647
|
+
for (const parent of parents) {
|
|
1648
|
+
if (parent.aborted) {
|
|
1649
|
+
abort(parent.reason);
|
|
1650
|
+
return requestSignal;
|
|
1651
|
+
}
|
|
1652
|
+
const onAbort = () => abort(parent.reason);
|
|
1653
|
+
parent.addEventListener("abort", onAbort, { once: true });
|
|
1654
|
+
detachers.push(() => parent.removeEventListener("abort", onAbort));
|
|
1655
|
+
}
|
|
1656
|
+
const timeout = timeoutMs ?? this._config.timeout;
|
|
1657
|
+
if (typeof timeout === "number" && timeout > 0 && timeout <= MAX_TIMER_DELAY_MS) {
|
|
1658
|
+
timer = setTimeout(() => abort(new RequestTimeoutError(timeout)), timeout);
|
|
1659
|
+
}
|
|
1660
|
+
return requestSignal;
|
|
1661
|
+
}
|
|
1414
1662
|
/**
|
|
1415
1663
|
* Wrap an operation with error handling and telemetry.
|
|
1416
1664
|
*
|
|
@@ -1671,7 +1919,7 @@ var KVService = class extends BaseService {
|
|
|
1671
1919
|
* @param path - Resource path
|
|
1672
1920
|
* @param action - KV action
|
|
1673
1921
|
* @param body - Optional request body
|
|
1674
|
-
* @param signal -
|
|
1922
|
+
* @param signal - Request signal from createRequestSignal()
|
|
1675
1923
|
* @returns Fetch response
|
|
1676
1924
|
*/
|
|
1677
1925
|
async invokeOperation(path, action, body, signal, extraHeaders) {
|
|
@@ -1687,7 +1935,7 @@ var KVService = class extends BaseService {
|
|
|
1687
1935
|
method: "POST",
|
|
1688
1936
|
headers: requestHeaders,
|
|
1689
1937
|
body,
|
|
1690
|
-
signal
|
|
1938
|
+
signal
|
|
1691
1939
|
});
|
|
1692
1940
|
}
|
|
1693
1941
|
/**
|
|
@@ -1864,6 +2112,7 @@ var KVService = class extends BaseService {
|
|
|
1864
2112
|
"kv"
|
|
1865
2113
|
));
|
|
1866
2114
|
}
|
|
2115
|
+
const request = this.createRequestSignal(options?.signal, options?.timeout);
|
|
1867
2116
|
try {
|
|
1868
2117
|
const session = this.context.session;
|
|
1869
2118
|
const invocationHeaders = this.context.invokeAny(
|
|
@@ -1885,15 +2134,17 @@ var KVService = class extends BaseService {
|
|
|
1885
2134
|
const response = await this.context.fetch(`${this.host}/invoke`, {
|
|
1886
2135
|
method: "POST",
|
|
1887
2136
|
headers,
|
|
1888
|
-
signal:
|
|
2137
|
+
signal: request.signal
|
|
1889
2138
|
});
|
|
1890
2139
|
if (!response.ok) {
|
|
1891
|
-
const errorText = await response.text();
|
|
2140
|
+
const errorText = response.status === 401 || response.status === 403 ? await this.readAuthorizationText(response) : await response.text();
|
|
1892
2141
|
if (response.status === 401 || response.status === 403) {
|
|
1893
2142
|
return this.authorizationFailure(
|
|
1894
2143
|
`Failed to batch read ${keys.length} key(s)`,
|
|
1895
2144
|
response,
|
|
1896
|
-
errorText
|
|
2145
|
+
errorText,
|
|
2146
|
+
paths,
|
|
2147
|
+
action
|
|
1897
2148
|
);
|
|
1898
2149
|
}
|
|
1899
2150
|
if (response.status === 413) {
|
|
@@ -1948,6 +2199,8 @@ var KVService = class extends BaseService {
|
|
|
1948
2199
|
return ok({ results, count: results.length });
|
|
1949
2200
|
} catch (error) {
|
|
1950
2201
|
return err(wrapError("kv", error));
|
|
2202
|
+
} finally {
|
|
2203
|
+
request.dispose();
|
|
1951
2204
|
}
|
|
1952
2205
|
}
|
|
1953
2206
|
/**
|
|
@@ -1983,7 +2236,7 @@ var KVService = class extends BaseService {
|
|
|
1983
2236
|
return text;
|
|
1984
2237
|
}
|
|
1985
2238
|
}
|
|
1986
|
-
async createSignedReadUrlError(response, key) {
|
|
2239
|
+
async createSignedReadUrlError(response, key, path) {
|
|
1987
2240
|
let errorText = response.statusText;
|
|
1988
2241
|
try {
|
|
1989
2242
|
const text = await response.text();
|
|
@@ -1996,7 +2249,9 @@ var KVService = class extends BaseService {
|
|
|
1996
2249
|
return this.authorizationFailure(
|
|
1997
2250
|
`Failed to create signed read URL for key ${JSON.stringify(key)}`,
|
|
1998
2251
|
response,
|
|
1999
|
-
errorText
|
|
2252
|
+
errorText,
|
|
2253
|
+
[path],
|
|
2254
|
+
KVAction.GET
|
|
2000
2255
|
);
|
|
2001
2256
|
}
|
|
2002
2257
|
const code = response.status === 400 ? ErrorCodes.INVALID_INPUT : ErrorCodes.NETWORK_ERROR;
|
|
@@ -2009,21 +2264,42 @@ var KVService = class extends BaseService {
|
|
|
2009
2264
|
)
|
|
2010
2265
|
);
|
|
2011
2266
|
}
|
|
2267
|
+
/** A known 401/403 keeps its typed status even if reading its body fails. */
|
|
2268
|
+
async readAuthorizationText(response) {
|
|
2269
|
+
try {
|
|
2270
|
+
return await response.text();
|
|
2271
|
+
} catch {
|
|
2272
|
+
return "";
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2012
2275
|
/**
|
|
2013
2276
|
* AUTH_UNAUTHORIZED for a 401/403 response. The message keeps the HTTP
|
|
2014
2277
|
* status and the server text (`<context>: <status> - <text>`, the same
|
|
2015
2278
|
* shape as every other KV failure) so callers that rethrow only the message
|
|
2016
2279
|
* still see the status; `meta.status` carries it for typed callers.
|
|
2017
|
-
*
|
|
2280
|
+
* Server hints must match the requested path/action (whether the node sends
|
|
2281
|
+
* a relative path or full resource); metadata uses only the request-derived
|
|
2282
|
+
* canonical resource under the authenticated session's space.
|
|
2018
2283
|
*/
|
|
2019
|
-
authorizationFailure(context, response, errorText, extraMeta = {}) {
|
|
2284
|
+
authorizationFailure(context, response, errorText, paths, expectedAction, extraMeta = {}) {
|
|
2020
2285
|
const { resource, action } = parseAuthError(errorText);
|
|
2286
|
+
const requestedPath = paths.find(
|
|
2287
|
+
(path) => resource === path || resource === `${this.context.session.spaceId}/kv/${path}`
|
|
2288
|
+
);
|
|
2289
|
+
const capability = requestedPath !== void 0 && action === expectedAction ? validatedCapabilityOf({
|
|
2290
|
+
service: "kv",
|
|
2291
|
+
code: ErrorCodes.AUTH_UNAUTHORIZED,
|
|
2292
|
+
meta: {
|
|
2293
|
+
status: response.status,
|
|
2294
|
+
resource: `${this.context.session.spaceId}/kv/${requestedPath}`,
|
|
2295
|
+
requiredAction: action
|
|
2296
|
+
}
|
|
2297
|
+
}) : void 0;
|
|
2021
2298
|
const detail = errorText.trim().length > 0 ? errorText : response.statusText || "authorization failed";
|
|
2022
2299
|
return err(authUnauthorizedError("kv", `${context}: ${response.status} - ${detail}`, {
|
|
2023
2300
|
status: response.status,
|
|
2024
|
-
...
|
|
2025
|
-
...
|
|
2026
|
-
...extraMeta
|
|
2301
|
+
...extraMeta,
|
|
2302
|
+
...capability
|
|
2027
2303
|
}));
|
|
2028
2304
|
}
|
|
2029
2305
|
normalizeSignedReadUrlResponse(data) {
|
|
@@ -2057,23 +2333,35 @@ var KVService = class extends BaseService {
|
|
|
2057
2333
|
));
|
|
2058
2334
|
}
|
|
2059
2335
|
const path = this.getFullPath(key, options?.prefix);
|
|
2336
|
+
const request = this.createRequestSignal(options?.signal, options?.timeout);
|
|
2060
2337
|
try {
|
|
2061
2338
|
const response = await this.invokeOperation(
|
|
2062
2339
|
path,
|
|
2063
2340
|
KVAction.GET,
|
|
2064
2341
|
void 0,
|
|
2065
|
-
|
|
2342
|
+
request.signal,
|
|
2066
2343
|
options?.maxResponseBytes === void 0 ? void 0 : { "x-tinycloud-max-response-bytes": String(options.maxResponseBytes) }
|
|
2067
2344
|
);
|
|
2068
2345
|
if (!response.ok) {
|
|
2069
2346
|
if (response.status === 401 || response.status === 403) {
|
|
2070
|
-
const errorText2 = await
|
|
2347
|
+
const errorText2 = await this.readAuthorizationText(response);
|
|
2071
2348
|
const permissionHint = parsePermissionHintFromErrorText(errorText2);
|
|
2349
|
+
const structuredCapability = permissionHint?.service === "tinycloud.kv" && permissionHint.space === this.context.session.spaceId && permissionHint.path === path ? validatedCapabilityOf({
|
|
2350
|
+
service: "kv",
|
|
2351
|
+
code: ErrorCodes.AUTH_UNAUTHORIZED,
|
|
2352
|
+
meta: {
|
|
2353
|
+
status: response.status,
|
|
2354
|
+
resource: `${this.context.session.spaceId}/kv/${path}`,
|
|
2355
|
+
requiredAction: KVAction.GET
|
|
2356
|
+
}
|
|
2357
|
+
}) : void 0;
|
|
2072
2358
|
return this.authorizationFailure(
|
|
2073
2359
|
`Failed to get key ${JSON.stringify(key)}`,
|
|
2074
2360
|
response,
|
|
2075
2361
|
errorText2,
|
|
2076
|
-
|
|
2362
|
+
[path],
|
|
2363
|
+
KVAction.GET,
|
|
2364
|
+
structuredCapability ? { permissionHint, ...structuredCapability } : {}
|
|
2077
2365
|
);
|
|
2078
2366
|
}
|
|
2079
2367
|
if (response.status === 404) {
|
|
@@ -2108,6 +2396,8 @@ var KVService = class extends BaseService {
|
|
|
2108
2396
|
});
|
|
2109
2397
|
} catch (error) {
|
|
2110
2398
|
return err(wrapError("kv", error));
|
|
2399
|
+
} finally {
|
|
2400
|
+
request.dispose();
|
|
2111
2401
|
}
|
|
2112
2402
|
});
|
|
2113
2403
|
}
|
|
@@ -2135,12 +2425,13 @@ var KVService = class extends BaseService {
|
|
|
2135
2425
|
}
|
|
2136
2426
|
const path = this.getFullPath(key, options?.prefix);
|
|
2137
2427
|
const body = this.serializePutValue(value, options?.contentType);
|
|
2428
|
+
const request = this.createRequestSignal(options?.signal, options?.timeout);
|
|
2138
2429
|
try {
|
|
2139
2430
|
const response = await this.invokeOperation(
|
|
2140
2431
|
path,
|
|
2141
2432
|
KVAction.PUT,
|
|
2142
2433
|
body,
|
|
2143
|
-
|
|
2434
|
+
request.signal,
|
|
2144
2435
|
{
|
|
2145
2436
|
...options?.ifMatch === void 0 ? {} : { "if-match": options.ifMatch },
|
|
2146
2437
|
...options?.ifNoneMatch === void 0 ? {} : { "if-none-match": options.ifNoneMatch }
|
|
@@ -2150,7 +2441,9 @@ var KVService = class extends BaseService {
|
|
|
2150
2441
|
return this.authorizationFailure(
|
|
2151
2442
|
`Failed to put key ${JSON.stringify(key)}`,
|
|
2152
2443
|
response,
|
|
2153
|
-
await
|
|
2444
|
+
await this.readAuthorizationText(response),
|
|
2445
|
+
[path],
|
|
2446
|
+
KVAction.PUT
|
|
2154
2447
|
);
|
|
2155
2448
|
}
|
|
2156
2449
|
if (!response.ok) {
|
|
@@ -2194,6 +2487,8 @@ var KVService = class extends BaseService {
|
|
|
2194
2487
|
});
|
|
2195
2488
|
} catch (error) {
|
|
2196
2489
|
return err(wrapError("kv", error));
|
|
2490
|
+
} finally {
|
|
2491
|
+
request.dispose();
|
|
2197
2492
|
}
|
|
2198
2493
|
});
|
|
2199
2494
|
}
|
|
@@ -2233,6 +2528,7 @@ var KVService = class extends BaseService {
|
|
|
2233
2528
|
seen.add(path);
|
|
2234
2529
|
}
|
|
2235
2530
|
let requestMayHaveDispatched = false;
|
|
2531
|
+
const request = this.createRequestSignal(options?.signal, options?.timeout);
|
|
2236
2532
|
try {
|
|
2237
2533
|
const body = new FormData();
|
|
2238
2534
|
for (let index = 0; index < items.length; index++) {
|
|
@@ -2255,7 +2551,7 @@ var KVService = class extends BaseService {
|
|
|
2255
2551
|
method: "POST",
|
|
2256
2552
|
headers,
|
|
2257
2553
|
body,
|
|
2258
|
-
signal:
|
|
2554
|
+
signal: request.signal
|
|
2259
2555
|
};
|
|
2260
2556
|
const fetchFn = this.context.fetch;
|
|
2261
2557
|
requestMayHaveDispatched = true;
|
|
@@ -2279,7 +2575,9 @@ var KVService = class extends BaseService {
|
|
|
2279
2575
|
return this.authorizationFailure(
|
|
2280
2576
|
`Failed to batch put ${items.length} key(s)`,
|
|
2281
2577
|
response,
|
|
2282
|
-
errorText
|
|
2578
|
+
errorText,
|
|
2579
|
+
paths,
|
|
2580
|
+
KVAction.PUT
|
|
2283
2581
|
);
|
|
2284
2582
|
}
|
|
2285
2583
|
const quotaError = this.handleQuotaErrorResponse(
|
|
@@ -2304,14 +2602,16 @@ var KVService = class extends BaseService {
|
|
|
2304
2602
|
rawBody = await response.json();
|
|
2305
2603
|
} catch (jsonError) {
|
|
2306
2604
|
const cause = jsonError instanceof Error ? jsonError : new Error(String(jsonError));
|
|
2605
|
+
const timedOut = isRequestTimeoutError(cause);
|
|
2307
2606
|
return err(
|
|
2308
2607
|
serviceError(
|
|
2309
|
-
ErrorCodes.NETWORK_ERROR,
|
|
2310
|
-
`KV batchPut response was not valid JSON: ${cause.message}`,
|
|
2608
|
+
timedOut ? ErrorCodes.TIMEOUT : ErrorCodes.NETWORK_ERROR,
|
|
2609
|
+
timedOut ? `KV batchPut response body did not arrive in time: ${cause.message}` : `KV batchPut response was not valid JSON: ${cause.message}`,
|
|
2311
2610
|
"kv",
|
|
2312
2611
|
{
|
|
2313
2612
|
cause,
|
|
2314
2613
|
meta: {
|
|
2614
|
+
...timedOut ? { timeoutMs: cause.timeoutMs } : {},
|
|
2315
2615
|
requestMayHaveDispatched: true,
|
|
2316
2616
|
responseReceived: true,
|
|
2317
2617
|
status: response.status,
|
|
@@ -2366,6 +2666,8 @@ var KVService = class extends BaseService {
|
|
|
2366
2666
|
...wrapped,
|
|
2367
2667
|
meta: { ...wrapped.meta, requestMayHaveDispatched }
|
|
2368
2668
|
});
|
|
2669
|
+
} finally {
|
|
2670
|
+
request.dispose();
|
|
2369
2671
|
}
|
|
2370
2672
|
});
|
|
2371
2673
|
}
|
|
@@ -2388,23 +2690,26 @@ var KVService = class extends BaseService {
|
|
|
2388
2690
|
if (options?.path) {
|
|
2389
2691
|
listPath = listPath ? `${listPath}/${options.path}` : options.path;
|
|
2390
2692
|
}
|
|
2693
|
+
const request = this.createRequestSignal(options?.signal, options?.timeout);
|
|
2391
2694
|
try {
|
|
2392
2695
|
const response = await this.invokeOperation(
|
|
2393
2696
|
listPath,
|
|
2394
2697
|
KVAction.LIST,
|
|
2395
2698
|
void 0,
|
|
2396
|
-
|
|
2699
|
+
request.signal,
|
|
2397
2700
|
options?.limit === void 0 && options?.cursor === void 0 ? void 0 : {
|
|
2398
2701
|
...options?.limit === void 0 ? {} : { "x-tinycloud-limit": String(options.limit) },
|
|
2399
2702
|
...options?.cursor === void 0 ? {} : { "x-tinycloud-cursor": options.cursor }
|
|
2400
2703
|
}
|
|
2401
2704
|
);
|
|
2402
2705
|
if (!response.ok) {
|
|
2403
|
-
if (response.status === 401) {
|
|
2706
|
+
if (response.status === 401 || response.status === 403) {
|
|
2404
2707
|
return this.authorizationFailure(
|
|
2405
2708
|
"Failed to list keys",
|
|
2406
2709
|
response,
|
|
2407
|
-
await
|
|
2710
|
+
await this.readAuthorizationText(response),
|
|
2711
|
+
[listPath],
|
|
2712
|
+
KVAction.LIST
|
|
2408
2713
|
);
|
|
2409
2714
|
}
|
|
2410
2715
|
const errorText = await response.text();
|
|
@@ -2432,6 +2737,8 @@ var KVService = class extends BaseService {
|
|
|
2432
2737
|
});
|
|
2433
2738
|
} catch (error) {
|
|
2434
2739
|
return err(wrapError("kv", error));
|
|
2740
|
+
} finally {
|
|
2741
|
+
request.dispose();
|
|
2435
2742
|
}
|
|
2436
2743
|
});
|
|
2437
2744
|
}
|
|
@@ -2444,20 +2751,23 @@ var KVService = class extends BaseService {
|
|
|
2444
2751
|
return err(authRequiredError("kv"));
|
|
2445
2752
|
}
|
|
2446
2753
|
const path = this.getFullPath(key, options?.prefix);
|
|
2754
|
+
const request = this.createRequestSignal(options?.signal, options?.timeout);
|
|
2447
2755
|
try {
|
|
2448
2756
|
const response = await this.invokeOperation(
|
|
2449
2757
|
path,
|
|
2450
2758
|
KVAction.DELETE,
|
|
2451
2759
|
void 0,
|
|
2452
|
-
|
|
2760
|
+
request.signal,
|
|
2453
2761
|
options?.ifMatch === void 0 ? void 0 : { "if-match": options.ifMatch }
|
|
2454
2762
|
);
|
|
2455
2763
|
if (!response.ok) {
|
|
2456
|
-
if (response.status === 401) {
|
|
2764
|
+
if (response.status === 401 || response.status === 403) {
|
|
2457
2765
|
return this.authorizationFailure(
|
|
2458
2766
|
`Failed to delete key ${JSON.stringify(key)}`,
|
|
2459
2767
|
response,
|
|
2460
|
-
await
|
|
2768
|
+
await this.readAuthorizationText(response),
|
|
2769
|
+
[path],
|
|
2770
|
+
KVAction.DELETE
|
|
2461
2771
|
);
|
|
2462
2772
|
}
|
|
2463
2773
|
if (response.status === 404) {
|
|
@@ -2495,6 +2805,8 @@ var KVService = class extends BaseService {
|
|
|
2495
2805
|
});
|
|
2496
2806
|
} catch (error) {
|
|
2497
2807
|
return err(wrapError("kv", error));
|
|
2808
|
+
} finally {
|
|
2809
|
+
request.dispose();
|
|
2498
2810
|
}
|
|
2499
2811
|
});
|
|
2500
2812
|
}
|
|
@@ -2507,19 +2819,22 @@ var KVService = class extends BaseService {
|
|
|
2507
2819
|
return err(authRequiredError("kv"));
|
|
2508
2820
|
}
|
|
2509
2821
|
const path = this.getFullPath(key, options?.prefix);
|
|
2822
|
+
const request = this.createRequestSignal(options?.signal, options?.timeout);
|
|
2510
2823
|
try {
|
|
2511
2824
|
const response = await this.invokeOperation(
|
|
2512
2825
|
path,
|
|
2513
2826
|
KVAction.HEAD,
|
|
2514
2827
|
void 0,
|
|
2515
|
-
|
|
2828
|
+
request.signal
|
|
2516
2829
|
);
|
|
2517
2830
|
if (!response.ok) {
|
|
2518
|
-
if (response.status === 401) {
|
|
2831
|
+
if (response.status === 401 || response.status === 403) {
|
|
2519
2832
|
return this.authorizationFailure(
|
|
2520
2833
|
`Failed to get metadata for key ${JSON.stringify(key)}`,
|
|
2521
2834
|
response,
|
|
2522
|
-
await
|
|
2835
|
+
await this.readAuthorizationText(response),
|
|
2836
|
+
[path],
|
|
2837
|
+
KVAction.HEAD
|
|
2523
2838
|
);
|
|
2524
2839
|
}
|
|
2525
2840
|
if (response.status === 404) {
|
|
@@ -2541,6 +2856,8 @@ var KVService = class extends BaseService {
|
|
|
2541
2856
|
});
|
|
2542
2857
|
} catch (error) {
|
|
2543
2858
|
return err(wrapError("kv", error));
|
|
2859
|
+
} finally {
|
|
2860
|
+
request.dispose();
|
|
2544
2861
|
}
|
|
2545
2862
|
});
|
|
2546
2863
|
}
|
|
@@ -2578,15 +2895,16 @@ var KVService = class extends BaseService {
|
|
|
2578
2895
|
if (options?.etag !== void 0) {
|
|
2579
2896
|
body.etag = options.etag;
|
|
2580
2897
|
}
|
|
2898
|
+
const request = this.createRequestSignal(options?.signal, options?.timeout);
|
|
2581
2899
|
try {
|
|
2582
2900
|
const response = await this.context.fetch(`${this.host}/signed/kv`, {
|
|
2583
2901
|
method: "POST",
|
|
2584
2902
|
headers: this.withJsonContentType(headers),
|
|
2585
2903
|
body: JSON.stringify(body),
|
|
2586
|
-
signal:
|
|
2904
|
+
signal: request.signal
|
|
2587
2905
|
});
|
|
2588
2906
|
if (!response.ok) {
|
|
2589
|
-
return this.createSignedReadUrlError(response, key);
|
|
2907
|
+
return this.createSignedReadUrlError(response, key, path);
|
|
2590
2908
|
}
|
|
2591
2909
|
const signedUrl = this.normalizeSignedReadUrlResponse(
|
|
2592
2910
|
await response.json()
|
|
@@ -2603,6 +2921,8 @@ var KVService = class extends BaseService {
|
|
|
2603
2921
|
return ok(signedUrl);
|
|
2604
2922
|
} catch (error) {
|
|
2605
2923
|
return err(wrapError("kv", error));
|
|
2924
|
+
} finally {
|
|
2925
|
+
request.dispose();
|
|
2606
2926
|
}
|
|
2607
2927
|
});
|
|
2608
2928
|
}
|
|
@@ -2729,16 +3049,16 @@ var DatabaseHandle = class {
|
|
|
2729
3049
|
};
|
|
2730
3050
|
|
|
2731
3051
|
// src/sql/types.ts
|
|
2732
|
-
var
|
|
3052
|
+
var import_bootstrap2 = require("@tinycloud/bootstrap");
|
|
2733
3053
|
var SQLAction = {
|
|
2734
|
-
READ:
|
|
2735
|
-
WRITE:
|
|
2736
|
-
SCHEMA:
|
|
2737
|
-
ADMIN:
|
|
2738
|
-
SELECT:
|
|
2739
|
-
EXECUTE:
|
|
2740
|
-
EXPORT:
|
|
2741
|
-
ALL:
|
|
3054
|
+
READ: import_bootstrap2.SQL.READ,
|
|
3055
|
+
WRITE: import_bootstrap2.SQL.WRITE,
|
|
3056
|
+
SCHEMA: import_bootstrap2.SQL.SCHEMA,
|
|
3057
|
+
ADMIN: import_bootstrap2.SQL.ADMIN,
|
|
3058
|
+
SELECT: import_bootstrap2.SQL.SELECT,
|
|
3059
|
+
EXECUTE: import_bootstrap2.SQL.EXECUTE,
|
|
3060
|
+
EXPORT: import_bootstrap2.SQL.EXPORT,
|
|
3061
|
+
ALL: import_bootstrap2.SQL.ALL
|
|
2742
3062
|
};
|
|
2743
3063
|
|
|
2744
3064
|
// src/sql/SQLService.ts
|
|
@@ -2816,6 +3136,7 @@ var SQLService = class extends BaseService {
|
|
|
2816
3136
|
if (!this.requireAuth()) {
|
|
2817
3137
|
return err(authRequiredError("sql"));
|
|
2818
3138
|
}
|
|
3139
|
+
const request = this.createRequestSignal(options?.signal);
|
|
2819
3140
|
try {
|
|
2820
3141
|
const body = {
|
|
2821
3142
|
action: "query",
|
|
@@ -2824,19 +3145,22 @@ var SQLService = class extends BaseService {
|
|
|
2824
3145
|
};
|
|
2825
3146
|
if (options?.maxRows !== void 0) body.maxRows = options.maxRows;
|
|
2826
3147
|
if (options?.maxBytes !== void 0) body.maxBytes = options.maxBytes;
|
|
3148
|
+
const action = this.actionForSql(sql, SQLAction.READ);
|
|
2827
3149
|
const response = await this.invokeSQL(
|
|
2828
3150
|
dbName,
|
|
2829
|
-
|
|
3151
|
+
action,
|
|
2830
3152
|
body,
|
|
2831
|
-
|
|
3153
|
+
request.signal
|
|
2832
3154
|
);
|
|
2833
3155
|
if (!response.ok) {
|
|
2834
|
-
return this.handleErrorResponse(response, "query");
|
|
3156
|
+
return this.handleErrorResponse(response, "query", dbName, [action]);
|
|
2835
3157
|
}
|
|
2836
3158
|
const data = await response.json();
|
|
2837
3159
|
return ok(data);
|
|
2838
3160
|
} catch (error) {
|
|
2839
3161
|
return err(wrapError("sql", error));
|
|
3162
|
+
} finally {
|
|
3163
|
+
request.dispose();
|
|
2840
3164
|
}
|
|
2841
3165
|
});
|
|
2842
3166
|
}
|
|
@@ -2845,6 +3169,7 @@ var SQLService = class extends BaseService {
|
|
|
2845
3169
|
if (!this.requireAuth()) {
|
|
2846
3170
|
return err(authRequiredError("sql"));
|
|
2847
3171
|
}
|
|
3172
|
+
const request = this.createRequestSignal(options?.signal);
|
|
2848
3173
|
try {
|
|
2849
3174
|
const body = {
|
|
2850
3175
|
action: "execute",
|
|
@@ -2860,19 +3185,22 @@ var SQLService = class extends BaseService {
|
|
|
2860
3185
|
(statement) => this.actionForSql(statement, SQLAction.SCHEMA)
|
|
2861
3186
|
)
|
|
2862
3187
|
];
|
|
3188
|
+
const requestedActions = this.dedupeActions(actions);
|
|
2863
3189
|
const response = await this.invokeSQL(
|
|
2864
3190
|
dbName,
|
|
2865
|
-
|
|
3191
|
+
requestedActions,
|
|
2866
3192
|
body,
|
|
2867
|
-
|
|
3193
|
+
request.signal
|
|
2868
3194
|
);
|
|
2869
3195
|
if (!response.ok) {
|
|
2870
|
-
return this.handleErrorResponse(response, "execute");
|
|
3196
|
+
return this.handleErrorResponse(response, "execute", dbName, requestedActions);
|
|
2871
3197
|
}
|
|
2872
3198
|
const data = await response.json();
|
|
2873
3199
|
return ok(data);
|
|
2874
3200
|
} catch (error) {
|
|
2875
3201
|
return err(wrapError("sql", error));
|
|
3202
|
+
} finally {
|
|
3203
|
+
request.dispose();
|
|
2876
3204
|
}
|
|
2877
3205
|
});
|
|
2878
3206
|
}
|
|
@@ -2881,20 +3209,24 @@ var SQLService = class extends BaseService {
|
|
|
2881
3209
|
if (!this.requireAuth()) {
|
|
2882
3210
|
return err(authRequiredError("sql"));
|
|
2883
3211
|
}
|
|
3212
|
+
const request = this.createRequestSignal(options?.signal);
|
|
2884
3213
|
try {
|
|
3214
|
+
const requestedActions = this.actionsForSqlBatch(statements);
|
|
2885
3215
|
const response = await this.invokeSQL(
|
|
2886
3216
|
dbName,
|
|
2887
|
-
|
|
3217
|
+
requestedActions,
|
|
2888
3218
|
{ action: "batch", statements },
|
|
2889
|
-
|
|
3219
|
+
request.signal
|
|
2890
3220
|
);
|
|
2891
3221
|
if (!response.ok) {
|
|
2892
|
-
return this.handleErrorResponse(response, "batch");
|
|
3222
|
+
return this.handleErrorResponse(response, "batch", dbName, requestedActions);
|
|
2893
3223
|
}
|
|
2894
3224
|
const data = await response.json();
|
|
2895
3225
|
return ok(data);
|
|
2896
3226
|
} catch (error) {
|
|
2897
3227
|
return err(wrapError("sql", error));
|
|
3228
|
+
} finally {
|
|
3229
|
+
request.dispose();
|
|
2898
3230
|
}
|
|
2899
3231
|
});
|
|
2900
3232
|
}
|
|
@@ -2903,20 +3235,23 @@ var SQLService = class extends BaseService {
|
|
|
2903
3235
|
if (!this.requireAuth()) {
|
|
2904
3236
|
return err(authRequiredError("sql"));
|
|
2905
3237
|
}
|
|
3238
|
+
const request = this.createRequestSignal(options?.signal);
|
|
2906
3239
|
try {
|
|
2907
3240
|
const response = await this.invokeSQL(
|
|
2908
3241
|
dbName,
|
|
2909
3242
|
SQLAction.WRITE,
|
|
2910
3243
|
{ action: "execute_statement", name, params: params ?? [] },
|
|
2911
|
-
|
|
3244
|
+
request.signal
|
|
2912
3245
|
);
|
|
2913
3246
|
if (!response.ok) {
|
|
2914
|
-
return this.handleErrorResponse(response, "executeStatement");
|
|
3247
|
+
return this.handleErrorResponse(response, "executeStatement", dbName, [SQLAction.WRITE]);
|
|
2915
3248
|
}
|
|
2916
3249
|
const data = await response.json();
|
|
2917
3250
|
return ok(data);
|
|
2918
3251
|
} catch (error) {
|
|
2919
3252
|
return err(wrapError("sql", error));
|
|
3253
|
+
} finally {
|
|
3254
|
+
request.dispose();
|
|
2920
3255
|
}
|
|
2921
3256
|
});
|
|
2922
3257
|
}
|
|
@@ -2925,15 +3260,16 @@ var SQLService = class extends BaseService {
|
|
|
2925
3260
|
if (!this.requireAuth()) {
|
|
2926
3261
|
return err(authRequiredError("sql"));
|
|
2927
3262
|
}
|
|
3263
|
+
const request = this.createRequestSignal(options?.signal);
|
|
2928
3264
|
try {
|
|
2929
3265
|
const response = await this.invokeSQL(
|
|
2930
3266
|
dbName,
|
|
2931
3267
|
SQLAction.READ,
|
|
2932
3268
|
{ action: "export" },
|
|
2933
|
-
|
|
3269
|
+
request.signal
|
|
2934
3270
|
);
|
|
2935
3271
|
if (!response.ok) {
|
|
2936
|
-
return this.handleErrorResponse(response, "export");
|
|
3272
|
+
return this.handleErrorResponse(response, "export", dbName, [SQLAction.READ]);
|
|
2937
3273
|
}
|
|
2938
3274
|
const resp = response;
|
|
2939
3275
|
if (typeof resp.blob === "function") {
|
|
@@ -2944,6 +3280,8 @@ var SQLService = class extends BaseService {
|
|
|
2944
3280
|
return ok(text);
|
|
2945
3281
|
} catch (error) {
|
|
2946
3282
|
return err(wrapError("sql", error));
|
|
3283
|
+
} finally {
|
|
3284
|
+
request.dispose();
|
|
2947
3285
|
}
|
|
2948
3286
|
});
|
|
2949
3287
|
}
|
|
@@ -3034,7 +3372,7 @@ var SQLService = class extends BaseService {
|
|
|
3034
3372
|
"Content-Type": "application/json"
|
|
3035
3373
|
},
|
|
3036
3374
|
body: JSON.stringify(body),
|
|
3037
|
-
signal
|
|
3375
|
+
signal
|
|
3038
3376
|
});
|
|
3039
3377
|
}
|
|
3040
3378
|
actionForSql(sql, fallback) {
|
|
@@ -3067,7 +3405,7 @@ var SQLService = class extends BaseService {
|
|
|
3067
3405
|
}))
|
|
3068
3406
|
);
|
|
3069
3407
|
}
|
|
3070
|
-
async handleErrorResponse(response, operation) {
|
|
3408
|
+
async handleErrorResponse(response, operation, dbName, requestedActions) {
|
|
3071
3409
|
const errorText = await response.text();
|
|
3072
3410
|
const meta = responseErrorMeta(response.status, response.statusText, errorText);
|
|
3073
3411
|
if (response.status === 402) {
|
|
@@ -3086,9 +3424,11 @@ var SQLService = class extends BaseService {
|
|
|
3086
3424
|
errorBody
|
|
3087
3425
|
);
|
|
3088
3426
|
if (response.status === 401) {
|
|
3089
|
-
const {
|
|
3090
|
-
if (action
|
|
3091
|
-
|
|
3427
|
+
const { action } = parseAuthError(errorText);
|
|
3428
|
+
if (action && requestedActions.includes(action)) {
|
|
3429
|
+
meta.requiredAction = action;
|
|
3430
|
+
meta.resource = `${this.context.session.spaceId}/sql/${dbName}`;
|
|
3431
|
+
}
|
|
3092
3432
|
}
|
|
3093
3433
|
return err(
|
|
3094
3434
|
serviceError(errorCode, message, "sql", { meta })
|
|
@@ -3233,16 +3573,16 @@ var DuckDbDatabaseHandle = class {
|
|
|
3233
3573
|
};
|
|
3234
3574
|
|
|
3235
3575
|
// src/duckdb/types.ts
|
|
3236
|
-
var
|
|
3576
|
+
var import_bootstrap3 = require("@tinycloud/bootstrap");
|
|
3237
3577
|
var DuckDbAction = {
|
|
3238
|
-
READ:
|
|
3239
|
-
WRITE:
|
|
3240
|
-
ADMIN:
|
|
3241
|
-
DESCRIBE:
|
|
3242
|
-
EXPORT:
|
|
3243
|
-
IMPORT:
|
|
3244
|
-
EXECUTE:
|
|
3245
|
-
ALL:
|
|
3578
|
+
READ: import_bootstrap3.DUCKDB.READ,
|
|
3579
|
+
WRITE: import_bootstrap3.DUCKDB.WRITE,
|
|
3580
|
+
ADMIN: import_bootstrap3.DUCKDB.ADMIN,
|
|
3581
|
+
DESCRIBE: import_bootstrap3.DUCKDB.DESCRIBE,
|
|
3582
|
+
EXPORT: import_bootstrap3.DUCKDB.EXPORT,
|
|
3583
|
+
IMPORT: import_bootstrap3.DUCKDB.IMPORT,
|
|
3584
|
+
EXECUTE: import_bootstrap3.DUCKDB.EXECUTE,
|
|
3585
|
+
ALL: import_bootstrap3.DUCKDB.ALL
|
|
3246
3586
|
};
|
|
3247
3587
|
|
|
3248
3588
|
// src/duckdb/DuckDbService.ts
|
|
@@ -3296,12 +3636,13 @@ var DuckDbService = class extends BaseService {
|
|
|
3296
3636
|
if (!this.requireAuth()) {
|
|
3297
3637
|
return err(authRequiredError("duckdb"));
|
|
3298
3638
|
}
|
|
3639
|
+
const request = this.createRequestSignal(options?.signal);
|
|
3299
3640
|
try {
|
|
3300
3641
|
const response = await this.invokeDuckDb(
|
|
3301
3642
|
dbName,
|
|
3302
3643
|
DuckDbAction.READ,
|
|
3303
3644
|
{ action: "query", sql, params: params ?? [] },
|
|
3304
|
-
|
|
3645
|
+
request.signal
|
|
3305
3646
|
);
|
|
3306
3647
|
if (!response.ok) {
|
|
3307
3648
|
return this.handleErrorResponse(response, "query");
|
|
@@ -3310,6 +3651,8 @@ var DuckDbService = class extends BaseService {
|
|
|
3310
3651
|
return ok(data);
|
|
3311
3652
|
} catch (error) {
|
|
3312
3653
|
return err(wrapError("duckdb", error));
|
|
3654
|
+
} finally {
|
|
3655
|
+
request.dispose();
|
|
3313
3656
|
}
|
|
3314
3657
|
});
|
|
3315
3658
|
}
|
|
@@ -3318,12 +3661,13 @@ var DuckDbService = class extends BaseService {
|
|
|
3318
3661
|
if (!this.requireAuth()) {
|
|
3319
3662
|
return err(authRequiredError("duckdb"));
|
|
3320
3663
|
}
|
|
3664
|
+
const request = this.createRequestSignal(options?.signal);
|
|
3321
3665
|
try {
|
|
3322
3666
|
const response = await this.invokeDuckDb(
|
|
3323
3667
|
dbName,
|
|
3324
3668
|
DuckDbAction.READ,
|
|
3325
3669
|
{ action: "query", sql, params: params ?? [] },
|
|
3326
|
-
|
|
3670
|
+
request.signal,
|
|
3327
3671
|
{ Accept: "application/vnd.apache.arrow.stream" }
|
|
3328
3672
|
);
|
|
3329
3673
|
if (!response.ok) {
|
|
@@ -3333,6 +3677,8 @@ var DuckDbService = class extends BaseService {
|
|
|
3333
3677
|
return ok(buffer);
|
|
3334
3678
|
} catch (error) {
|
|
3335
3679
|
return err(wrapError("duckdb", error));
|
|
3680
|
+
} finally {
|
|
3681
|
+
request.dispose();
|
|
3336
3682
|
}
|
|
3337
3683
|
});
|
|
3338
3684
|
}
|
|
@@ -3341,6 +3687,7 @@ var DuckDbService = class extends BaseService {
|
|
|
3341
3687
|
if (!this.requireAuth()) {
|
|
3342
3688
|
return err(authRequiredError("duckdb"));
|
|
3343
3689
|
}
|
|
3690
|
+
const request = this.createRequestSignal(options?.signal);
|
|
3344
3691
|
try {
|
|
3345
3692
|
const body = {
|
|
3346
3693
|
action: "execute",
|
|
@@ -3354,7 +3701,7 @@ var DuckDbService = class extends BaseService {
|
|
|
3354
3701
|
dbName,
|
|
3355
3702
|
DuckDbAction.WRITE,
|
|
3356
3703
|
body,
|
|
3357
|
-
|
|
3704
|
+
request.signal
|
|
3358
3705
|
);
|
|
3359
3706
|
if (!response.ok) {
|
|
3360
3707
|
return this.handleErrorResponse(response, "execute");
|
|
@@ -3363,6 +3710,8 @@ var DuckDbService = class extends BaseService {
|
|
|
3363
3710
|
return ok(data);
|
|
3364
3711
|
} catch (error) {
|
|
3365
3712
|
return err(wrapError("duckdb", error));
|
|
3713
|
+
} finally {
|
|
3714
|
+
request.dispose();
|
|
3366
3715
|
}
|
|
3367
3716
|
});
|
|
3368
3717
|
}
|
|
@@ -3371,6 +3720,7 @@ var DuckDbService = class extends BaseService {
|
|
|
3371
3720
|
if (!this.requireAuth()) {
|
|
3372
3721
|
return err(authRequiredError("duckdb"));
|
|
3373
3722
|
}
|
|
3723
|
+
const request = this.createRequestSignal(options?.signal);
|
|
3374
3724
|
try {
|
|
3375
3725
|
const body = {
|
|
3376
3726
|
action: "batch",
|
|
@@ -3383,7 +3733,7 @@ var DuckDbService = class extends BaseService {
|
|
|
3383
3733
|
dbName,
|
|
3384
3734
|
DuckDbAction.WRITE,
|
|
3385
3735
|
body,
|
|
3386
|
-
|
|
3736
|
+
request.signal
|
|
3387
3737
|
);
|
|
3388
3738
|
if (!response.ok) {
|
|
3389
3739
|
return this.handleErrorResponse(response, "batch");
|
|
@@ -3392,6 +3742,8 @@ var DuckDbService = class extends BaseService {
|
|
|
3392
3742
|
return ok(data);
|
|
3393
3743
|
} catch (error) {
|
|
3394
3744
|
return err(wrapError("duckdb", error));
|
|
3745
|
+
} finally {
|
|
3746
|
+
request.dispose();
|
|
3395
3747
|
}
|
|
3396
3748
|
});
|
|
3397
3749
|
}
|
|
@@ -3400,12 +3752,13 @@ var DuckDbService = class extends BaseService {
|
|
|
3400
3752
|
if (!this.requireAuth()) {
|
|
3401
3753
|
return err(authRequiredError("duckdb"));
|
|
3402
3754
|
}
|
|
3755
|
+
const request = this.createRequestSignal(options?.signal);
|
|
3403
3756
|
try {
|
|
3404
3757
|
const response = await this.invokeDuckDb(
|
|
3405
3758
|
dbName,
|
|
3406
3759
|
DuckDbAction.WRITE,
|
|
3407
3760
|
{ action: "executeStatement", name, params: params ?? [] },
|
|
3408
|
-
|
|
3761
|
+
request.signal
|
|
3409
3762
|
);
|
|
3410
3763
|
if (!response.ok) {
|
|
3411
3764
|
return this.handleErrorResponse(response, "executeStatement");
|
|
@@ -3414,6 +3767,8 @@ var DuckDbService = class extends BaseService {
|
|
|
3414
3767
|
return ok(data);
|
|
3415
3768
|
} catch (error) {
|
|
3416
3769
|
return err(wrapError("duckdb", error));
|
|
3770
|
+
} finally {
|
|
3771
|
+
request.dispose();
|
|
3417
3772
|
}
|
|
3418
3773
|
});
|
|
3419
3774
|
}
|
|
@@ -3422,12 +3777,13 @@ var DuckDbService = class extends BaseService {
|
|
|
3422
3777
|
if (!this.requireAuth()) {
|
|
3423
3778
|
return err(authRequiredError("duckdb"));
|
|
3424
3779
|
}
|
|
3780
|
+
const request = this.createRequestSignal(options?.signal);
|
|
3425
3781
|
try {
|
|
3426
3782
|
const response = await this.invokeDuckDb(
|
|
3427
3783
|
dbName,
|
|
3428
3784
|
DuckDbAction.READ,
|
|
3429
3785
|
{ action: "describe" },
|
|
3430
|
-
|
|
3786
|
+
request.signal
|
|
3431
3787
|
);
|
|
3432
3788
|
if (!response.ok) {
|
|
3433
3789
|
return this.handleErrorResponse(response, "describe");
|
|
@@ -3436,6 +3792,8 @@ var DuckDbService = class extends BaseService {
|
|
|
3436
3792
|
return ok(data);
|
|
3437
3793
|
} catch (error) {
|
|
3438
3794
|
return err(wrapError("duckdb", error));
|
|
3795
|
+
} finally {
|
|
3796
|
+
request.dispose();
|
|
3439
3797
|
}
|
|
3440
3798
|
});
|
|
3441
3799
|
}
|
|
@@ -3444,12 +3802,13 @@ var DuckDbService = class extends BaseService {
|
|
|
3444
3802
|
if (!this.requireAuth()) {
|
|
3445
3803
|
return err(authRequiredError("duckdb"));
|
|
3446
3804
|
}
|
|
3805
|
+
const request = this.createRequestSignal(options?.signal);
|
|
3447
3806
|
try {
|
|
3448
3807
|
const response = await this.invokeDuckDb(
|
|
3449
3808
|
dbName,
|
|
3450
3809
|
DuckDbAction.EXPORT,
|
|
3451
3810
|
{ action: "export" },
|
|
3452
|
-
|
|
3811
|
+
request.signal
|
|
3453
3812
|
);
|
|
3454
3813
|
if (!response.ok) {
|
|
3455
3814
|
return this.handleErrorResponse(response, "export");
|
|
@@ -3458,6 +3817,8 @@ var DuckDbService = class extends BaseService {
|
|
|
3458
3817
|
return ok(blob);
|
|
3459
3818
|
} catch (error) {
|
|
3460
3819
|
return err(wrapError("duckdb", error));
|
|
3820
|
+
} finally {
|
|
3821
|
+
request.dispose();
|
|
3461
3822
|
}
|
|
3462
3823
|
});
|
|
3463
3824
|
}
|
|
@@ -3466,6 +3827,7 @@ var DuckDbService = class extends BaseService {
|
|
|
3466
3827
|
if (!this.requireAuth()) {
|
|
3467
3828
|
return err(authRequiredError("duckdb"));
|
|
3468
3829
|
}
|
|
3830
|
+
const request = this.createRequestSignal(options?.signal);
|
|
3469
3831
|
try {
|
|
3470
3832
|
const session = this.context.session;
|
|
3471
3833
|
const headers = this.context.invoke(
|
|
@@ -3481,7 +3843,7 @@ var DuckDbService = class extends BaseService {
|
|
|
3481
3843
|
"Content-Type": "application/x-duckdb"
|
|
3482
3844
|
},
|
|
3483
3845
|
body: new Blob([data]),
|
|
3484
|
-
signal:
|
|
3846
|
+
signal: request.signal
|
|
3485
3847
|
});
|
|
3486
3848
|
if (!response.ok) {
|
|
3487
3849
|
return this.handleErrorResponse(response, "import");
|
|
@@ -3489,6 +3851,8 @@ var DuckDbService = class extends BaseService {
|
|
|
3489
3851
|
return ok(void 0);
|
|
3490
3852
|
} catch (error) {
|
|
3491
3853
|
return err(wrapError("duckdb", error));
|
|
3854
|
+
} finally {
|
|
3855
|
+
request.dispose();
|
|
3492
3856
|
}
|
|
3493
3857
|
});
|
|
3494
3858
|
}
|
|
@@ -3504,7 +3868,7 @@ var DuckDbService = class extends BaseService {
|
|
|
3504
3868
|
...extraHeaders
|
|
3505
3869
|
},
|
|
3506
3870
|
body: JSON.stringify(body),
|
|
3507
|
-
signal
|
|
3871
|
+
signal
|
|
3508
3872
|
});
|
|
3509
3873
|
}
|
|
3510
3874
|
async handleErrorResponse(response, operation) {
|
|
@@ -6067,103 +6431,6 @@ function canonicalHashHex(sha256, value) {
|
|
|
6067
6431
|
return hexEncode2(sha256(utf8Encode(canonical)));
|
|
6068
6432
|
}
|
|
6069
6433
|
|
|
6070
|
-
// src/encryption/networkId.ts
|
|
6071
|
-
var URN_PREFIX = "urn:tinycloud:encryption:";
|
|
6072
|
-
var NETWORK_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
6073
|
-
var PKH_EIP155_DID_RE = /^did:pkh:eip155:(\d+):(0x[a-fA-F0-9]{40})$/;
|
|
6074
|
-
var NetworkIdError = class extends Error {
|
|
6075
|
-
constructor(message) {
|
|
6076
|
-
super(message);
|
|
6077
|
-
this.name = "NetworkIdError";
|
|
6078
|
-
}
|
|
6079
|
-
};
|
|
6080
|
-
function parseNetworkId(networkId) {
|
|
6081
|
-
if (typeof networkId !== "string" || networkId.length === 0) {
|
|
6082
|
-
throw new NetworkIdError("networkId must be a non-empty string");
|
|
6083
|
-
}
|
|
6084
|
-
if (!networkId.startsWith(URN_PREFIX)) {
|
|
6085
|
-
throw new NetworkIdError(
|
|
6086
|
-
`networkId must start with ${URN_PREFIX} (got ${JSON.stringify(networkId)})`
|
|
6087
|
-
);
|
|
6088
|
-
}
|
|
6089
|
-
const body = networkId.slice(URN_PREFIX.length);
|
|
6090
|
-
const lastColon = body.lastIndexOf(":");
|
|
6091
|
-
if (lastColon <= 0 || lastColon === body.length - 1) {
|
|
6092
|
-
throw new NetworkIdError(
|
|
6093
|
-
`networkId missing ownerDid or name segment (got ${JSON.stringify(networkId)})`
|
|
6094
|
-
);
|
|
6095
|
-
}
|
|
6096
|
-
const ownerDid = body.slice(0, lastColon);
|
|
6097
|
-
const name = body.slice(lastColon + 1);
|
|
6098
|
-
if (!ownerDid.startsWith("did:")) {
|
|
6099
|
-
throw new NetworkIdError(
|
|
6100
|
-
`networkId ownerDid must be a DID (got ${JSON.stringify(ownerDid)})`
|
|
6101
|
-
);
|
|
6102
|
-
}
|
|
6103
|
-
const didParts = ownerDid.split(":");
|
|
6104
|
-
if (didParts.length < 3 || didParts.some((p) => p.length === 0)) {
|
|
6105
|
-
throw new NetworkIdError(
|
|
6106
|
-
`networkId ownerDid is not a well-formed DID (got ${JSON.stringify(ownerDid)})`
|
|
6107
|
-
);
|
|
6108
|
-
}
|
|
6109
|
-
if (!NETWORK_NAME_RE.test(name)) {
|
|
6110
|
-
throw new NetworkIdError(
|
|
6111
|
-
`networkId name ${JSON.stringify(name)} must match ${NETWORK_NAME_RE.source}`
|
|
6112
|
-
);
|
|
6113
|
-
}
|
|
6114
|
-
return { networkId, ownerDid, name };
|
|
6115
|
-
}
|
|
6116
|
-
function buildNetworkId(ownerDid, name) {
|
|
6117
|
-
if (typeof ownerDid !== "string" || !ownerDid.startsWith("did:")) {
|
|
6118
|
-
throw new NetworkIdError("ownerDid must be a DID");
|
|
6119
|
-
}
|
|
6120
|
-
if (typeof name !== "string" || !NETWORK_NAME_RE.test(name)) {
|
|
6121
|
-
throw new NetworkIdError(
|
|
6122
|
-
`network name ${JSON.stringify(name)} must match ${NETWORK_NAME_RE.source}`
|
|
6123
|
-
);
|
|
6124
|
-
}
|
|
6125
|
-
const networkId = `${URN_PREFIX}${ownerDid}:${name}`;
|
|
6126
|
-
parseNetworkId(networkId);
|
|
6127
|
-
return networkId;
|
|
6128
|
-
}
|
|
6129
|
-
function isNetworkId(networkId) {
|
|
6130
|
-
if (typeof networkId !== "string") {
|
|
6131
|
-
return false;
|
|
6132
|
-
}
|
|
6133
|
-
try {
|
|
6134
|
-
parseNetworkId(networkId);
|
|
6135
|
-
return true;
|
|
6136
|
-
} catch {
|
|
6137
|
-
return false;
|
|
6138
|
-
}
|
|
6139
|
-
}
|
|
6140
|
-
function parsePkhOwnerDid(ownerDid) {
|
|
6141
|
-
const match = ownerDid.match(PKH_EIP155_DID_RE);
|
|
6142
|
-
if (!match) return null;
|
|
6143
|
-
return {
|
|
6144
|
-
chainId: match[1],
|
|
6145
|
-
address: match[2].toLowerCase()
|
|
6146
|
-
};
|
|
6147
|
-
}
|
|
6148
|
-
function ownerDidMatches(a, b) {
|
|
6149
|
-
const aPkh = parsePkhOwnerDid(a);
|
|
6150
|
-
const bPkh = parsePkhOwnerDid(b);
|
|
6151
|
-
if (aPkh && bPkh) {
|
|
6152
|
-
return aPkh.chainId === bPkh.chainId && aPkh.address === bPkh.address;
|
|
6153
|
-
}
|
|
6154
|
-
return a === b;
|
|
6155
|
-
}
|
|
6156
|
-
function networkDiscoveryKey(name) {
|
|
6157
|
-
if (!NETWORK_NAME_RE.test(name)) {
|
|
6158
|
-
throw new NetworkIdError(
|
|
6159
|
-
`network name ${JSON.stringify(name)} must match ${NETWORK_NAME_RE.source}`
|
|
6160
|
-
);
|
|
6161
|
-
}
|
|
6162
|
-
return `.well-known/encryption/network/${name}`;
|
|
6163
|
-
}
|
|
6164
|
-
var ENCRYPTION_NETWORK_URN_PREFIX = URN_PREFIX;
|
|
6165
|
-
var NETWORK_NAME_PATTERN = NETWORK_NAME_RE;
|
|
6166
|
-
|
|
6167
6434
|
// src/encryption/types.ts
|
|
6168
6435
|
var DEFAULT_ENCRYPTION_ALG = "x25519-aes256gcm/v1";
|
|
6169
6436
|
var ENVELOPE_VERSION = 1;
|
|
@@ -7107,6 +7374,7 @@ var import_decrypt_transport_response_error3 = require("@tinycloud/sdk-services/
|
|
|
7107
7374
|
ok,
|
|
7108
7375
|
openWrappedKey,
|
|
7109
7376
|
parseAuthError,
|
|
7377
|
+
parseCapabilityResource,
|
|
7110
7378
|
parseNetworkId,
|
|
7111
7379
|
parsePermissionHint,
|
|
7112
7380
|
parsePermissionHintFromErrorText,
|
|
@@ -7132,6 +7400,7 @@ var import_decrypt_transport_response_error3 = require("@tinycloud/sdk-services/
|
|
|
7132
7400
|
validateServiceResponseEvent,
|
|
7133
7401
|
validateServiceSession,
|
|
7134
7402
|
validateTelemetrySpanEvent,
|
|
7403
|
+
validatedCapabilityOf,
|
|
7135
7404
|
verifyDecryptResponse,
|
|
7136
7405
|
wrapError
|
|
7137
7406
|
});
|