@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 +97 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -40
- package/dist/index.d.ts +61 -40
- package/dist/index.js +94 -34
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2694,12 +2694,6 @@ var DEFAULT_STANDARD_ENTRIES = [
|
|
|
2694
2694
|
space: DEFAULT_MANIFEST_SPACE,
|
|
2695
2695
|
path: "/",
|
|
2696
2696
|
actions: ["read", "write"]
|
|
2697
|
-
},
|
|
2698
|
-
{
|
|
2699
|
-
service: "tinycloud.capabilities",
|
|
2700
|
-
space: DEFAULT_MANIFEST_SPACE,
|
|
2701
|
-
path: "/",
|
|
2702
|
-
actions: ["read"]
|
|
2703
2697
|
}
|
|
2704
2698
|
];
|
|
2705
2699
|
var DEFAULT_ADMIN_ENTRIES = [
|
|
@@ -2714,12 +2708,6 @@ var DEFAULT_ADMIN_ENTRIES = [
|
|
|
2714
2708
|
space: DEFAULT_MANIFEST_SPACE,
|
|
2715
2709
|
path: "/",
|
|
2716
2710
|
actions: ["read", "write", "ddl"]
|
|
2717
|
-
},
|
|
2718
|
-
{
|
|
2719
|
-
service: "tinycloud.capabilities",
|
|
2720
|
-
space: DEFAULT_MANIFEST_SPACE,
|
|
2721
|
-
path: "/",
|
|
2722
|
-
actions: ["read", "admin"]
|
|
2723
2711
|
}
|
|
2724
2712
|
];
|
|
2725
2713
|
var DEFAULT_ALL_ENTRIES = [
|
|
@@ -2740,12 +2728,6 @@ var DEFAULT_ALL_ENTRIES = [
|
|
|
2740
2728
|
space: DEFAULT_MANIFEST_SPACE,
|
|
2741
2729
|
path: "/",
|
|
2742
2730
|
actions: ["read", "write"]
|
|
2743
|
-
},
|
|
2744
|
-
{
|
|
2745
|
-
service: "tinycloud.capabilities",
|
|
2746
|
-
space: DEFAULT_MANIFEST_SPACE,
|
|
2747
|
-
path: "/",
|
|
2748
|
-
actions: ["read", "admin"]
|
|
2749
2731
|
}
|
|
2750
2732
|
];
|
|
2751
2733
|
function parseExpiry(duration) {
|
|
@@ -2895,7 +2877,8 @@ function defaultEntriesForTier(tier) {
|
|
|
2895
2877
|
service: e.service,
|
|
2896
2878
|
space: e.space,
|
|
2897
2879
|
path: e.path,
|
|
2898
|
-
actions: [...e.actions]
|
|
2880
|
+
actions: [...e.actions],
|
|
2881
|
+
...e.skipPrefix !== void 0 ? { skipPrefix: e.skipPrefix } : {}
|
|
2899
2882
|
}));
|
|
2900
2883
|
}
|
|
2901
2884
|
function resolveManifest(input) {
|
|
@@ -2908,8 +2891,8 @@ function resolveManifest(input) {
|
|
|
2908
2891
|
const defaultEntries = defaultEntriesForTier(tier);
|
|
2909
2892
|
const explicitEntries = manifest.permissions ?? [];
|
|
2910
2893
|
const allEntries = [...defaultEntries, ...explicitEntries];
|
|
2911
|
-
const resources =
|
|
2912
|
-
(entry) => resolveEntry(entry, prefix, expiryMs, space)
|
|
2894
|
+
const resources = withCapabilitiesReadForSpaces(
|
|
2895
|
+
allEntries.map((entry) => resolveEntry(entry, prefix, expiryMs, space))
|
|
2913
2896
|
);
|
|
2914
2897
|
const additionalDelegates = manifest.did === void 0 ? [] : [
|
|
2915
2898
|
{
|
|
@@ -2992,6 +2975,24 @@ function dedupeResources(resources) {
|
|
|
2992
2975
|
}
|
|
2993
2976
|
return [...byKey.values()];
|
|
2994
2977
|
}
|
|
2978
|
+
function capabilitiesReadPermission(space) {
|
|
2979
|
+
return {
|
|
2980
|
+
service: "tinycloud.capabilities",
|
|
2981
|
+
space,
|
|
2982
|
+
path: "",
|
|
2983
|
+
actions: ["tinycloud.capabilities/read"]
|
|
2984
|
+
};
|
|
2985
|
+
}
|
|
2986
|
+
function withCapabilitiesReadForSpaces(resources) {
|
|
2987
|
+
if (resources.length === 0) {
|
|
2988
|
+
return [];
|
|
2989
|
+
}
|
|
2990
|
+
const spaces = new Set(resources.map((resource) => resource.space));
|
|
2991
|
+
return dedupeResources([
|
|
2992
|
+
...resources,
|
|
2993
|
+
...[...spaces].map(capabilitiesReadPermission)
|
|
2994
|
+
]);
|
|
2995
|
+
}
|
|
2995
2996
|
function accountRegistryPermission() {
|
|
2996
2997
|
return {
|
|
2997
2998
|
service: "tinycloud.kv",
|
|
@@ -3019,6 +3020,7 @@ function composeManifestRequest(inputs, options = {}) {
|
|
|
3019
3020
|
if (includeAccountRegistryPermissions) {
|
|
3020
3021
|
resources.push(accountRegistryPermission());
|
|
3021
3022
|
}
|
|
3023
|
+
const resourcesWithImplicitCapabilities = withCapabilitiesReadForSpaces(resources);
|
|
3022
3024
|
const manifestsByAppId = /* @__PURE__ */ new Map();
|
|
3023
3025
|
for (const manifest of manifests) {
|
|
3024
3026
|
const current = manifestsByAppId.get(manifest.app_id);
|
|
@@ -3038,7 +3040,7 @@ function composeManifestRequest(inputs, options = {}) {
|
|
|
3038
3040
|
})) : [];
|
|
3039
3041
|
return {
|
|
3040
3042
|
manifests,
|
|
3041
|
-
resources:
|
|
3043
|
+
resources: resourcesWithImplicitCapabilities,
|
|
3042
3044
|
delegationTargets,
|
|
3043
3045
|
registryRecords,
|
|
3044
3046
|
expiryMs: Math.max(...resolved.map((entry) => entry.expiryMs)),
|
|
@@ -4257,6 +4259,8 @@ import { uriToMultiaddr } from "@multiformats/uri-to-multiaddr";
|
|
|
4257
4259
|
import { ed25519 } from "@noble/curves/ed25519";
|
|
4258
4260
|
import { bases } from "multiformats/basics";
|
|
4259
4261
|
import { verifyMessage } from "viem";
|
|
4262
|
+
var DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL = "https://registry.tinycloud.xyz";
|
|
4263
|
+
var DEFAULT_TINYCLOUD_FALLBACK_HOST = "https://node.tinycloud.xyz";
|
|
4260
4264
|
var LocationRecordValidationError = class extends Error {
|
|
4261
4265
|
constructor(message) {
|
|
4262
4266
|
super(`Location record validation failed: ${message}`);
|
|
@@ -4291,7 +4295,9 @@ function canonicalLocationPayload(payload) {
|
|
|
4291
4295
|
async function signLocationRecord(payload, signer) {
|
|
4292
4296
|
validateLocationRecordPayload(payload);
|
|
4293
4297
|
const message = canonicalLocationPayload(payload);
|
|
4294
|
-
const signature = signer.type === "did:pkh" ? await signer.signMessage(message) : base64UrlEncode2(
|
|
4298
|
+
const signature = signer.type === "did:pkh" ? await signer.signMessage(message) : base64UrlEncode2(
|
|
4299
|
+
await signer.signBytes(new TextEncoder().encode(message))
|
|
4300
|
+
);
|
|
4295
4301
|
return { ...payload, signature };
|
|
4296
4302
|
}
|
|
4297
4303
|
function validateLocationRecordPayload(input) {
|
|
@@ -4305,7 +4311,9 @@ function validateLocationRecordPayload(input) {
|
|
|
4305
4311
|
validateSubject(payload.subject);
|
|
4306
4312
|
validateMultiaddrs(payload.multiaddrs);
|
|
4307
4313
|
if (typeof payload.updated_at !== "string" || Number.isNaN(Date.parse(payload.updated_at))) {
|
|
4308
|
-
throw new LocationRecordValidationError(
|
|
4314
|
+
throw new LocationRecordValidationError(
|
|
4315
|
+
"updated_at must be an ISO timestamp"
|
|
4316
|
+
);
|
|
4309
4317
|
}
|
|
4310
4318
|
if (typeof payload.sequence !== "number" || !Number.isSafeInteger(payload.sequence) || payload.sequence < 0) {
|
|
4311
4319
|
throw new LocationRecordValidationError(
|
|
@@ -4324,7 +4332,9 @@ function validateLocationRecord(input) {
|
|
|
4324
4332
|
const payload = validateLocationRecordPayload(input);
|
|
4325
4333
|
const signature = input.signature;
|
|
4326
4334
|
if (typeof signature !== "string" || signature.length === 0) {
|
|
4327
|
-
throw new LocationRecordValidationError(
|
|
4335
|
+
throw new LocationRecordValidationError(
|
|
4336
|
+
"signature must be a non-empty string"
|
|
4337
|
+
);
|
|
4328
4338
|
}
|
|
4329
4339
|
return { ...payload, signature };
|
|
4330
4340
|
}
|
|
@@ -4376,6 +4386,22 @@ async function resolveCloudLocation(subject, options = {}) {
|
|
|
4376
4386
|
resolvedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4377
4387
|
};
|
|
4378
4388
|
}
|
|
4389
|
+
async function resolveTinyCloudHosts(subject, options = {}) {
|
|
4390
|
+
const location = await resolveCloudLocation(subject, {
|
|
4391
|
+
explicitMultiaddrs: hostsToMultiaddrs(options.explicitHosts),
|
|
4392
|
+
blockchain: options.blockchain,
|
|
4393
|
+
centralizedRegistryUrl: options.registryUrl === null ? void 0 : options.registryUrl ?? DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL,
|
|
4394
|
+
fallbackMultiaddrs: hostsToMultiaddrs(
|
|
4395
|
+
options.fallbackHosts === null ? void 0 : options.fallbackHosts ?? [DEFAULT_TINYCLOUD_FALLBACK_HOST]
|
|
4396
|
+
),
|
|
4397
|
+
fetch: options.fetch,
|
|
4398
|
+
verifyRecords: options.verifyRecords
|
|
4399
|
+
});
|
|
4400
|
+
return {
|
|
4401
|
+
hosts: location.multiaddrs.map((addr) => multiaddrToHttpUrl(addr)),
|
|
4402
|
+
location
|
|
4403
|
+
};
|
|
4404
|
+
}
|
|
4379
4405
|
function multiaddrToHttpUrl(input) {
|
|
4380
4406
|
const uri = multiaddrToUri(multiaddr(input));
|
|
4381
4407
|
if (!uri.startsWith("http://") && !uri.startsWith("https://")) {
|
|
@@ -4392,6 +4418,14 @@ function httpUrlToMultiaddr(input) {
|
|
|
4392
4418
|
}
|
|
4393
4419
|
return uriToMultiaddr(url.toString()).toString();
|
|
4394
4420
|
}
|
|
4421
|
+
function hostsToMultiaddrs(hosts) {
|
|
4422
|
+
if (hosts === void 0 || hosts.length === 0) {
|
|
4423
|
+
return void 0;
|
|
4424
|
+
}
|
|
4425
|
+
return hosts.map(
|
|
4426
|
+
(host) => host.startsWith("/") ? host : httpUrlToMultiaddr(host)
|
|
4427
|
+
);
|
|
4428
|
+
}
|
|
4395
4429
|
async function resolveExplicit(subject, multiaddrs) {
|
|
4396
4430
|
return resolveAttempt("explicit", async () => {
|
|
4397
4431
|
if (multiaddrs === void 0 || multiaddrs.length === 0) {
|
|
@@ -4405,7 +4439,12 @@ async function resolveBlockchain(subject, resolver, verifyRecords) {
|
|
|
4405
4439
|
if (!resolver) {
|
|
4406
4440
|
return null;
|
|
4407
4441
|
}
|
|
4408
|
-
return toCandidate(
|
|
4442
|
+
return toCandidate(
|
|
4443
|
+
subject,
|
|
4444
|
+
"blockchain",
|
|
4445
|
+
await resolver(subject),
|
|
4446
|
+
verifyRecords
|
|
4447
|
+
);
|
|
4409
4448
|
});
|
|
4410
4449
|
}
|
|
4411
4450
|
async function resolveCentralized(subject, options, verifyRecords) {
|
|
@@ -4457,13 +4496,17 @@ async function toCandidate(subject, source, input, verifyRecord) {
|
|
|
4457
4496
|
);
|
|
4458
4497
|
}
|
|
4459
4498
|
if (verifyRecord && !await verifyLocationRecord(record)) {
|
|
4460
|
-
throw new LocationRecordValidationError(
|
|
4499
|
+
throw new LocationRecordValidationError(
|
|
4500
|
+
"location record signature is invalid"
|
|
4501
|
+
);
|
|
4461
4502
|
}
|
|
4462
4503
|
return { source, multiaddrs: [...record.multiaddrs], record };
|
|
4463
4504
|
}
|
|
4464
4505
|
const candidateInput = input;
|
|
4465
4506
|
if (!Array.isArray(candidateInput.multiaddrs)) {
|
|
4466
|
-
throw new LocationRecordValidationError(
|
|
4507
|
+
throw new LocationRecordValidationError(
|
|
4508
|
+
"candidate multiaddrs must be an array"
|
|
4509
|
+
);
|
|
4467
4510
|
}
|
|
4468
4511
|
validateMultiaddrs(candidateInput.multiaddrs);
|
|
4469
4512
|
if (candidateInput.record !== void 0) {
|
|
@@ -4474,7 +4517,9 @@ async function toCandidate(subject, source, input, verifyRecord) {
|
|
|
4474
4517
|
);
|
|
4475
4518
|
}
|
|
4476
4519
|
if (verifyRecord && !await verifyLocationRecord(record)) {
|
|
4477
|
-
throw new LocationRecordValidationError(
|
|
4520
|
+
throw new LocationRecordValidationError(
|
|
4521
|
+
"location record signature is invalid"
|
|
4522
|
+
);
|
|
4478
4523
|
}
|
|
4479
4524
|
return { source, multiaddrs: [...candidateInput.multiaddrs], record };
|
|
4480
4525
|
}
|
|
@@ -4482,10 +4527,14 @@ async function toCandidate(subject, source, input, verifyRecord) {
|
|
|
4482
4527
|
}
|
|
4483
4528
|
function validateSubject(subject) {
|
|
4484
4529
|
if (typeof subject !== "string" || subject.length === 0) {
|
|
4485
|
-
throw new LocationRecordValidationError(
|
|
4530
|
+
throw new LocationRecordValidationError(
|
|
4531
|
+
"subject must be a non-empty string"
|
|
4532
|
+
);
|
|
4486
4533
|
}
|
|
4487
4534
|
if (!subject.startsWith("did:pkh:") && !subject.startsWith("did:key:")) {
|
|
4488
|
-
throw new LocationRecordValidationError(
|
|
4535
|
+
throw new LocationRecordValidationError(
|
|
4536
|
+
"subject must be did:pkh or did:key"
|
|
4537
|
+
);
|
|
4489
4538
|
}
|
|
4490
4539
|
}
|
|
4491
4540
|
function validateMultiaddrs(input) {
|
|
@@ -4529,16 +4578,24 @@ function verifyDidKeySignature(did, payload, signature) {
|
|
|
4529
4578
|
"did:key signature must be a base64url Ed25519 signature"
|
|
4530
4579
|
);
|
|
4531
4580
|
}
|
|
4532
|
-
return ed25519.verify(
|
|
4581
|
+
return ed25519.verify(
|
|
4582
|
+
signatureBytes,
|
|
4583
|
+
new TextEncoder().encode(payload),
|
|
4584
|
+
publicKey
|
|
4585
|
+
);
|
|
4533
4586
|
}
|
|
4534
4587
|
function ed25519PublicKeyFromDidKey(did) {
|
|
4535
4588
|
const identifier = did.slice("did:key:".length);
|
|
4536
4589
|
if (!identifier.startsWith("z")) {
|
|
4537
|
-
throw new LocationRecordValidationError(
|
|
4590
|
+
throw new LocationRecordValidationError(
|
|
4591
|
+
"did:key must use base58btc multibase"
|
|
4592
|
+
);
|
|
4538
4593
|
}
|
|
4539
4594
|
const bytes = bases.base58btc.decode(identifier);
|
|
4540
4595
|
if (bytes.length !== 34 || bytes[0] !== 237 || bytes[1] !== 1) {
|
|
4541
|
-
throw new LocationRecordValidationError(
|
|
4596
|
+
throw new LocationRecordValidationError(
|
|
4597
|
+
"did:key must be an Ed25519 public key"
|
|
4598
|
+
);
|
|
4542
4599
|
}
|
|
4543
4600
|
return bytes.slice(2);
|
|
4544
4601
|
}
|
|
@@ -4708,6 +4765,8 @@ export {
|
|
|
4708
4765
|
DEFAULT_EXPIRY,
|
|
4709
4766
|
DEFAULT_MANIFEST_SPACE,
|
|
4710
4767
|
DEFAULT_MANIFEST_VERSION,
|
|
4768
|
+
DEFAULT_TINYCLOUD_FALLBACK_HOST,
|
|
4769
|
+
DEFAULT_TINYCLOUD_LOCATION_REGISTRY_URL,
|
|
4711
4770
|
DataVaultService,
|
|
4712
4771
|
DatabaseHandle,
|
|
4713
4772
|
DelegationErrorCodes,
|
|
@@ -4773,6 +4832,7 @@ export {
|
|
|
4773
4832
|
parseSpaceUri,
|
|
4774
4833
|
resolveCloudLocation,
|
|
4775
4834
|
resolveManifest,
|
|
4835
|
+
resolveTinyCloudHosts,
|
|
4776
4836
|
resourceCapabilitiesToAbilitiesMap,
|
|
4777
4837
|
resourceCapabilitiesToSpaceAbilitiesMap,
|
|
4778
4838
|
serviceError4 as serviceError,
|