@tinycloud/sdk-core 2.2.0-beta.0 → 2.2.0-beta.3
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 +388 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +87 -5
- package/dist/index.d.ts +87 -5
- package/dist/index.js +375 -18
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
package/dist/index.js
CHANGED
|
@@ -2754,9 +2754,7 @@ function parseExpiry(duration) {
|
|
|
2754
2754
|
`expiry must be a non-empty duration string (got ${JSON.stringify(duration)})`
|
|
2755
2755
|
);
|
|
2756
2756
|
}
|
|
2757
|
-
const parsed = ms(
|
|
2758
|
-
duration
|
|
2759
|
-
);
|
|
2757
|
+
const parsed = ms(duration);
|
|
2760
2758
|
if (typeof parsed !== "number" || !Number.isFinite(parsed) || parsed <= 0) {
|
|
2761
2759
|
throw new ManifestValidationError(
|
|
2762
2760
|
`invalid expiry duration: ${JSON.stringify(duration)}`
|
|
@@ -2811,23 +2809,33 @@ function validateManifest(input) {
|
|
|
2811
2809
|
);
|
|
2812
2810
|
}
|
|
2813
2811
|
if (typeof m.app_id !== "string" || m.app_id.length === 0) {
|
|
2814
|
-
throw new ManifestValidationError(
|
|
2812
|
+
throw new ManifestValidationError(
|
|
2813
|
+
"manifest.app_id is required and must be a non-empty string"
|
|
2814
|
+
);
|
|
2815
2815
|
}
|
|
2816
2816
|
if (typeof m.name !== "string" || m.name.length === 0) {
|
|
2817
|
-
throw new ManifestValidationError(
|
|
2817
|
+
throw new ManifestValidationError(
|
|
2818
|
+
"manifest.name is required and must be a non-empty string"
|
|
2819
|
+
);
|
|
2818
2820
|
}
|
|
2819
2821
|
if (m.did !== void 0 && (typeof m.did !== "string" || m.did.length === 0)) {
|
|
2820
|
-
throw new ManifestValidationError(
|
|
2822
|
+
throw new ManifestValidationError(
|
|
2823
|
+
"manifest.did must be a non-empty DID string"
|
|
2824
|
+
);
|
|
2821
2825
|
}
|
|
2822
2826
|
if (m.space !== void 0 && (typeof m.space !== "string" || m.space.length === 0)) {
|
|
2823
|
-
throw new ManifestValidationError(
|
|
2827
|
+
throw new ManifestValidationError(
|
|
2828
|
+
"manifest.space must be a non-empty string"
|
|
2829
|
+
);
|
|
2824
2830
|
}
|
|
2825
2831
|
if (m.expiry !== void 0) {
|
|
2826
2832
|
parseExpiry(m.expiry);
|
|
2827
2833
|
}
|
|
2828
2834
|
if (m.permissions !== void 0) {
|
|
2829
2835
|
if (!Array.isArray(m.permissions)) {
|
|
2830
|
-
throw new ManifestValidationError(
|
|
2836
|
+
throw new ManifestValidationError(
|
|
2837
|
+
"manifest.permissions must be an array"
|
|
2838
|
+
);
|
|
2831
2839
|
}
|
|
2832
2840
|
m.permissions.forEach(
|
|
2833
2841
|
(p, i) => validatePermissionEntry(p, `permissions[${i}]`)
|
|
@@ -2844,7 +2852,9 @@ function validatePermissionEntry(p, path) {
|
|
|
2844
2852
|
throw new ManifestValidationError(`${path}.service is required`);
|
|
2845
2853
|
}
|
|
2846
2854
|
if (entry.space !== void 0 && (typeof entry.space !== "string" || entry.space.length === 0)) {
|
|
2847
|
-
throw new ManifestValidationError(
|
|
2855
|
+
throw new ManifestValidationError(
|
|
2856
|
+
`${path}.space must be a non-empty string`
|
|
2857
|
+
);
|
|
2848
2858
|
}
|
|
2849
2859
|
if (typeof entry.path !== "string") {
|
|
2850
2860
|
throw new ManifestValidationError(
|
|
@@ -2935,7 +2945,8 @@ function resolveEntry(entry, prefix, _inheritedExpiryMs, inheritedSpace) {
|
|
|
2935
2945
|
// Only populate `expiryMs` when the entry had its own expiry override.
|
|
2936
2946
|
// When absent, callers use the parent (delegation or manifest) expiry
|
|
2937
2947
|
// which is carried on ResolvedDelegate.expiryMs / ResolvedCapabilities.expiryMs.
|
|
2938
|
-
...entryExpiryMs !== void 0 ? { expiryMs: entryExpiryMs } : {}
|
|
2948
|
+
...entryExpiryMs !== void 0 ? { expiryMs: entryExpiryMs } : {},
|
|
2949
|
+
...entry.description !== void 0 ? { description: entry.description } : {}
|
|
2939
2950
|
};
|
|
2940
2951
|
}
|
|
2941
2952
|
function cloneResourceCapability(entry) {
|
|
@@ -2944,7 +2955,8 @@ function cloneResourceCapability(entry) {
|
|
|
2944
2955
|
space: entry.space,
|
|
2945
2956
|
path: entry.path,
|
|
2946
2957
|
actions: [...entry.actions],
|
|
2947
|
-
...entry.expiryMs !== void 0 ? { expiryMs: entry.expiryMs } : {}
|
|
2958
|
+
...entry.expiryMs !== void 0 ? { expiryMs: entry.expiryMs } : {},
|
|
2959
|
+
...entry.description !== void 0 ? { description: entry.description } : {}
|
|
2948
2960
|
};
|
|
2949
2961
|
}
|
|
2950
2962
|
function clonePermissionEntry(entry) {
|
|
@@ -2954,7 +2966,8 @@ function clonePermissionEntry(entry) {
|
|
|
2954
2966
|
path: entry.path,
|
|
2955
2967
|
actions: [...entry.actions],
|
|
2956
2968
|
...entry.skipPrefix !== void 0 ? { skipPrefix: entry.skipPrefix } : {},
|
|
2957
|
-
...entry.expiry !== void 0 ? { expiry: entry.expiry } : {}
|
|
2969
|
+
...entry.expiry !== void 0 ? { expiry: entry.expiry } : {},
|
|
2970
|
+
...entry.description !== void 0 ? { description: entry.description } : {}
|
|
2958
2971
|
};
|
|
2959
2972
|
}
|
|
2960
2973
|
function dedupeResources(resources) {
|
|
@@ -2973,6 +2986,9 @@ function dedupeResources(resources) {
|
|
|
2973
2986
|
seen.add(action);
|
|
2974
2987
|
}
|
|
2975
2988
|
}
|
|
2989
|
+
if (existing.description === void 0 && resource.description !== void 0) {
|
|
2990
|
+
existing.description = resource.description;
|
|
2991
|
+
}
|
|
2976
2992
|
}
|
|
2977
2993
|
return [...byKey.values()];
|
|
2978
2994
|
}
|
|
@@ -2981,11 +2997,7 @@ function accountRegistryPermission() {
|
|
|
2981
2997
|
service: "tinycloud.kv",
|
|
2982
2998
|
space: ACCOUNT_REGISTRY_SPACE,
|
|
2983
2999
|
path: ACCOUNT_REGISTRY_PATH,
|
|
2984
|
-
actions: [
|
|
2985
|
-
"tinycloud.kv/get",
|
|
2986
|
-
"tinycloud.kv/put",
|
|
2987
|
-
"tinycloud.kv/list"
|
|
2988
|
-
]
|
|
3000
|
+
actions: ["tinycloud.kv/get", "tinycloud.kv/put", "tinycloud.kv/list"]
|
|
2989
3001
|
};
|
|
2990
3002
|
}
|
|
2991
3003
|
function composeManifestRequest(inputs, options = {}) {
|
|
@@ -4238,6 +4250,339 @@ async function checkNodeInfo(host, sdkProtocol, fetchFn = globalThis.fetch.bind(
|
|
|
4238
4250
|
};
|
|
4239
4251
|
}
|
|
4240
4252
|
|
|
4253
|
+
// src/location.ts
|
|
4254
|
+
import { multiaddr } from "@multiformats/multiaddr";
|
|
4255
|
+
import { multiaddrToUri } from "@multiformats/multiaddr-to-uri";
|
|
4256
|
+
import { uriToMultiaddr } from "@multiformats/uri-to-multiaddr";
|
|
4257
|
+
import { ed25519 } from "@noble/curves/ed25519";
|
|
4258
|
+
import { bases } from "multiformats/basics";
|
|
4259
|
+
import { verifyMessage } from "viem";
|
|
4260
|
+
var LocationRecordValidationError = class extends Error {
|
|
4261
|
+
constructor(message) {
|
|
4262
|
+
super(`Location record validation failed: ${message}`);
|
|
4263
|
+
this.name = "LocationRecordValidationError";
|
|
4264
|
+
}
|
|
4265
|
+
};
|
|
4266
|
+
var CloudLocationResolutionError = class extends Error {
|
|
4267
|
+
constructor(subject, attempts) {
|
|
4268
|
+
super(`Unable to resolve TinyCloud location for ${subject}`);
|
|
4269
|
+
this.name = "CloudLocationResolutionError";
|
|
4270
|
+
this.attempts = attempts;
|
|
4271
|
+
}
|
|
4272
|
+
};
|
|
4273
|
+
function locationPayloadForRecord(record) {
|
|
4274
|
+
return {
|
|
4275
|
+
version: record.version,
|
|
4276
|
+
subject: record.subject,
|
|
4277
|
+
multiaddrs: [...record.multiaddrs],
|
|
4278
|
+
updated_at: record.updated_at,
|
|
4279
|
+
sequence: record.sequence
|
|
4280
|
+
};
|
|
4281
|
+
}
|
|
4282
|
+
function canonicalLocationPayload(payload) {
|
|
4283
|
+
return JSON.stringify({
|
|
4284
|
+
version: payload.version,
|
|
4285
|
+
subject: payload.subject,
|
|
4286
|
+
multiaddrs: payload.multiaddrs,
|
|
4287
|
+
updated_at: payload.updated_at,
|
|
4288
|
+
sequence: payload.sequence
|
|
4289
|
+
});
|
|
4290
|
+
}
|
|
4291
|
+
async function signLocationRecord(payload, signer) {
|
|
4292
|
+
validateLocationRecordPayload(payload);
|
|
4293
|
+
const message = canonicalLocationPayload(payload);
|
|
4294
|
+
const signature = signer.type === "did:pkh" ? await signer.signMessage(message) : base64UrlEncode2(await signer.signBytes(new TextEncoder().encode(message)));
|
|
4295
|
+
return { ...payload, signature };
|
|
4296
|
+
}
|
|
4297
|
+
function validateLocationRecordPayload(input) {
|
|
4298
|
+
if (input === null || typeof input !== "object") {
|
|
4299
|
+
throw new LocationRecordValidationError("payload must be an object");
|
|
4300
|
+
}
|
|
4301
|
+
const payload = input;
|
|
4302
|
+
if (payload.version !== 1) {
|
|
4303
|
+
throw new LocationRecordValidationError("version must be 1");
|
|
4304
|
+
}
|
|
4305
|
+
validateSubject(payload.subject);
|
|
4306
|
+
validateMultiaddrs(payload.multiaddrs);
|
|
4307
|
+
if (typeof payload.updated_at !== "string" || Number.isNaN(Date.parse(payload.updated_at))) {
|
|
4308
|
+
throw new LocationRecordValidationError("updated_at must be an ISO timestamp");
|
|
4309
|
+
}
|
|
4310
|
+
if (typeof payload.sequence !== "number" || !Number.isSafeInteger(payload.sequence) || payload.sequence < 0) {
|
|
4311
|
+
throw new LocationRecordValidationError(
|
|
4312
|
+
"sequence must be a non-negative safe integer"
|
|
4313
|
+
);
|
|
4314
|
+
}
|
|
4315
|
+
return {
|
|
4316
|
+
version: 1,
|
|
4317
|
+
subject: payload.subject,
|
|
4318
|
+
multiaddrs: [...payload.multiaddrs],
|
|
4319
|
+
updated_at: payload.updated_at,
|
|
4320
|
+
sequence: payload.sequence
|
|
4321
|
+
};
|
|
4322
|
+
}
|
|
4323
|
+
function validateLocationRecord(input) {
|
|
4324
|
+
const payload = validateLocationRecordPayload(input);
|
|
4325
|
+
const signature = input.signature;
|
|
4326
|
+
if (typeof signature !== "string" || signature.length === 0) {
|
|
4327
|
+
throw new LocationRecordValidationError("signature must be a non-empty string");
|
|
4328
|
+
}
|
|
4329
|
+
return { ...payload, signature };
|
|
4330
|
+
}
|
|
4331
|
+
async function verifyLocationRecord(input) {
|
|
4332
|
+
const record = validateLocationRecord(input);
|
|
4333
|
+
const payload = canonicalLocationPayload(locationPayloadForRecord(record));
|
|
4334
|
+
if (record.subject.startsWith("did:pkh:")) {
|
|
4335
|
+
return verifyPkhSignature(record.subject, payload, record.signature);
|
|
4336
|
+
}
|
|
4337
|
+
if (record.subject.startsWith("did:key:")) {
|
|
4338
|
+
return verifyDidKeySignature(record.subject, payload, record.signature);
|
|
4339
|
+
}
|
|
4340
|
+
return false;
|
|
4341
|
+
}
|
|
4342
|
+
async function fetchLocationRecord(registryUrl, subject, fetchFn = globalThis.fetch) {
|
|
4343
|
+
const url = `${registryUrl.replace(/\/$/, "")}/v1/locations/${encodeURIComponent(subject)}`;
|
|
4344
|
+
const response = await fetchFn(url);
|
|
4345
|
+
if (response.status === 404) {
|
|
4346
|
+
return null;
|
|
4347
|
+
}
|
|
4348
|
+
if (!response.ok) {
|
|
4349
|
+
throw new Error(`location registry returned HTTP ${response.status}`);
|
|
4350
|
+
}
|
|
4351
|
+
const body = await response.json();
|
|
4352
|
+
if (body.record === void 0) {
|
|
4353
|
+
throw new LocationRecordValidationError("registry response missing record");
|
|
4354
|
+
}
|
|
4355
|
+
return validateLocationRecord(body.record);
|
|
4356
|
+
}
|
|
4357
|
+
async function resolveCloudLocation(subject, options = {}) {
|
|
4358
|
+
validateSubject(subject);
|
|
4359
|
+
const verifyRecords = options.verifyRecords ?? true;
|
|
4360
|
+
const attempts = await Promise.all([
|
|
4361
|
+
resolveExplicit(subject, options.explicitMultiaddrs),
|
|
4362
|
+
resolveBlockchain(subject, options.blockchain, verifyRecords),
|
|
4363
|
+
resolveCentralized(subject, options, verifyRecords),
|
|
4364
|
+
resolveFallback(subject, options.fallbackMultiaddrs)
|
|
4365
|
+
]);
|
|
4366
|
+
const winner = attempts.find((attempt) => attempt.candidate)?.candidate;
|
|
4367
|
+
if (!winner) {
|
|
4368
|
+
throw new CloudLocationResolutionError(subject, attempts);
|
|
4369
|
+
}
|
|
4370
|
+
return {
|
|
4371
|
+
subject,
|
|
4372
|
+
source: winner.source,
|
|
4373
|
+
multiaddrs: [...winner.multiaddrs],
|
|
4374
|
+
...winner.record ? { record: winner.record } : {},
|
|
4375
|
+
attempts,
|
|
4376
|
+
resolvedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4377
|
+
};
|
|
4378
|
+
}
|
|
4379
|
+
function multiaddrToHttpUrl(input) {
|
|
4380
|
+
const uri = multiaddrToUri(multiaddr(input));
|
|
4381
|
+
if (!uri.startsWith("http://") && !uri.startsWith("https://")) {
|
|
4382
|
+
throw new LocationRecordValidationError(
|
|
4383
|
+
`multiaddr does not resolve to http/https: ${input}`
|
|
4384
|
+
);
|
|
4385
|
+
}
|
|
4386
|
+
return uri;
|
|
4387
|
+
}
|
|
4388
|
+
function httpUrlToMultiaddr(input) {
|
|
4389
|
+
const url = new URL(input);
|
|
4390
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
4391
|
+
throw new LocationRecordValidationError("URL must use http or https");
|
|
4392
|
+
}
|
|
4393
|
+
return uriToMultiaddr(url.toString()).toString();
|
|
4394
|
+
}
|
|
4395
|
+
async function resolveExplicit(subject, multiaddrs) {
|
|
4396
|
+
return resolveAttempt("explicit", async () => {
|
|
4397
|
+
if (multiaddrs === void 0 || multiaddrs.length === 0) {
|
|
4398
|
+
return null;
|
|
4399
|
+
}
|
|
4400
|
+
return toCandidate(subject, "explicit", multiaddrs, false);
|
|
4401
|
+
});
|
|
4402
|
+
}
|
|
4403
|
+
async function resolveBlockchain(subject, resolver, verifyRecords) {
|
|
4404
|
+
return resolveAttempt("blockchain", async () => {
|
|
4405
|
+
if (!resolver) {
|
|
4406
|
+
return null;
|
|
4407
|
+
}
|
|
4408
|
+
return toCandidate(subject, "blockchain", await resolver(subject), verifyRecords);
|
|
4409
|
+
});
|
|
4410
|
+
}
|
|
4411
|
+
async function resolveCentralized(subject, options, verifyRecords) {
|
|
4412
|
+
return resolveAttempt("centralized", async () => {
|
|
4413
|
+
if (!options.centralizedRegistryUrl) {
|
|
4414
|
+
return null;
|
|
4415
|
+
}
|
|
4416
|
+
const record = await fetchLocationRecord(
|
|
4417
|
+
options.centralizedRegistryUrl,
|
|
4418
|
+
subject,
|
|
4419
|
+
options.fetch
|
|
4420
|
+
);
|
|
4421
|
+
return toCandidate(subject, "centralized", record, verifyRecords);
|
|
4422
|
+
});
|
|
4423
|
+
}
|
|
4424
|
+
async function resolveFallback(subject, multiaddrs) {
|
|
4425
|
+
return resolveAttempt("fallback", async () => {
|
|
4426
|
+
if (multiaddrs === void 0 || multiaddrs.length === 0) {
|
|
4427
|
+
return null;
|
|
4428
|
+
}
|
|
4429
|
+
return toCandidate(subject, "fallback", multiaddrs, false);
|
|
4430
|
+
});
|
|
4431
|
+
}
|
|
4432
|
+
async function resolveAttempt(source, resolve) {
|
|
4433
|
+
try {
|
|
4434
|
+
const candidate = await resolve();
|
|
4435
|
+
return candidate ? { source, candidate } : { source };
|
|
4436
|
+
} catch (error) {
|
|
4437
|
+
return {
|
|
4438
|
+
source,
|
|
4439
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
4440
|
+
};
|
|
4441
|
+
}
|
|
4442
|
+
}
|
|
4443
|
+
async function toCandidate(subject, source, input, verifyRecord) {
|
|
4444
|
+
if (input === null || input === void 0) {
|
|
4445
|
+
return null;
|
|
4446
|
+
}
|
|
4447
|
+
if (Array.isArray(input)) {
|
|
4448
|
+
validateMultiaddrs(input);
|
|
4449
|
+
return { source, multiaddrs: [...input] };
|
|
4450
|
+
}
|
|
4451
|
+
const maybeRecord = input;
|
|
4452
|
+
if (maybeRecord.version === 1 && maybeRecord.signature !== void 0) {
|
|
4453
|
+
const record = validateLocationRecord(input);
|
|
4454
|
+
if (record.subject !== subject) {
|
|
4455
|
+
throw new LocationRecordValidationError(
|
|
4456
|
+
"location record subject does not match requested subject"
|
|
4457
|
+
);
|
|
4458
|
+
}
|
|
4459
|
+
if (verifyRecord && !await verifyLocationRecord(record)) {
|
|
4460
|
+
throw new LocationRecordValidationError("location record signature is invalid");
|
|
4461
|
+
}
|
|
4462
|
+
return { source, multiaddrs: [...record.multiaddrs], record };
|
|
4463
|
+
}
|
|
4464
|
+
const candidateInput = input;
|
|
4465
|
+
if (!Array.isArray(candidateInput.multiaddrs)) {
|
|
4466
|
+
throw new LocationRecordValidationError("candidate multiaddrs must be an array");
|
|
4467
|
+
}
|
|
4468
|
+
validateMultiaddrs(candidateInput.multiaddrs);
|
|
4469
|
+
if (candidateInput.record !== void 0) {
|
|
4470
|
+
const record = validateLocationRecord(candidateInput.record);
|
|
4471
|
+
if (record.subject !== subject) {
|
|
4472
|
+
throw new LocationRecordValidationError(
|
|
4473
|
+
"location record subject does not match requested subject"
|
|
4474
|
+
);
|
|
4475
|
+
}
|
|
4476
|
+
if (verifyRecord && !await verifyLocationRecord(record)) {
|
|
4477
|
+
throw new LocationRecordValidationError("location record signature is invalid");
|
|
4478
|
+
}
|
|
4479
|
+
return { source, multiaddrs: [...candidateInput.multiaddrs], record };
|
|
4480
|
+
}
|
|
4481
|
+
return { source, multiaddrs: [...candidateInput.multiaddrs] };
|
|
4482
|
+
}
|
|
4483
|
+
function validateSubject(subject) {
|
|
4484
|
+
if (typeof subject !== "string" || subject.length === 0) {
|
|
4485
|
+
throw new LocationRecordValidationError("subject must be a non-empty string");
|
|
4486
|
+
}
|
|
4487
|
+
if (!subject.startsWith("did:pkh:") && !subject.startsWith("did:key:")) {
|
|
4488
|
+
throw new LocationRecordValidationError("subject must be did:pkh or did:key");
|
|
4489
|
+
}
|
|
4490
|
+
}
|
|
4491
|
+
function validateMultiaddrs(input) {
|
|
4492
|
+
if (!Array.isArray(input)) {
|
|
4493
|
+
throw new LocationRecordValidationError("multiaddrs must be an array");
|
|
4494
|
+
}
|
|
4495
|
+
for (const addr of input) {
|
|
4496
|
+
if (typeof addr !== "string" || addr.length === 0) {
|
|
4497
|
+
throw new LocationRecordValidationError(
|
|
4498
|
+
"multiaddr entries must be non-empty strings"
|
|
4499
|
+
);
|
|
4500
|
+
}
|
|
4501
|
+
try {
|
|
4502
|
+
multiaddr(addr);
|
|
4503
|
+
} catch {
|
|
4504
|
+
throw new LocationRecordValidationError(`invalid multiaddr: ${addr}`);
|
|
4505
|
+
}
|
|
4506
|
+
}
|
|
4507
|
+
}
|
|
4508
|
+
async function verifyPkhSignature(did, payload, signature) {
|
|
4509
|
+
const address = did.split(":").at(-1);
|
|
4510
|
+
if (!address || !/^0x[a-fA-F0-9]{40}$/.test(address)) {
|
|
4511
|
+
throw new LocationRecordValidationError(
|
|
4512
|
+
"did:pkh subject must end with an EVM address"
|
|
4513
|
+
);
|
|
4514
|
+
}
|
|
4515
|
+
if (!/^0x[0-9a-fA-F]+$/.test(signature)) {
|
|
4516
|
+
throw new LocationRecordValidationError("did:pkh signature must be hex");
|
|
4517
|
+
}
|
|
4518
|
+
return verifyMessage({
|
|
4519
|
+
address,
|
|
4520
|
+
message: payload,
|
|
4521
|
+
signature
|
|
4522
|
+
});
|
|
4523
|
+
}
|
|
4524
|
+
function verifyDidKeySignature(did, payload, signature) {
|
|
4525
|
+
const publicKey = ed25519PublicKeyFromDidKey(did);
|
|
4526
|
+
const signatureBytes = decodeBase64Url(signature);
|
|
4527
|
+
if (signatureBytes.length !== 64) {
|
|
4528
|
+
throw new LocationRecordValidationError(
|
|
4529
|
+
"did:key signature must be a base64url Ed25519 signature"
|
|
4530
|
+
);
|
|
4531
|
+
}
|
|
4532
|
+
return ed25519.verify(signatureBytes, new TextEncoder().encode(payload), publicKey);
|
|
4533
|
+
}
|
|
4534
|
+
function ed25519PublicKeyFromDidKey(did) {
|
|
4535
|
+
const identifier = did.slice("did:key:".length);
|
|
4536
|
+
if (!identifier.startsWith("z")) {
|
|
4537
|
+
throw new LocationRecordValidationError("did:key must use base58btc multibase");
|
|
4538
|
+
}
|
|
4539
|
+
const bytes = bases.base58btc.decode(identifier);
|
|
4540
|
+
if (bytes.length !== 34 || bytes[0] !== 237 || bytes[1] !== 1) {
|
|
4541
|
+
throw new LocationRecordValidationError("did:key must be an Ed25519 public key");
|
|
4542
|
+
}
|
|
4543
|
+
return bytes.slice(2);
|
|
4544
|
+
}
|
|
4545
|
+
function base64UrlEncode2(bytes) {
|
|
4546
|
+
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
4547
|
+
let output = "";
|
|
4548
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
4549
|
+
const a = bytes[i];
|
|
4550
|
+
const b = bytes[i + 1];
|
|
4551
|
+
const c = bytes[i + 2];
|
|
4552
|
+
const triplet = a << 16 | (b ?? 0) << 8 | (c ?? 0);
|
|
4553
|
+
output += alphabet[triplet >> 18 & 63];
|
|
4554
|
+
output += alphabet[triplet >> 12 & 63];
|
|
4555
|
+
if (i + 1 < bytes.length) {
|
|
4556
|
+
output += alphabet[triplet >> 6 & 63];
|
|
4557
|
+
}
|
|
4558
|
+
if (i + 2 < bytes.length) {
|
|
4559
|
+
output += alphabet[triplet & 63];
|
|
4560
|
+
}
|
|
4561
|
+
}
|
|
4562
|
+
return output;
|
|
4563
|
+
}
|
|
4564
|
+
function decodeBase64Url(value) {
|
|
4565
|
+
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
4566
|
+
const bytes = [];
|
|
4567
|
+
let buffer = 0;
|
|
4568
|
+
let bits = 0;
|
|
4569
|
+
for (const char of value) {
|
|
4570
|
+
const index = alphabet.indexOf(char);
|
|
4571
|
+
if (index < 0) {
|
|
4572
|
+
throw new LocationRecordValidationError(
|
|
4573
|
+
"did:key signature must be base64url"
|
|
4574
|
+
);
|
|
4575
|
+
}
|
|
4576
|
+
buffer = buffer << 6 | index;
|
|
4577
|
+
bits += 6;
|
|
4578
|
+
if (bits >= 8) {
|
|
4579
|
+
bits -= 8;
|
|
4580
|
+
bytes.push(buffer >> bits & 255);
|
|
4581
|
+
}
|
|
4582
|
+
}
|
|
4583
|
+
return Uint8Array.from(bytes);
|
|
4584
|
+
}
|
|
4585
|
+
|
|
4241
4586
|
// src/capabilities.ts
|
|
4242
4587
|
var PermissionNotInManifestError = class extends Error {
|
|
4243
4588
|
constructor(missing, granted) {
|
|
@@ -4358,6 +4703,7 @@ export {
|
|
|
4358
4703
|
CapabilityKeyRegistry,
|
|
4359
4704
|
CapabilityKeyRegistryErrorCodes,
|
|
4360
4705
|
ClientSessionSchema,
|
|
4706
|
+
CloudLocationResolutionError,
|
|
4361
4707
|
DEFAULT_DEFAULTS,
|
|
4362
4708
|
DEFAULT_EXPIRY,
|
|
4363
4709
|
DEFAULT_MANIFEST_SPACE,
|
|
@@ -4373,6 +4719,7 @@ export {
|
|
|
4373
4719
|
ErrorCodes2 as ErrorCodes,
|
|
4374
4720
|
HooksService2 as HooksService,
|
|
4375
4721
|
KVService2 as KVService,
|
|
4722
|
+
LocationRecordValidationError,
|
|
4376
4723
|
ManifestValidationError,
|
|
4377
4724
|
PermissionNotInManifestError,
|
|
4378
4725
|
PrefixedKVService,
|
|
@@ -4398,6 +4745,7 @@ export {
|
|
|
4398
4745
|
activateSessionWithHost,
|
|
4399
4746
|
applyPrefix,
|
|
4400
4747
|
buildSpaceUri,
|
|
4748
|
+
canonicalLocationPayload,
|
|
4401
4749
|
checkNodeInfo,
|
|
4402
4750
|
composeManifestRequest,
|
|
4403
4751
|
createCapabilityKeyRegistry,
|
|
@@ -4409,23 +4757,32 @@ export {
|
|
|
4409
4757
|
defaultSpaceCreationHandler,
|
|
4410
4758
|
err4 as err,
|
|
4411
4759
|
expandActionShortNames,
|
|
4760
|
+
fetchLocationRecord,
|
|
4412
4761
|
fetchPeerId,
|
|
4762
|
+
httpUrlToMultiaddr,
|
|
4413
4763
|
isCapabilitySubset,
|
|
4414
4764
|
loadManifest,
|
|
4765
|
+
locationPayloadForRecord,
|
|
4415
4766
|
makePublicSpaceId,
|
|
4416
4767
|
manifestAbilitiesUnion,
|
|
4768
|
+
multiaddrToHttpUrl,
|
|
4417
4769
|
normalizeDefaults,
|
|
4418
4770
|
ok4 as ok,
|
|
4419
4771
|
parseExpiry,
|
|
4420
4772
|
parseRecapCapabilities,
|
|
4421
4773
|
parseSpaceUri,
|
|
4774
|
+
resolveCloudLocation,
|
|
4422
4775
|
resolveManifest,
|
|
4423
4776
|
resourceCapabilitiesToAbilitiesMap,
|
|
4424
4777
|
resourceCapabilitiesToSpaceAbilitiesMap,
|
|
4425
4778
|
serviceError4 as serviceError,
|
|
4779
|
+
signLocationRecord,
|
|
4426
4780
|
submitHostDelegation,
|
|
4427
4781
|
validateClientSession,
|
|
4782
|
+
validateLocationRecord,
|
|
4783
|
+
validateLocationRecordPayload,
|
|
4428
4784
|
validateManifest,
|
|
4429
|
-
validatePersistedSessionData
|
|
4785
|
+
validatePersistedSessionData,
|
|
4786
|
+
verifyLocationRecord
|
|
4430
4787
|
};
|
|
4431
4788
|
//# sourceMappingURL=index.js.map
|