@fedify/vocab 2.4.0-dev.2035 → 2.4.0-dev.2047
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/deno.json +1 -1
- package/dist/mod.cjs +5472 -645
- package/dist/mod.d.cts +416 -1
- package/dist/mod.d.ts +416 -1
- package/dist/mod.js +5472 -645
- package/dist-tests/{actor-BX07d5tK.mjs → actor-chbmxipX.mjs} +71 -2
- package/dist-tests/actor.test.mjs +3 -3
- package/dist-tests/{esm-C_FjLvhG.mjs → esm-Df0Yo-Tp.mjs} +1 -1
- package/dist-tests/gateway.test.mjs +604 -0
- package/dist-tests/{lookup-B9lgdxnM.mjs → lookup-CvrMdVSJ.mjs} +211 -9
- package/dist-tests/lookup.test.mjs +3 -3
- package/dist-tests/portable-lookup.test.mjs +335 -0
- package/dist-tests/signed-representation.test.mjs +1 -1
- package/dist-tests/translation.test.mjs +3 -3
- package/dist-tests/type.test.mjs +1 -1
- package/dist-tests/{vocab-Dw_Vm0NE.mjs → vocab-BJGPw--L.mjs} +5109 -551
- package/dist-tests/vocab.test.mjs +9 -4
- package/package.json +4 -4
- package/src/actor.ts +110 -1
- package/src/gateway.test.ts +872 -0
- package/src/lookup.ts +302 -2
- package/src/portable-lookup.test.ts +457 -0
- package/src/vocab.test.ts +8 -1
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
|
-
import { H as Service, N as Organization, P as Person, a as Application, y as Group } from "./vocab-
|
|
3
|
+
import { H as Service, N as Organization, P as Person, a as Application, y as Group } from "./vocab-BJGPw--L.mjs";
|
|
4
4
|
import { t as getTypeId } from "./type-BMdjm4Eg.mjs";
|
|
5
|
+
import { canonicalizePortableUri, formatIri, fromCompatibleEf61Id, isGatewayUrl } from "@fedify/vocab-runtime";
|
|
5
6
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
6
7
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
7
8
|
import { domainToASCII, domainToUnicode } from "node:url";
|
|
8
9
|
//#region deno.json
|
|
9
10
|
var name = "@fedify/vocab";
|
|
10
|
-
var version = "2.4.0-dev.
|
|
11
|
+
var version = "2.4.0-dev.2047+140b94db";
|
|
11
12
|
//#endregion
|
|
12
13
|
//#region src/actor.ts
|
|
13
14
|
const ACTOR_DISCOVERY_HISTOGRAM_BUCKETS = [
|
|
@@ -49,6 +50,7 @@ function getActorDiscoveryInstruments(meterProvider) {
|
|
|
49
50
|
function getActorDiscoveryRemoteHost(actor) {
|
|
50
51
|
const id = actor instanceof URL ? actor : actor.id;
|
|
51
52
|
if (id == null) return void 0;
|
|
53
|
+
if (isPortableActorId(id)) return actor instanceof URL ? void 0 : actor.gateway?.host;
|
|
52
54
|
return id.host === "" ? void 0 : id.host;
|
|
53
55
|
}
|
|
54
56
|
var ActorHandleNotFoundError = class extends TypeError {
|
|
@@ -108,6 +110,17 @@ function getActorClassByTypeName(typeName) {
|
|
|
108
110
|
* await getActorHandle(new URL("https://fosstodon.org/users/hongminhee"));
|
|
109
111
|
* ```
|
|
110
112
|
*
|
|
113
|
+
* For an [FEP-ef61] portable actor, whose ID is an `ap:` or `ap+ef61:` URI,
|
|
114
|
+
* the domain is taken from the first gateway in the actor's `gateways` rather
|
|
115
|
+
* than from its ID. The handle is returned only if its WebFinger response
|
|
116
|
+
* links back to the actor, since the actor's `gateways` are claimed by the
|
|
117
|
+
* actor itself; a failed WebFinger lookup is not enough information to get
|
|
118
|
+
* the handle. A portable actor without `gateways` or
|
|
119
|
+
* `preferredUsername`, or a portable actor URI (which does not tell its
|
|
120
|
+
* gateways), is not supported.
|
|
121
|
+
*
|
|
122
|
+
* [FEP-ef61]: https://w3id.org/fep/ef61
|
|
123
|
+
*
|
|
111
124
|
* @param actor The actor or actor URI to get the handle from.
|
|
112
125
|
* @param options The extra options for getting the actor handle.
|
|
113
126
|
* @returns The actor handle. It starts with `@` and is followed by the
|
|
@@ -152,6 +165,10 @@ async function getActorHandle(actor, options = {}) {
|
|
|
152
165
|
}
|
|
153
166
|
async function getActorHandleInternal(actor, options = {}) {
|
|
154
167
|
const actorId = actor instanceof URL ? actor : actor.id;
|
|
168
|
+
if (actorId != null && isPortableActorId(actorId)) {
|
|
169
|
+
if (actor instanceof URL) throw new ActorHandleNotFoundError();
|
|
170
|
+
return await getPortableActorHandle(actor, actorId, options);
|
|
171
|
+
}
|
|
155
172
|
if (actorId != null) {
|
|
156
173
|
const result = await lookupWebFinger(actorId, {
|
|
157
174
|
userAgent: options.userAgent,
|
|
@@ -173,6 +190,58 @@ async function getActorHandleInternal(actor, options = {}) {
|
|
|
173
190
|
if (!(actor instanceof URL) && actor.preferredUsername != null && actor.id != null) return normalizeActorHandle(`@${actor.preferredUsername}@${actor.id.host}`, options);
|
|
174
191
|
throw new ActorHandleNotFoundError();
|
|
175
192
|
}
|
|
193
|
+
function isPortableActorId(id) {
|
|
194
|
+
return id.protocol === "ap:" || id.protocol === "ap+ef61:";
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* The reverse discovery of an FEP-ef61 portable actor's WebFinger address,
|
|
198
|
+
* which takes the domain from the first gateway in its `gateways`.
|
|
199
|
+
*/
|
|
200
|
+
async function getPortableActorHandle(actor, actorId, options) {
|
|
201
|
+
const gateway = actor.gateway;
|
|
202
|
+
const username = actor.preferredUsername?.toString();
|
|
203
|
+
if (gateway == null || !isGatewayUrl(gateway) || username == null) throw new ActorHandleNotFoundError();
|
|
204
|
+
const canonicalId = canonicalizePortableUri(formatIri(actorId));
|
|
205
|
+
const handle = `acct:${username}@${gateway.host}`;
|
|
206
|
+
const result = await lookupWebFinger(handle, {
|
|
207
|
+
userAgent: options.userAgent,
|
|
208
|
+
tracerProvider: options.tracerProvider,
|
|
209
|
+
meterProvider: options.meterProvider
|
|
210
|
+
});
|
|
211
|
+
if (result == null || !linksToPortableActor(result, canonicalId)) throw new ActorHandleNotFoundError();
|
|
212
|
+
const subject = result.subject?.match(/^acct:([^@]+)@([^@]+)$/);
|
|
213
|
+
if (subject != null && result.subject !== handle) {
|
|
214
|
+
const subjectResult = await lookupWebFinger(result.subject, {
|
|
215
|
+
userAgent: options.userAgent,
|
|
216
|
+
tracerProvider: options.tracerProvider,
|
|
217
|
+
meterProvider: options.meterProvider
|
|
218
|
+
});
|
|
219
|
+
if (subjectResult != null && linksToPortableActor(subjectResult, canonicalId)) return normalizeActorHandle(`@${subject[1]}@${subject[2]}`, options);
|
|
220
|
+
}
|
|
221
|
+
return normalizeActorHandle(`@${username}@${gateway.host}`, options);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Checks if the first ActivityStreams `self` link of a WebFinger response
|
|
225
|
+
* identifies the portable actor, either by its portable ID or by
|
|
226
|
+
* a compatible identifier.
|
|
227
|
+
*/
|
|
228
|
+
function linksToPortableActor(jrd, canonicalId) {
|
|
229
|
+
const link = jrd.links?.find((l) => l.rel === "self" && l.href != null && (l.type === "application/activity+json" || l.type?.match(/application\/ld\+json;\s*profile="https:\/\/www.w3.org\/ns\/activitystreams"/) != null));
|
|
230
|
+
if (link?.href == null) return false;
|
|
231
|
+
try {
|
|
232
|
+
let id;
|
|
233
|
+
if (/^ap(?:\+ef61)?:/i.test(link.href)) id = link.href;
|
|
234
|
+
else {
|
|
235
|
+
const portable = URL.canParse(link.href) ? fromCompatibleEf61Id(link.href) : null;
|
|
236
|
+
if (portable == null) return false;
|
|
237
|
+
id = formatIri(portable);
|
|
238
|
+
}
|
|
239
|
+
return canonicalizePortableUri(id) === canonicalId;
|
|
240
|
+
} catch (error) {
|
|
241
|
+
if (error instanceof TypeError) return false;
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
176
245
|
async function verifyCrossOriginActorHandle(actorId, alias, userAgent, tracerProvider, meterProvider) {
|
|
177
246
|
const response = await lookupWebFinger(alias, {
|
|
178
247
|
userAgent,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
|
-
import { H as Service, N as Organization, P as Person, Z as __exportAll, a as Application, y as Group } from "./vocab-
|
|
4
|
-
import { t as esm_default } from "./esm-
|
|
5
|
-
import { a as normalizeActorHandle, i as isActor, n as getActorHandle, r as getActorTypeName, t as getActorClassByTypeName } from "./actor-
|
|
3
|
+
import { H as Service, N as Organization, P as Person, Z as __exportAll, a as Application, y as Group } from "./vocab-BJGPw--L.mjs";
|
|
4
|
+
import { t as esm_default } from "./esm-Df0Yo-Tp.mjs";
|
|
5
|
+
import { a as normalizeActorHandle, i as isActor, n as getActorHandle, r as getActorTypeName, t as getActorClassByTypeName } from "./actor-chbmxipX.mjs";
|
|
6
6
|
import { createTestMeterProvider, test } from "@fedify/fixture";
|
|
7
7
|
import { deepStrictEqual, ok, rejects, strictEqual, throws } from "node:assert/strict";
|
|
8
8
|
//#region ../../node_modules/.pnpm/fast-check@3.23.2/node_modules/fast-check/lib/esm/check/precondition/PreconditionFailure.js
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
|
-
import { Q as __toESM, X as __commonJSMin } from "./vocab-
|
|
3
|
+
import { Q as __toESM, X as __commonJSMin } from "./vocab-BJGPw--L.mjs";
|
|
4
4
|
//#endregion
|
|
5
5
|
//#region ../../node_modules/.pnpm/regexparam@3.0.0/node_modules/regexparam/dist/index.mjs
|
|
6
6
|
var import_glob_to_regexp = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
|