@fedify/vocab 2.5.0-dev.2446 → 2.5.0-dev.2448
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 +36 -3
- package/dist/mod.d.cts +35 -1
- package/dist/mod.d.ts +35 -1
- package/dist/mod.js +37 -5
- package/dist-tests/{actor-C89Bex4F.mjs → actor-C93GLWk5.mjs} +1 -1
- package/dist-tests/actor.test.mjs +1 -1
- package/dist-tests/gateway.test.mjs +1 -1
- package/dist-tests/license.test.mjs +1 -1
- package/dist-tests/{lookup-BehNGq4X.mjs → lookup-C4i0dNeY.mjs} +37 -5
- package/dist-tests/lookup.test.mjs +100 -1
- package/dist-tests/portable-lookup.test.mjs +2 -2
- package/dist-tests/{src-fpZm9WyF.mjs → src-Dn87CPDV.mjs} +2 -2
- package/dist-tests/translation.test.mjs +1 -1
- package/package.json +4 -4
- package/src/lookup.test.ts +124 -1
- package/src/lookup.ts +67 -7
package/deno.json
CHANGED
package/dist/mod.cjs
CHANGED
|
@@ -36,7 +36,7 @@ let _fedify_vocab_runtime_temporal = require("@fedify/vocab-runtime/temporal");
|
|
|
36
36
|
let es_toolkit = require("es-toolkit");
|
|
37
37
|
//#region deno.json
|
|
38
38
|
var name = "@fedify/vocab";
|
|
39
|
-
var version = "2.5.0-dev.
|
|
39
|
+
var version = "2.5.0-dev.2448+756933d0";
|
|
40
40
|
//#endregion
|
|
41
41
|
//#region src/type.ts
|
|
42
42
|
function getTypeId(object) {
|
|
@@ -81571,6 +81571,20 @@ const logger = (0, _logtape_logtape.getLogger)([
|
|
|
81571
81571
|
"lookup"
|
|
81572
81572
|
]);
|
|
81573
81573
|
/**
|
|
81574
|
+
* Options for the {@link lookupObject} function.
|
|
81575
|
+
*
|
|
81576
|
+
* @since 0.2.0
|
|
81577
|
+
*/
|
|
81578
|
+
/**
|
|
81579
|
+
* The key of the {@link LookupObjectOptions} property that observes how
|
|
81580
|
+
* {@link lookupObject} selects the object it returns.
|
|
81581
|
+
*
|
|
81582
|
+
* @internal Technically exported for other Fedify packages, but not part of
|
|
81583
|
+
* the public API contract. This is not considered public API for Semantic
|
|
81584
|
+
* Versioning decisions.
|
|
81585
|
+
*/
|
|
81586
|
+
const lookupObserver = Symbol.for("@fedify/vocab/lookupObserver");
|
|
81587
|
+
/**
|
|
81574
81588
|
* The maximum number of requests to FEP-ef61 gateways that a single
|
|
81575
81589
|
* {@link lookupObject} call makes for portable objects. Gateways come from
|
|
81576
81590
|
* possibly untrusted WebFinger responses and location hints, so they are
|
|
@@ -81690,8 +81704,13 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
81690
81704
|
remoteDoc = await documentLoader(identifier.href, { signal: options.signal });
|
|
81691
81705
|
} catch (error) {
|
|
81692
81706
|
logger.debug("Failed to fetch remote document:\n{error}", { error });
|
|
81707
|
+
options[lookupObserver]?.failed?.({
|
|
81708
|
+
operation: "fetch",
|
|
81709
|
+
error
|
|
81710
|
+
});
|
|
81693
81711
|
}
|
|
81694
81712
|
}
|
|
81713
|
+
if (remoteDoc == null && options[lookupObserver]?.webFinger === false) return null;
|
|
81695
81714
|
if (remoteDoc == null) {
|
|
81696
81715
|
const jrd = await (0, _fedify_webfinger.lookupWebFinger)(identifier, {
|
|
81697
81716
|
userAgent: options.userAgent,
|
|
@@ -81736,7 +81755,7 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
81736
81755
|
}
|
|
81737
81756
|
}
|
|
81738
81757
|
if (remoteDoc == null) return null;
|
|
81739
|
-
const snapshot = options.verifyPortableObject == null ? null : (0, _fedify_vocab_runtime_internal_portable_dereference.createSnapshotContextLoader)(options.contextLoader ?? (0, _fedify_vocab_runtime.getDocumentLoader)({ userAgent: options.userAgent }));
|
|
81758
|
+
const snapshot = options.verifyPortableObject == null && options[lookupObserver] == null ? null : (0, _fedify_vocab_runtime_internal_portable_dereference.createSnapshotContextLoader)(options.contextLoader ?? (0, _fedify_vocab_runtime.getDocumentLoader)({ userAgent: options.userAgent }));
|
|
81740
81759
|
try {
|
|
81741
81760
|
let object;
|
|
81742
81761
|
let documentUrl;
|
|
@@ -81750,6 +81769,10 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
81750
81769
|
baseUrl: documentUrl
|
|
81751
81770
|
});
|
|
81752
81771
|
} catch (error) {
|
|
81772
|
+
options[lookupObserver]?.failed?.({
|
|
81773
|
+
operation: "parse",
|
|
81774
|
+
error
|
|
81775
|
+
});
|
|
81753
81776
|
if (error instanceof TypeError) {
|
|
81754
81777
|
logger.debug("Failed to parse JSON-LD document: {error}\n{document}", {
|
|
81755
81778
|
...remoteDoc,
|
|
@@ -81759,7 +81782,7 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
81759
81782
|
}
|
|
81760
81783
|
throw error;
|
|
81761
81784
|
}
|
|
81762
|
-
if (snapshot != null) {
|
|
81785
|
+
if (options.verifyPortableObject != null && snapshot != null) {
|
|
81763
81786
|
const claim = (0, _fedify_vocab_runtime_internal_portable_dereference.getPortableResponseClaim)(remoteDoc.documentUrl, object.id);
|
|
81764
81787
|
if (claim === null) {
|
|
81765
81788
|
logger.debug("Refusing the document {documentUrl}, as it claims to be a portable object with a malformed compatible identifier.", { documentUrl: remoteDoc.documentUrl });
|
|
@@ -81778,8 +81801,16 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
81778
81801
|
...remoteDoc,
|
|
81779
81802
|
objectId: object.id.href
|
|
81780
81803
|
});
|
|
81804
|
+
options[lookupObserver]?.failed?.({ operation: "origin" });
|
|
81781
81805
|
return null;
|
|
81782
81806
|
}
|
|
81807
|
+
if (!await (0, _fedify_vocab_runtime_internal_portable_dereference.acceptCandidate)(options[lookupObserver], {
|
|
81808
|
+
document: remoteDoc.document,
|
|
81809
|
+
documentUrl: remoteDoc.documentUrl,
|
|
81810
|
+
baseUrl: documentUrl,
|
|
81811
|
+
contextLoader: snapshot?.loader ?? options.contextLoader ?? (0, _fedify_vocab_runtime.getDocumentLoader)({ userAgent: options.userAgent }),
|
|
81812
|
+
object
|
|
81813
|
+
})) return null;
|
|
81783
81814
|
return object;
|
|
81784
81815
|
} finally {
|
|
81785
81816
|
snapshot?.release();
|
|
@@ -81893,6 +81924,7 @@ async function dereference({ options, documentLoader }, id, inferredGateways, ga
|
|
|
81893
81924
|
verifyPortableObject: options.verifyPortableObject,
|
|
81894
81925
|
crossOrigin: options.crossOrigin === "throw" ? "throw" : "ignore",
|
|
81895
81926
|
signal: options.signal,
|
|
81927
|
+
observer: options[lookupObserver],
|
|
81896
81928
|
parse: (document, { contextLoader, baseUrl }) => Object$1.fromJsonLd(document, {
|
|
81897
81929
|
documentLoader,
|
|
81898
81930
|
contextLoader,
|
|
@@ -82043,6 +82075,7 @@ exports.isActor = isActor;
|
|
|
82043
82075
|
exports.isEntityType = isEntityType;
|
|
82044
82076
|
exports.isFediverseHandle = isFediverseHandle;
|
|
82045
82077
|
exports.lookupObject = lookupObject;
|
|
82078
|
+
exports.lookupObserver = lookupObserver;
|
|
82046
82079
|
exports.normalizeActorHandle = normalizeActorHandle;
|
|
82047
82080
|
exports.normalizeLinkToImage = normalizeLinkToImage;
|
|
82048
82081
|
exports.parseFediverseHandle = parseFediverseHandle;
|
package/dist/mod.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
2
|
import { Decimal, Decimal as Decimal$1, DocumentLoader, DocumentLoader as DocumentLoader$1, DocumentLoaderOptions, GetUserAgentOptions, GetUserAgentOptions as GetUserAgentOptions$1, Json, LanguageString, LanguageString as LanguageString$1, PortableObjectReferrer, PortableObjectVerification, PortableObjectVerifier, PortableObjectVerifier as PortableObjectVerifier$1, PortableObjectVerifierOptions, PropertyPreprocessor, PropertyPreprocessor as PropertyPreprocessor$1, PropertyPreprocessorContext, RemoteDocument } from "@fedify/vocab-runtime";
|
|
3
3
|
import { MeterProvider, Span, TracerProvider } from "@opentelemetry/api";
|
|
4
|
+
import { DereferenceObserver } from "@fedify/vocab-runtime/internal/portable-dereference";
|
|
4
5
|
|
|
5
6
|
//#region src/vocab.d.ts
|
|
6
7
|
/** Describes an object of any kind. The Object type serves as the base type for
|
|
@@ -25673,6 +25674,34 @@ type ObjectLookupKind = "actor" | "object" | "other";
|
|
|
25673
25674
|
*
|
|
25674
25675
|
* @since 0.2.0
|
|
25675
25676
|
*/
|
|
25677
|
+
/**
|
|
25678
|
+
* The key of the {@link LookupObjectOptions} property that observes how
|
|
25679
|
+
* {@link lookupObject} selects the object it returns.
|
|
25680
|
+
*
|
|
25681
|
+
* @internal Technically exported for other Fedify packages, but not part of
|
|
25682
|
+
* the public API contract. This is not considered public API for Semantic
|
|
25683
|
+
* Versioning decisions.
|
|
25684
|
+
*/
|
|
25685
|
+
declare const lookupObserver: unique symbol;
|
|
25686
|
+
/**
|
|
25687
|
+
* Observes how {@link lookupObject} selects the object it returns: each
|
|
25688
|
+
* candidate is offered to {@link DereferenceObserver.accept} at the boundary
|
|
25689
|
+
* that would otherwise return it, both for ordinary documents and for
|
|
25690
|
+
* FEP-ef61 portable objects, and each failure that does not propagate is
|
|
25691
|
+
* reported to {@link DereferenceObserver.failed}. The observer is not passed
|
|
25692
|
+
* on to the returned object.
|
|
25693
|
+
*
|
|
25694
|
+
* @internal Technically exported for other Fedify packages, but not part of
|
|
25695
|
+
* the public API contract. This is not considered public API for Semantic
|
|
25696
|
+
* Versioning decisions.
|
|
25697
|
+
*/
|
|
25698
|
+
interface LookupObserver extends DereferenceObserver<Object$1> {
|
|
25699
|
+
/**
|
|
25700
|
+
* Whether to fall back to WebFinger when an HTTP(S) URL cannot be fetched.
|
|
25701
|
+
* Defaults to `true`.
|
|
25702
|
+
*/
|
|
25703
|
+
readonly webFinger?: boolean;
|
|
25704
|
+
}
|
|
25676
25705
|
interface LookupObjectOptions {
|
|
25677
25706
|
/**
|
|
25678
25707
|
* The document loader for loading remote JSON-LD documents.
|
|
@@ -25768,6 +25797,11 @@ interface LookupObjectOptions {
|
|
|
25768
25797
|
* @since 2.4.0
|
|
25769
25798
|
*/
|
|
25770
25799
|
verifyPortableObject?: PortableObjectVerifier$1;
|
|
25800
|
+
/**
|
|
25801
|
+
* See {@link LookupObserver}.
|
|
25802
|
+
* @internal
|
|
25803
|
+
*/
|
|
25804
|
+
[lookupObserver]?: LookupObserver;
|
|
25771
25805
|
}
|
|
25772
25806
|
/**
|
|
25773
25807
|
* Looks up an ActivityStreams object by its URI (including `acct:` URIs)
|
|
@@ -25992,4 +26026,4 @@ declare function getTypeId(object: Object$1 | Link | null): URL | null;
|
|
|
25992
26026
|
*/
|
|
25993
26027
|
declare function getTypeId(object: Object$1 | Link | null | undefined): URL | null | undefined;
|
|
25994
26028
|
//#endregion
|
|
25995
|
-
export { $EntityType, Accept, Activity, Actor, ActorDiscoveryResult, ActorTypeName, Add, Agreement, Announce, AnnounceAuthorization, AnnounceRequest, Application, Arrive, Article, Audio, Block, ChatMessage, Collection, CollectionPage, Commitment, Create, CryptographicKey, DataIntegrityProof, type Decimal, Delete, DidService, Dislike, Document, type DocumentLoader, type DocumentLoaderOptions, Emoji, EmojiReact, Endpoints, Event, Export, FeatureAuthorization, FeatureRequest, FeaturedCollection, FeaturedItem, FediverseHandle, Flag, Follow, GetActorHandleOptions, type GetUserAgentOptions, Group, Hashtag, Ignore, Image, Intent, InteractionPolicy, InteractionRule, IntransitiveActivity, Invite, Join, type Json, LanguageString, Leave, Like, LikeAuthorization, LikeRequest, Link, Listen, LookupObjectOptions, Measure, Mention, Move, Multikey, NormalizeActorHandleOptions, Note, Object$1 as Object, ObjectLookupKind, Offer, OrderedCollection, OrderedCollectionPage, Organization, PUBLIC_COLLECTION, Page, Person, Place, type PortableObjectReferrer, type PortableObjectVerification, type PortableObjectVerifier, type PortableObjectVerifierOptions, Profile, type PropertyPreprocessor, type PropertyPreprocessorContext, PropertyValue, Proposal, Question, QuoteAuthorization, QuoteRequest, Read, Recipient, Reject, Relationship, type RemoteDocument, Remove, ReplyAuthorization, ReplyRequest, Service, Source, TentativeAccept, TentativeReject, Tombstone, Translation, Travel, TraverseCollectionOptions, Undo, Update, Video, View, getActorClassByTypeName, getActorHandle, getActorTypeName, getEntityTypeById, getTypeId, isActor, isEntityType, isFediverseHandle, lookupObject, normalizeActorHandle, normalizeLinkToImage, parseFediverseHandle, toAcctUrl, traverseCollection };
|
|
26029
|
+
export { $EntityType, Accept, Activity, Actor, ActorDiscoveryResult, ActorTypeName, Add, Agreement, Announce, AnnounceAuthorization, AnnounceRequest, Application, Arrive, Article, Audio, Block, ChatMessage, Collection, CollectionPage, Commitment, Create, CryptographicKey, DataIntegrityProof, type Decimal, Delete, DidService, Dislike, Document, type DocumentLoader, type DocumentLoaderOptions, Emoji, EmojiReact, Endpoints, Event, Export, FeatureAuthorization, FeatureRequest, FeaturedCollection, FeaturedItem, FediverseHandle, Flag, Follow, GetActorHandleOptions, type GetUserAgentOptions, Group, Hashtag, Ignore, Image, Intent, InteractionPolicy, InteractionRule, IntransitiveActivity, Invite, Join, type Json, LanguageString, Leave, Like, LikeAuthorization, LikeRequest, Link, Listen, LookupObjectOptions, LookupObserver, Measure, Mention, Move, Multikey, NormalizeActorHandleOptions, Note, Object$1 as Object, ObjectLookupKind, Offer, OrderedCollection, OrderedCollectionPage, Organization, PUBLIC_COLLECTION, Page, Person, Place, type PortableObjectReferrer, type PortableObjectVerification, type PortableObjectVerifier, type PortableObjectVerifierOptions, Profile, type PropertyPreprocessor, type PropertyPreprocessorContext, PropertyValue, Proposal, Question, QuoteAuthorization, QuoteRequest, Read, Recipient, Reject, Relationship, type RemoteDocument, Remove, ReplyAuthorization, ReplyRequest, Service, Source, TentativeAccept, TentativeReject, Tombstone, Translation, Travel, TraverseCollectionOptions, Undo, Update, Video, View, getActorClassByTypeName, getActorHandle, getActorTypeName, getEntityTypeById, getTypeId, isActor, isEntityType, isFediverseHandle, lookupObject, lookupObserver, normalizeActorHandle, normalizeLinkToImage, parseFediverseHandle, toAcctUrl, traverseCollection };
|
package/dist/mod.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference lib="esnext.temporal" />
|
|
2
2
|
import { Decimal, Decimal as Decimal$1, DocumentLoader, DocumentLoader as DocumentLoader$1, DocumentLoaderOptions, GetUserAgentOptions, GetUserAgentOptions as GetUserAgentOptions$1, Json, LanguageString, LanguageString as LanguageString$1, PortableObjectReferrer, PortableObjectVerification, PortableObjectVerifier, PortableObjectVerifier as PortableObjectVerifier$1, PortableObjectVerifierOptions, PropertyPreprocessor, PropertyPreprocessor as PropertyPreprocessor$1, PropertyPreprocessorContext, RemoteDocument } from "@fedify/vocab-runtime";
|
|
3
3
|
import { MeterProvider, Span, TracerProvider } from "@opentelemetry/api";
|
|
4
|
+
import { DereferenceObserver } from "@fedify/vocab-runtime/internal/portable-dereference";
|
|
4
5
|
|
|
5
6
|
//#region src/vocab.d.ts
|
|
6
7
|
/** Describes an object of any kind. The Object type serves as the base type for
|
|
@@ -25673,6 +25674,34 @@ type ObjectLookupKind = "actor" | "object" | "other";
|
|
|
25673
25674
|
*
|
|
25674
25675
|
* @since 0.2.0
|
|
25675
25676
|
*/
|
|
25677
|
+
/**
|
|
25678
|
+
* The key of the {@link LookupObjectOptions} property that observes how
|
|
25679
|
+
* {@link lookupObject} selects the object it returns.
|
|
25680
|
+
*
|
|
25681
|
+
* @internal Technically exported for other Fedify packages, but not part of
|
|
25682
|
+
* the public API contract. This is not considered public API for Semantic
|
|
25683
|
+
* Versioning decisions.
|
|
25684
|
+
*/
|
|
25685
|
+
declare const lookupObserver: unique symbol;
|
|
25686
|
+
/**
|
|
25687
|
+
* Observes how {@link lookupObject} selects the object it returns: each
|
|
25688
|
+
* candidate is offered to {@link DereferenceObserver.accept} at the boundary
|
|
25689
|
+
* that would otherwise return it, both for ordinary documents and for
|
|
25690
|
+
* FEP-ef61 portable objects, and each failure that does not propagate is
|
|
25691
|
+
* reported to {@link DereferenceObserver.failed}. The observer is not passed
|
|
25692
|
+
* on to the returned object.
|
|
25693
|
+
*
|
|
25694
|
+
* @internal Technically exported for other Fedify packages, but not part of
|
|
25695
|
+
* the public API contract. This is not considered public API for Semantic
|
|
25696
|
+
* Versioning decisions.
|
|
25697
|
+
*/
|
|
25698
|
+
interface LookupObserver extends DereferenceObserver<Object$1> {
|
|
25699
|
+
/**
|
|
25700
|
+
* Whether to fall back to WebFinger when an HTTP(S) URL cannot be fetched.
|
|
25701
|
+
* Defaults to `true`.
|
|
25702
|
+
*/
|
|
25703
|
+
readonly webFinger?: boolean;
|
|
25704
|
+
}
|
|
25676
25705
|
interface LookupObjectOptions {
|
|
25677
25706
|
/**
|
|
25678
25707
|
* The document loader for loading remote JSON-LD documents.
|
|
@@ -25768,6 +25797,11 @@ interface LookupObjectOptions {
|
|
|
25768
25797
|
* @since 2.4.0
|
|
25769
25798
|
*/
|
|
25770
25799
|
verifyPortableObject?: PortableObjectVerifier$1;
|
|
25800
|
+
/**
|
|
25801
|
+
* See {@link LookupObserver}.
|
|
25802
|
+
* @internal
|
|
25803
|
+
*/
|
|
25804
|
+
[lookupObserver]?: LookupObserver;
|
|
25771
25805
|
}
|
|
25772
25806
|
/**
|
|
25773
25807
|
* Looks up an ActivityStreams object by its URI (including `acct:` URIs)
|
|
@@ -25992,4 +26026,4 @@ declare function getTypeId(object: Object$1 | Link | null): URL | null;
|
|
|
25992
26026
|
*/
|
|
25993
26027
|
declare function getTypeId(object: Object$1 | Link | null | undefined): URL | null | undefined;
|
|
25994
26028
|
//#endregion
|
|
25995
|
-
export { $EntityType, Accept, Activity, Actor, ActorDiscoveryResult, ActorTypeName, Add, Agreement, Announce, AnnounceAuthorization, AnnounceRequest, Application, Arrive, Article, Audio, Block, ChatMessage, Collection, CollectionPage, Commitment, Create, CryptographicKey, DataIntegrityProof, type Decimal, Delete, DidService, Dislike, Document, type DocumentLoader, type DocumentLoaderOptions, Emoji, EmojiReact, Endpoints, Event, Export, FeatureAuthorization, FeatureRequest, FeaturedCollection, FeaturedItem, FediverseHandle, Flag, Follow, GetActorHandleOptions, type GetUserAgentOptions, Group, Hashtag, Ignore, Image, Intent, InteractionPolicy, InteractionRule, IntransitiveActivity, Invite, Join, type Json, LanguageString, Leave, Like, LikeAuthorization, LikeRequest, Link, Listen, LookupObjectOptions, Measure, Mention, Move, Multikey, NormalizeActorHandleOptions, Note, Object$1 as Object, ObjectLookupKind, Offer, OrderedCollection, OrderedCollectionPage, Organization, PUBLIC_COLLECTION, Page, Person, Place, type PortableObjectReferrer, type PortableObjectVerification, type PortableObjectVerifier, type PortableObjectVerifierOptions, Profile, type PropertyPreprocessor, type PropertyPreprocessorContext, PropertyValue, Proposal, Question, QuoteAuthorization, QuoteRequest, Read, Recipient, Reject, Relationship, type RemoteDocument, Remove, ReplyAuthorization, ReplyRequest, Service, Source, TentativeAccept, TentativeReject, Tombstone, Translation, Travel, TraverseCollectionOptions, Undo, Update, Video, View, getActorClassByTypeName, getActorHandle, getActorTypeName, getEntityTypeById, getTypeId, isActor, isEntityType, isFediverseHandle, lookupObject, normalizeActorHandle, normalizeLinkToImage, parseFediverseHandle, toAcctUrl, traverseCollection };
|
|
26029
|
+
export { $EntityType, Accept, Activity, Actor, ActorDiscoveryResult, ActorTypeName, Add, Agreement, Announce, AnnounceAuthorization, AnnounceRequest, Application, Arrive, Article, Audio, Block, ChatMessage, Collection, CollectionPage, Commitment, Create, CryptographicKey, DataIntegrityProof, type Decimal, Delete, DidService, Dislike, Document, type DocumentLoader, type DocumentLoaderOptions, Emoji, EmojiReact, Endpoints, Event, Export, FeatureAuthorization, FeatureRequest, FeaturedCollection, FeaturedItem, FediverseHandle, Flag, Follow, GetActorHandleOptions, type GetUserAgentOptions, Group, Hashtag, Ignore, Image, Intent, InteractionPolicy, InteractionRule, IntransitiveActivity, Invite, Join, type Json, LanguageString, Leave, Like, LikeAuthorization, LikeRequest, Link, Listen, LookupObjectOptions, LookupObserver, Measure, Mention, Move, Multikey, NormalizeActorHandleOptions, Note, Object$1 as Object, ObjectLookupKind, Offer, OrderedCollection, OrderedCollectionPage, Organization, PUBLIC_COLLECTION, Page, Person, Place, type PortableObjectReferrer, type PortableObjectVerification, type PortableObjectVerifier, type PortableObjectVerifierOptions, Profile, type PropertyPreprocessor, type PropertyPreprocessorContext, PropertyValue, Proposal, Question, QuoteAuthorization, QuoteRequest, Read, Recipient, Reject, Relationship, type RemoteDocument, Remove, ReplyAuthorization, ReplyRequest, Service, Source, TentativeAccept, TentativeReject, Tombstone, Translation, Travel, TraverseCollectionOptions, Undo, Update, Video, View, getActorClassByTypeName, getActorHandle, getActorTypeName, getEntityTypeById, getTypeId, isActor, isEntityType, isFediverseHandle, lookupObject, lookupObserver, normalizeActorHandle, normalizeLinkToImage, parseFediverseHandle, toAcctUrl, traverseCollection };
|
package/dist/mod.js
CHANGED
|
@@ -6,13 +6,13 @@ import { domainToASCII, domainToUnicode } from "node:url";
|
|
|
6
6
|
import jsonld from "@fedify/vocab-runtime/jsonld";
|
|
7
7
|
import { getLogger } from "@logtape/logtape";
|
|
8
8
|
import { compactJsonLdCache, createScopedContextLoader, getPortableActorGateways, isTrustedIriOrigin, normalizeJsonLdIris } from "@fedify/vocab-runtime/internal/jsonld-cache";
|
|
9
|
-
import { PortableObjectRejectedError, copyPortableProvenance, createSnapshotContextLoader, dereferencePortableIri, getPortableGatewayCandidates, getPortableResponseClaim, getReferrerGateways, isPortableIri, isPortableMode, isUnsecuredPortableObject, isUnverifiedPortableClaim, markUnverifiedPortableClaim, mustDereferencePortableObject, parseCompatibleEf61Reference, recordPortableReferrer, rejectMalformedCompatibleReference, warnUnverifiableEmbeddedObject } from "@fedify/vocab-runtime/internal/portable-dereference";
|
|
9
|
+
import { PortableObjectRejectedError, acceptCandidate, copyPortableProvenance, createSnapshotContextLoader, dereferencePortableIri, getPortableGatewayCandidates, getPortableResponseClaim, getReferrerGateways, isPortableIri, isPortableMode, isUnsecuredPortableObject, isUnverifiedPortableClaim, markUnverifiedPortableClaim, mustDereferencePortableObject, parseCompatibleEf61Reference, recordPortableReferrer, rejectMalformedCompatibleReference, warnUnverifiableEmbeddedObject } from "@fedify/vocab-runtime/internal/portable-dereference";
|
|
10
10
|
import { enterSignedValueScope, resolveSignedValues, retainedSignedValueRef } from "@fedify/vocab-runtime/internal/signed-representation";
|
|
11
11
|
import { isTemporalDuration, isTemporalInstant } from "@fedify/vocab-runtime/temporal";
|
|
12
12
|
import { delay } from "es-toolkit";
|
|
13
13
|
//#region deno.json
|
|
14
14
|
var name = "@fedify/vocab";
|
|
15
|
-
var version = "2.5.0-dev.
|
|
15
|
+
var version = "2.5.0-dev.2448+756933d0";
|
|
16
16
|
//#endregion
|
|
17
17
|
//#region src/type.ts
|
|
18
18
|
function getTypeId(object) {
|
|
@@ -77981,6 +77981,20 @@ const logger = getLogger([
|
|
|
77981
77981
|
"lookup"
|
|
77982
77982
|
]);
|
|
77983
77983
|
/**
|
|
77984
|
+
* Options for the {@link lookupObject} function.
|
|
77985
|
+
*
|
|
77986
|
+
* @since 0.2.0
|
|
77987
|
+
*/
|
|
77988
|
+
/**
|
|
77989
|
+
* The key of the {@link LookupObjectOptions} property that observes how
|
|
77990
|
+
* {@link lookupObject} selects the object it returns.
|
|
77991
|
+
*
|
|
77992
|
+
* @internal Technically exported for other Fedify packages, but not part of
|
|
77993
|
+
* the public API contract. This is not considered public API for Semantic
|
|
77994
|
+
* Versioning decisions.
|
|
77995
|
+
*/
|
|
77996
|
+
const lookupObserver = Symbol.for("@fedify/vocab/lookupObserver");
|
|
77997
|
+
/**
|
|
77984
77998
|
* The maximum number of requests to FEP-ef61 gateways that a single
|
|
77985
77999
|
* {@link lookupObject} call makes for portable objects. Gateways come from
|
|
77986
78000
|
* possibly untrusted WebFinger responses and location hints, so they are
|
|
@@ -78100,8 +78114,13 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
78100
78114
|
remoteDoc = await documentLoader(identifier.href, { signal: options.signal });
|
|
78101
78115
|
} catch (error) {
|
|
78102
78116
|
logger.debug("Failed to fetch remote document:\n{error}", { error });
|
|
78117
|
+
options[lookupObserver]?.failed?.({
|
|
78118
|
+
operation: "fetch",
|
|
78119
|
+
error
|
|
78120
|
+
});
|
|
78103
78121
|
}
|
|
78104
78122
|
}
|
|
78123
|
+
if (remoteDoc == null && options[lookupObserver]?.webFinger === false) return null;
|
|
78105
78124
|
if (remoteDoc == null) {
|
|
78106
78125
|
const jrd = await lookupWebFinger(identifier, {
|
|
78107
78126
|
userAgent: options.userAgent,
|
|
@@ -78146,7 +78165,7 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
78146
78165
|
}
|
|
78147
78166
|
}
|
|
78148
78167
|
if (remoteDoc == null) return null;
|
|
78149
|
-
const snapshot = options.verifyPortableObject == null ? null : createSnapshotContextLoader(options.contextLoader ?? getDocumentLoader({ userAgent: options.userAgent }));
|
|
78168
|
+
const snapshot = options.verifyPortableObject == null && options[lookupObserver] == null ? null : createSnapshotContextLoader(options.contextLoader ?? getDocumentLoader({ userAgent: options.userAgent }));
|
|
78150
78169
|
try {
|
|
78151
78170
|
let object;
|
|
78152
78171
|
let documentUrl;
|
|
@@ -78160,6 +78179,10 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
78160
78179
|
baseUrl: documentUrl
|
|
78161
78180
|
});
|
|
78162
78181
|
} catch (error) {
|
|
78182
|
+
options[lookupObserver]?.failed?.({
|
|
78183
|
+
operation: "parse",
|
|
78184
|
+
error
|
|
78185
|
+
});
|
|
78163
78186
|
if (error instanceof TypeError) {
|
|
78164
78187
|
logger.debug("Failed to parse JSON-LD document: {error}\n{document}", {
|
|
78165
78188
|
...remoteDoc,
|
|
@@ -78169,7 +78192,7 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
78169
78192
|
}
|
|
78170
78193
|
throw error;
|
|
78171
78194
|
}
|
|
78172
|
-
if (snapshot != null) {
|
|
78195
|
+
if (options.verifyPortableObject != null && snapshot != null) {
|
|
78173
78196
|
const claim = getPortableResponseClaim(remoteDoc.documentUrl, object.id);
|
|
78174
78197
|
if (claim === null) {
|
|
78175
78198
|
logger.debug("Refusing the document {documentUrl}, as it claims to be a portable object with a malformed compatible identifier.", { documentUrl: remoteDoc.documentUrl });
|
|
@@ -78188,8 +78211,16 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
78188
78211
|
...remoteDoc,
|
|
78189
78212
|
objectId: object.id.href
|
|
78190
78213
|
});
|
|
78214
|
+
options[lookupObserver]?.failed?.({ operation: "origin" });
|
|
78191
78215
|
return null;
|
|
78192
78216
|
}
|
|
78217
|
+
if (!await acceptCandidate(options[lookupObserver], {
|
|
78218
|
+
document: remoteDoc.document,
|
|
78219
|
+
documentUrl: remoteDoc.documentUrl,
|
|
78220
|
+
baseUrl: documentUrl,
|
|
78221
|
+
contextLoader: snapshot?.loader ?? options.contextLoader ?? getDocumentLoader({ userAgent: options.userAgent }),
|
|
78222
|
+
object
|
|
78223
|
+
})) return null;
|
|
78193
78224
|
return object;
|
|
78194
78225
|
} finally {
|
|
78195
78226
|
snapshot?.release();
|
|
@@ -78303,6 +78334,7 @@ async function dereference({ options, documentLoader }, id, inferredGateways, ga
|
|
|
78303
78334
|
verifyPortableObject: options.verifyPortableObject,
|
|
78304
78335
|
crossOrigin: options.crossOrigin === "throw" ? "throw" : "ignore",
|
|
78305
78336
|
signal: options.signal,
|
|
78337
|
+
observer: options[lookupObserver],
|
|
78306
78338
|
parse: (document, { contextLoader, baseUrl }) => Object$1.fromJsonLd(document, {
|
|
78307
78339
|
documentLoader,
|
|
78308
78340
|
contextLoader,
|
|
@@ -78351,4 +78383,4 @@ async function* traverseCollection(collection, options = {}) {
|
|
|
78351
78383
|
}
|
|
78352
78384
|
}
|
|
78353
78385
|
//#endregion
|
|
78354
|
-
export { Accept, Activity, Add, Agreement, Announce, AnnounceAuthorization, AnnounceRequest, Application, Arrive, Article, Audio, Block, ChatMessage, Collection, CollectionPage, Commitment, Create, CryptographicKey, DataIntegrityProof, Delete, DidService, Dislike, Document, Emoji, EmojiReact, Endpoints, Event, Export, FeatureAuthorization, FeatureRequest, FeaturedCollection, FeaturedItem, Flag, Follow, Group, Hashtag, Ignore, Image, Intent, InteractionPolicy, InteractionRule, IntransitiveActivity, Invite, Join, LanguageString, Leave, Like, LikeAuthorization, LikeRequest, Link, Listen, Measure, Mention, Move, Multikey, Note, Object$1 as Object, Offer, OrderedCollection, OrderedCollectionPage, Organization, PUBLIC_COLLECTION, Page, Person, Place, Profile, PropertyValue, Proposal, Question, QuoteAuthorization, QuoteRequest, Read, Reject, Relationship, Remove, ReplyAuthorization, ReplyRequest, Service, Source, TentativeAccept, TentativeReject, Tombstone, Translation, Travel, Undo, Update, Video, View, getActorClassByTypeName, getActorHandle, getActorTypeName, getEntityTypeById, getTypeId, isActor, isEntityType, isFediverseHandle, lookupObject, normalizeActorHandle, normalizeLinkToImage, parseFediverseHandle, toAcctUrl, traverseCollection };
|
|
78386
|
+
export { Accept, Activity, Add, Agreement, Announce, AnnounceAuthorization, AnnounceRequest, Application, Arrive, Article, Audio, Block, ChatMessage, Collection, CollectionPage, Commitment, Create, CryptographicKey, DataIntegrityProof, Delete, DidService, Dislike, Document, Emoji, EmojiReact, Endpoints, Event, Export, FeatureAuthorization, FeatureRequest, FeaturedCollection, FeaturedItem, Flag, Follow, Group, Hashtag, Ignore, Image, Intent, InteractionPolicy, InteractionRule, IntransitiveActivity, Invite, Join, LanguageString, Leave, Like, LikeAuthorization, LikeRequest, Link, Listen, Measure, Mention, Move, Multikey, Note, Object$1 as Object, Offer, OrderedCollection, OrderedCollectionPage, Organization, PUBLIC_COLLECTION, Page, Person, Place, Profile, PropertyValue, Proposal, Question, QuoteAuthorization, QuoteRequest, Read, Reject, Relationship, Remove, ReplyAuthorization, ReplyRequest, Service, Source, TentativeAccept, TentativeReject, Tombstone, Translation, Travel, Undo, Update, Video, View, getActorClassByTypeName, getActorHandle, getActorTypeName, getEntityTypeById, getTypeId, isActor, isEntityType, isFediverseHandle, lookupObject, lookupObserver, normalizeActorHandle, normalizeLinkToImage, parseFediverseHandle, toAcctUrl, traverseCollection };
|
|
@@ -8,7 +8,7 @@ import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
|
8
8
|
import { domainToASCII, domainToUnicode } from "node:url";
|
|
9
9
|
//#region deno.json
|
|
10
10
|
var name = "@fedify/vocab";
|
|
11
|
-
var version = "2.5.0-dev.
|
|
11
|
+
var version = "2.5.0-dev.2448+756933d0";
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region src/actor.ts
|
|
14
14
|
const ACTOR_DISCOVERY_HISTOGRAM_BUCKETS = [
|
|
@@ -2,7 +2,7 @@ import "temporal-polyfill";
|
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { $ as __exportAll, F as Person, P as Organization, U as Service, a as Application, b as Group } from "./vocab-jHKm_LJ6.mjs";
|
|
4
4
|
import { t as esm_default } from "./esm-DtAfYdqR.mjs";
|
|
5
|
-
import { a as normalizeActorHandle, i as isActor, n as getActorHandle, r as getActorTypeName, t as getActorClassByTypeName } from "./actor-
|
|
5
|
+
import { a as normalizeActorHandle, i as isActor, n as getActorHandle, r as getActorTypeName, t as getActorClassByTypeName } from "./actor-C93GLWk5.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
|
|
@@ -2,7 +2,7 @@ import "temporal-polyfill";
|
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { F as Person, M as OrderedCollection, S as Image, c as CollectionPage, k as Note, s as Collection, u as Create } from "./vocab-jHKm_LJ6.mjs";
|
|
4
4
|
import { t as esm_default } from "./esm-DtAfYdqR.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { r as traverseCollection, t as lookupObject } from "./lookup-C4i0dNeY.mjs";
|
|
6
6
|
import { t as assertInstanceOf } from "./utils-Df2odC27.mjs";
|
|
7
7
|
import { createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
8
8
|
import { deepStrictEqual, ok, rejects } from "node:assert/strict";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { E as Link, F as Person, J as Video, P as Organization, S as Image, U as Service, a as Application, b as Group, k as Note, s as Collection, u as Create, z as Question } from "./vocab-jHKm_LJ6.mjs";
|
|
4
|
-
import "./src-
|
|
4
|
+
import "./src-Dn87CPDV.mjs";
|
|
5
5
|
import { test } from "@fedify/fixture";
|
|
6
6
|
import { deepStrictEqual, ok } from "node:assert/strict";
|
|
7
7
|
import { getDocumentLoader, preloadedContexts } from "@fedify/vocab-runtime";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Temporal } from "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { A as Object$1 } from "./vocab-jHKm_LJ6.mjs";
|
|
4
|
-
import { i as isActor, o as name, s as version } from "./actor-
|
|
4
|
+
import { i as isActor, o as name, s as version } from "./actor-C93GLWk5.mjs";
|
|
5
5
|
import { t as getTypeId } from "./type-BMdjm4Eg.mjs";
|
|
6
6
|
import { canonicalizePortableUri, formatIri, getDocumentLoader, haveSameFe34Origin, haveSameIriOrigin, parseIri } from "@fedify/vocab-runtime";
|
|
7
7
|
import { lookupWebFinger } from "@fedify/webfinger";
|
|
8
8
|
import { SpanStatusCode, trace } from "@opentelemetry/api";
|
|
9
9
|
import { getLogger } from "@logtape/logtape";
|
|
10
|
-
import { PortableObjectRejectedError, createSnapshotContextLoader, dereferencePortableIri, getPortableGatewayCandidates, getPortableResponseClaim, isPortableIri, parseCompatibleEf61Reference } from "@fedify/vocab-runtime/internal/portable-dereference";
|
|
10
|
+
import { PortableObjectRejectedError, acceptCandidate, createSnapshotContextLoader, dereferencePortableIri, getPortableGatewayCandidates, getPortableResponseClaim, isPortableIri, parseCompatibleEf61Reference } from "@fedify/vocab-runtime/internal/portable-dereference";
|
|
11
11
|
import { delay } from "es-toolkit";
|
|
12
12
|
//#region src/handle.ts
|
|
13
13
|
/**
|
|
@@ -107,6 +107,20 @@ const logger = getLogger([
|
|
|
107
107
|
"lookup"
|
|
108
108
|
]);
|
|
109
109
|
/**
|
|
110
|
+
* Options for the {@link lookupObject} function.
|
|
111
|
+
*
|
|
112
|
+
* @since 0.2.0
|
|
113
|
+
*/
|
|
114
|
+
/**
|
|
115
|
+
* The key of the {@link LookupObjectOptions} property that observes how
|
|
116
|
+
* {@link lookupObject} selects the object it returns.
|
|
117
|
+
*
|
|
118
|
+
* @internal Technically exported for other Fedify packages, but not part of
|
|
119
|
+
* the public API contract. This is not considered public API for Semantic
|
|
120
|
+
* Versioning decisions.
|
|
121
|
+
*/
|
|
122
|
+
const lookupObserver = Symbol.for("@fedify/vocab/lookupObserver");
|
|
123
|
+
/**
|
|
110
124
|
* The maximum number of requests to FEP-ef61 gateways that a single
|
|
111
125
|
* {@link lookupObject} call makes for portable objects. Gateways come from
|
|
112
126
|
* possibly untrusted WebFinger responses and location hints, so they are
|
|
@@ -226,8 +240,13 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
226
240
|
remoteDoc = await documentLoader(identifier.href, { signal: options.signal });
|
|
227
241
|
} catch (error) {
|
|
228
242
|
logger.debug("Failed to fetch remote document:\n{error}", { error });
|
|
243
|
+
options[lookupObserver]?.failed?.({
|
|
244
|
+
operation: "fetch",
|
|
245
|
+
error
|
|
246
|
+
});
|
|
229
247
|
}
|
|
230
248
|
}
|
|
249
|
+
if (remoteDoc == null && options[lookupObserver]?.webFinger === false) return null;
|
|
231
250
|
if (remoteDoc == null) {
|
|
232
251
|
const jrd = await lookupWebFinger(identifier, {
|
|
233
252
|
userAgent: options.userAgent,
|
|
@@ -272,7 +291,7 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
272
291
|
}
|
|
273
292
|
}
|
|
274
293
|
if (remoteDoc == null) return null;
|
|
275
|
-
const snapshot = options.verifyPortableObject == null ? null : createSnapshotContextLoader(options.contextLoader ?? getDocumentLoader({ userAgent: options.userAgent }));
|
|
294
|
+
const snapshot = options.verifyPortableObject == null && options[lookupObserver] == null ? null : createSnapshotContextLoader(options.contextLoader ?? getDocumentLoader({ userAgent: options.userAgent }));
|
|
276
295
|
try {
|
|
277
296
|
let object;
|
|
278
297
|
let documentUrl;
|
|
@@ -286,6 +305,10 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
286
305
|
baseUrl: documentUrl
|
|
287
306
|
});
|
|
288
307
|
} catch (error) {
|
|
308
|
+
options[lookupObserver]?.failed?.({
|
|
309
|
+
operation: "parse",
|
|
310
|
+
error
|
|
311
|
+
});
|
|
289
312
|
if (error instanceof TypeError) {
|
|
290
313
|
logger.debug("Failed to parse JSON-LD document: {error}\n{document}", {
|
|
291
314
|
...remoteDoc,
|
|
@@ -295,7 +318,7 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
295
318
|
}
|
|
296
319
|
throw error;
|
|
297
320
|
}
|
|
298
|
-
if (snapshot != null) {
|
|
321
|
+
if (options.verifyPortableObject != null && snapshot != null) {
|
|
299
322
|
const claim = getPortableResponseClaim(remoteDoc.documentUrl, object.id);
|
|
300
323
|
if (claim === null) {
|
|
301
324
|
logger.debug("Refusing the document {documentUrl}, as it claims to be a portable object with a malformed compatible identifier.", { documentUrl: remoteDoc.documentUrl });
|
|
@@ -314,8 +337,16 @@ async function lookupObjectInternal(identifier, options = {}) {
|
|
|
314
337
|
...remoteDoc,
|
|
315
338
|
objectId: object.id.href
|
|
316
339
|
});
|
|
340
|
+
options[lookupObserver]?.failed?.({ operation: "origin" });
|
|
317
341
|
return null;
|
|
318
342
|
}
|
|
343
|
+
if (!await acceptCandidate(options[lookupObserver], {
|
|
344
|
+
document: remoteDoc.document,
|
|
345
|
+
documentUrl: remoteDoc.documentUrl,
|
|
346
|
+
baseUrl: documentUrl,
|
|
347
|
+
contextLoader: snapshot?.loader ?? options.contextLoader ?? getDocumentLoader({ userAgent: options.userAgent }),
|
|
348
|
+
object
|
|
349
|
+
})) return null;
|
|
319
350
|
return object;
|
|
320
351
|
} finally {
|
|
321
352
|
snapshot?.release();
|
|
@@ -429,6 +460,7 @@ async function dereference({ options, documentLoader }, id, inferredGateways, ga
|
|
|
429
460
|
verifyPortableObject: options.verifyPortableObject,
|
|
430
461
|
crossOrigin: options.crossOrigin === "throw" ? "throw" : "ignore",
|
|
431
462
|
signal: options.signal,
|
|
463
|
+
observer: options[lookupObserver],
|
|
432
464
|
parse: (document, { contextLoader, baseUrl }) => Object$1.fromJsonLd(document, {
|
|
433
465
|
documentLoader,
|
|
434
466
|
contextLoader,
|
|
@@ -477,4 +509,4 @@ async function* traverseCollection(collection, options = {}) {
|
|
|
477
509
|
}
|
|
478
510
|
}
|
|
479
511
|
//#endregion
|
|
480
|
-
export {
|
|
512
|
+
export { lookupObserver as n, traverseCollection as r, lookupObject as t };
|
|
@@ -2,7 +2,7 @@ import "temporal-polyfill";
|
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { A as Object$1, F as Person, k as Note, s as Collection } from "./vocab-jHKm_LJ6.mjs";
|
|
4
4
|
import { t as esm_default } from "./esm-DtAfYdqR.mjs";
|
|
5
|
-
import { n as traverseCollection, t as lookupObject } from "./lookup-
|
|
5
|
+
import { n as lookupObserver, r as traverseCollection, t as lookupObject } from "./lookup-C4i0dNeY.mjs";
|
|
6
6
|
import { t as assertInstanceOf } from "./utils-Df2odC27.mjs";
|
|
7
7
|
import { createTestMeterProvider, createTestTracerProvider, mockDocumentLoader, test } from "@fedify/fixture";
|
|
8
8
|
import { deepStrictEqual, equal, ok, rejects } from "node:assert/strict";
|
|
@@ -665,5 +665,104 @@ test("lookupObject() records activitypub.object.lookup counter", {
|
|
|
665
665
|
esm_default.hardReset();
|
|
666
666
|
}
|
|
667
667
|
});
|
|
668
|
+
const OBSERVER_DID = "did:key:z6MkhVPuyvgG1RkMv67azDqDCDERPXVrUg1i3qchXY5EACE3";
|
|
669
|
+
test("lookupObject() offers each candidate to the observer", async () => {
|
|
670
|
+
const note = {
|
|
671
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
672
|
+
id: "https://example.com/notes/1",
|
|
673
|
+
type: "Note",
|
|
674
|
+
content: "Hello"
|
|
675
|
+
};
|
|
676
|
+
const fetched = [];
|
|
677
|
+
const documentLoader = (url) => {
|
|
678
|
+
fetched.push(url);
|
|
679
|
+
if (url === "https://example.com/notes/1") return Promise.resolve({
|
|
680
|
+
contextUrl: null,
|
|
681
|
+
document: note,
|
|
682
|
+
documentUrl: "https://example.com/notes/1?redirected"
|
|
683
|
+
});
|
|
684
|
+
return Promise.reject(/* @__PURE__ */ new Error(`Not found: ${url}`));
|
|
685
|
+
};
|
|
686
|
+
const candidates = [];
|
|
687
|
+
const failures = [];
|
|
688
|
+
const accepted = await lookupObject("https://example.com/notes/1", {
|
|
689
|
+
documentLoader,
|
|
690
|
+
contextLoader: mockDocumentLoader,
|
|
691
|
+
[lookupObserver]: {
|
|
692
|
+
accept: (candidate) => {
|
|
693
|
+
candidates.push(candidate);
|
|
694
|
+
return Promise.resolve(true);
|
|
695
|
+
},
|
|
696
|
+
failed: (failure) => failures.push(failure)
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
ok(accepted instanceof Note);
|
|
700
|
+
equal(candidates.length, 1);
|
|
701
|
+
deepStrictEqual(candidates[0].document, note);
|
|
702
|
+
equal(candidates[0].documentUrl, "https://example.com/notes/1?redirected");
|
|
703
|
+
equal(candidates[0].baseUrl.href, "https://example.com/notes/1?redirected");
|
|
704
|
+
equal(candidates[0].object, accepted);
|
|
705
|
+
deepStrictEqual(failures, []);
|
|
706
|
+
for (const accept of [() => Promise.resolve(false), () => Promise.reject(/* @__PURE__ */ new Error("Oops"))]) {
|
|
707
|
+
const refusals = [];
|
|
708
|
+
equal(await lookupObject("https://example.com/notes/1", {
|
|
709
|
+
documentLoader,
|
|
710
|
+
contextLoader: mockDocumentLoader,
|
|
711
|
+
[lookupObserver]: {
|
|
712
|
+
accept,
|
|
713
|
+
failed: (f) => refusals.push(f)
|
|
714
|
+
}
|
|
715
|
+
}), null);
|
|
716
|
+
deepStrictEqual(refusals.map((f) => f.operation), ["accept"]);
|
|
717
|
+
}
|
|
718
|
+
fetched.length = 0;
|
|
719
|
+
const missing = [];
|
|
720
|
+
equal(await lookupObject("https://example.com/notes/2", {
|
|
721
|
+
documentLoader,
|
|
722
|
+
contextLoader: mockDocumentLoader,
|
|
723
|
+
[lookupObserver]: {
|
|
724
|
+
webFinger: false,
|
|
725
|
+
failed: (f) => missing.push(f)
|
|
726
|
+
}
|
|
727
|
+
}), null);
|
|
728
|
+
deepStrictEqual(fetched, ["https://example.com/notes/2"]);
|
|
729
|
+
deepStrictEqual(missing.map((f) => f.operation), ["fetch"]);
|
|
730
|
+
});
|
|
731
|
+
test("lookupObject() keeps looking after the observer refuses a portable candidate", async () => {
|
|
732
|
+
const id = `ap://${OBSERVER_DID}/notes/1`;
|
|
733
|
+
const gateways = ["https://gw1.example", "https://gw2.example"];
|
|
734
|
+
const documentLoader = (url) => Promise.resolve({
|
|
735
|
+
contextUrl: null,
|
|
736
|
+
document: {
|
|
737
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
738
|
+
id,
|
|
739
|
+
type: "Note",
|
|
740
|
+
content: url.startsWith("https://gw1.example/") ? "first" : "second"
|
|
741
|
+
},
|
|
742
|
+
documentUrl: url
|
|
743
|
+
});
|
|
744
|
+
const verifier = () => Promise.resolve({ verified: true });
|
|
745
|
+
const offered = [];
|
|
746
|
+
const failures = [];
|
|
747
|
+
const object = await lookupObject(id, {
|
|
748
|
+
documentLoader,
|
|
749
|
+
contextLoader: mockDocumentLoader,
|
|
750
|
+
gateways,
|
|
751
|
+
verifyPortableObject: verifier,
|
|
752
|
+
[lookupObserver]: {
|
|
753
|
+
accept: (candidate) => {
|
|
754
|
+
offered.push(candidate.documentUrl);
|
|
755
|
+
return Promise.resolve(offered.length > 1);
|
|
756
|
+
},
|
|
757
|
+
failed: (failure) => failures.push(failure)
|
|
758
|
+
}
|
|
759
|
+
});
|
|
760
|
+
ok(object instanceof Note);
|
|
761
|
+
equal(object.content, "second");
|
|
762
|
+
equal(offered.length, 2);
|
|
763
|
+
ok(offered[0].startsWith("https://gw1.example/"));
|
|
764
|
+
ok(offered[1].startsWith("https://gw2.example/"));
|
|
765
|
+
deepStrictEqual(failures.map((f) => f.operation), ["accept"]);
|
|
766
|
+
});
|
|
668
767
|
//#endregion
|
|
669
768
|
export {};
|
|
@@ -2,8 +2,8 @@ import "temporal-polyfill";
|
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { F as Person } from "./vocab-jHKm_LJ6.mjs";
|
|
4
4
|
import { t as esm_default } from "./esm-DtAfYdqR.mjs";
|
|
5
|
-
import { n as getActorHandle } from "./actor-
|
|
6
|
-
import { t as lookupObject } from "./lookup-
|
|
5
|
+
import { n as getActorHandle } from "./actor-C93GLWk5.mjs";
|
|
6
|
+
import { t as lookupObject } from "./lookup-C4i0dNeY.mjs";
|
|
7
7
|
import { t as assertInstanceOf } from "./utils-Df2odC27.mjs";
|
|
8
8
|
import { mockDocumentLoader, test } from "@fedify/fixture";
|
|
9
9
|
import { deepStrictEqual, equal, rejects } from "node:assert/strict";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import "./vocab-jHKm_LJ6.mjs";
|
|
4
|
-
import "./actor-
|
|
5
|
-
import "./lookup-
|
|
4
|
+
import "./actor-C93GLWk5.mjs";
|
|
5
|
+
import "./lookup-C4i0dNeY.mjs";
|
|
6
6
|
import { LanguageString as LanguageString$1 } from "@fedify/vocab-runtime";
|
|
7
7
|
new URL("https://www.w3.org/ns/activitystreams#Public");
|
|
8
8
|
//#endregion
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "temporal-polyfill";
|
|
2
2
|
globalThis.addEventListener = () => {};
|
|
3
3
|
import { A as Object$1, E as Link, F as Person, K as Translation, L as PropertyValue, P as Organization, U as Service, a as Application, b as Group, k as Note, o as Article, q as Update, s as Collection, u as Create } from "./vocab-jHKm_LJ6.mjs";
|
|
4
|
-
import { t as LanguageString$1 } from "./src-
|
|
4
|
+
import { t as LanguageString$1 } from "./src-Dn87CPDV.mjs";
|
|
5
5
|
import { test } from "@fedify/fixture";
|
|
6
6
|
import { deepStrictEqual, ok, rejects } from "node:assert/strict";
|
|
7
7
|
import { getDocumentLoader, preloadedContexts } from "@fedify/vocab-runtime";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fedify/vocab",
|
|
3
|
-
"version": "2.5.0-dev.
|
|
3
|
+
"version": "2.5.0-dev.2448+756933d0",
|
|
4
4
|
"homepage": "https://fedify.dev/",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
"jsonld": "^9.0.0",
|
|
44
44
|
"pkijs": "^3.3.3",
|
|
45
45
|
"temporal-polyfill": "^1.0.1",
|
|
46
|
-
"@fedify/
|
|
47
|
-
"@fedify/
|
|
48
|
-
"@fedify/vocab-runtime": "2.5.0-dev.
|
|
46
|
+
"@fedify/vocab-tools": "2.5.0-dev.2448+756933d0",
|
|
47
|
+
"@fedify/webfinger": "2.5.0-dev.2448+756933d0",
|
|
48
|
+
"@fedify/vocab-runtime": "2.5.0-dev.2448+756933d0"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "^24.12.2",
|
package/src/lookup.test.ts
CHANGED
|
@@ -6,7 +6,15 @@ import {
|
|
|
6
6
|
} from "@fedify/fixture";
|
|
7
7
|
import fetchMock from "fetch-mock";
|
|
8
8
|
import { deepStrictEqual, equal, ok, rejects } from "node:assert/strict";
|
|
9
|
-
import {
|
|
9
|
+
import type {
|
|
10
|
+
DocumentLoader,
|
|
11
|
+
PortableObjectVerifier,
|
|
12
|
+
} from "@fedify/vocab-runtime";
|
|
13
|
+
import type {
|
|
14
|
+
DereferenceCandidate,
|
|
15
|
+
DereferenceFailure,
|
|
16
|
+
} from "@fedify/vocab-runtime/internal/portable-dereference";
|
|
17
|
+
import { lookupObject, lookupObserver, traverseCollection } from "./lookup.ts";
|
|
10
18
|
import { assertInstanceOf } from "./utils.ts";
|
|
11
19
|
import { Collection, Note, Object, Person } from "./vocab.ts";
|
|
12
20
|
|
|
@@ -1051,3 +1059,118 @@ test("lookupObject() records activitypub.object.lookup counter", {
|
|
|
1051
1059
|
});
|
|
1052
1060
|
|
|
1053
1061
|
// cSpell: ignore gildong
|
|
1062
|
+
|
|
1063
|
+
const OBSERVER_DID = "did:key:z6MkhVPuyvgG1RkMv67azDqDCDERPXVrUg1i3qchXY5EACE3";
|
|
1064
|
+
|
|
1065
|
+
test("lookupObject() offers each candidate to the observer", async () => {
|
|
1066
|
+
const note = {
|
|
1067
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
1068
|
+
id: "https://example.com/notes/1",
|
|
1069
|
+
type: "Note",
|
|
1070
|
+
content: "Hello",
|
|
1071
|
+
};
|
|
1072
|
+
const fetched: string[] = [];
|
|
1073
|
+
const documentLoader: DocumentLoader = (url) => {
|
|
1074
|
+
fetched.push(url);
|
|
1075
|
+
if (url === "https://example.com/notes/1") {
|
|
1076
|
+
return Promise.resolve({
|
|
1077
|
+
contextUrl: null,
|
|
1078
|
+
document: note,
|
|
1079
|
+
documentUrl: "https://example.com/notes/1?redirected",
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
return Promise.reject(new Error(`Not found: ${url}`));
|
|
1083
|
+
};
|
|
1084
|
+
const candidates: DereferenceCandidate<Object>[] = [];
|
|
1085
|
+
const failures: DereferenceFailure[] = [];
|
|
1086
|
+
const accepted = await lookupObject("https://example.com/notes/1", {
|
|
1087
|
+
documentLoader,
|
|
1088
|
+
contextLoader: mockDocumentLoader,
|
|
1089
|
+
[lookupObserver]: {
|
|
1090
|
+
accept: (candidate) => {
|
|
1091
|
+
candidates.push(candidate);
|
|
1092
|
+
return Promise.resolve(true);
|
|
1093
|
+
},
|
|
1094
|
+
failed: (failure) => failures.push(failure),
|
|
1095
|
+
},
|
|
1096
|
+
});
|
|
1097
|
+
ok(accepted instanceof Note);
|
|
1098
|
+
equal(candidates.length, 1);
|
|
1099
|
+
deepStrictEqual(candidates[0].document, note);
|
|
1100
|
+
equal(candidates[0].documentUrl, "https://example.com/notes/1?redirected");
|
|
1101
|
+
equal(candidates[0].baseUrl.href, "https://example.com/notes/1?redirected");
|
|
1102
|
+
equal(candidates[0].object, accepted);
|
|
1103
|
+
deepStrictEqual(failures, []);
|
|
1104
|
+
|
|
1105
|
+
// A refused candidate is not returned, and neither is an observer error:
|
|
1106
|
+
for (
|
|
1107
|
+
const accept of [
|
|
1108
|
+
() => Promise.resolve(false),
|
|
1109
|
+
() => Promise.reject(new Error("Oops")),
|
|
1110
|
+
]
|
|
1111
|
+
) {
|
|
1112
|
+
const refusals: DereferenceFailure[] = [];
|
|
1113
|
+
equal(
|
|
1114
|
+
await lookupObject("https://example.com/notes/1", {
|
|
1115
|
+
documentLoader,
|
|
1116
|
+
contextLoader: mockDocumentLoader,
|
|
1117
|
+
[lookupObserver]: { accept, failed: (f) => refusals.push(f) },
|
|
1118
|
+
}),
|
|
1119
|
+
null,
|
|
1120
|
+
);
|
|
1121
|
+
deepStrictEqual(refusals.map((f) => f.operation), ["accept"]);
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
// Without WebFinger, a URL that cannot be fetched is not looked up further:
|
|
1125
|
+
fetched.length = 0;
|
|
1126
|
+
const missing: DereferenceFailure[] = [];
|
|
1127
|
+
equal(
|
|
1128
|
+
await lookupObject("https://example.com/notes/2", {
|
|
1129
|
+
documentLoader,
|
|
1130
|
+
contextLoader: mockDocumentLoader,
|
|
1131
|
+
[lookupObserver]: { webFinger: false, failed: (f) => missing.push(f) },
|
|
1132
|
+
}),
|
|
1133
|
+
null,
|
|
1134
|
+
);
|
|
1135
|
+
deepStrictEqual(fetched, ["https://example.com/notes/2"]);
|
|
1136
|
+
deepStrictEqual(missing.map((f) => f.operation), ["fetch"]);
|
|
1137
|
+
});
|
|
1138
|
+
|
|
1139
|
+
test("lookupObject() keeps looking after the observer refuses a portable candidate", async () => {
|
|
1140
|
+
const id = `ap://${OBSERVER_DID}/notes/1`;
|
|
1141
|
+
const gateways = ["https://gw1.example", "https://gw2.example"];
|
|
1142
|
+
const documentLoader: DocumentLoader = (url) =>
|
|
1143
|
+
Promise.resolve({
|
|
1144
|
+
contextUrl: null,
|
|
1145
|
+
document: {
|
|
1146
|
+
"@context": "https://www.w3.org/ns/activitystreams",
|
|
1147
|
+
id,
|
|
1148
|
+
type: "Note",
|
|
1149
|
+
content: url.startsWith("https://gw1.example/") ? "first" : "second",
|
|
1150
|
+
},
|
|
1151
|
+
documentUrl: url,
|
|
1152
|
+
});
|
|
1153
|
+
const verifier: PortableObjectVerifier = () =>
|
|
1154
|
+
Promise.resolve({ verified: true });
|
|
1155
|
+
const offered: string[] = [];
|
|
1156
|
+
const failures: DereferenceFailure[] = [];
|
|
1157
|
+
const object = await lookupObject(id, {
|
|
1158
|
+
documentLoader,
|
|
1159
|
+
contextLoader: mockDocumentLoader,
|
|
1160
|
+
gateways,
|
|
1161
|
+
verifyPortableObject: verifier,
|
|
1162
|
+
[lookupObserver]: {
|
|
1163
|
+
accept: (candidate) => {
|
|
1164
|
+
offered.push(candidate.documentUrl);
|
|
1165
|
+
return Promise.resolve(offered.length > 1);
|
|
1166
|
+
},
|
|
1167
|
+
failed: (failure) => failures.push(failure),
|
|
1168
|
+
},
|
|
1169
|
+
});
|
|
1170
|
+
ok(object instanceof Note);
|
|
1171
|
+
equal(object.content, "second");
|
|
1172
|
+
equal(offered.length, 2);
|
|
1173
|
+
ok(offered[0].startsWith("https://gw1.example/"));
|
|
1174
|
+
ok(offered[1].startsWith("https://gw2.example/"));
|
|
1175
|
+
deepStrictEqual(failures.map((f) => f.operation), ["accept"]);
|
|
1176
|
+
});
|
package/src/lookup.ts
CHANGED
|
@@ -13,7 +13,9 @@ import {
|
|
|
13
13
|
type RemoteDocument,
|
|
14
14
|
} from "@fedify/vocab-runtime";
|
|
15
15
|
import {
|
|
16
|
+
acceptCandidate,
|
|
16
17
|
createSnapshotContextLoader,
|
|
18
|
+
type DereferenceObserver,
|
|
17
19
|
dereferencePortableIri,
|
|
18
20
|
getPortableGatewayCandidates,
|
|
19
21
|
getPortableResponseClaim,
|
|
@@ -123,6 +125,38 @@ const logger = getLogger(["fedify", "vocab", "lookup"]);
|
|
|
123
125
|
*
|
|
124
126
|
* @since 0.2.0
|
|
125
127
|
*/
|
|
128
|
+
/**
|
|
129
|
+
* The key of the {@link LookupObjectOptions} property that observes how
|
|
130
|
+
* {@link lookupObject} selects the object it returns.
|
|
131
|
+
*
|
|
132
|
+
* @internal Technically exported for other Fedify packages, but not part of
|
|
133
|
+
* the public API contract. This is not considered public API for Semantic
|
|
134
|
+
* Versioning decisions.
|
|
135
|
+
*/
|
|
136
|
+
export const lookupObserver: unique symbol = Symbol.for(
|
|
137
|
+
"@fedify/vocab/lookupObserver",
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Observes how {@link lookupObject} selects the object it returns: each
|
|
142
|
+
* candidate is offered to {@link DereferenceObserver.accept} at the boundary
|
|
143
|
+
* that would otherwise return it, both for ordinary documents and for
|
|
144
|
+
* FEP-ef61 portable objects, and each failure that does not propagate is
|
|
145
|
+
* reported to {@link DereferenceObserver.failed}. The observer is not passed
|
|
146
|
+
* on to the returned object.
|
|
147
|
+
*
|
|
148
|
+
* @internal Technically exported for other Fedify packages, but not part of
|
|
149
|
+
* the public API contract. This is not considered public API for Semantic
|
|
150
|
+
* Versioning decisions.
|
|
151
|
+
*/
|
|
152
|
+
export interface LookupObserver extends DereferenceObserver<Object> {
|
|
153
|
+
/**
|
|
154
|
+
* Whether to fall back to WebFinger when an HTTP(S) URL cannot be fetched.
|
|
155
|
+
* Defaults to `true`.
|
|
156
|
+
*/
|
|
157
|
+
readonly webFinger?: boolean;
|
|
158
|
+
}
|
|
159
|
+
|
|
126
160
|
export interface LookupObjectOptions {
|
|
127
161
|
/**
|
|
128
162
|
* The document loader for loading remote JSON-LD documents.
|
|
@@ -226,6 +260,12 @@ export interface LookupObjectOptions {
|
|
|
226
260
|
* @since 2.4.0
|
|
227
261
|
*/
|
|
228
262
|
verifyPortableObject?: PortableObjectVerifier;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* See {@link LookupObserver}.
|
|
266
|
+
* @internal
|
|
267
|
+
*/
|
|
268
|
+
[lookupObserver]?: LookupObserver;
|
|
229
269
|
}
|
|
230
270
|
|
|
231
271
|
/**
|
|
@@ -395,8 +435,12 @@ async function lookupObjectInternal(
|
|
|
395
435
|
});
|
|
396
436
|
} catch (error) {
|
|
397
437
|
logger.debug("Failed to fetch remote document:\n{error}", { error });
|
|
438
|
+
options[lookupObserver]?.failed?.({ operation: "fetch", error });
|
|
398
439
|
}
|
|
399
440
|
}
|
|
441
|
+
if (remoteDoc == null && options[lookupObserver]?.webFinger === false) {
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
400
444
|
if (remoteDoc == null) {
|
|
401
445
|
const jrd = await lookupWebFinger(identifier, {
|
|
402
446
|
userAgent: options.userAgent,
|
|
@@ -467,12 +511,13 @@ async function lookupObjectInternal(
|
|
|
467
511
|
if (remoteDoc == null) return null;
|
|
468
512
|
// With verifyPortableObject, the document may turn out to be a portable
|
|
469
513
|
// object, which has to be verified with the same context documents:
|
|
470
|
-
const snapshot =
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
514
|
+
const snapshot =
|
|
515
|
+
options.verifyPortableObject == null && options[lookupObserver] == null
|
|
516
|
+
? null
|
|
517
|
+
: createSnapshotContextLoader(
|
|
518
|
+
options.contextLoader ??
|
|
519
|
+
getDocumentLoader({ userAgent: options.userAgent }),
|
|
520
|
+
);
|
|
476
521
|
try {
|
|
477
522
|
let object: Object;
|
|
478
523
|
let documentUrl: URL;
|
|
@@ -486,6 +531,7 @@ async function lookupObjectInternal(
|
|
|
486
531
|
baseUrl: documentUrl,
|
|
487
532
|
});
|
|
488
533
|
} catch (error) {
|
|
534
|
+
options[lookupObserver]?.failed?.({ operation: "parse", error });
|
|
489
535
|
if (error instanceof TypeError) {
|
|
490
536
|
logger.debug(
|
|
491
537
|
"Failed to parse JSON-LD document: {error}\n{document}",
|
|
@@ -495,7 +541,7 @@ async function lookupObjectInternal(
|
|
|
495
541
|
}
|
|
496
542
|
throw error;
|
|
497
543
|
}
|
|
498
|
-
if (snapshot != null) {
|
|
544
|
+
if (options.verifyPortableObject != null && snapshot != null) {
|
|
499
545
|
// A document whose final URL or @id stands for a portable object is
|
|
500
546
|
// verified as one instead of being trusted because of its origin:
|
|
501
547
|
const claim = getPortableResponseClaim(remoteDoc.documentUrl, object.id);
|
|
@@ -540,6 +586,19 @@ async function lookupObjectInternal(
|
|
|
540
586
|
'implications, set the crossOrigin option to "trust".',
|
|
541
587
|
{ ...remoteDoc, objectId: object.id.href },
|
|
542
588
|
);
|
|
589
|
+
options[lookupObserver]?.failed?.({ operation: "origin" });
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
if (
|
|
593
|
+
!await acceptCandidate(options[lookupObserver], {
|
|
594
|
+
document: remoteDoc.document,
|
|
595
|
+
documentUrl: remoteDoc.documentUrl,
|
|
596
|
+
baseUrl: documentUrl,
|
|
597
|
+
contextLoader: snapshot?.loader ?? options.contextLoader ??
|
|
598
|
+
getDocumentLoader({ userAgent: options.userAgent }),
|
|
599
|
+
object,
|
|
600
|
+
})
|
|
601
|
+
) {
|
|
543
602
|
return null;
|
|
544
603
|
}
|
|
545
604
|
return object;
|
|
@@ -728,6 +787,7 @@ async function dereference(
|
|
|
728
787
|
verifyPortableObject: options.verifyPortableObject,
|
|
729
788
|
crossOrigin: options.crossOrigin === "throw" ? "throw" : "ignore",
|
|
730
789
|
signal: options.signal,
|
|
790
|
+
observer: options[lookupObserver],
|
|
731
791
|
parse: (document, { contextLoader, baseUrl }) =>
|
|
732
792
|
Object.fromJsonLd(document, {
|
|
733
793
|
documentLoader,
|