@tinycloud/sdk-core 2.2.0-beta.3 → 2.2.0-beta.6

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 CHANGED
@@ -41,6 +41,8 @@ __export(index_exports, {
41
41
  DEFAULT_EXPIRY: () => DEFAULT_EXPIRY,
42
42
  DEFAULT_MANIFEST_SPACE: () => DEFAULT_MANIFEST_SPACE,
43
43
  DEFAULT_MANIFEST_VERSION: () => DEFAULT_MANIFEST_VERSION,
44
+ DEFAULT_TINYCLOUD_FALLBACK_HOST: () => DEFAULT_TINYCLOUD_FALLBACK_HOST,
45
+ DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL: () => DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL,
44
46
  DataVaultService: () => import_sdk_services4.DataVaultService,
45
47
  DatabaseHandle: () => import_sdk_services4.DatabaseHandle,
46
48
  DelegationErrorCodes: () => DelegationErrorCodes,
@@ -106,6 +108,7 @@ __export(index_exports, {
106
108
  parseSpaceUri: () => parseSpaceUri,
107
109
  resolveCloudLocation: () => resolveCloudLocation,
108
110
  resolveManifest: () => resolveManifest,
111
+ resolveTinyCloudHosts: () => resolveTinyCloudHosts,
109
112
  resourceCapabilitiesToAbilitiesMap: () => resourceCapabilitiesToAbilitiesMap,
110
113
  resourceCapabilitiesToSpaceAbilitiesMap: () => resourceCapabilitiesToSpaceAbilitiesMap,
111
114
  serviceError: () => import_sdk_services4.serviceError,
@@ -2786,12 +2789,6 @@ var DEFAULT_STANDARD_ENTRIES = [
2786
2789
  space: DEFAULT_MANIFEST_SPACE,
2787
2790
  path: "/",
2788
2791
  actions: ["read", "write"]
2789
- },
2790
- {
2791
- service: "tinycloud.capabilities",
2792
- space: DEFAULT_MANIFEST_SPACE,
2793
- path: "/",
2794
- actions: ["read"]
2795
2792
  }
2796
2793
  ];
2797
2794
  var DEFAULT_ADMIN_ENTRIES = [
@@ -2806,12 +2803,6 @@ var DEFAULT_ADMIN_ENTRIES = [
2806
2803
  space: DEFAULT_MANIFEST_SPACE,
2807
2804
  path: "/",
2808
2805
  actions: ["read", "write", "ddl"]
2809
- },
2810
- {
2811
- service: "tinycloud.capabilities",
2812
- space: DEFAULT_MANIFEST_SPACE,
2813
- path: "/",
2814
- actions: ["read", "admin"]
2815
2806
  }
2816
2807
  ];
2817
2808
  var DEFAULT_ALL_ENTRIES = [
@@ -2832,12 +2823,6 @@ var DEFAULT_ALL_ENTRIES = [
2832
2823
  space: DEFAULT_MANIFEST_SPACE,
2833
2824
  path: "/",
2834
2825
  actions: ["read", "write"]
2835
- },
2836
- {
2837
- service: "tinycloud.capabilities",
2838
- space: DEFAULT_MANIFEST_SPACE,
2839
- path: "/",
2840
- actions: ["read", "admin"]
2841
2826
  }
2842
2827
  ];
2843
2828
  function parseExpiry(duration) {
@@ -2987,7 +2972,8 @@ function defaultEntriesForTier(tier) {
2987
2972
  service: e.service,
2988
2973
  space: e.space,
2989
2974
  path: e.path,
2990
- actions: [...e.actions]
2975
+ actions: [...e.actions],
2976
+ ...e.skipPrefix !== void 0 ? { skipPrefix: e.skipPrefix } : {}
2991
2977
  }));
2992
2978
  }
2993
2979
  function resolveManifest(input) {
@@ -3000,8 +2986,8 @@ function resolveManifest(input) {
3000
2986
  const defaultEntries = defaultEntriesForTier(tier);
3001
2987
  const explicitEntries = manifest.permissions ?? [];
3002
2988
  const allEntries = [...defaultEntries, ...explicitEntries];
3003
- const resources = allEntries.map(
3004
- (entry) => resolveEntry(entry, prefix, expiryMs, space)
2989
+ const resources = withCapabilitiesReadForSpaces(
2990
+ allEntries.map((entry) => resolveEntry(entry, prefix, expiryMs, space))
3005
2991
  );
3006
2992
  const additionalDelegates = manifest.did === void 0 ? [] : [
3007
2993
  {
@@ -3084,6 +3070,24 @@ function dedupeResources(resources) {
3084
3070
  }
3085
3071
  return [...byKey.values()];
3086
3072
  }
3073
+ function capabilitiesReadPermission(space) {
3074
+ return {
3075
+ service: "tinycloud.capabilities",
3076
+ space,
3077
+ path: "",
3078
+ actions: ["tinycloud.capabilities/read"]
3079
+ };
3080
+ }
3081
+ function withCapabilitiesReadForSpaces(resources) {
3082
+ if (resources.length === 0) {
3083
+ return [];
3084
+ }
3085
+ const spaces = new Set(resources.map((resource) => resource.space));
3086
+ return dedupeResources([
3087
+ ...resources,
3088
+ ...[...spaces].map(capabilitiesReadPermission)
3089
+ ]);
3090
+ }
3087
3091
  function accountRegistryPermission() {
3088
3092
  return {
3089
3093
  service: "tinycloud.kv",
@@ -3111,6 +3115,7 @@ function composeManifestRequest(inputs, options = {}) {
3111
3115
  if (includeAccountRegistryPermissions) {
3112
3116
  resources.push(accountRegistryPermission());
3113
3117
  }
3118
+ const resourcesWithImplicitCapabilities = withCapabilitiesReadForSpaces(resources);
3114
3119
  const manifestsByAppId = /* @__PURE__ */ new Map();
3115
3120
  for (const manifest of manifests) {
3116
3121
  const current = manifestsByAppId.get(manifest.app_id);
@@ -3130,7 +3135,7 @@ function composeManifestRequest(inputs, options = {}) {
3130
3135
  })) : [];
3131
3136
  return {
3132
3137
  manifests,
3133
- resources: dedupeResources(resources),
3138
+ resources: resourcesWithImplicitCapabilities,
3134
3139
  delegationTargets,
3135
3140
  registryRecords,
3136
3141
  expiryMs: Math.max(...resolved.map((entry) => entry.expiryMs)),
@@ -4349,6 +4354,8 @@ var import_uri_to_multiaddr = require("@multiformats/uri-to-multiaddr");
4349
4354
  var import_ed25519 = require("@noble/curves/ed25519");
4350
4355
  var import_basics = require("multiformats/basics");
4351
4356
  var import_viem = require("viem");
4357
+ var DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL = "https://registry.tinycloud.xyz";
4358
+ var DEFAULT_TINYCLOUD_FALLBACK_HOST = "https://node.tinycloud.xyz";
4352
4359
  var LocationRecordValidationError = class extends Error {
4353
4360
  constructor(message) {
4354
4361
  super(`Location record validation failed: ${message}`);
@@ -4383,7 +4390,9 @@ function canonicalLocationPayload(payload) {
4383
4390
  async function signLocationRecord(payload, signer) {
4384
4391
  validateLocationRecordPayload(payload);
4385
4392
  const message = canonicalLocationPayload(payload);
4386
- const signature = signer.type === "did:pkh" ? await signer.signMessage(message) : base64UrlEncode2(await signer.signBytes(new TextEncoder().encode(message)));
4393
+ const signature = signer.type === "did:pkh" ? await signer.signMessage(message) : base64UrlEncode2(
4394
+ await signer.signBytes(new TextEncoder().encode(message))
4395
+ );
4387
4396
  return { ...payload, signature };
4388
4397
  }
4389
4398
  function validateLocationRecordPayload(input) {
@@ -4397,7 +4406,9 @@ function validateLocationRecordPayload(input) {
4397
4406
  validateSubject(payload.subject);
4398
4407
  validateMultiaddrs(payload.multiaddrs);
4399
4408
  if (typeof payload.updated_at !== "string" || Number.isNaN(Date.parse(payload.updated_at))) {
4400
- throw new LocationRecordValidationError("updated_at must be an ISO timestamp");
4409
+ throw new LocationRecordValidationError(
4410
+ "updated_at must be an ISO timestamp"
4411
+ );
4401
4412
  }
4402
4413
  if (typeof payload.sequence !== "number" || !Number.isSafeInteger(payload.sequence) || payload.sequence < 0) {
4403
4414
  throw new LocationRecordValidationError(
@@ -4416,7 +4427,9 @@ function validateLocationRecord(input) {
4416
4427
  const payload = validateLocationRecordPayload(input);
4417
4428
  const signature = input.signature;
4418
4429
  if (typeof signature !== "string" || signature.length === 0) {
4419
- throw new LocationRecordValidationError("signature must be a non-empty string");
4430
+ throw new LocationRecordValidationError(
4431
+ "signature must be a non-empty string"
4432
+ );
4420
4433
  }
4421
4434
  return { ...payload, signature };
4422
4435
  }
@@ -4468,6 +4481,22 @@ async function resolveCloudLocation(subject, options = {}) {
4468
4481
  resolvedAt: (/* @__PURE__ */ new Date()).toISOString()
4469
4482
  };
4470
4483
  }
4484
+ async function resolveTinyCloudHosts(subject, options = {}) {
4485
+ const location = await resolveCloudLocation(subject, {
4486
+ explicitMultiaddrs: hostsToMultiaddrs(options.explicitHosts),
4487
+ blockchain: options.blockchain,
4488
+ centralizedRegistryUrl: options.registryUrl === null ? void 0 : options.registryUrl ?? DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL,
4489
+ fallbackMultiaddrs: hostsToMultiaddrs(
4490
+ options.fallbackHosts === null ? void 0 : options.fallbackHosts ?? [DEFAULT_TINYCLOUD_FALLBACK_HOST]
4491
+ ),
4492
+ fetch: options.fetch,
4493
+ verifyRecords: options.verifyRecords
4494
+ });
4495
+ return {
4496
+ hosts: location.multiaddrs.map((addr) => multiaddrToHttpUrl(addr)),
4497
+ location
4498
+ };
4499
+ }
4471
4500
  function multiaddrToHttpUrl(input) {
4472
4501
  const uri = (0, import_multiaddr_to_uri.multiaddrToUri)((0, import_multiaddr.multiaddr)(input));
4473
4502
  if (!uri.startsWith("http://") && !uri.startsWith("https://")) {
@@ -4484,6 +4513,14 @@ function httpUrlToMultiaddr(input) {
4484
4513
  }
4485
4514
  return (0, import_uri_to_multiaddr.uriToMultiaddr)(url.toString()).toString();
4486
4515
  }
4516
+ function hostsToMultiaddrs(hosts) {
4517
+ if (hosts === void 0 || hosts.length === 0) {
4518
+ return void 0;
4519
+ }
4520
+ return hosts.map(
4521
+ (host) => host.startsWith("/") ? host : httpUrlToMultiaddr(host)
4522
+ );
4523
+ }
4487
4524
  async function resolveExplicit(subject, multiaddrs) {
4488
4525
  return resolveAttempt("explicit", async () => {
4489
4526
  if (multiaddrs === void 0 || multiaddrs.length === 0) {
@@ -4497,7 +4534,12 @@ async function resolveBlockchain(subject, resolver, verifyRecords) {
4497
4534
  if (!resolver) {
4498
4535
  return null;
4499
4536
  }
4500
- return toCandidate(subject, "blockchain", await resolver(subject), verifyRecords);
4537
+ return toCandidate(
4538
+ subject,
4539
+ "blockchain",
4540
+ await resolver(subject),
4541
+ verifyRecords
4542
+ );
4501
4543
  });
4502
4544
  }
4503
4545
  async function resolveCentralized(subject, options, verifyRecords) {
@@ -4549,13 +4591,17 @@ async function toCandidate(subject, source, input, verifyRecord) {
4549
4591
  );
4550
4592
  }
4551
4593
  if (verifyRecord && !await verifyLocationRecord(record)) {
4552
- throw new LocationRecordValidationError("location record signature is invalid");
4594
+ throw new LocationRecordValidationError(
4595
+ "location record signature is invalid"
4596
+ );
4553
4597
  }
4554
4598
  return { source, multiaddrs: [...record.multiaddrs], record };
4555
4599
  }
4556
4600
  const candidateInput = input;
4557
4601
  if (!Array.isArray(candidateInput.multiaddrs)) {
4558
- throw new LocationRecordValidationError("candidate multiaddrs must be an array");
4602
+ throw new LocationRecordValidationError(
4603
+ "candidate multiaddrs must be an array"
4604
+ );
4559
4605
  }
4560
4606
  validateMultiaddrs(candidateInput.multiaddrs);
4561
4607
  if (candidateInput.record !== void 0) {
@@ -4566,7 +4612,9 @@ async function toCandidate(subject, source, input, verifyRecord) {
4566
4612
  );
4567
4613
  }
4568
4614
  if (verifyRecord && !await verifyLocationRecord(record)) {
4569
- throw new LocationRecordValidationError("location record signature is invalid");
4615
+ throw new LocationRecordValidationError(
4616
+ "location record signature is invalid"
4617
+ );
4570
4618
  }
4571
4619
  return { source, multiaddrs: [...candidateInput.multiaddrs], record };
4572
4620
  }
@@ -4574,10 +4622,14 @@ async function toCandidate(subject, source, input, verifyRecord) {
4574
4622
  }
4575
4623
  function validateSubject(subject) {
4576
4624
  if (typeof subject !== "string" || subject.length === 0) {
4577
- throw new LocationRecordValidationError("subject must be a non-empty string");
4625
+ throw new LocationRecordValidationError(
4626
+ "subject must be a non-empty string"
4627
+ );
4578
4628
  }
4579
4629
  if (!subject.startsWith("did:pkh:") && !subject.startsWith("did:key:")) {
4580
- throw new LocationRecordValidationError("subject must be did:pkh or did:key");
4630
+ throw new LocationRecordValidationError(
4631
+ "subject must be did:pkh or did:key"
4632
+ );
4581
4633
  }
4582
4634
  }
4583
4635
  function validateMultiaddrs(input) {
@@ -4621,16 +4673,24 @@ function verifyDidKeySignature(did, payload, signature) {
4621
4673
  "did:key signature must be a base64url Ed25519 signature"
4622
4674
  );
4623
4675
  }
4624
- return import_ed25519.ed25519.verify(signatureBytes, new TextEncoder().encode(payload), publicKey);
4676
+ return import_ed25519.ed25519.verify(
4677
+ signatureBytes,
4678
+ new TextEncoder().encode(payload),
4679
+ publicKey
4680
+ );
4625
4681
  }
4626
4682
  function ed25519PublicKeyFromDidKey(did) {
4627
4683
  const identifier = did.slice("did:key:".length);
4628
4684
  if (!identifier.startsWith("z")) {
4629
- throw new LocationRecordValidationError("did:key must use base58btc multibase");
4685
+ throw new LocationRecordValidationError(
4686
+ "did:key must use base58btc multibase"
4687
+ );
4630
4688
  }
4631
4689
  const bytes = import_basics.bases.base58btc.decode(identifier);
4632
4690
  if (bytes.length !== 34 || bytes[0] !== 237 || bytes[1] !== 1) {
4633
- throw new LocationRecordValidationError("did:key must be an Ed25519 public key");
4691
+ throw new LocationRecordValidationError(
4692
+ "did:key must be an Ed25519 public key"
4693
+ );
4634
4694
  }
4635
4695
  return bytes.slice(2);
4636
4696
  }
@@ -4801,6 +4861,8 @@ function parseRecapCapabilities(parseWasm, siwe) {
4801
4861
  DEFAULT_EXPIRY,
4802
4862
  DEFAULT_MANIFEST_SPACE,
4803
4863
  DEFAULT_MANIFEST_VERSION,
4864
+ DEFAULT_TINYCLOUD_FALLBACK_HOST,
4865
+ DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL,
4804
4866
  DataVaultService,
4805
4867
  DatabaseHandle,
4806
4868
  DelegationErrorCodes,
@@ -4866,6 +4928,7 @@ function parseRecapCapabilities(parseWasm, siwe) {
4866
4928
  parseSpaceUri,
4867
4929
  resolveCloudLocation,
4868
4930
  resolveManifest,
4931
+ resolveTinyCloudHosts,
4869
4932
  resourceCapabilitiesToAbilitiesMap,
4870
4933
  resourceCapabilitiesToSpaceAbilitiesMap,
4871
4934
  serviceError,