@fedify/testing 2.4.0-dev.2157 → 2.4.0-dev.2164
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/mod.cjs +58 -10
- package/dist/mod.js +59 -11
- package/package.json +4 -4
package/dist/mod.cjs
CHANGED
|
@@ -248,9 +248,56 @@ function expandUriTemplate(template, values) {
|
|
|
248
248
|
function buildPortableUri(authority, path) {
|
|
249
249
|
if (typeof authority !== "string" || !/^did:[a-z0-9]+:[^/?#]+$/i.test(authority)) throw new TypeError("The authority of a portable ID must be a DID without a path, query, or fragment.");
|
|
250
250
|
const did = (0, _fedify_vocab_runtime.getFe34Origin)(authority);
|
|
251
|
-
if (
|
|
251
|
+
if (!isBase58BtcDidKey(did)) throw new TypeError("The did:key authority of a portable ID must be encoded in base58-btc, i.e., start with z.");
|
|
252
252
|
return (0, _fedify_vocab_runtime.parseIri)(`ap+ef61://${did}${path}`);
|
|
253
253
|
}
|
|
254
|
+
/**
|
|
255
|
+
* Checks that a normalized DID, if it is a `did:key` DID, is encoded in
|
|
256
|
+
* base58-btc, as `@fedify/fedify` requires of portable IDs.
|
|
257
|
+
*/
|
|
258
|
+
function isBase58BtcDidKey(did) {
|
|
259
|
+
return !did.startsWith("did:key:") || /^z[1-9A-HJ-NP-Za-km-z]+$/.test(did.slice(8));
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Recognizes an FEP-ef61 portable ID, i.e., an `ap:` or `ap+ef61:` URI, or
|
|
263
|
+
* a compatible identifier on any gateway, validating it the same way as
|
|
264
|
+
* `Context.parseUri()` of `@fedify/fedify` does.
|
|
265
|
+
* @returns The DID and the path of the portable ID, `null` if it is
|
|
266
|
+
* malformed, or `undefined` if the URI is not a portable ID.
|
|
267
|
+
*/
|
|
268
|
+
function parseMockPortableId(uri) {
|
|
269
|
+
const portable = uri.protocol === "ap:" || uri.protocol === "ap+ef61:";
|
|
270
|
+
if (!portable && !((uri.protocol === "http:" || uri.protocol === "https:") && /^\/\.well-known\/apgateway\/did(?::|%3A)/i.test(uri.pathname))) return;
|
|
271
|
+
if (uri.username !== "" || uri.password !== "") return null;
|
|
272
|
+
try {
|
|
273
|
+
const id = portable ? (0, _fedify_vocab_runtime.parseIri)(uri) : (0, _fedify_vocab_runtime.fromCompatibleEf61Id)(uri.origin + uri.pathname);
|
|
274
|
+
if (id == null) return null;
|
|
275
|
+
(0, _fedify_vocab_runtime.canonicalizePortableUri)((0, _fedify_vocab_runtime.formatIri)(id));
|
|
276
|
+
const authority = (0, _fedify_vocab_runtime.getFe34Origin)(id);
|
|
277
|
+
if (!isBase58BtcDidKey(authority)) return null;
|
|
278
|
+
return {
|
|
279
|
+
authority,
|
|
280
|
+
path: id.pathname
|
|
281
|
+
};
|
|
282
|
+
} catch (error) {
|
|
283
|
+
if (error instanceof TypeError) return null;
|
|
284
|
+
throw error;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Parses a path in the way {@link MockContext.parseUri} does, i.e., only
|
|
289
|
+
* `/users/{identifier}` and its subpaths are recognized, as actors.
|
|
290
|
+
*/
|
|
291
|
+
function parseMockPath(path) {
|
|
292
|
+
if (path.startsWith("/users/")) {
|
|
293
|
+
const parts = path.split("/");
|
|
294
|
+
if (parts.length >= 3) return {
|
|
295
|
+
type: "actor",
|
|
296
|
+
identifier: parts[2]
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
254
301
|
function validateOutboxListenerPath(path, dispatcherPath) {
|
|
255
302
|
if (!path.startsWith("/")) throw new TypeError("Path must start with a slash.");
|
|
256
303
|
if (dispatcherPath != null && dispatcherPath !== path) throw new TypeError("Outbox listener path and outbox dispatcher path must match.");
|
|
@@ -978,15 +1025,16 @@ var MockContext = class MockContext {
|
|
|
978
1025
|
const path = globalThis.Object.entries(values).map(([key, value]) => `${key}/${value}`).join("/");
|
|
979
1026
|
return new URL(`/collections/${String(_name)}/${path}`, this.origin);
|
|
980
1027
|
}
|
|
981
|
-
parseUri(uri) {
|
|
982
|
-
if (uri
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
1028
|
+
parseUri(uri, options = {}) {
|
|
1029
|
+
if (uri == null) return null;
|
|
1030
|
+
const portable = parseMockPortableId(uri);
|
|
1031
|
+
if (portable === void 0) return parseMockPath(uri.pathname);
|
|
1032
|
+
if (portable === null || !options.portable) return null;
|
|
1033
|
+
const result = parseMockPath(portable.path);
|
|
1034
|
+
return result == null ? null : {
|
|
1035
|
+
...result,
|
|
1036
|
+
authority: portable.authority
|
|
1037
|
+
};
|
|
990
1038
|
}
|
|
991
1039
|
async getActorKeyPairs(identifier) {
|
|
992
1040
|
if (this.federation instanceof MockFederation && this.federation.actorKeyPairsDispatcher) {
|
package/dist/mod.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
import { hasProofLike, hasSignatureLike } from "@fedify/fedify/sig";
|
|
3
3
|
import { Activity, CryptographicKey, Multikey, Tombstone, lookupObject, traverseCollection } from "@fedify/vocab";
|
|
4
|
-
import { getFe34Origin, parseIri } from "@fedify/vocab-runtime";
|
|
4
|
+
import { canonicalizePortableUri, formatIri, fromCompatibleEf61Id, getFe34Origin, parseIri } from "@fedify/vocab-runtime";
|
|
5
5
|
import { RouterError } from "@fedify/fedify/federation";
|
|
6
6
|
import { delay } from "es-toolkit";
|
|
7
7
|
import { deepStrictEqual, ok, strictEqual } from "node:assert/strict";
|
|
@@ -247,9 +247,56 @@ function expandUriTemplate(template, values) {
|
|
|
247
247
|
function buildPortableUri(authority, path) {
|
|
248
248
|
if (typeof authority !== "string" || !/^did:[a-z0-9]+:[^/?#]+$/i.test(authority)) throw new TypeError("The authority of a portable ID must be a DID without a path, query, or fragment.");
|
|
249
249
|
const did = getFe34Origin(authority);
|
|
250
|
-
if (
|
|
250
|
+
if (!isBase58BtcDidKey(did)) throw new TypeError("The did:key authority of a portable ID must be encoded in base58-btc, i.e., start with z.");
|
|
251
251
|
return parseIri(`ap+ef61://${did}${path}`);
|
|
252
252
|
}
|
|
253
|
+
/**
|
|
254
|
+
* Checks that a normalized DID, if it is a `did:key` DID, is encoded in
|
|
255
|
+
* base58-btc, as `@fedify/fedify` requires of portable IDs.
|
|
256
|
+
*/
|
|
257
|
+
function isBase58BtcDidKey(did) {
|
|
258
|
+
return !did.startsWith("did:key:") || /^z[1-9A-HJ-NP-Za-km-z]+$/.test(did.slice(8));
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Recognizes an FEP-ef61 portable ID, i.e., an `ap:` or `ap+ef61:` URI, or
|
|
262
|
+
* a compatible identifier on any gateway, validating it the same way as
|
|
263
|
+
* `Context.parseUri()` of `@fedify/fedify` does.
|
|
264
|
+
* @returns The DID and the path of the portable ID, `null` if it is
|
|
265
|
+
* malformed, or `undefined` if the URI is not a portable ID.
|
|
266
|
+
*/
|
|
267
|
+
function parseMockPortableId(uri) {
|
|
268
|
+
const portable = uri.protocol === "ap:" || uri.protocol === "ap+ef61:";
|
|
269
|
+
if (!portable && !((uri.protocol === "http:" || uri.protocol === "https:") && /^\/\.well-known\/apgateway\/did(?::|%3A)/i.test(uri.pathname))) return;
|
|
270
|
+
if (uri.username !== "" || uri.password !== "") return null;
|
|
271
|
+
try {
|
|
272
|
+
const id = portable ? parseIri(uri) : fromCompatibleEf61Id(uri.origin + uri.pathname);
|
|
273
|
+
if (id == null) return null;
|
|
274
|
+
canonicalizePortableUri(formatIri(id));
|
|
275
|
+
const authority = getFe34Origin(id);
|
|
276
|
+
if (!isBase58BtcDidKey(authority)) return null;
|
|
277
|
+
return {
|
|
278
|
+
authority,
|
|
279
|
+
path: id.pathname
|
|
280
|
+
};
|
|
281
|
+
} catch (error) {
|
|
282
|
+
if (error instanceof TypeError) return null;
|
|
283
|
+
throw error;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Parses a path in the way {@link MockContext.parseUri} does, i.e., only
|
|
288
|
+
* `/users/{identifier}` and its subpaths are recognized, as actors.
|
|
289
|
+
*/
|
|
290
|
+
function parseMockPath(path) {
|
|
291
|
+
if (path.startsWith("/users/")) {
|
|
292
|
+
const parts = path.split("/");
|
|
293
|
+
if (parts.length >= 3) return {
|
|
294
|
+
type: "actor",
|
|
295
|
+
identifier: parts[2]
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
253
300
|
function validateOutboxListenerPath(path, dispatcherPath) {
|
|
254
301
|
if (!path.startsWith("/")) throw new TypeError("Path must start with a slash.");
|
|
255
302
|
if (dispatcherPath != null && dispatcherPath !== path) throw new TypeError("Outbox listener path and outbox dispatcher path must match.");
|
|
@@ -977,15 +1024,16 @@ var MockContext = class MockContext {
|
|
|
977
1024
|
const path = globalThis.Object.entries(values).map(([key, value]) => `${key}/${value}`).join("/");
|
|
978
1025
|
return new URL(`/collections/${String(_name)}/${path}`, this.origin);
|
|
979
1026
|
}
|
|
980
|
-
parseUri(uri) {
|
|
981
|
-
if (uri
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
1027
|
+
parseUri(uri, options = {}) {
|
|
1028
|
+
if (uri == null) return null;
|
|
1029
|
+
const portable = parseMockPortableId(uri);
|
|
1030
|
+
if (portable === void 0) return parseMockPath(uri.pathname);
|
|
1031
|
+
if (portable === null || !options.portable) return null;
|
|
1032
|
+
const result = parseMockPath(portable.path);
|
|
1033
|
+
return result == null ? null : {
|
|
1034
|
+
...result,
|
|
1035
|
+
authority: portable.authority
|
|
1036
|
+
};
|
|
989
1037
|
}
|
|
990
1038
|
async getActorKeyPairs(identifier) {
|
|
991
1039
|
if (this.federation instanceof MockFederation && this.federation.actorKeyPairsDispatcher) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/testing",
|
|
3
|
-
"version": "2.4.0-dev.
|
|
3
|
+
"version": "2.4.0-dev.2164+db2b8571",
|
|
4
4
|
"description": "Testing utilities for Fedify applications",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fedify",
|
|
@@ -47,13 +47,13 @@
|
|
|
47
47
|
"package.json"
|
|
48
48
|
],
|
|
49
49
|
"peerDependencies": {
|
|
50
|
-
"@fedify/fedify": "^2.4.0-dev.
|
|
50
|
+
"@fedify/fedify": "^2.4.0-dev.2164+db2b8571"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"es-toolkit": "1.46.1",
|
|
54
54
|
"temporal-polyfill": "^1.0.1",
|
|
55
|
-
"@fedify/vocab
|
|
56
|
-
"@fedify/vocab": "2.4.0-dev.
|
|
55
|
+
"@fedify/vocab": "2.4.0-dev.2164+db2b8571",
|
|
56
|
+
"@fedify/vocab-runtime": "^2.4.0-dev.2164+db2b8571"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@standard-schema/spec": "^1.1.0",
|