@fedify/fedify 0.10.0-dev.207 → 0.10.0-dev.211
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGES.md +6 -0
- package/FEDERATION.md +63 -0
- package/esm/vocab/lookup.js +11 -7
- package/esm/vocab/question.yaml +43 -0
- package/esm/vocab/vocab.js +311 -0
- package/esm/webfinger/lookup.js +13 -2
- package/package.json +1 -1
- package/types/vocab/lookup.d.ts.map +1 -1
- package/types/vocab/vocab.d.ts +186 -0
- package/types/vocab/vocab.d.ts.map +1 -1
- package/types/webfinger/lookup.d.ts.map +1 -1
package/CHANGES.md
CHANGED
@@ -106,6 +106,8 @@ To be released.
|
|
106
106
|
- The `Context.sendActivity()` method's first parameter now accepts
|
107
107
|
`SenderKeyPair[]` as well.
|
108
108
|
|
109
|
+
- Added `Question` class to Activity Vocabulary API.
|
110
|
+
|
109
111
|
- Added `context` option to `Object.toJsonLd()` method. This applies to
|
110
112
|
any subclasses of the `Object` class too.
|
111
113
|
|
@@ -119,12 +121,16 @@ To be released.
|
|
119
121
|
- Ephemeral actors now have the following properties: `summary`,
|
120
122
|
`following`, `followers`, `outbox`, `manuallyApprovesFollowers`, and
|
121
123
|
`url`.
|
124
|
+
- Improved the compatibility of the `fedify inbox` command with Misskey
|
125
|
+
and Mitra.
|
122
126
|
|
123
127
|
- Added more log messages using the [LogTape] library. Currently the below
|
124
128
|
logger categories are used:
|
125
129
|
|
126
130
|
- `["fedify", "sig", "proof"]`
|
127
131
|
- `["fedify", "sig", "key"]`
|
132
|
+
- `["fedify", "vocab", "lookup"]`
|
133
|
+
- `["fedify", "webfinger", "lookup"]`
|
128
134
|
|
129
135
|
[#54]: https://github.com/dahlia/fedify/issues/54
|
130
136
|
[#55]: https://github.com/dahlia/fedify/issues/55
|
package/FEDERATION.md
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
<!-- deno-fmt-ignore-file -->
|
2
|
+
|
3
|
+
Federation
|
4
|
+
==========
|
5
|
+
|
6
|
+
Supported federation protocols and standards
|
7
|
+
--------------------------------------------
|
8
|
+
|
9
|
+
- [ActivityPub] (S2S)
|
10
|
+
- [WebFinger]
|
11
|
+
- [HTTP Signatures]
|
12
|
+
- [NodeInfo]
|
13
|
+
|
14
|
+
[ActivityPub]: https://www.w3.org/TR/activitypub/
|
15
|
+
[WebFinger]: https://datatracker.ietf.org/doc/html/rfc7033
|
16
|
+
[HTTP Signatures]: https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures
|
17
|
+
[NodeInfo]: https://nodeinfo.diaspora.software/
|
18
|
+
|
19
|
+
|
20
|
+
Supported FEPs
|
21
|
+
--------------
|
22
|
+
|
23
|
+
- [FEP-67ff][]: FEDERATION.md
|
24
|
+
- [FEP-8fcf][]: Followers collection synchronization across servers
|
25
|
+
- [FEP-f1d5][]: NodeInfo in Fediverse Software
|
26
|
+
- [FEP-8b32][]: Object Integrity Proofs
|
27
|
+
- [FEP-521a][]: Representing actor's public keys
|
28
|
+
- [FEP-5feb][]: Search indexing consent for actors
|
29
|
+
- [FEP-c7d3][]: Ownership
|
30
|
+
|
31
|
+
[FEP-67ff]: https://codeberg.org/fediverse/fep/src/branch/main/fep/67ff/fep-67ff.md
|
32
|
+
[FEP-8fcf]: https://codeberg.org/fediverse/fep/src/branch/main/fep/8fcf/fep-8fcf.md
|
33
|
+
[FEP-f1d5]: https://codeberg.org/fediverse/fep/src/branch/main/fep/f1d5/fep-f1d5.md
|
34
|
+
[FEP-8b32]: https://codeberg.org/fediverse/fep/src/branch/main/fep/8b32/fep-8b32.md
|
35
|
+
[FEP-521a]: https://codeberg.org/fediverse/fep/src/branch/main/fep/521a/fep-521a.md
|
36
|
+
[FEP-5feb]: https://codeberg.org/fediverse/fep/src/branch/main/fep/5feb/fep-5feb.md
|
37
|
+
[FEP-c7d3]: https://codeberg.org/silverpill/feps/src/branch/main/c7d3/fep-c7d3.md
|
38
|
+
|
39
|
+
|
40
|
+
ActivityPub
|
41
|
+
-----------
|
42
|
+
|
43
|
+
Since Fedify is a framework, what activity types it uses is up to
|
44
|
+
the application developers. However, Fedify provides a set of
|
45
|
+
activity types that are commonly used in the Fediverse. The following
|
46
|
+
lists the activity types that Fedify provides:
|
47
|
+
|
48
|
+
- [`Accept`](https://jsr.io/@fedify/fedify/doc/vocab/~/Accept)
|
49
|
+
- [`Add`](https://jsr.io/@fedify/fedify/doc/vocab/~/Add)
|
50
|
+
- [`Announce`](https://jsr.io/@fedify/fedify/doc/vocab/~/Announce)
|
51
|
+
- [`Block`](https://jsr.io/@fedify/fedify/doc/vocab/~/Block)
|
52
|
+
- [`Create`](https://jsr.io/@fedify/fedify/doc/vocab/~/Create)
|
53
|
+
- [`Delete`](https://jsr.io/@fedify/fedify/doc/vocab/~/Delete)
|
54
|
+
- [`Dislike`](https://jsr.io/@fedify/fedify/doc/vocab/~/Dislike)
|
55
|
+
- [`Flag`](https://jsr.io/@fedify/fedify/doc/vocab/~/Flag)
|
56
|
+
- [`Follow`](https://jsr.io/@fedify/fedify/doc/vocab/~/Follow)
|
57
|
+
- [`Ignore`](https://jsr.io/@fedify/fedify/doc/vocab/~/Ignore)
|
58
|
+
- [`Like`](https://jsr.io/@fedify/fedify/doc/vocab/~/Like)
|
59
|
+
- [`Question`](https://jsr.io/@fedify/fedify/doc/vocab/~/Question)
|
60
|
+
- [`Reject`](https://jsr.io/@fedify/fedify/doc/vocab/~/Reject)
|
61
|
+
- [`Remove`](https://jsr.io/@fedify/fedify/doc/vocab/~/Remove)
|
62
|
+
- [`Undo`](https://jsr.io/@fedify/fedify/doc/vocab/~/Undo)
|
63
|
+
- [`Update`](https://jsr.io/@fedify/fedify/doc/vocab/~/Update)
|
package/esm/vocab/lookup.js
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
import { getLogger } from "@logtape/logtape";
|
1
2
|
import { fetchDocumentLoader, } from "../runtime/docloader.js";
|
2
3
|
import { lookupWebFinger } from "../webfinger/lookup.js";
|
3
4
|
import { Object } from "./vocab.js";
|
5
|
+
const logger = getLogger(["fedify", "vocab", "lookup"]);
|
4
6
|
const handleRegexp = /^@?((?:[-A-Za-z0-9._~!$&'()*+,;=]|%[A-Fa-f0-9]{2})+)@([^@]+)$/;
|
5
7
|
/**
|
6
8
|
* Looks up an ActivityStreams object by its URI (including `acct:` URIs)
|
@@ -48,8 +50,8 @@ export async function lookupObject(identifier, options = {}) {
|
|
48
50
|
const remoteDoc = await documentLoader(identifier.href);
|
49
51
|
document = remoteDoc.document;
|
50
52
|
}
|
51
|
-
catch (
|
52
|
-
|
53
|
+
catch (error) {
|
54
|
+
logger.debug("Failed to fetch remote document:\n{error}", { error });
|
53
55
|
}
|
54
56
|
}
|
55
57
|
if (document == null) {
|
@@ -65,8 +67,8 @@ export async function lookupObject(identifier, options = {}) {
|
|
65
67
|
document = remoteDoc.document;
|
66
68
|
break;
|
67
69
|
}
|
68
|
-
catch (
|
69
|
-
|
70
|
+
catch (error) {
|
71
|
+
logger.debug("Failed to fetch remote document:\n{error}", { error });
|
70
72
|
continue;
|
71
73
|
}
|
72
74
|
}
|
@@ -79,9 +81,11 @@ export async function lookupObject(identifier, options = {}) {
|
|
79
81
|
contextLoader: options.contextLoader,
|
80
82
|
});
|
81
83
|
}
|
82
|
-
catch (
|
83
|
-
if (
|
84
|
+
catch (error) {
|
85
|
+
if (error instanceof TypeError) {
|
86
|
+
logger.debug("Failed to parse JSON-LD document:\n{error}", { error });
|
84
87
|
return null;
|
85
|
-
|
88
|
+
}
|
89
|
+
throw error;
|
86
90
|
}
|
87
91
|
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
$schema: ../codegen/schema.yaml
|
2
|
+
name: Question
|
3
|
+
uri: "https://www.w3.org/ns/activitystreams#Question"
|
4
|
+
extends: "https://www.w3.org/ns/activitystreams#IntransitiveActivity"
|
5
|
+
entity: true
|
6
|
+
description: |
|
7
|
+
Represents a question being asked. Question objects are an extension of
|
8
|
+
{@link IntransitiveActivity}. That is, the Question object is an Activity,
|
9
|
+
but the direct object is the question itself and therefore it would not
|
10
|
+
contain an `object` property.
|
11
|
+
|
12
|
+
Either of the `anyOf` and `oneOf` properties *may* be used to express possible
|
13
|
+
answers, but a Question object *must not* have both properties.
|
14
|
+
defaultContext:
|
15
|
+
- "https://www.w3.org/ns/activitystreams"
|
16
|
+
- "https://w3id.org/security/data-integrity/v1"
|
17
|
+
- toot: "http://joinmastodon.org/ns#"
|
18
|
+
sensitive: "as:sensitive"
|
19
|
+
Emoji: "toot:Emoji"
|
20
|
+
Hashtag: "as:Hashtag"
|
21
|
+
|
22
|
+
properties:
|
23
|
+
- pluralName: exclusiveOptions
|
24
|
+
singularName: exclusiveOption
|
25
|
+
singularAccessor: false
|
26
|
+
uri: "https://www.w3.org/ns/activitystreams#oneOf"
|
27
|
+
description: |
|
28
|
+
Identifies an exclusive option for a Question. Use of `exclusiveOptions`
|
29
|
+
implies that the Question can have only a single answer. To indicate that
|
30
|
+
a Question can have multiple answers, use `inclusiveOptions`.
|
31
|
+
range:
|
32
|
+
- "https://www.w3.org/ns/activitystreams#Object"
|
33
|
+
|
34
|
+
- pluralName: inclusiveOptions
|
35
|
+
singularName: inclusiveOption
|
36
|
+
singularAccessor: false
|
37
|
+
uri: "https://www.w3.org/ns/activitystreams#anyOf"
|
38
|
+
description: |
|
39
|
+
Identifies an inclusive option for a Question. Use of `inclusiveOptions`
|
40
|
+
implies that the Question can have multiple answers. To indicate that
|
41
|
+
a Question can have only one answer, use `exclusiveOptions`.
|
42
|
+
range:
|
43
|
+
- "https://www.w3.org/ns/activitystreams#Object"
|
package/esm/vocab/vocab.js
CHANGED
@@ -2198,6 +2198,10 @@ export class Object {
|
|
2198
2198
|
delete values["@type"];
|
2199
2199
|
return await IntransitiveActivity.fromJsonLd(values, options);
|
2200
2200
|
}
|
2201
|
+
if (values["@type"].includes("https://www.w3.org/ns/activitystreams#Question")) {
|
2202
|
+
delete values["@type"];
|
2203
|
+
return await Question.fromJsonLd(values, options);
|
2204
|
+
}
|
2201
2205
|
if (values["@type"].includes("https://www.w3.org/ns/activitystreams#Like")) {
|
2202
2206
|
delete values["@type"];
|
2203
2207
|
return await Like.fromJsonLd(values, options);
|
@@ -2334,6 +2338,7 @@ export class Object {
|
|
2334
2338
|
"https://www.w3.org/ns/activitystreams#Ignore",
|
2335
2339
|
"https://www.w3.org/ns/activitystreams#Block",
|
2336
2340
|
"https://www.w3.org/ns/activitystreams#IntransitiveActivity",
|
2341
|
+
"https://www.w3.org/ns/activitystreams#Question",
|
2337
2342
|
"https://www.w3.org/ns/activitystreams#Like",
|
2338
2343
|
"https://www.w3.org/ns/activitystreams#Reject",
|
2339
2344
|
"https://www.w3.org/ns/activitystreams#Remove",
|
@@ -2471,6 +2476,7 @@ export class Object {
|
|
2471
2476
|
"https://www.w3.org/ns/activitystreams#Ignore",
|
2472
2477
|
"https://www.w3.org/ns/activitystreams#Block",
|
2473
2478
|
"https://www.w3.org/ns/activitystreams#IntransitiveActivity",
|
2479
|
+
"https://www.w3.org/ns/activitystreams#Question",
|
2474
2480
|
"https://www.w3.org/ns/activitystreams#Like",
|
2475
2481
|
"https://www.w3.org/ns/activitystreams#Reject",
|
2476
2482
|
"https://www.w3.org/ns/activitystreams#Remove",
|
@@ -2563,6 +2569,7 @@ export class Object {
|
|
2563
2569
|
"https://www.w3.org/ns/activitystreams#Ignore",
|
2564
2570
|
"https://www.w3.org/ns/activitystreams#Block",
|
2565
2571
|
"https://www.w3.org/ns/activitystreams#IntransitiveActivity",
|
2572
|
+
"https://www.w3.org/ns/activitystreams#Question",
|
2566
2573
|
"https://www.w3.org/ns/activitystreams#Like",
|
2567
2574
|
"https://www.w3.org/ns/activitystreams#Reject",
|
2568
2575
|
"https://www.w3.org/ns/activitystreams#Remove",
|
@@ -2655,6 +2662,7 @@ export class Object {
|
|
2655
2662
|
"https://www.w3.org/ns/activitystreams#Ignore",
|
2656
2663
|
"https://www.w3.org/ns/activitystreams#Block",
|
2657
2664
|
"https://www.w3.org/ns/activitystreams#IntransitiveActivity",
|
2665
|
+
"https://www.w3.org/ns/activitystreams#Question",
|
2658
2666
|
"https://www.w3.org/ns/activitystreams#Like",
|
2659
2667
|
"https://www.w3.org/ns/activitystreams#Reject",
|
2660
2668
|
"https://www.w3.org/ns/activitystreams#Remove",
|
@@ -2723,6 +2731,7 @@ export class Object {
|
|
2723
2731
|
"https://www.w3.org/ns/activitystreams#Ignore",
|
2724
2732
|
"https://www.w3.org/ns/activitystreams#Block",
|
2725
2733
|
"https://www.w3.org/ns/activitystreams#IntransitiveActivity",
|
2734
|
+
"https://www.w3.org/ns/activitystreams#Question",
|
2726
2735
|
"https://www.w3.org/ns/activitystreams#Like",
|
2727
2736
|
"https://www.w3.org/ns/activitystreams#Reject",
|
2728
2737
|
"https://www.w3.org/ns/activitystreams#Remove",
|
@@ -2799,6 +2808,7 @@ export class Object {
|
|
2799
2808
|
"https://www.w3.org/ns/activitystreams#Ignore",
|
2800
2809
|
"https://www.w3.org/ns/activitystreams#Block",
|
2801
2810
|
"https://www.w3.org/ns/activitystreams#IntransitiveActivity",
|
2811
|
+
"https://www.w3.org/ns/activitystreams#Question",
|
2802
2812
|
"https://www.w3.org/ns/activitystreams#Like",
|
2803
2813
|
"https://www.w3.org/ns/activitystreams#Reject",
|
2804
2814
|
"https://www.w3.org/ns/activitystreams#Remove",
|
@@ -2902,6 +2912,7 @@ export class Object {
|
|
2902
2912
|
"https://www.w3.org/ns/activitystreams#Ignore",
|
2903
2913
|
"https://www.w3.org/ns/activitystreams#Block",
|
2904
2914
|
"https://www.w3.org/ns/activitystreams#IntransitiveActivity",
|
2915
|
+
"https://www.w3.org/ns/activitystreams#Question",
|
2905
2916
|
"https://www.w3.org/ns/activitystreams#Like",
|
2906
2917
|
"https://www.w3.org/ns/activitystreams#Reject",
|
2907
2918
|
"https://www.w3.org/ns/activitystreams#Remove",
|
@@ -5195,6 +5206,10 @@ export class Activity extends Object {
|
|
5195
5206
|
delete values["@type"];
|
5196
5207
|
return await IntransitiveActivity.fromJsonLd(values, options);
|
5197
5208
|
}
|
5209
|
+
if (values["@type"].includes("https://www.w3.org/ns/activitystreams#Question")) {
|
5210
|
+
delete values["@type"];
|
5211
|
+
return await Question.fromJsonLd(values, options);
|
5212
|
+
}
|
5198
5213
|
if (values["@type"].includes("https://www.w3.org/ns/activitystreams#Like")) {
|
5199
5214
|
delete values["@type"];
|
5200
5215
|
return await Like.fromJsonLd(values, options);
|
@@ -8136,6 +8151,7 @@ export class Collection extends Object {
|
|
8136
8151
|
"https://www.w3.org/ns/activitystreams#Ignore",
|
8137
8152
|
"https://www.w3.org/ns/activitystreams#Block",
|
8138
8153
|
"https://www.w3.org/ns/activitystreams#IntransitiveActivity",
|
8154
|
+
"https://www.w3.org/ns/activitystreams#Question",
|
8139
8155
|
"https://www.w3.org/ns/activitystreams#Like",
|
8140
8156
|
"https://www.w3.org/ns/activitystreams#Reject",
|
8141
8157
|
"https://www.w3.org/ns/activitystreams#Remove",
|
@@ -11532,6 +11548,7 @@ export class Link {
|
|
11532
11548
|
"https://www.w3.org/ns/activitystreams#Ignore",
|
11533
11549
|
"https://www.w3.org/ns/activitystreams#Block",
|
11534
11550
|
"https://www.w3.org/ns/activitystreams#IntransitiveActivity",
|
11551
|
+
"https://www.w3.org/ns/activitystreams#Question",
|
11535
11552
|
"https://www.w3.org/ns/activitystreams#Like",
|
11536
11553
|
"https://www.w3.org/ns/activitystreams#Reject",
|
11537
11554
|
"https://www.w3.org/ns/activitystreams#Remove",
|
@@ -11994,6 +12011,10 @@ export class IntransitiveActivity extends Activity {
|
|
11994
12011
|
(expanded[0] ?? {});
|
11995
12012
|
}
|
11996
12013
|
if ("@type" in values) {
|
12014
|
+
if (values["@type"].includes("https://www.w3.org/ns/activitystreams#Question")) {
|
12015
|
+
delete values["@type"];
|
12016
|
+
return await Question.fromJsonLd(values, options);
|
12017
|
+
}
|
11997
12018
|
if (!values["@type"].includes("https://www.w3.org/ns/activitystreams#IntransitiveActivity")) {
|
11998
12019
|
throw new TypeError("Invalid type: " + values["@type"]);
|
11999
12020
|
}
|
@@ -15835,6 +15856,296 @@ export class Profile extends Object {
|
|
15835
15856
|
return "Profile " + inspect(proxy, options);
|
15836
15857
|
}
|
15837
15858
|
}
|
15859
|
+
/** Represents a question being asked. Question objects are an extension of
|
15860
|
+
* {@link IntransitiveActivity}. That is, the Question object is an Activity,
|
15861
|
+
* but the direct object is the question itself and therefore it would not
|
15862
|
+
* contain an `object` property.
|
15863
|
+
*
|
15864
|
+
* Either of the `anyOf` and `oneOf` properties *may* be used to express possible
|
15865
|
+
* answers, but a Question object *must not* have both properties.
|
15866
|
+
*/
|
15867
|
+
export class Question extends IntransitiveActivity {
|
15868
|
+
/**
|
15869
|
+
* The type URI of {@link Question}: `https://www.w3.org/ns/activitystreams#Question`.
|
15870
|
+
*/
|
15871
|
+
static get typeId() {
|
15872
|
+
return new URL("https://www.w3.org/ns/activitystreams#Question");
|
15873
|
+
}
|
15874
|
+
#_2N5scKaVEcdYHFmfKYYacAwUhUgQ = [];
|
15875
|
+
#_2mV6isMTPRKbWdLCjcpiEysq5dAY = [];
|
15876
|
+
/**
|
15877
|
+
* Constructs a new instance of Question with the given values.
|
15878
|
+
* @param values The values to initialize the instance with.
|
15879
|
+
* @param options The options to use for initialization.
|
15880
|
+
*/
|
15881
|
+
constructor(values, { documentLoader, contextLoader, } = {}) {
|
15882
|
+
super(values, { documentLoader, contextLoader });
|
15883
|
+
if ("exclusiveOptions" in values && values.exclusiveOptions != null) {
|
15884
|
+
this.#_2N5scKaVEcdYHFmfKYYacAwUhUgQ = values.exclusiveOptions;
|
15885
|
+
}
|
15886
|
+
if ("inclusiveOptions" in values && values.inclusiveOptions != null) {
|
15887
|
+
this.#_2mV6isMTPRKbWdLCjcpiEysq5dAY = values.inclusiveOptions;
|
15888
|
+
}
|
15889
|
+
}
|
15890
|
+
/**
|
15891
|
+
* Clones this instance, optionally updating it with the given values.
|
15892
|
+
* @param values The values to update the clone with.
|
15893
|
+
* @options The options to use for cloning.
|
15894
|
+
* @returns The cloned instance.
|
15895
|
+
*/
|
15896
|
+
clone(values = {}, options = {}) {
|
15897
|
+
const clone = super.clone(values, options);
|
15898
|
+
clone.#_2N5scKaVEcdYHFmfKYYacAwUhUgQ = this.#_2N5scKaVEcdYHFmfKYYacAwUhUgQ;
|
15899
|
+
if ("exclusiveOptions" in values && values.exclusiveOptions != null) {
|
15900
|
+
clone.#_2N5scKaVEcdYHFmfKYYacAwUhUgQ = values.exclusiveOptions;
|
15901
|
+
}
|
15902
|
+
clone.#_2mV6isMTPRKbWdLCjcpiEysq5dAY = this.#_2mV6isMTPRKbWdLCjcpiEysq5dAY;
|
15903
|
+
if ("inclusiveOptions" in values && values.inclusiveOptions != null) {
|
15904
|
+
clone.#_2mV6isMTPRKbWdLCjcpiEysq5dAY = values.inclusiveOptions;
|
15905
|
+
}
|
15906
|
+
return clone;
|
15907
|
+
}
|
15908
|
+
async #fetchExclusiveOption(url, options = {}) {
|
15909
|
+
const documentLoader = options.documentLoader ?? this._documentLoader ??
|
15910
|
+
fetchDocumentLoader;
|
15911
|
+
const contextLoader = options.contextLoader ?? this._contextLoader ??
|
15912
|
+
fetchDocumentLoader;
|
15913
|
+
const { document } = await documentLoader(url.href);
|
15914
|
+
try {
|
15915
|
+
return await Object.fromJsonLd(document, { documentLoader, contextLoader });
|
15916
|
+
}
|
15917
|
+
catch (e) {
|
15918
|
+
if (!(e instanceof TypeError))
|
15919
|
+
throw e;
|
15920
|
+
}
|
15921
|
+
throw new TypeError("Expected an object of any type of: " +
|
15922
|
+
["https://www.w3.org/ns/activitystreams#Object"].join(", "));
|
15923
|
+
}
|
15924
|
+
/**
|
15925
|
+
* Similar to
|
15926
|
+
* {@link Question.getExclusiveOptions},
|
15927
|
+
* but returns their `@id`s instead of the objects themselves.
|
15928
|
+
*/
|
15929
|
+
get exclusiveOptionIds() {
|
15930
|
+
return this.#_2N5scKaVEcdYHFmfKYYacAwUhUgQ.map((v) => v instanceof URL ? v : v.id).filter((id) => id !== null);
|
15931
|
+
}
|
15932
|
+
/** Identifies an exclusive option for a Question. Use of `exclusiveOptions`
|
15933
|
+
* implies that the Question can have only a single answer. To indicate that
|
15934
|
+
* a Question can have multiple answers, use `inclusiveOptions`.
|
15935
|
+
*/
|
15936
|
+
async *getExclusiveOptions(options = {}) {
|
15937
|
+
const vs = this.#_2N5scKaVEcdYHFmfKYYacAwUhUgQ;
|
15938
|
+
for (let i = 0; i < vs.length; i++) {
|
15939
|
+
const v = vs[i];
|
15940
|
+
if (v instanceof URL) {
|
15941
|
+
const fetched = await this.#fetchExclusiveOption(v, options);
|
15942
|
+
vs[i] = fetched;
|
15943
|
+
yield fetched;
|
15944
|
+
continue;
|
15945
|
+
}
|
15946
|
+
yield v;
|
15947
|
+
}
|
15948
|
+
}
|
15949
|
+
async #fetchInclusiveOption(url, options = {}) {
|
15950
|
+
const documentLoader = options.documentLoader ?? this._documentLoader ??
|
15951
|
+
fetchDocumentLoader;
|
15952
|
+
const contextLoader = options.contextLoader ?? this._contextLoader ??
|
15953
|
+
fetchDocumentLoader;
|
15954
|
+
const { document } = await documentLoader(url.href);
|
15955
|
+
try {
|
15956
|
+
return await Object.fromJsonLd(document, { documentLoader, contextLoader });
|
15957
|
+
}
|
15958
|
+
catch (e) {
|
15959
|
+
if (!(e instanceof TypeError))
|
15960
|
+
throw e;
|
15961
|
+
}
|
15962
|
+
throw new TypeError("Expected an object of any type of: " +
|
15963
|
+
["https://www.w3.org/ns/activitystreams#Object"].join(", "));
|
15964
|
+
}
|
15965
|
+
/**
|
15966
|
+
* Similar to
|
15967
|
+
* {@link Question.getInclusiveOptions},
|
15968
|
+
* but returns their `@id`s instead of the objects themselves.
|
15969
|
+
*/
|
15970
|
+
get inclusiveOptionIds() {
|
15971
|
+
return this.#_2mV6isMTPRKbWdLCjcpiEysq5dAY.map((v) => v instanceof URL ? v : v.id).filter((id) => id !== null);
|
15972
|
+
}
|
15973
|
+
/** Identifies an inclusive option for a Question. Use of `inclusiveOptions`
|
15974
|
+
* implies that the Question can have multiple answers. To indicate that
|
15975
|
+
* a Question can have only one answer, use `exclusiveOptions`.
|
15976
|
+
*/
|
15977
|
+
async *getInclusiveOptions(options = {}) {
|
15978
|
+
const vs = this.#_2mV6isMTPRKbWdLCjcpiEysq5dAY;
|
15979
|
+
for (let i = 0; i < vs.length; i++) {
|
15980
|
+
const v = vs[i];
|
15981
|
+
if (v instanceof URL) {
|
15982
|
+
const fetched = await this.#fetchInclusiveOption(v, options);
|
15983
|
+
vs[i] = fetched;
|
15984
|
+
yield fetched;
|
15985
|
+
continue;
|
15986
|
+
}
|
15987
|
+
yield v;
|
15988
|
+
}
|
15989
|
+
}
|
15990
|
+
/**
|
15991
|
+
* Converts this object to a JSON-LD structure.
|
15992
|
+
* @returns The JSON-LD representation of this object.
|
15993
|
+
*/
|
15994
|
+
async toJsonLd(options = {}) {
|
15995
|
+
options = {
|
15996
|
+
...options,
|
15997
|
+
contextLoader: options.contextLoader ?? fetchDocumentLoader,
|
15998
|
+
};
|
15999
|
+
// deno-lint-ignore no-unused-vars prefer-const
|
16000
|
+
let array;
|
16001
|
+
const baseValues = await super.toJsonLd({
|
16002
|
+
...options,
|
16003
|
+
expand: true,
|
16004
|
+
});
|
16005
|
+
const values = baseValues[0];
|
16006
|
+
array = [];
|
16007
|
+
for (const v of this.#_2N5scKaVEcdYHFmfKYYacAwUhUgQ) {
|
16008
|
+
const element = v instanceof URL
|
16009
|
+
? { "@id": v.href }
|
16010
|
+
: await v.toJsonLd(options);
|
16011
|
+
array.push(element);
|
16012
|
+
}
|
16013
|
+
if (array.length > 0) {
|
16014
|
+
values["https://www.w3.org/ns/activitystreams#oneOf"] = array;
|
16015
|
+
}
|
16016
|
+
array = [];
|
16017
|
+
for (const v of this.#_2mV6isMTPRKbWdLCjcpiEysq5dAY) {
|
16018
|
+
const element = v instanceof URL
|
16019
|
+
? { "@id": v.href }
|
16020
|
+
: await v.toJsonLd(options);
|
16021
|
+
array.push(element);
|
16022
|
+
}
|
16023
|
+
if (array.length > 0) {
|
16024
|
+
values["https://www.w3.org/ns/activitystreams#anyOf"] = array;
|
16025
|
+
}
|
16026
|
+
values["@type"] = ["https://www.w3.org/ns/activitystreams#Question"];
|
16027
|
+
if (this.id)
|
16028
|
+
values["@id"] = this.id.href;
|
16029
|
+
if (options.expand) {
|
16030
|
+
return await jsonld.expand(values, { documentLoader: options.contextLoader });
|
16031
|
+
}
|
16032
|
+
return await jsonld.compact(values, options.context ??
|
16033
|
+
[
|
16034
|
+
"https://www.w3.org/ns/activitystreams",
|
16035
|
+
"https://w3id.org/security/data-integrity/v1",
|
16036
|
+
{
|
16037
|
+
"toot": "http://joinmastodon.org/ns#",
|
16038
|
+
"sensitive": "as:sensitive",
|
16039
|
+
"Emoji": "toot:Emoji",
|
16040
|
+
"Hashtag": "as:Hashtag",
|
16041
|
+
},
|
16042
|
+
], { documentLoader: options.contextLoader });
|
16043
|
+
}
|
16044
|
+
/**
|
16045
|
+
* Converts a JSON-LD structure to an object of this type.
|
16046
|
+
* @param json The JSON-LD structure to convert.
|
16047
|
+
* @returns The object of this type.
|
16048
|
+
* @throws {TypeError} If the given `json` is invalid.
|
16049
|
+
*/
|
16050
|
+
static async fromJsonLd(json, options = {}) {
|
16051
|
+
if (typeof json === "undefined") {
|
16052
|
+
throw new TypeError("Invalid JSON-LD: undefined.");
|
16053
|
+
}
|
16054
|
+
else if (json === null)
|
16055
|
+
throw new TypeError("Invalid JSON-LD: null.");
|
16056
|
+
options = {
|
16057
|
+
...options,
|
16058
|
+
documentLoader: options.documentLoader ?? fetchDocumentLoader,
|
16059
|
+
contextLoader: options.contextLoader ?? fetchDocumentLoader,
|
16060
|
+
};
|
16061
|
+
// deno-lint-ignore no-explicit-any
|
16062
|
+
let values;
|
16063
|
+
if (globalThis.Object.keys(json).length == 0) {
|
16064
|
+
values = {};
|
16065
|
+
}
|
16066
|
+
else {
|
16067
|
+
const expanded = await jsonld.expand(json, {
|
16068
|
+
documentLoader: options.contextLoader,
|
16069
|
+
keepFreeFloatingNodes: true,
|
16070
|
+
});
|
16071
|
+
values =
|
16072
|
+
// deno-lint-ignore no-explicit-any
|
16073
|
+
(expanded[0] ?? {});
|
16074
|
+
}
|
16075
|
+
if ("@type" in values) {
|
16076
|
+
if (!values["@type"].includes("https://www.w3.org/ns/activitystreams#Question")) {
|
16077
|
+
throw new TypeError("Invalid type: " + values["@type"]);
|
16078
|
+
}
|
16079
|
+
}
|
16080
|
+
const instance = await super.fromJsonLd(values, options);
|
16081
|
+
if (!(instance instanceof Question)) {
|
16082
|
+
throw new TypeError("Unexpected type: " + instance.constructor.name);
|
16083
|
+
}
|
16084
|
+
const _2N5scKaVEcdYHFmfKYYacAwUhUgQ = [];
|
16085
|
+
for (const v of values["https://www.w3.org/ns/activitystreams#oneOf"] ?? []) {
|
16086
|
+
if (v == null)
|
16087
|
+
continue;
|
16088
|
+
if (typeof v === "object" && "@id" in v && !("@type" in v) &&
|
16089
|
+
globalThis.Object.keys(v).length === 1) {
|
16090
|
+
_2N5scKaVEcdYHFmfKYYacAwUhUgQ.push(new URL(v["@id"]));
|
16091
|
+
continue;
|
16092
|
+
}
|
16093
|
+
_2N5scKaVEcdYHFmfKYYacAwUhUgQ.push(await Object.fromJsonLd(v, options));
|
16094
|
+
}
|
16095
|
+
instance.#_2N5scKaVEcdYHFmfKYYacAwUhUgQ = _2N5scKaVEcdYHFmfKYYacAwUhUgQ;
|
16096
|
+
const _2mV6isMTPRKbWdLCjcpiEysq5dAY = [];
|
16097
|
+
for (const v of values["https://www.w3.org/ns/activitystreams#anyOf"] ?? []) {
|
16098
|
+
if (v == null)
|
16099
|
+
continue;
|
16100
|
+
if (typeof v === "object" && "@id" in v && !("@type" in v) &&
|
16101
|
+
globalThis.Object.keys(v).length === 1) {
|
16102
|
+
_2mV6isMTPRKbWdLCjcpiEysq5dAY.push(new URL(v["@id"]));
|
16103
|
+
continue;
|
16104
|
+
}
|
16105
|
+
_2mV6isMTPRKbWdLCjcpiEysq5dAY.push(await Object.fromJsonLd(v, options));
|
16106
|
+
}
|
16107
|
+
instance.#_2mV6isMTPRKbWdLCjcpiEysq5dAY = _2mV6isMTPRKbWdLCjcpiEysq5dAY;
|
16108
|
+
return instance;
|
16109
|
+
}
|
16110
|
+
_getCustomInspectProxy() {
|
16111
|
+
const proxy = super._getCustomInspectProxy();
|
16112
|
+
const _2N5scKaVEcdYHFmfKYYacAwUhUgQ = this.#_2N5scKaVEcdYHFmfKYYacAwUhUgQ
|
16113
|
+
// deno-lint-ignore no-explicit-any
|
16114
|
+
.map((v) => v instanceof URL
|
16115
|
+
? {
|
16116
|
+
[Symbol.for("Deno.customInspect")]: (inspect, options) => "URL " + inspect(v.href, options),
|
16117
|
+
[Symbol.for("nodejs.util.inspect.custom")]: (_depth, options, inspect) => "URL " + inspect(v.href, options),
|
16118
|
+
}
|
16119
|
+
: v);
|
16120
|
+
if (_2N5scKaVEcdYHFmfKYYacAwUhUgQ.length > 1 ||
|
16121
|
+
!("exclusiveOption" in proxy) &&
|
16122
|
+
_2N5scKaVEcdYHFmfKYYacAwUhUgQ.length > 0) {
|
16123
|
+
proxy.exclusiveOptions = _2N5scKaVEcdYHFmfKYYacAwUhUgQ;
|
16124
|
+
}
|
16125
|
+
const _2mV6isMTPRKbWdLCjcpiEysq5dAY = this.#_2mV6isMTPRKbWdLCjcpiEysq5dAY
|
16126
|
+
// deno-lint-ignore no-explicit-any
|
16127
|
+
.map((v) => v instanceof URL
|
16128
|
+
? {
|
16129
|
+
[Symbol.for("Deno.customInspect")]: (inspect, options) => "URL " + inspect(v.href, options),
|
16130
|
+
[Symbol.for("nodejs.util.inspect.custom")]: (_depth, options, inspect) => "URL " + inspect(v.href, options),
|
16131
|
+
}
|
16132
|
+
: v);
|
16133
|
+
if (_2mV6isMTPRKbWdLCjcpiEysq5dAY.length > 1 ||
|
16134
|
+
!("inclusiveOption" in proxy) &&
|
16135
|
+
_2mV6isMTPRKbWdLCjcpiEysq5dAY.length > 0) {
|
16136
|
+
proxy.inclusiveOptions = _2mV6isMTPRKbWdLCjcpiEysq5dAY;
|
16137
|
+
}
|
16138
|
+
return proxy;
|
16139
|
+
}
|
16140
|
+
[Symbol.for("Deno.customInspect")](inspect, options) {
|
16141
|
+
const proxy = this._getCustomInspectProxy();
|
16142
|
+
return "Question " + inspect(proxy, options);
|
16143
|
+
}
|
16144
|
+
[Symbol.for("nodejs.util.inspect.custom")](_depth, options, inspect) {
|
16145
|
+
const proxy = this._getCustomInspectProxy();
|
16146
|
+
return "Question " + inspect(proxy, options);
|
16147
|
+
}
|
16148
|
+
}
|
15838
16149
|
/** Indicates that the `actor` is rejecting the `object`. The `target` and
|
15839
16150
|
* `origin` typically have no defined meaning.
|
15840
16151
|
*/
|
package/esm/webfinger/lookup.js
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
import { getLogger } from "@logtape/logtape";
|
2
|
+
const logger = getLogger(["fedify", "webfinger", "lookup"]);
|
1
3
|
/**
|
2
4
|
* Looks up a WebFinger resource.
|
3
5
|
* @param resource The resource URL to look up.
|
@@ -22,6 +24,7 @@ export async function lookupWebFinger(resource) {
|
|
22
24
|
let url = new URL(`https://${server}/.well-known/webfinger`);
|
23
25
|
url.searchParams.set("resource", resource.href);
|
24
26
|
while (true) {
|
27
|
+
logger.debug("Fetching WebFinger resource descriptor from {url}...", { url: url.href });
|
25
28
|
const response = await fetch(url, {
|
26
29
|
headers: { Accept: "application/jrd+json" },
|
27
30
|
redirect: "manual",
|
@@ -31,14 +34,22 @@ export async function lookupWebFinger(resource) {
|
|
31
34
|
url = new URL(response.headers.get("Location"));
|
32
35
|
continue;
|
33
36
|
}
|
34
|
-
if (!response.ok)
|
37
|
+
if (!response.ok) {
|
38
|
+
logger.debug("Failed to fetch WebFinger resource descriptor: {status} {statusText}.", {
|
39
|
+
url: url.href,
|
40
|
+
status: response.status,
|
41
|
+
statusText: response.statusText,
|
42
|
+
});
|
35
43
|
return null;
|
44
|
+
}
|
36
45
|
try {
|
37
46
|
return await response.json();
|
38
47
|
}
|
39
48
|
catch (e) {
|
40
|
-
if (e instanceof SyntaxError)
|
49
|
+
if (e instanceof SyntaxError) {
|
50
|
+
logger.debug("Failed to parse WebFinger resource descriptor as JSON: {error}", { error: e });
|
41
51
|
return null;
|
52
|
+
}
|
42
53
|
throw e;
|
43
54
|
}
|
44
55
|
}
|
package/package.json
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"lookup.d.ts","sourceRoot":"","sources":["../../src/vocab/lookup.ts"],"names":[],"mappings":";
|
1
|
+
{"version":3,"file":"lookup.d.ts","sourceRoot":"","sources":["../../src/vocab/lookup.ts"],"names":[],"mappings":";AACA,OAAO,EACL,KAAK,cAAc,EAEpB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAIpC;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC;;OAEG;IACH,cAAc,CAAC,EAAE,cAAc,CAAC;IAEhC;;;OAGG;IACH,aAAa,CAAC,EAAE,cAAc,CAAC;CAChC;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,GAAG,GAAG,EACxB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiDxB"}
|