@fedify/fedify 0.11.0-dev.240 → 0.11.0-dev.242
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/CHANGES.md +51 -0
- package/esm/federation/handler.js +2 -2
- package/esm/federation/middleware.js +78 -0
- package/esm/vocab/activity.yaml +47 -0
- package/esm/vocab/application.yaml +14 -0
- package/esm/vocab/collection.yaml +0 -4
- package/esm/vocab/collectionpage.yaml +0 -3
- package/esm/vocab/group.yaml +14 -0
- package/esm/vocab/organization.yaml +14 -0
- package/esm/vocab/person.yaml +14 -0
- package/esm/vocab/service.yaml +14 -0
- package/esm/vocab/vocab.js +1350 -337
- package/package.json +1 -1
- package/types/federation/context.d.ts +16 -0
- package/types/federation/context.d.ts.map +1 -1
- package/types/federation/handler.d.ts +2 -2
- package/types/federation/handler.d.ts.map +1 -1
- package/types/federation/middleware.d.ts +13 -0
- package/types/federation/middleware.d.ts.map +1 -1
- package/types/testing/context.d.ts.map +1 -1
- package/types/vocab/vocab.d.ts +587 -51
- package/types/vocab/vocab.d.ts.map +1 -1
package/CHANGES.md
CHANGED
@@ -21,6 +21,10 @@ To be released.
|
|
21
21
|
- Added `{ type: "liked"; handle: string }` case to `ParseUriResult` type.
|
22
22
|
- Renamed `linked` property (which was a typo) to `liked` in
|
23
23
|
`Application`, `Group`, `Organization`, `Person`, and `Service` classes.
|
24
|
+
- Added `Federation.setFeaturedDispatcher()` method.
|
25
|
+
- Added `Context.getFeaturedUri()` method.
|
26
|
+
- Added `{ type: "featured"; handle: string }` case to `ParseUriResult`
|
27
|
+
type.
|
24
28
|
|
25
29
|
- Frequently used JSON-LD contexts are now preloaded. [[74]]
|
26
30
|
|
@@ -39,6 +43,53 @@ To be released.
|
|
39
43
|
- Added `Offer` class to Activity Vocabulary API.
|
40
44
|
[[#65], [#76] by Lee Dogeon]
|
41
45
|
|
46
|
+
- The below properties of `Collection` and `CollectionPage` in Activity
|
47
|
+
Vocabulary API now do not accept `Link` objects:
|
48
|
+
|
49
|
+
- `Collection.current`
|
50
|
+
- `Collection.first`
|
51
|
+
- `Collection.last`
|
52
|
+
- `Collection.items`
|
53
|
+
- `CollectionPage.partOf`
|
54
|
+
- `CollectionPage.next`
|
55
|
+
- `CollectionPage.prev`
|
56
|
+
|
57
|
+
- Added `target` property to `Activity` class in Activity Vocabulary API.
|
58
|
+
|
59
|
+
- Added `Activity.getTarget()` method.
|
60
|
+
- Added `Activity.getTargets()` method.
|
61
|
+
- `new Activity()` constructor now accepts `target` option.
|
62
|
+
- `new Activity()` constructor now accepts `targets` option.
|
63
|
+
- `Activity.clone()` method now accepts `target` option.
|
64
|
+
- `Activity.clone()` method now accepts `targets` option.
|
65
|
+
|
66
|
+
- Added `result` property to `Activity` class in Activity Vocabulary API.
|
67
|
+
|
68
|
+
- Added `Activity.getResult()` method.
|
69
|
+
- Added `Activity.getResults()` method.
|
70
|
+
- `new Activity()` constructor now accepts `result` option.
|
71
|
+
- `new Activity()` constructor now accepts `results` option.
|
72
|
+
- `Activity.clone()` method now accepts `result` option.
|
73
|
+
- `Activity.clone()` method now accepts `results` option.
|
74
|
+
|
75
|
+
- Added `origin` property to `Activity` class in Activity Vocabulary API.
|
76
|
+
|
77
|
+
- Added `Activity.getOrigin()` method.
|
78
|
+
- Added `Activity.getOrigins()` method.
|
79
|
+
- `new Activity()` constructor now accepts `origin` option.
|
80
|
+
- `new Activity()` constructor now accepts `origins` option.
|
81
|
+
- `Activity.clone()` method now accepts `origin` option.
|
82
|
+
- `Activity.clone()` method now accepts `origins` option.
|
83
|
+
|
84
|
+
- Added `instrument` property to `Activity` class in Activity Vocabulary API.
|
85
|
+
|
86
|
+
- Added `Activity.getInstrument()` method.
|
87
|
+
- Added `Activity.getInstruments()` method.
|
88
|
+
- `new Activity()` constructor now accepts `instrument` option.
|
89
|
+
- `new Activity()` constructor now accepts `instruments` option.
|
90
|
+
- `Activity.clone()` method now accepts `instrument` option.
|
91
|
+
- `Activity.clone()` method now accepts `instruments` option.
|
92
|
+
|
42
93
|
- The key pair or the key pair for signing outgoing HTTP requests made from
|
43
94
|
the shared inbox now can be configured. This improves the compatibility
|
44
95
|
with other ActivityPub implementations that require authorized fetches
|
@@ -4,7 +4,7 @@ import { accepts } from "../deps/jsr.io/@std/http/0.224.5/negotiation.js";
|
|
4
4
|
import { verifyRequest } from "../sig/http.js";
|
5
5
|
import { doesActorOwnKey } from "../sig/owner.js";
|
6
6
|
import { verifyObject } from "../sig/proof.js";
|
7
|
-
import { Activity,
|
7
|
+
import { Activity, Object, OrderedCollection, OrderedCollectionPage, } from "../vocab/vocab.js";
|
8
8
|
export function acceptsJsonLd(request) {
|
9
9
|
const types = accepts(request);
|
10
10
|
if (types == null)
|
@@ -146,7 +146,7 @@ function filterCollectionItems(items, collectionName, filterPredicate) {
|
|
146
146
|
let logged = false;
|
147
147
|
for (const item of items) {
|
148
148
|
let mappedItem;
|
149
|
-
if (item instanceof Object || item instanceof
|
149
|
+
if (item instanceof Object || item instanceof URL) {
|
150
150
|
mappedItem = item;
|
151
151
|
}
|
152
152
|
else if (item.id == null)
|
@@ -48,6 +48,7 @@ export class Federation {
|
|
48
48
|
#followingCallbacks;
|
49
49
|
#followersCallbacks;
|
50
50
|
#likedCallbacks;
|
51
|
+
#featuredCallbacks;
|
51
52
|
#inboxListeners;
|
52
53
|
#inboxErrorHandler;
|
53
54
|
#sharedInboxKeyDispatcher;
|
@@ -334,6 +335,19 @@ export class Federation {
|
|
334
335
|
"URI. Set the property with Context.getLikedUri(handle).");
|
335
336
|
}
|
336
337
|
}
|
338
|
+
if (this.#featuredCallbacks != null &&
|
339
|
+
this.#featuredCallbacks.dispatcher != null) {
|
340
|
+
if (actor?.featuredId == null) {
|
341
|
+
logger.warn("You configured a featured collection dispatcher, but the " +
|
342
|
+
"actor does not have a featured property. Set the property " +
|
343
|
+
"with Context.getFeaturedUri(handle).");
|
344
|
+
}
|
345
|
+
else if (actor.featuredId.href != context.getFeaturedUri(handle).href) {
|
346
|
+
logger.warn("You configured a featured collection dispatcher, but the " +
|
347
|
+
"actor's featured property does not match the featured collection " +
|
348
|
+
"URI. Set the property with Context.getFeaturedUri(handle).");
|
349
|
+
}
|
350
|
+
}
|
337
351
|
if (this.#router.has("inbox")) {
|
338
352
|
if (actor.inboxId == null) {
|
339
353
|
logger.warn("You configured inbox listeners, but the actor does not " +
|
@@ -658,6 +672,50 @@ export class Federation {
|
|
658
672
|
};
|
659
673
|
return setters;
|
660
674
|
}
|
675
|
+
/**
|
676
|
+
* Registers a featured collection dispatcher.
|
677
|
+
* @param path The URI path pattern for the featured collection. The syntax
|
678
|
+
* is based on URI Template
|
679
|
+
* ([RFC 6570](https://tools.ietf.org/html/rfc6570)). The path
|
680
|
+
* must have one variable: `{handle}`.
|
681
|
+
* @param dispatcher A featured collection callback to register.
|
682
|
+
* @returns An object with methods to set other featured collection
|
683
|
+
* callbacks.
|
684
|
+
* @throws {@link RouterError} Thrown if the path pattern is invalid.
|
685
|
+
* @since 0.11.0
|
686
|
+
*/
|
687
|
+
setFeaturedDispatcher(path, dispatcher) {
|
688
|
+
if (this.#router.has("featured")) {
|
689
|
+
throw new RouterError("Featured collection dispatcher already set.");
|
690
|
+
}
|
691
|
+
const variables = this.#router.add(path, "featured");
|
692
|
+
if (variables.size !== 1 || !variables.has("handle")) {
|
693
|
+
throw new RouterError("Path for featured collection dispatcher must have one variable: {handle}");
|
694
|
+
}
|
695
|
+
const callbacks = {
|
696
|
+
dispatcher,
|
697
|
+
};
|
698
|
+
this.#featuredCallbacks = callbacks;
|
699
|
+
const setters = {
|
700
|
+
setCounter(counter) {
|
701
|
+
callbacks.counter = counter;
|
702
|
+
return setters;
|
703
|
+
},
|
704
|
+
setFirstCursor(cursor) {
|
705
|
+
callbacks.firstCursor = cursor;
|
706
|
+
return setters;
|
707
|
+
},
|
708
|
+
setLastCursor(cursor) {
|
709
|
+
callbacks.lastCursor = cursor;
|
710
|
+
return setters;
|
711
|
+
},
|
712
|
+
authorize(predicate) {
|
713
|
+
callbacks.authorizePredicate = predicate;
|
714
|
+
return setters;
|
715
|
+
},
|
716
|
+
};
|
717
|
+
return setters;
|
718
|
+
}
|
661
719
|
/**
|
662
720
|
* Assigns the URL path for the inbox and starts setting inbox listeners.
|
663
721
|
*
|
@@ -994,6 +1052,16 @@ export class Federation {
|
|
994
1052
|
onNotFound,
|
995
1053
|
onNotAcceptable,
|
996
1054
|
});
|
1055
|
+
case "featured":
|
1056
|
+
return await handleCollection(request, {
|
1057
|
+
name: "featured",
|
1058
|
+
handle: route.values.handle,
|
1059
|
+
context,
|
1060
|
+
collectionCallbacks: this.#featuredCallbacks,
|
1061
|
+
onUnauthorized,
|
1062
|
+
onNotFound,
|
1063
|
+
onNotAcceptable,
|
1064
|
+
});
|
997
1065
|
default: {
|
998
1066
|
const response = onNotFound(request);
|
999
1067
|
return response instanceof Promise ? await response : response;
|
@@ -1099,6 +1167,13 @@ class ContextImpl {
|
|
1099
1167
|
}
|
1100
1168
|
return new URL(path, this.#url);
|
1101
1169
|
}
|
1170
|
+
getFeaturedUri(handle) {
|
1171
|
+
const path = this.#router.build("featured", { handle });
|
1172
|
+
if (path == null) {
|
1173
|
+
throw new RouterError("No featured collection path registered.");
|
1174
|
+
}
|
1175
|
+
return new URL(path, this.#url);
|
1176
|
+
}
|
1102
1177
|
parseUri(uri) {
|
1103
1178
|
if (uri.origin !== this.#url.origin)
|
1104
1179
|
return null;
|
@@ -1135,6 +1210,9 @@ class ContextImpl {
|
|
1135
1210
|
else if (route.name === "liked") {
|
1136
1211
|
return { type: "liked", handle: route.values.handle };
|
1137
1212
|
}
|
1213
|
+
else if (route.name === "featured") {
|
1214
|
+
return { type: "featured", handle: route.values.handle };
|
1215
|
+
}
|
1138
1216
|
return null;
|
1139
1217
|
}
|
1140
1218
|
getHandleFromActorUri(actorUri) {
|
package/esm/vocab/activity.yaml
CHANGED
@@ -41,3 +41,50 @@ properties:
|
|
41
41
|
wishlist", the object of the activity is the movie added.
|
42
42
|
range:
|
43
43
|
- "https://www.w3.org/ns/activitystreams#Object"
|
44
|
+
|
45
|
+
- pluralName: targets
|
46
|
+
singularName: target
|
47
|
+
singularAccessor: true
|
48
|
+
uri: "https://www.w3.org/ns/activitystreams#target"
|
49
|
+
description: |
|
50
|
+
Describes the indirect object, or target, of the activity. The precise
|
51
|
+
meaning of the target is largely dependent on the type of action being
|
52
|
+
described but will often be the object of the English preposition "to".
|
53
|
+
For instance, in the activity "John added a movie to his wishlist",
|
54
|
+
the target of the activity is John's wishlist. An activity can have more
|
55
|
+
than one target.
|
56
|
+
range:
|
57
|
+
- "https://www.w3.org/ns/activitystreams#Object"
|
58
|
+
|
59
|
+
- pluralName: results
|
60
|
+
singularName: result
|
61
|
+
singularAccessor: true
|
62
|
+
uri: "https://www.w3.org/ns/activitystreams#result"
|
63
|
+
description: |
|
64
|
+
Describes the result of the activity. For instance, if a particular action
|
65
|
+
results in the creation of a new resource, the result property can be used
|
66
|
+
to describe that new resource.
|
67
|
+
range:
|
68
|
+
- "https://www.w3.org/ns/activitystreams#Object"
|
69
|
+
|
70
|
+
- pluralName: origins
|
71
|
+
singularName: origin
|
72
|
+
singularAccessor: true
|
73
|
+
uri: "https://www.w3.org/ns/activitystreams#origin"
|
74
|
+
description: |
|
75
|
+
Describes an indirect object of the activity from which the activity is
|
76
|
+
directed. The precise meaning of the origin is the object of the English
|
77
|
+
preposition "from". For instance, in the activity "John moved an item to
|
78
|
+
List B from List A", the origin of the activity is "List A".
|
79
|
+
range:
|
80
|
+
- "https://www.w3.org/ns/activitystreams#Object"
|
81
|
+
|
82
|
+
- pluralName: instruments
|
83
|
+
singularName: instrument
|
84
|
+
singularAccessor: true
|
85
|
+
uri: "https://www.w3.org/ns/activitystreams#instrument"
|
86
|
+
description: |
|
87
|
+
Identifies one or more objects used (or to be used) in the completion of
|
88
|
+
an {@link Activity}.
|
89
|
+
range:
|
90
|
+
- "https://www.w3.org/ns/activitystreams#Object"
|
@@ -12,6 +12,9 @@ defaultContext:
|
|
12
12
|
- "https://w3id.org/security/multikey/v1"
|
13
13
|
- manuallyApprovesFollowers: "as:manuallyApprovesFollowers"
|
14
14
|
toot: "http://joinmastodon.org/ns#"
|
15
|
+
featured:
|
16
|
+
"@id": "toot:featured"
|
17
|
+
"@type": "@id"
|
15
18
|
discoverable: "toot:discoverable"
|
16
19
|
suspended: "toot:suspended"
|
17
20
|
memorial: "toot:memorial"
|
@@ -143,6 +146,17 @@ properties:
|
|
143
146
|
range:
|
144
147
|
- "https://www.w3.org/ns/activitystreams#Collection"
|
145
148
|
|
149
|
+
- singularName: featured
|
150
|
+
functional: true
|
151
|
+
uri: "http://joinmastodon.org/ns#featured"
|
152
|
+
description: |
|
153
|
+
What is known in Mastodon as "pinned statuses", or statuses that are always
|
154
|
+
featured at the top of people's profiles, is implemented using an extra
|
155
|
+
property `featured` on the actor object that points to a {@link Collection}
|
156
|
+
of objects.
|
157
|
+
range:
|
158
|
+
- "https://www.w3.org/ns/activitystreams#Collection"
|
159
|
+
|
146
160
|
- pluralName: streams
|
147
161
|
singularName: stream
|
148
162
|
singularAccessor: false
|
@@ -30,7 +30,6 @@ properties:
|
|
30
30
|
the most recently updated member items.
|
31
31
|
range:
|
32
32
|
- "https://www.w3.org/ns/activitystreams#CollectionPage"
|
33
|
-
- "https://www.w3.org/ns/activitystreams#Link"
|
34
33
|
|
35
34
|
- singularName: first
|
36
35
|
functional: true
|
@@ -40,7 +39,6 @@ properties:
|
|
40
39
|
items in the collection.
|
41
40
|
range:
|
42
41
|
- "https://www.w3.org/ns/activitystreams#CollectionPage"
|
43
|
-
- "https://www.w3.org/ns/activitystreams#Link"
|
44
42
|
|
45
43
|
- singularName: last
|
46
44
|
functional: true
|
@@ -50,7 +48,6 @@ properties:
|
|
50
48
|
the collection.
|
51
49
|
range:
|
52
50
|
- "https://www.w3.org/ns/activitystreams#CollectionPage"
|
53
|
-
- "https://www.w3.org/ns/activitystreams#Link"
|
54
51
|
|
55
52
|
- pluralName: items
|
56
53
|
singularName: item
|
@@ -60,4 +57,3 @@ properties:
|
|
60
57
|
or unordered.
|
61
58
|
range:
|
62
59
|
- "https://www.w3.org/ns/activitystreams#Object"
|
63
|
-
- "https://www.w3.org/ns/activitystreams#Link"
|
@@ -17,7 +17,6 @@ properties:
|
|
17
17
|
Identifies the {@link Collection} to which a {@link CollectionPage} objects
|
18
18
|
items belong.
|
19
19
|
range:
|
20
|
-
- "https://www.w3.org/ns/activitystreams#Link"
|
21
20
|
- "https://www.w3.org/ns/activitystreams#Collection"
|
22
21
|
|
23
22
|
- singularName: next
|
@@ -26,7 +25,6 @@ properties:
|
|
26
25
|
description: In a paged {@link Collection}, indicates the next page of items.
|
27
26
|
range:
|
28
27
|
- "https://www.w3.org/ns/activitystreams#CollectionPage"
|
29
|
-
- "https://www.w3.org/ns/activitystreams#Link"
|
30
28
|
|
31
29
|
- singularName: prev
|
32
30
|
functional: true
|
@@ -35,4 +33,3 @@ properties:
|
|
35
33
|
In a paged {@link Collection}, identifies the previous page of items.
|
36
34
|
range:
|
37
35
|
- "https://www.w3.org/ns/activitystreams#CollectionPage"
|
38
|
-
- "https://www.w3.org/ns/activitystreams#Link"
|
package/esm/vocab/group.yaml
CHANGED
@@ -12,6 +12,9 @@ defaultContext:
|
|
12
12
|
- "https://w3id.org/security/multikey/v1"
|
13
13
|
- manuallyApprovesFollowers: "as:manuallyApprovesFollowers"
|
14
14
|
toot: "http://joinmastodon.org/ns#"
|
15
|
+
featured:
|
16
|
+
"@id": "toot:featured"
|
17
|
+
"@type": "@id"
|
15
18
|
discoverable: "toot:discoverable"
|
16
19
|
suspended: "toot:suspended"
|
17
20
|
memorial: "toot:memorial"
|
@@ -143,6 +146,17 @@ properties:
|
|
143
146
|
range:
|
144
147
|
- "https://www.w3.org/ns/activitystreams#Collection"
|
145
148
|
|
149
|
+
- singularName: featured
|
150
|
+
functional: true
|
151
|
+
uri: "http://joinmastodon.org/ns#featured"
|
152
|
+
description: |
|
153
|
+
What is known in Mastodon as "pinned statuses", or statuses that are always
|
154
|
+
featured at the top of people's profiles, is implemented using an extra
|
155
|
+
property `featured` on the actor object that points to a {@link Collection}
|
156
|
+
of objects.
|
157
|
+
range:
|
158
|
+
- "https://www.w3.org/ns/activitystreams#Collection"
|
159
|
+
|
146
160
|
- pluralName: streams
|
147
161
|
singularName: stream
|
148
162
|
singularAccessor: false
|
@@ -12,6 +12,9 @@ defaultContext:
|
|
12
12
|
- "https://w3id.org/security/multikey/v1"
|
13
13
|
- manuallyApprovesFollowers: "as:manuallyApprovesFollowers"
|
14
14
|
toot: "http://joinmastodon.org/ns#"
|
15
|
+
featured:
|
16
|
+
"@id": "toot:featured"
|
17
|
+
"@type": "@id"
|
15
18
|
discoverable: "toot:discoverable"
|
16
19
|
suspended: "toot:suspended"
|
17
20
|
memorial: "toot:memorial"
|
@@ -143,6 +146,17 @@ properties:
|
|
143
146
|
range:
|
144
147
|
- "https://www.w3.org/ns/activitystreams#Collection"
|
145
148
|
|
149
|
+
- singularName: featured
|
150
|
+
functional: true
|
151
|
+
uri: "http://joinmastodon.org/ns#featured"
|
152
|
+
description: |
|
153
|
+
What is known in Mastodon as "pinned statuses", or statuses that are always
|
154
|
+
featured at the top of people's profiles, is implemented using an extra
|
155
|
+
property `featured` on the actor object that points to a {@link Collection}
|
156
|
+
of objects.
|
157
|
+
range:
|
158
|
+
- "https://www.w3.org/ns/activitystreams#Collection"
|
159
|
+
|
146
160
|
- pluralName: streams
|
147
161
|
singularName: stream
|
148
162
|
singularAccessor: false
|
package/esm/vocab/person.yaml
CHANGED
@@ -12,6 +12,9 @@ defaultContext:
|
|
12
12
|
- "https://w3id.org/security/multikey/v1"
|
13
13
|
- manuallyApprovesFollowers: "as:manuallyApprovesFollowers"
|
14
14
|
toot: "http://joinmastodon.org/ns#"
|
15
|
+
featured:
|
16
|
+
"@id": "toot:featured"
|
17
|
+
"@type": "@id"
|
15
18
|
discoverable: "toot:discoverable"
|
16
19
|
suspended: "toot:suspended"
|
17
20
|
memorial: "toot:memorial"
|
@@ -143,6 +146,17 @@ properties:
|
|
143
146
|
range:
|
144
147
|
- "https://www.w3.org/ns/activitystreams#Collection"
|
145
148
|
|
149
|
+
- singularName: featured
|
150
|
+
functional: true
|
151
|
+
uri: "http://joinmastodon.org/ns#featured"
|
152
|
+
description: |
|
153
|
+
What is known in Mastodon as "pinned statuses", or statuses that are always
|
154
|
+
featured at the top of people's profiles, is implemented using an extra
|
155
|
+
property `featured` on the actor object that points to a {@link Collection}
|
156
|
+
of objects.
|
157
|
+
range:
|
158
|
+
- "https://www.w3.org/ns/activitystreams#Collection"
|
159
|
+
|
146
160
|
- pluralName: streams
|
147
161
|
singularName: stream
|
148
162
|
singularAccessor: false
|
package/esm/vocab/service.yaml
CHANGED
@@ -12,6 +12,9 @@ defaultContext:
|
|
12
12
|
- "https://w3id.org/security/multikey/v1"
|
13
13
|
- manuallyApprovesFollowers: "as:manuallyApprovesFollowers"
|
14
14
|
toot: "http://joinmastodon.org/ns#"
|
15
|
+
featured:
|
16
|
+
"@id": "toot:featured"
|
17
|
+
"@type": "@id"
|
15
18
|
discoverable: "toot:discoverable"
|
16
19
|
suspended: "toot:suspended"
|
17
20
|
memorial: "toot:memorial"
|
@@ -143,6 +146,17 @@ properties:
|
|
143
146
|
range:
|
144
147
|
- "https://www.w3.org/ns/activitystreams#Collection"
|
145
148
|
|
149
|
+
- singularName: featured
|
150
|
+
functional: true
|
151
|
+
uri: "http://joinmastodon.org/ns#featured"
|
152
|
+
description: |
|
153
|
+
What is known in Mastodon as "pinned statuses", or statuses that are always
|
154
|
+
featured at the top of people's profiles, is implemented using an extra
|
155
|
+
property `featured` on the actor object that points to a {@link Collection}
|
156
|
+
of objects.
|
157
|
+
range:
|
158
|
+
- "https://www.w3.org/ns/activitystreams#Collection"
|
159
|
+
|
146
160
|
- pluralName: streams
|
147
161
|
singularName: stream
|
148
162
|
singularAccessor: false
|