@tinycloud/sdk-services 3.12.0-beta.4 → 3.12.0-beta.8

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.d.cts CHANGED
@@ -2,8 +2,8 @@ import { g as ServiceError, f as Result, P as PermissionHint, c as IService, S a
2
2
  export { k as ErrorCode, l as ErrorCodes, E as EventHandler, F as FetchFunction, d as FetchRequestInit, e as FetchResponse, m as InvocationFact, n as InvocationFacts, o as InvokeAnyEntry, b as InvokeAnyFunction, a as InvokeFunction, R as RetryPolicy, i as RetryStats, p as ServiceErrorEvent, h as ServiceHeaders, q as ServiceRequestEvent, r as ServiceResponseEvent, s as ServiceRetryEvent, T as TelemetryConfig, t as TelemetryEventHandler, u as TelemetryEvents, v as TelemetrySpanEvent, w as defaultRetryPolicy, x as err, y as ok, z as serviceError } from './types-DjAP8dve.cjs';
3
3
  import { z } from 'zod';
4
4
  export { ServiceContext, ServiceContextConfig } from './context.cjs';
5
- import { D as DecryptCapabilityProof, R as RoutingFailure } from './types-cWtQmCCw.cjs';
6
- export { B as BuildDecryptInvocationInput, a as BuiltDecryptInvocation, C as CanonicalJson, b as DECRYPT_ACTION, c as DECRYPT_FACT_TYPE, d as DECRYPT_RESULT_TYPE, e as DEFAULT_ENCRYPTION_ALG, f as DEFAULT_KEY_VERSION, g as DecryptInvocationFact, h as DecryptInvocationSigner, i as DecryptRequestBody, j as DecryptResponseBody, k as ENCRYPTION_SERVICE, l as ENCRYPTION_SERVICE_SHORT, m as ENVELOPE_VERSION, E as EncryptionCrypto, n as EncryptionError, o as EncryptionErrorInput, I as InlineEncryptedEnvelope, J as Json, N as NetworkDescriptor, p as NodeIdentityMismatchError, q as NodeNotRespondingError, P as PartialNodeWriteError, r as ReceiverKeyPair, s as ReceiverKeySigner, t as ResourceAccess, u as ResourceDestination, v as ResourceNotRoutedError, w as ResourceRoutingConfig, x as base64Decode, y as base64Encode, z as canonicalHashHex, A as canonicalizeEncryptionJson, F as createResourceRoutingFetch, G as encryptionError, H as hexDecode, K as hexEncode, L as routingFailure, M as utf8Decode, O as utf8Encode, Q as verifyResourceDestination } from './types-cWtQmCCw.cjs';
5
+ import { D as DecryptCapabilityProof, R as RoutingFailure } from './types-CoZ0vXo8.cjs';
6
+ export { B as BuildDecryptInvocationInput, a as BuiltDecryptInvocation, C as CanonicalJson, b as DECRYPT_ACTION, c as DECRYPT_FACT_TYPE, d as DECRYPT_RESULT_TYPE, e as DEFAULT_ENCRYPTION_ALG, f as DEFAULT_KEY_VERSION, g as DecryptInvocationFact, h as DecryptInvocationSigner, i as DecryptRequestBody, j as DecryptResponseBody, k as ENCRYPTION_SERVICE, l as ENCRYPTION_SERVICE_SHORT, m as ENVELOPE_VERSION, E as EncryptionCrypto, n as EncryptionError, o as EncryptionErrorInput, I as InlineEncryptedEnvelope, J as Json, N as NetworkDescriptor, p as NodeIdentityMismatchError, q as NodeNotRespondingError, P as PartialNodeWriteError, r as ReceiverKeyPair, s as ReceiverKeySigner, t as ResourceAccess, u as ResourceDestination, v as ResourceNodeInfo, w as ResourceNotRoutedError, x as ResourceRoutingConfig, y as ResourceTransport, z as ResourceTransportOptions, A as ResourceTransportTarget, F as base64Decode, G as base64Encode, H as canonicalHashHex, K as canonicalizeEncryptionJson, L as createResourceRoutingFetch, M as createResourceTransportInvocationFetch, O as encryptionError, Q as hexDecode, S as hexEncode, T as routeResourceRequest, U as routingFailure, V as routingResourceOf, W as utf8Decode, X as utf8Encode, Y as verifyResourceDestination } from './types-CoZ0vXo8.cjs';
7
7
  export { RequestEvent, RequestLog, RequestLogReader, RequestService, RequestSink } from './telemetry/requestLog.cjs';
8
8
  import { B as BaseService } from './BaseService-CdBkfPGE.cjs';
9
9
  export { a as BaseServiceOptions, R as RequestSignal, S as ServiceConstructor, b as ServiceRegistration } from './BaseService-CdBkfPGE.cjs';
package/dist/index.d.ts CHANGED
@@ -2,8 +2,8 @@ import { g as ServiceError, f as Result, P as PermissionHint, c as IService, S a
2
2
  export { k as ErrorCode, l as ErrorCodes, E as EventHandler, F as FetchFunction, d as FetchRequestInit, e as FetchResponse, m as InvocationFact, n as InvocationFacts, o as InvokeAnyEntry, b as InvokeAnyFunction, a as InvokeFunction, R as RetryPolicy, i as RetryStats, p as ServiceErrorEvent, h as ServiceHeaders, q as ServiceRequestEvent, r as ServiceResponseEvent, s as ServiceRetryEvent, T as TelemetryConfig, t as TelemetryEventHandler, u as TelemetryEvents, v as TelemetrySpanEvent, w as defaultRetryPolicy, x as err, y as ok, z as serviceError } from './types-DjAP8dve.js';
3
3
  import { z } from 'zod';
4
4
  export { ServiceContext, ServiceContextConfig } from './context.js';
5
- import { D as DecryptCapabilityProof, R as RoutingFailure } from './types-XE4tyBLH.js';
6
- export { B as BuildDecryptInvocationInput, a as BuiltDecryptInvocation, C as CanonicalJson, b as DECRYPT_ACTION, c as DECRYPT_FACT_TYPE, d as DECRYPT_RESULT_TYPE, e as DEFAULT_ENCRYPTION_ALG, f as DEFAULT_KEY_VERSION, g as DecryptInvocationFact, h as DecryptInvocationSigner, i as DecryptRequestBody, j as DecryptResponseBody, k as ENCRYPTION_SERVICE, l as ENCRYPTION_SERVICE_SHORT, m as ENVELOPE_VERSION, E as EncryptionCrypto, n as EncryptionError, o as EncryptionErrorInput, I as InlineEncryptedEnvelope, J as Json, N as NetworkDescriptor, p as NodeIdentityMismatchError, q as NodeNotRespondingError, P as PartialNodeWriteError, r as ReceiverKeyPair, s as ReceiverKeySigner, t as ResourceAccess, u as ResourceDestination, v as ResourceNotRoutedError, w as ResourceRoutingConfig, x as base64Decode, y as base64Encode, z as canonicalHashHex, A as canonicalizeEncryptionJson, F as createResourceRoutingFetch, G as encryptionError, H as hexDecode, K as hexEncode, L as routingFailure, M as utf8Decode, O as utf8Encode, Q as verifyResourceDestination } from './types-XE4tyBLH.js';
5
+ import { D as DecryptCapabilityProof, R as RoutingFailure } from './types-Ceti5xVp.js';
6
+ export { B as BuildDecryptInvocationInput, a as BuiltDecryptInvocation, C as CanonicalJson, b as DECRYPT_ACTION, c as DECRYPT_FACT_TYPE, d as DECRYPT_RESULT_TYPE, e as DEFAULT_ENCRYPTION_ALG, f as DEFAULT_KEY_VERSION, g as DecryptInvocationFact, h as DecryptInvocationSigner, i as DecryptRequestBody, j as DecryptResponseBody, k as ENCRYPTION_SERVICE, l as ENCRYPTION_SERVICE_SHORT, m as ENVELOPE_VERSION, E as EncryptionCrypto, n as EncryptionError, o as EncryptionErrorInput, I as InlineEncryptedEnvelope, J as Json, N as NetworkDescriptor, p as NodeIdentityMismatchError, q as NodeNotRespondingError, P as PartialNodeWriteError, r as ReceiverKeyPair, s as ReceiverKeySigner, t as ResourceAccess, u as ResourceDestination, v as ResourceNodeInfo, w as ResourceNotRoutedError, x as ResourceRoutingConfig, y as ResourceTransport, z as ResourceTransportOptions, A as ResourceTransportTarget, F as base64Decode, G as base64Encode, H as canonicalHashHex, K as canonicalizeEncryptionJson, L as createResourceRoutingFetch, M as createResourceTransportInvocationFetch, O as encryptionError, Q as hexDecode, S as hexEncode, T as routeResourceRequest, U as routingFailure, V as routingResourceOf, W as utf8Decode, X as utf8Encode, Y as verifyResourceDestination } from './types-Ceti5xVp.js';
7
7
  export { RequestEvent, RequestLog, RequestLogReader, RequestService, RequestSink } from './telemetry/requestLog.js';
8
8
  import { B as BaseService } from './BaseService-BRDG69KR.js';
9
9
  export { a as BaseServiceOptions, R as RequestSignal, S as ServiceConstructor, b as ServiceRegistration } from './BaseService-BRDG69KR.js';
package/dist/index.js CHANGED
@@ -815,6 +815,7 @@ async function verifyResourceDestination(target, fetchFn) {
815
815
  if (infoDid !== target.nodeDid || keysDid !== target.nodeDid) {
816
816
  throw new NodeIdentityMismatchError(target.url, target.nodeDid, infoDid !== target.nodeDid ? infoDid : keysDid);
817
817
  }
818
+ return info;
818
819
  }
819
820
  var NodeNotRespondingError = class extends Error {
820
821
  constructor(hosts, cause) {
@@ -882,6 +883,17 @@ function authorizationOf(headers) {
882
883
  if (headers === void 0) return void 0;
883
884
  return (Array.isArray(headers) ? headers : Object.entries(headers)).find(([name]) => name.toLowerCase() === "authorization")?.[1];
884
885
  }
886
+ function routingResourceOf(uri) {
887
+ if (uri.startsWith("tinycloud://")) {
888
+ const resource = uri.slice("tinycloud://".length).split("/", 1)[0];
889
+ if (resource) return resource;
890
+ } else if (uri.startsWith("urn:tinycloud:encryption:")) {
891
+ return uri;
892
+ } else if (uri.startsWith("tinycloud:")) {
893
+ return uri.split("/", 1)[0];
894
+ }
895
+ throw new ResourceNotRoutedError(uri);
896
+ }
885
897
  function invocationResources(authorization) {
886
898
  const encoded = authorization.split(".")[1];
887
899
  if (!encoded) throw new ResourceNotRoutedError("invalid invocation");
@@ -893,8 +905,7 @@ function invocationResources(authorization) {
893
905
  for (const [uri, abilities] of Object.entries(payload.att)) {
894
906
  if (typeof abilities !== "object" || abilities === null || Array.isArray(abilities)) throw new ResourceNotRoutedError(uri);
895
907
  for (const action of Object.keys(abilities)) {
896
- const resource = uri.startsWith("tinycloud:") ? uri.split("/")[0] : uri;
897
- if (!resource.startsWith("tinycloud:") && !resource.startsWith("urn:tinycloud:encryption:")) throw new ResourceNotRoutedError(uri);
908
+ const resource = routingResourceOf(uri);
898
909
  const read2 = /^(tinycloud\.(kv\/(get|list|metadata|head|sync)|sql\/(read|export)|duckdb\/(read|describe|export)|capabilities\/read|space\/(list|info)|hooks\/list))$/.test(action);
899
910
  const access = resource.startsWith("urn:tinycloud:encryption:") ? "encryption" : action === "tinycloud.space/host" ? "host" : read2 ? "read" : "write";
900
911
  if (!resources.some((entry) => entry.resource === resource && entry.access === access)) resources.push({ resource, access });
@@ -903,6 +914,83 @@ function invocationResources(authorization) {
903
914
  if (resources.length === 0) throw new ResourceNotRoutedError("empty invocation");
904
915
  return resources;
905
916
  }
917
+ async function routeResourceRequest(resources, routing, send, options) {
918
+ if (resources.length === 0) throw new ResourceNotRoutedError("empty request");
919
+ const routes = await Promise.all(resources.map(({ resource, access }) => routing.resolveResource(resource, access)));
920
+ if (routes.some((route) => route.length === 0)) throw new ResourceNotRoutedError(resources[routes.findIndex((route) => route.length === 0)].resource);
921
+ const write = options?.independentResources === true || resources.some(({ access }) => access === "write" || access === "host");
922
+ let targets;
923
+ if (options?.independentResources) {
924
+ targets = routes.flat();
925
+ const identities = /* @__PURE__ */ new Map();
926
+ for (const target of targets) {
927
+ if (identities.has(target.url) && identities.get(target.url) !== target.nodeDid) throw new ResourceNotRoutedError(target.url);
928
+ identities.set(target.url, target.nodeDid);
929
+ }
930
+ } else {
931
+ targets = routes[0].filter((target) => routes.every((route) => route.some((other) => other.url === target.url && other.nodeDid === target.nodeDid)));
932
+ if (targets.length === 0 || write && routes.some((route) => route.length !== targets.length)) throw new ResourceNotRoutedError(resources.map(({ resource }) => resource).join(", "));
933
+ }
934
+ targets = targets.filter((target, index) => targets.findIndex((other) => other.url === target.url) === index);
935
+ if (options?.nodeDid) targets = targets.filter((target) => target.nodeDid === options.nodeDid || target.nodeDid === void 0);
936
+ if (targets.length === 0 || options?.nodeLocal && targets.length !== 1) throw new ResourceNotRoutedError(resources.map(({ resource }) => resource).join(", "));
937
+ if (!write) {
938
+ let response2;
939
+ let failure;
940
+ for (const target of targets) {
941
+ try {
942
+ response2 = await send(target);
943
+ if (response2.ok || response2.status !== 404) return response2;
944
+ } catch (error) {
945
+ if (!(error instanceof NodeNotRespondingError)) throw error;
946
+ failure = error;
947
+ }
948
+ }
949
+ if (failure) throw new NodeNotRespondingError(targets.map(({ url }) => url), failure);
950
+ if (response2) return response2;
951
+ throw new NodeNotRespondingError(targets.map(({ url }) => url), failure);
952
+ }
953
+ const succeeded = [];
954
+ const failed = [];
955
+ let response;
956
+ let failureResponse;
957
+ for (const target of targets) {
958
+ try {
959
+ const result = await send(target);
960
+ if (result.ok) {
961
+ succeeded.push(target.url);
962
+ response ?? (response = result);
963
+ } else {
964
+ failed.push({ url: target.url, status: result.status });
965
+ failureResponse ?? (failureResponse = result);
966
+ }
967
+ } catch (error) {
968
+ if (!routingFailure(error) && succeeded.length === 0) throw error;
969
+ failed.push({ url: target.url, cause: error });
970
+ }
971
+ }
972
+ if (failed.length > 0) {
973
+ if (succeeded.length > 0 || targets.length > 1) throw new PartialNodeWriteError(succeeded, failed);
974
+ if (failureResponse) return failureResponse;
975
+ if (failed[0]?.cause && !(failed[0].cause instanceof NodeNotRespondingError)) throw failed[0].cause;
976
+ throw new NodeNotRespondingError(targets.map(({ url }) => url), failed[0]?.cause);
977
+ }
978
+ return response;
979
+ }
980
+ function createResourceTransportInvocationFetch(transport, session) {
981
+ return async (url, init) => {
982
+ const parsed = new URL(url);
983
+ if (parsed.pathname !== "/invoke") throw new ResourceNotRoutedError(parsed.pathname);
984
+ const authorization = authorizationOf(init?.headers);
985
+ if (!authorization) throw new ResourceNotRoutedError("unsigned invocation");
986
+ return transport(invocationResources(authorization), async (target) => {
987
+ const signed = await target.bindAudience(authorization);
988
+ const headers = (Array.isArray(init?.headers) ? init.headers : Object.entries(init?.headers ?? {})).filter(([name]) => name.toLowerCase() !== "authorization");
989
+ headers.push(["Authorization", signed]);
990
+ return target.fetch(`${target.url}${parsed.pathname}${parsed.search}`, { ...init, headers });
991
+ }, { invocationSession: session });
992
+ };
993
+ }
906
994
  function createResourceRoutingFetch(fetchFn, routing) {
907
995
  return async (url, init) => {
908
996
  const parsed = new URL(url);
@@ -910,12 +998,6 @@ function createResourceRoutingFetch(fetchFn, routing) {
910
998
  const authorization = authorizationOf(init?.headers);
911
999
  if (!authorization) throw new ResourceNotRoutedError("unsigned invocation");
912
1000
  const resources = invocationResources(authorization);
913
- const routes = await Promise.all(resources.map(({ resource, access }) => routing.resolveResource(resource, access)));
914
- if (routes.some((route) => route.length === 0)) throw new ResourceNotRoutedError(resources[routes.findIndex((route) => route.length === 0)].resource);
915
- const write = resources.some(({ access }) => access === "write" || access === "host");
916
- let targets = routes[0].filter((target) => routes.every((route) => route.some((other) => other.url === target.url && other.nodeDid === target.nodeDid)));
917
- if (targets.length === 0 || write && routes.some((route) => route.length !== targets.length)) throw new ResourceNotRoutedError(resources.map(({ resource }) => resource).join(", "));
918
- targets = targets.filter((target, index) => targets.findIndex((other) => other.url === target.url) === index);
919
1001
  const send = async (target) => {
920
1002
  init?.signal?.throwIfAborted();
921
1003
  if (routing.verifyDestination) await routing.verifyDestination(target);
@@ -933,48 +1015,7 @@ function createResourceRoutingFetch(fetchFn, routing) {
933
1015
  throw new NodeNotRespondingError([target.url], error);
934
1016
  }
935
1017
  };
936
- if (!write) {
937
- let response2;
938
- let failure;
939
- for (const target of targets) {
940
- try {
941
- response2 = await send(target);
942
- if (response2.ok || response2.status !== 404) return response2;
943
- } catch (error) {
944
- if (!(error instanceof NodeNotRespondingError)) throw error;
945
- failure = error;
946
- }
947
- }
948
- if (failure) throw new NodeNotRespondingError(targets.map(({ url: url2 }) => url2), failure);
949
- if (response2) return response2;
950
- throw new NodeNotRespondingError(targets.map(({ url: url2 }) => url2), failure);
951
- }
952
- const succeeded = [];
953
- const failed = [];
954
- let response;
955
- let failureResponse;
956
- for (const target of targets) {
957
- try {
958
- const result = await send(target);
959
- if (result.ok) {
960
- succeeded.push(target.url);
961
- response ?? (response = result);
962
- } else {
963
- failed.push({ url: target.url, status: result.status });
964
- failureResponse ?? (failureResponse = result);
965
- }
966
- } catch (error) {
967
- if (!routingFailure(error) && succeeded.length === 0) throw error;
968
- failed.push({ url: target.url, cause: error });
969
- }
970
- }
971
- if (failed.length > 0) {
972
- if (succeeded.length > 0 || targets.length > 1) throw new PartialNodeWriteError(succeeded, failed);
973
- if (failureResponse) return failureResponse;
974
- if (failed[0]?.cause && !(failed[0].cause instanceof NodeNotRespondingError)) throw failed[0].cause;
975
- throw new NodeNotRespondingError(targets.map(({ url: url2 }) => url2), failed[0]?.cause);
976
- }
977
- return response;
1018
+ return routeResourceRequest(resources, routing, send);
978
1019
  };
979
1020
  }
980
1021
 
@@ -8905,6 +8946,7 @@ export {
8905
8946
  clearTinyCloudDebugLogs,
8906
8947
  createKVResponseSchema,
8907
8948
  createResourceRoutingFetch,
8949
+ createResourceTransportInvocationFetch,
8908
8950
  createResultSchema,
8909
8951
  createVaultCrypto,
8910
8952
  decryptEnvelopeWithKey,
@@ -8947,7 +8989,9 @@ export {
8947
8989
  requiresSecretsOptIn,
8948
8990
  resolveSecretListPrefix,
8949
8991
  resolveSecretPath,
8992
+ routeResourceRequest,
8950
8993
  routingFailure,
8994
+ routingResourceOf,
8951
8995
  serviceError,
8952
8996
  storageLimitReachedError,
8953
8997
  storageQuotaExceededError,