@graffiti-garden/api 0.6.3 → 1.0.0
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/README.md +0 -4
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +3 -3
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +3 -3
- package/dist/src/1-api.d.ts +198 -330
- package/dist/src/1-api.d.ts.map +1 -1
- package/dist/src/2-types.d.ts +52 -161
- package/dist/src/2-types.d.ts.map +1 -1
- package/dist/src/3-errors.d.ts +2 -2
- package/dist/src/3-errors.d.ts.map +1 -1
- package/dist/tests/crud.d.ts +1 -1
- package/dist/tests/crud.d.ts.map +1 -1
- package/dist/tests/discover.d.ts +1 -1
- package/dist/tests/discover.d.ts.map +1 -1
- package/dist/tests/index.d.ts +0 -4
- package/dist/tests/index.d.ts.map +1 -1
- package/dist/tests/utils.d.ts +3 -3
- package/dist/tests/utils.d.ts.map +1 -1
- package/dist/tests.mjs +3 -1269
- package/dist/tests.mjs.map +4 -4
- package/package.json +6 -7
- package/src/1-api.ts +203 -338
- package/src/2-types.ts +53 -166
- package/src/3-errors.ts +6 -6
- package/tests/crud.ts +42 -320
- package/tests/discover.ts +51 -349
- package/tests/index.ts +2 -4
- package/tests/utils.ts +4 -4
- package/dist/tests/channel-stats.d.ts +0 -3
- package/dist/tests/channel-stats.d.ts.map +0 -1
- package/dist/tests/orphans.d.ts +0 -3
- package/dist/tests/orphans.d.ts.map +0 -1
- package/tests/channel-stats.ts +0 -129
- package/tests/orphans.ts +0 -128
package/dist/src/1-api.d.ts
CHANGED
|
@@ -1,237 +1,143 @@
|
|
|
1
|
-
import type { GraffitiObjectUrl, GraffitiObject,
|
|
1
|
+
import type { GraffitiObjectUrl, GraffitiObject, GraffitiSession, GraffitiPostObject, GraffitiObjectStream, GraffitiObjectStreamContinue } from "./2-types";
|
|
2
2
|
import type { JSONSchema } from "json-schema-to-ts";
|
|
3
3
|
/**
|
|
4
4
|
* This API describes a small but powerful set of methods that
|
|
5
|
-
* can be used to create many different kinds of social
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* can be used to create many different kinds of social applications,
|
|
6
|
+
* from applications like Twitter, to Messenger, to Wikipedia, to many more new designs.
|
|
7
|
+
* See the [Graffiti project website](https://graffiti.garden)
|
|
8
|
+
* for links to example applications. Additionally, apps built on top
|
|
9
|
+
* of the API interoperate with each other so you can seamlessly switch
|
|
10
|
+
* between apps without losing your friends or data.
|
|
11
|
+
*
|
|
12
|
+
* These API methods should satisfy all of an application's needs for
|
|
8
13
|
* the communication, storage, and access management of social data.
|
|
9
14
|
* The rest of the application can be built with standard client-side
|
|
10
|
-
* user interface tools to present and interact with
|
|
11
|
-
*
|
|
12
|
-
* The Typescript
|
|
13
|
-
* [graffiti-garden/api](https://github.com/graffiti-garden/api).
|
|
15
|
+
* user interface tools to present and interact with that data—no server code necessary!
|
|
16
|
+
*
|
|
17
|
+
* The Typescript code for this API is [open source on Github](https://github.com/graffiti-garden/api).
|
|
14
18
|
*
|
|
15
19
|
* There are several different implementations of this Graffiti API available,
|
|
16
|
-
* including a [federated implementation](https://github.com/graffiti-garden/implementation-
|
|
17
|
-
* that lets
|
|
20
|
+
* including a [federated implementation](https://github.com/graffiti-garden/implementation-remote),
|
|
21
|
+
* that lets people choose where their data is stored (you do not need to host your own server)
|
|
18
22
|
* and a [local implementation](https://github.com/graffiti-garden/implementation-local)
|
|
19
|
-
* that can be used for testing and development.
|
|
20
|
-
*
|
|
21
|
-
* of
|
|
22
|
-
*
|
|
23
|
-
* are useless if the system as a whole doesn't expose useful functionality to developers.
|
|
24
|
-
*
|
|
25
|
-
* On the other side of the stack, there is [Vue plugin](https://github.com/graffiti-garden/wrapper-vue/)
|
|
26
|
-
* that wraps around this API to provide reactivity. Other high-level libraries
|
|
27
|
-
* will be available in the future.
|
|
28
|
-
*
|
|
29
|
-
* ## Overview
|
|
30
|
-
*
|
|
31
|
-
* Graffiti provides applications with methods to create and store data
|
|
32
|
-
* on behalf of their users using standard CRUD operations:
|
|
33
|
-
* {@link put}, {@link get}, {@link patch}, and {@link delete}.
|
|
34
|
-
* This data can represent both social artifacts (e.g. posts, profiles) and
|
|
35
|
-
* activities (e.g. likes, follows) and is stored as JSON.
|
|
36
|
-
*
|
|
37
|
-
* The social aspect of Graffiti comes from the {@link discover} method
|
|
38
|
-
* which allows applications to find objects that other users made.
|
|
39
|
-
* It is a lot like a traditional query operation, but it only
|
|
40
|
-
* returns objects that have been placed in particular
|
|
41
|
-
* {@link GraffitiObjectBase.channels | `channels`}
|
|
42
|
-
* specified by the discovering application.
|
|
43
|
-
*
|
|
44
|
-
* Graffiti builds on well known concepts and standards wherever possible.
|
|
45
|
-
* JSON Objects can be typed with [JSON Schema](https://json-schema.org/) and patches
|
|
46
|
-
* can be applied with [JSON Patch](https://jsonpatch.com).
|
|
47
|
-
* For interoperability between Graffiti applications, we recommend that
|
|
48
|
-
* objects use established properties from the
|
|
49
|
-
* [Activity Vocabulary](https://www.w3.org/TR/activitystreams-vocabulary/) when available,
|
|
50
|
-
* however it is always possible to create additional properties, contributing
|
|
51
|
-
* to the broader [folksonomy](https://en.wikipedia.org/wiki/Folksonomy).
|
|
23
|
+
* that can be used for testing and development. Different implementations can
|
|
24
|
+
* be swapped-in in the future without changing the API or any of the apps built on
|
|
25
|
+
* top of it. In fact, we're working on an end-to-end encrypted version now!
|
|
26
|
+
* [Follow Theia on BlueSky for updates](https://bsky.app/profile/theias.place).
|
|
52
27
|
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* [context collapse](https://en.wikipedia.org/wiki/Context_collapse)
|
|
57
|
-
* even in a highly interoperable environment.
|
|
58
|
-
* Interaction relativity means that all interactions between users are
|
|
59
|
-
* actually atomic single-user operations that can be interpreted in different ways,
|
|
60
|
-
* which also supports interoperability and pluralism.
|
|
28
|
+
* On the other side of the stack, there is [Vue plugin](https://vue.graffiti.garden/variables/GraffitiPlugin.html)
|
|
29
|
+
* that wraps around this API to provide reactivity. Other plugin frameworks
|
|
30
|
+
* and high-level libraries will be available in the future.
|
|
61
31
|
*
|
|
62
|
-
*
|
|
32
|
+
* ## API Overview
|
|
63
33
|
*
|
|
64
|
-
* {@link
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
34
|
+
* The Graffiti API provides applications with methods for {@link login} and {@link logout},
|
|
35
|
+
* methods to interact with data objects using standard database operations ({@link post}, {@link get}, and {@link delete}),
|
|
36
|
+
* and a method to {@link discover} data objects created by others.
|
|
37
|
+
* These data objects have a couple structured properties:
|
|
38
|
+
* - {@link GraffitiObjectBase.url | `url`} (string): A globally unique identifier and locator for the object.
|
|
39
|
+
* - {@link GraffitiObjectBase.actor | `actor`} (string): An unforgeable identifier for the creator of the object.
|
|
40
|
+
* - {@link GraffitiObjectBase.allowed | `allowed`} (string[] | undefined): An array of the actors who are allowed to access the object (undefined for public objects).
|
|
41
|
+
* - {@link GraffitiObjectBase.channels | `channels`} (string[]): An array of the *contexts* in which the object should appear.
|
|
70
42
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* {@link GraffitiObjectBase.actor | `actor` URI}), then people viewing the commenter's profile
|
|
83
|
-
* will also see the comment, giving it more visibility, like a reply on Twitter.
|
|
84
|
-
* If we *only* place the comment in the channel represented by the commenter's URI, then
|
|
85
|
-
* it becomes like a quote tweet ([prior to 2020](https://x.com/Support/status/1300555325750292480)),
|
|
86
|
-
* where the comment is only visible to the commenter's followers but not the audience
|
|
87
|
-
* of the original post.
|
|
88
|
-
*
|
|
89
|
-
* The channel model differs from other models of communication such as the
|
|
90
|
-
* [actor model](https://www.w3.org/TR/activitypub/#Overview) used by ActivityPub,
|
|
91
|
-
* the protocol underlying Mastodon, or the [firehose model](https://bsky.social/about/blog/5-5-2023-federation-architecture)
|
|
92
|
-
* used by the AT Protocol, the protocol underlying BlueSky.
|
|
93
|
-
* The actor model is a fusion of direct messaging (like Email) and broadcasting
|
|
94
|
-
* (like RSS) and works well for follow-based communication but struggles
|
|
95
|
-
* to pass information via other rendez-vous.
|
|
96
|
-
* In the actor model, even something as simple as comments can be
|
|
97
|
-
* [very tricky and require server "side effects"](https://seb.jambor.dev/posts/understanding-activitypub-part-3-the-state-of-mastodon/).
|
|
98
|
-
* The firehose model dumps all user data into one public database,
|
|
99
|
-
* which doesn't allow for the carving out of different contexts that we did in our comment
|
|
100
|
-
* example above. In the firehose model a comment will always be visible to *both* the original post's audience and
|
|
101
|
-
* the commenter's followers.
|
|
102
|
-
*
|
|
103
|
-
* In some sense, channels provide a sort of "social access control" by forming
|
|
104
|
-
* expectations about the audiences of different online spaces.
|
|
105
|
-
* As a real world analogy, oftentimes support groups, such as alcoholics
|
|
106
|
-
* anonymous, are open to the public but people in those spaces feel comfortable sharing intimate details
|
|
107
|
-
* because they have expectations about the other people attending.
|
|
108
|
-
* If someone malicious went to support groups just to spread people's secrets,
|
|
109
|
-
* they would be shamed for violating these norms.
|
|
110
|
-
* Similarly, in Graffiti, while you could spider public channels like a search engine
|
|
111
|
-
* to find content about a person, revealing that you've done such a thing
|
|
112
|
-
* would be shameful.
|
|
43
|
+
* All other data is stored in the object's unstructured {@link GraffitiObjectBase.value | `value`} property.
|
|
44
|
+
* This data can be used to represent social artifacts (e.g. posts, profiles) and activities (e.g. likes, follows).
|
|
45
|
+
* For example, a post might have the value:
|
|
46
|
+
|
|
47
|
+
* ```js
|
|
48
|
+
* {
|
|
49
|
+
* title: "My First Post",
|
|
50
|
+
* content: "Hello, world!",
|
|
51
|
+
* published: 1630483200000
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
113
54
|
*
|
|
114
|
-
*
|
|
115
|
-
* objects can also be given
|
|
116
|
-
* an {@link GraffitiObjectBase.allowed | `allowed`} list.
|
|
117
|
-
* For example, to send someone a direct message you should put an object representing
|
|
118
|
-
* that message in the channel that represents them (their {@link GraffitiObjectBase.actor | `actor` URI}),
|
|
119
|
-
* so they can find it, *and* set the `allowed` field to only include the recipient,
|
|
120
|
-
* so only they can read it.
|
|
55
|
+
* a profile might have the value:
|
|
121
56
|
*
|
|
122
|
-
*
|
|
57
|
+
* ```js
|
|
58
|
+
* {
|
|
59
|
+
* name: "Theia Henderson",
|
|
60
|
+
* pronouns: "she/her",
|
|
61
|
+
* describes: "did:web:theias.place" // Theia's actor ID
|
|
62
|
+
* }
|
|
63
|
+
* ```
|
|
123
64
|
*
|
|
124
|
-
*
|
|
125
|
-
* exists relative to an observer," or equivalently, all interaction is [reified](https://en.wikipedia.org/wiki/Reification_(computer_science)).
|
|
126
|
-
* For example, if one user creates a post and another user wants to "like" that post,
|
|
127
|
-
* their like is not modifying the original post, it is simply another data object that points
|
|
128
|
-
* to the post being liked, via its {@link GraffitiObjectBase.url | URL}.
|
|
65
|
+
* and a "Like" might have the value:
|
|
129
66
|
*
|
|
130
|
-
* ```
|
|
67
|
+
* ```js
|
|
131
68
|
* {
|
|
132
|
-
* activity:
|
|
133
|
-
* target:
|
|
134
|
-
* actor: 'my-user-id'
|
|
69
|
+
* activity: "Like",
|
|
70
|
+
* target: "graffiti:remote:pod.graffiti.garden/12345" // The URL of the graffiti object being liked
|
|
135
71
|
* }
|
|
136
72
|
* ```
|
|
137
73
|
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
* users can freely switch between them.
|
|
147
|
-
*
|
|
148
|
-
* Interaction relativy also allows applications to introduce new sorts of interactions
|
|
149
|
-
* without having to coordinate with all the other existing applications,
|
|
150
|
-
* keeping the ecosystem flexible and interoperable.
|
|
151
|
-
* For example, an application could [add a "Trust" button to posts](https://social.cs.washington.edu/pub_details.html?id=trustnet)
|
|
152
|
-
* and use it assess the truthfulness of posts made on applications across Graffiti.
|
|
153
|
-
* New sorts of interactions like these can be smoothly absorbed by the broader ecosystem
|
|
154
|
-
* as a [folksonomy](https://en.wikipedia.org/wiki/Folksonomy).
|
|
74
|
+
* New social artifacts and activities can be easily created, simply
|
|
75
|
+
* by creating new objects with appropriate properties. Despite the lack of
|
|
76
|
+
* structure, we expect Graffiti object properties to adhere to a "[folksonomy](https://en.wikipedia.org/wiki/Folksonomy)",
|
|
77
|
+
* similar to hashtags. Any string can be used as a hashtag on Twitter,
|
|
78
|
+
* but there is social value in using the same hashtags at other people and
|
|
79
|
+
* so a structure naturally emerges. Similarly, Graffiti objects
|
|
80
|
+
* can have arbitrary properties but if people use the same properties as each other,
|
|
81
|
+
* their apps will interoperate, which has social value.
|
|
155
82
|
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
* Many interactions can be reified via pointers, as in the "like" example above, and collaborative
|
|
162
|
-
* edits can be refieid via [CRDTs](https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type).
|
|
163
|
-
* 2. No one owns channels. Unlike IRC/Slack channels or [Matrix rooms](https://matrix.org/docs/matrix-concepts/rooms_and_events/),
|
|
164
|
-
* anyone can post to any channel, so long as they know the URI of that channel.
|
|
165
|
-
* It is up to applications to hide content from channels either according to manual
|
|
166
|
-
* filters or in response to user action.
|
|
167
|
-
* For example, a user may create a post with the flag `disableReplies`.
|
|
168
|
-
* Applications could then filter out any content from the replies channel
|
|
169
|
-
* that the original poster has not specifically approved.
|
|
83
|
+
* For a more complete and detailed overview of Graffiti's design, please
|
|
84
|
+
* refer to [this section of the Graffiti paper](https://dl.acm.org/doi/10.1145/3746059.3747627#sec-3),
|
|
85
|
+
* published in ACM UIST 2025. The paper also overviews {@link GraffitiObjectBase.channels | `channels`},
|
|
86
|
+
* which are Graffiti's means of organizing data contextually, and a concept called "total reification",
|
|
87
|
+
* which handles explains how moderation, collaboration, and other interactions are managed.
|
|
170
88
|
*
|
|
171
|
-
* @groupDescription
|
|
172
|
-
* Methods for {@link
|
|
89
|
+
* @groupDescription 1 - Single-Object Methods
|
|
90
|
+
* Methods for {@link post | creating}, {@link get | reading},
|
|
173
91
|
* and {@link delete | deleting} {@link GraffitiObjectBase | Graffiti objects}.
|
|
174
|
-
* @groupDescription
|
|
92
|
+
* @groupDescription 2 - Multi-Object Methods
|
|
175
93
|
* Methods that retrieve or accumulate information about multiple {@link GraffitiObjectBase | Graffiti objects} at a time.
|
|
176
|
-
* @groupDescription
|
|
177
|
-
* Methods
|
|
94
|
+
* @groupDescription 3 - Media Methods
|
|
95
|
+
* Methods for {@link postMedia | creating}, {@link getMedia | reading},
|
|
96
|
+
* and {@link deleteMedia | deleting} media data.
|
|
97
|
+
* @groupDescription 4 - Session Management
|
|
98
|
+
* Methods and properties for logging in and out.
|
|
178
99
|
*/
|
|
179
100
|
export declare abstract class Graffiti {
|
|
180
101
|
/**
|
|
181
|
-
* Creates a new {@link GraffitiObjectBase | object}
|
|
182
|
-
* An object can only be replaced by the same {@link GraffitiObjectBase.actor | `actor`}
|
|
183
|
-
* that created it.
|
|
102
|
+
* Creates a new {@link GraffitiObjectBase | object}.
|
|
184
103
|
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
* @throws {@link GraffitiErrorNotFound} if a {@link GraffitiObjectBase.url | `url`}
|
|
189
|
-
* is provided that has not been created yet or the {@link GraffitiObjectBase.actor | `actor`}
|
|
190
|
-
* is not {@link GraffitiObjectBase.allowed | `allowed`} to see it.
|
|
191
|
-
*
|
|
192
|
-
* @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}
|
|
193
|
-
* is not the same `actor` as the one who created the object.
|
|
194
|
-
*
|
|
195
|
-
* @returns The object that was replaced if one one exists, otherwise an object with
|
|
196
|
-
* with an empty {@link GraffitiObjectBase.value | `value`},
|
|
197
|
-
* {@link GraffitiObjectBase.channels | `channels`}, and {@link GraffitiObjectBase.allowed | `allowed`}
|
|
198
|
-
* list.
|
|
199
|
-
* The {@link GraffitiObjectBase.lastModified | `lastModified`} property of the returned object
|
|
200
|
-
* will be updated to the time of replacement/creation.
|
|
104
|
+
* @returns Returns the object that has been posted, complete with its
|
|
105
|
+
* assigned {@link GraffitiObjectBase.url | `url`} and
|
|
106
|
+
* {@link GraffitiObjectBase.actor | `actor`}.
|
|
201
107
|
*
|
|
202
|
-
* @group
|
|
108
|
+
* @group 1 - Single-Object Methods
|
|
203
109
|
*/
|
|
204
|
-
abstract
|
|
110
|
+
abstract post<Schema extends JSONSchema>(
|
|
205
111
|
/**
|
|
206
|
-
*
|
|
207
|
-
* as the generic type parameter.
|
|
208
|
-
* ensure that the
|
|
112
|
+
* An object to post. This object is statically type-checked against the [JSON schema](https://json-schema.org/) that can be optionally provided
|
|
113
|
+
* as the generic type parameter. It is recommended to a schema to
|
|
114
|
+
* ensure that the posted object matches subsequent {@link get} or {@link discover}
|
|
209
115
|
* methods.
|
|
210
116
|
*/
|
|
211
|
-
object:
|
|
117
|
+
object: GraffitiPostObject<Schema>,
|
|
212
118
|
/**
|
|
213
119
|
* An implementation-specific object with information to authenticate the
|
|
214
120
|
* {@link GraffitiObjectBase.actor | `actor`}.
|
|
215
121
|
*/
|
|
216
|
-
session: GraffitiSession): Promise<
|
|
122
|
+
session: GraffitiSession): Promise<GraffitiObject<Schema>>;
|
|
217
123
|
/**
|
|
218
|
-
* Retrieves an object from a given {@link GraffitiObjectBase.url | `url`}
|
|
219
|
-
*
|
|
220
|
-
* The retrieved object is type-checked against the provided [JSON schema](https://json-schema.org/)
|
|
221
|
-
* otherwise a {@link GraffitiErrorSchemaMismatch} is thrown.
|
|
124
|
+
* Retrieves an object from a given {@link GraffitiObjectBase.url | `url`} matching
|
|
125
|
+
* the provided `schema`.
|
|
222
126
|
*
|
|
223
127
|
* If the retreiving {@link GraffitiObjectBase.actor | `actor`} is not
|
|
224
128
|
* the object's `actor`,
|
|
225
129
|
* the object's {@link GraffitiObjectBase.allowed | `allowed`} and
|
|
226
130
|
* {@link GraffitiObjectBase.channels | `channels`} properties are
|
|
227
|
-
* not revealed, similar to a BCC.
|
|
131
|
+
* not revealed, similar to a BCC email.
|
|
132
|
+
*
|
|
133
|
+
* @returns Returns the retrieved object.
|
|
228
134
|
*
|
|
229
|
-
* @throws {@link GraffitiErrorNotFound} if the object does not exist, has been deleted, or the
|
|
135
|
+
* @throws {@link GraffitiErrorNotFound} if the object does not exist, has been deleted, or the actor is not
|
|
230
136
|
* {@link GraffitiObjectBase.allowed | `allowed`} to access it.
|
|
231
137
|
*
|
|
232
138
|
* @throws {@link GraffitiErrorSchemaMismatch} if the retrieved object does not match the provided schema.
|
|
233
139
|
*
|
|
234
|
-
* @group
|
|
140
|
+
* @group 1 - Single-Object Methods
|
|
235
141
|
*/
|
|
236
142
|
abstract get<Schema extends JSONSchema>(
|
|
237
143
|
/**
|
|
@@ -250,59 +156,18 @@ export declare abstract class Graffiti {
|
|
|
250
156
|
*/
|
|
251
157
|
session?: GraffitiSession | null): Promise<GraffitiObject<Schema>>;
|
|
252
158
|
/**
|
|
253
|
-
*
|
|
254
|
-
*
|
|
255
|
-
* `actor` that created the object.
|
|
256
|
-
*
|
|
257
|
-
* @returns The original object prior to the patch with its
|
|
258
|
-
* {@link GraffitiObjectBase.lastModified | `lastModified`}
|
|
259
|
-
* property updated to the time of deletion.
|
|
260
|
-
*
|
|
261
|
-
* @throws {@link GraffitiErrorNotFound} if the object does not exist, has already been deleted,
|
|
262
|
-
* or the user is not {@link GraffitiObjectBase.allowed | `allowed`} to access it.
|
|
263
|
-
*
|
|
264
|
-
* @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}
|
|
265
|
-
* is not the same `actor` as the one who created the object.
|
|
266
|
-
*
|
|
267
|
-
* @group CRUD Methods
|
|
268
|
-
*/
|
|
269
|
-
abstract patch(
|
|
270
|
-
/**
|
|
271
|
-
* A collection of [JSON Patch](https://jsonpatch.com) operations
|
|
272
|
-
* to apply to the object. See {@link GraffitiPatch} for more information.
|
|
273
|
-
*/
|
|
274
|
-
patch: GraffitiPatch,
|
|
275
|
-
/**
|
|
276
|
-
* The location of the object to patch.
|
|
277
|
-
*/
|
|
278
|
-
url: string | GraffitiObjectUrl,
|
|
279
|
-
/**
|
|
280
|
-
* An implementation-specific object with information to authenticate the
|
|
281
|
-
* {@link GraffitiObjectBase.actor | `actor`}.
|
|
282
|
-
*/
|
|
283
|
-
session: GraffitiSession): Promise<GraffitiObjectBase>;
|
|
284
|
-
/**
|
|
285
|
-
* Deletes an object from a given {@link GraffitiObjectBase.url | `url`}.
|
|
159
|
+
* Deletes an object from a given {@link GraffitiObjectBase.url | `url`}
|
|
160
|
+
* that had previously been {@link post | `post`ed}.
|
|
286
161
|
* The deleting {@link GraffitiObjectBase.actor | `actor`} must be the same as the
|
|
287
162
|
* `actor` that created the object.
|
|
288
163
|
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
* In cases where deleting and restoring an object is useful, an object's
|
|
292
|
-
* {@link GraffitiObjectBase.allowed | `allowed`} property can be set to
|
|
293
|
-
* an empty list to hide it from all users except the creator.
|
|
294
|
-
*
|
|
295
|
-
* @returns The object that was deleted with its
|
|
296
|
-
* {@link GraffitiObjectBase.lastModified | `lastModified`}
|
|
297
|
-
* property updated to the time of deletion.
|
|
298
|
-
*
|
|
299
|
-
* @throws {@link GraffitiErrorNotFound} if the object does not exist, has already been deleted,
|
|
300
|
-
* or the user is not {@link GraffitiObjectBase.allowed | `allowed`} to access it.
|
|
164
|
+
* @throws {@link GraffitiErrorNotFound} if the object does not exist, has already been deleted,
|
|
165
|
+
* or the actor is not {@link GraffitiObjectBase.allowed | `allowed`} to access it.
|
|
301
166
|
*
|
|
302
167
|
* @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}
|
|
303
168
|
* is not the same `actor` as the one who created the object.
|
|
304
169
|
*
|
|
305
|
-
* @group
|
|
170
|
+
* @group 1 - Single-Object Methods
|
|
306
171
|
*/
|
|
307
172
|
abstract delete(
|
|
308
173
|
/**
|
|
@@ -313,9 +178,9 @@ export declare abstract class Graffiti {
|
|
|
313
178
|
* An implementation-specific object with information to authenticate the
|
|
314
179
|
* {@link GraffitiObjectBase.actor | `actor`}.
|
|
315
180
|
*/
|
|
316
|
-
session: GraffitiSession): Promise<
|
|
181
|
+
session: GraffitiSession): Promise<void>;
|
|
317
182
|
/**
|
|
318
|
-
* Discovers objects created by any
|
|
183
|
+
* Discovers objects created by any actor that are contained
|
|
319
184
|
* in at least one of the given {@link GraffitiObjectBase.channels | `channels`}
|
|
320
185
|
* and match the given [JSON Schema](https://json-schema.org).
|
|
321
186
|
*
|
|
@@ -329,7 +194,7 @@ export declare abstract class Graffiti {
|
|
|
329
194
|
* string can be serialized to continue the stream after an application is closed
|
|
330
195
|
* and reopened.
|
|
331
196
|
*
|
|
332
|
-
* `discover` will not return objects that the {@link GraffitiObjectBase.actor | `actor`}
|
|
197
|
+
* `discover` will not return objects that the querying {@link GraffitiObjectBase.actor | `actor`}
|
|
333
198
|
* is not {@link GraffitiObjectBase.allowed | `allowed`} to access.
|
|
334
199
|
* If the `actor` is not the creator of a discovered object,
|
|
335
200
|
* the allowed list will be masked to only contain the querying actor if the
|
|
@@ -340,14 +205,11 @@ export declare abstract class Graffiti {
|
|
|
340
205
|
*
|
|
341
206
|
* Since different implementations may fetch data from multiple sources there is
|
|
342
207
|
* no guarentee on the order that objects are returned in.
|
|
343
|
-
* It is also possible that duplicate objects are returned and their
|
|
344
|
-
* {@link GraffitiObjectBase.lastModified | `lastModified`} fields must be used
|
|
345
|
-
* to determine which object is the most recent.
|
|
346
208
|
*
|
|
347
|
-
* @returns
|
|
209
|
+
* @returns Returns a stream of objects that match the given {@link GraffitiObjectBase.channels | `channels`}
|
|
348
210
|
* and [JSON Schema](https://json-schema.org).
|
|
349
211
|
*
|
|
350
|
-
* @group
|
|
212
|
+
* @group 2 - Multi-Object Methods
|
|
351
213
|
*/
|
|
352
214
|
abstract discover<Schema extends JSONSchema>(
|
|
353
215
|
/**
|
|
@@ -366,138 +228,144 @@ export declare abstract class Graffiti {
|
|
|
366
228
|
*/
|
|
367
229
|
session?: GraffitiSession | null): GraffitiObjectStream<Schema>;
|
|
368
230
|
/**
|
|
369
|
-
*
|
|
370
|
-
* {@link
|
|
371
|
-
*
|
|
372
|
-
*
|
|
373
|
-
*
|
|
231
|
+
* Continues a {@link GraffitiObjectStream} from a given
|
|
232
|
+
* {@link GraffitiObjectStreamReturn.cursor | `cursor`} string.
|
|
233
|
+
* The continuation will return new objects that have been {@link post | `post`ed}
|
|
234
|
+
* that match the original stream, and also returns the
|
|
235
|
+
* {@link GraffitiObjectBase.url | `url`}s of objects that
|
|
236
|
+
* have been {@link delete | `delete`d}, as marked by a `tombstone`.
|
|
374
237
|
*
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
*
|
|
238
|
+
* The `cursor` allows the client to
|
|
239
|
+
* serialize the state of the stream and continue it later.
|
|
240
|
+
* However this method loses any typing information that was
|
|
241
|
+
* present in the original stream. For better type safety
|
|
242
|
+
* and when serializing is not necessary, use the
|
|
243
|
+
* {@link GraffitiObjectStreamReturn.continue | `continue`} method
|
|
244
|
+
* instead, which is returned along with the `cursor` at the
|
|
245
|
+
* end of the original stream.
|
|
378
246
|
*
|
|
379
|
-
*
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
* method or {@link GraffitiObjectStreamReturn.cursor | `cursor`} string.
|
|
247
|
+
* @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}
|
|
248
|
+
* provided in the `session` is not the same as the `actor`
|
|
249
|
+
* that initiated the original stream.
|
|
383
250
|
*
|
|
384
|
-
* @
|
|
385
|
-
|
|
386
|
-
|
|
251
|
+
* @group 2 - Multi-Object Methods
|
|
252
|
+
*/
|
|
253
|
+
abstract continueDiscover(cursor: string, session?: GraffitiSession | null): GraffitiObjectStreamContinue<{}>;
|
|
254
|
+
/**
|
|
255
|
+
* Uploads media data, such as an image or video.
|
|
256
|
+
*
|
|
257
|
+
* Unlike structured {@link GraffitiObjectBase | objects},
|
|
258
|
+
* media is not indexed for {@link discover | `discover`y} and
|
|
259
|
+
* must be retrieved by its exact URL using {@link getMedia}
|
|
260
|
+
*
|
|
261
|
+
* @returns The URL that the media was posted to.
|
|
387
262
|
*
|
|
388
|
-
* @group
|
|
263
|
+
* @group 3 - Media Methods
|
|
389
264
|
*/
|
|
390
|
-
abstract
|
|
265
|
+
abstract postMedia(
|
|
391
266
|
/**
|
|
392
|
-
*
|
|
267
|
+
* The binary data of the media to be uploaded,
|
|
268
|
+
* along with its [media type](https://www.iana.org/assignments/media-types/media-types.xhtml),
|
|
269
|
+
* formatted as a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob).
|
|
393
270
|
*/
|
|
394
|
-
|
|
271
|
+
media: Blob,
|
|
395
272
|
/**
|
|
396
273
|
* An implementation-specific object with information to authenticate the
|
|
397
274
|
* {@link GraffitiObjectBase.actor | `actor`}.
|
|
398
275
|
*/
|
|
399
|
-
session: GraffitiSession):
|
|
276
|
+
session: GraffitiSession): Promise<string>;
|
|
400
277
|
/**
|
|
401
|
-
*
|
|
402
|
-
* that an {@link GraffitiObjectBase.actor | `actor`} has posted to.
|
|
403
|
-
* This is not very useful for most applications, but
|
|
404
|
-
* necessary for certain applications where a user wants a
|
|
405
|
-
* global view of all their Graffiti data or to debug
|
|
406
|
-
* channel usage.
|
|
278
|
+
* Deletes media previously {@link postMedia | `post`ed} to a given URL.
|
|
407
279
|
*
|
|
408
|
-
*
|
|
409
|
-
* the stream will end once all leads have been exhausted.
|
|
280
|
+
* @throws {@link GraffitiErrorNotFound} if no media at that URL exists.
|
|
410
281
|
*
|
|
411
|
-
* @
|
|
282
|
+
* @throws {@link GraffitiErrorForbidden} if the {@link GraffitiObjectBase.actor | `actor`}
|
|
283
|
+
* provided in the `session` is not the same as the `actor` that {@link postMedia | `post`ed}
|
|
284
|
+
* the media.
|
|
412
285
|
*
|
|
413
|
-
* @
|
|
414
|
-
* that the {@link GraffitiObjectBase.actor | `actor`} has posted to.
|
|
286
|
+
* @group 3 - Media Methods
|
|
415
287
|
*/
|
|
416
|
-
abstract
|
|
288
|
+
abstract deleteMedia(
|
|
289
|
+
/**
|
|
290
|
+
* A globally unique identifier and locator for the media.
|
|
291
|
+
*/
|
|
292
|
+
mediaUrl: string,
|
|
417
293
|
/**
|
|
418
294
|
* An implementation-specific object with information to authenticate the
|
|
419
295
|
* {@link GraffitiObjectBase.actor | `actor`}.
|
|
420
296
|
*/
|
|
421
|
-
session: GraffitiSession):
|
|
297
|
+
session: GraffitiSession): Promise<void>;
|
|
422
298
|
/**
|
|
423
|
-
*
|
|
424
|
-
* {@link GraffitiObjectStreamReturn.cursor | `cursor`} string.
|
|
425
|
-
* The continuation will return new objects that have been created
|
|
426
|
-
* that match the original stream, and also returns the
|
|
427
|
-
* {@link GraffitiObjectBase.url | `url`}s of objects that
|
|
428
|
-
* have been deleted, as marked by a `tombstone`.
|
|
299
|
+
* Retrieves media from the given media URL, adhering to the given requirements.
|
|
429
300
|
*
|
|
430
|
-
*
|
|
431
|
-
* were already returned by the original stream. This is dependent
|
|
432
|
-
* on how much state the underlying implementation maintains.
|
|
301
|
+
* @throws {@link GraffitiErrorNotFound} if no media at that URL exists.
|
|
433
302
|
*
|
|
434
|
-
*
|
|
435
|
-
* serialize the state of the stream and continue it later.
|
|
436
|
-
* However this method loses any typing information that was
|
|
437
|
-
* present in the original stream. For better type safety
|
|
438
|
-
* and when serializing is not necessary, use the
|
|
439
|
-
* {@link GraffitiObjectStreamReturn.continue | `continue`} method
|
|
440
|
-
* instead, which is returned along with the `cursor` at the
|
|
441
|
-
* end of the original stream.
|
|
303
|
+
* @throws {@link GraffitiErrorTooLarge} if the media exceeds the given `maxBytes`.
|
|
442
304
|
*
|
|
443
|
-
* @throws {@link
|
|
444
|
-
*
|
|
445
|
-
*
|
|
305
|
+
* @throws {@link GraffitiErrorNotAcceptable} if the media does not match the given
|
|
306
|
+
* `accept` specification.
|
|
307
|
+
*
|
|
308
|
+
* @returns The URL of the retrieved media, as a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
|
|
309
|
+
* and the {@link GraffitiObjectBase.actor | `actor`} that posted it.
|
|
446
310
|
*
|
|
447
|
-
* @group
|
|
311
|
+
* @group 3 - Media Methods
|
|
448
312
|
*/
|
|
449
|
-
abstract
|
|
313
|
+
abstract getMedia(
|
|
314
|
+
/**
|
|
315
|
+
* A globally unique identifier and locator for the media.
|
|
316
|
+
*/
|
|
317
|
+
mediaUrl: string,
|
|
318
|
+
/**
|
|
319
|
+
* An optional set of requirements the retrieved media must meet.
|
|
320
|
+
*/
|
|
321
|
+
requirements?: {
|
|
322
|
+
/**
|
|
323
|
+
* A list of acceptable media types for the retrieved media,
|
|
324
|
+
* formatted as like an [HTTP Accept header](https://httpwg.org/specs/rfc9110.html#field.accept)
|
|
325
|
+
*/
|
|
326
|
+
accept?: string;
|
|
327
|
+
/**
|
|
328
|
+
* The maximum size, in bytes, of the media.
|
|
329
|
+
*/
|
|
330
|
+
maxBytes?: number;
|
|
331
|
+
}): Promise<{
|
|
332
|
+
media: Blob;
|
|
333
|
+
actor: string;
|
|
334
|
+
}>;
|
|
450
335
|
/**
|
|
451
336
|
* Begins the login process. Depending on the implementation, this may
|
|
452
|
-
* involve redirecting
|
|
453
|
-
* so it should always be called in response to a
|
|
337
|
+
* involve redirecting to a login page or opening a popup,
|
|
338
|
+
* so it should always be called in response to a gesture, such as clicking
|
|
339
|
+
* a button, due to the [feature-gating browser security feature](https://developer.mozilla.org/en-US/docs/Web/Security/User_activation).
|
|
454
340
|
*
|
|
455
341
|
* The {@link GraffitiSession | session} object is returned
|
|
456
342
|
* asynchronously via {@link Graffiti.sessionEvents | sessionEvents}
|
|
457
343
|
* as a {@link GraffitiLoginEvent} with event type `login`.
|
|
458
344
|
*
|
|
459
|
-
* @group Session Management
|
|
345
|
+
* @group 4 - Session Management
|
|
460
346
|
*/
|
|
461
347
|
abstract login(
|
|
462
348
|
/**
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
349
|
+
* A suggested actor to login as. For example, if a user tries to
|
|
350
|
+
* edit a post but are not logged in, the interface can infer that
|
|
351
|
+
* they might want to log in as the actor who created the post
|
|
352
|
+
* they are attempting to edit.
|
|
353
|
+
*
|
|
354
|
+
* Even if provided, the implementation should allow the user
|
|
355
|
+
* to log in as a different actor if they choose.
|
|
466
356
|
*/
|
|
467
|
-
|
|
468
|
-
/**
|
|
469
|
-
* A suggested actor to login as. For example, if a user tries to
|
|
470
|
-
* edit a post but are not logged in, the interface can infer that
|
|
471
|
-
* they might want to log in as the actor who created the post
|
|
472
|
-
* they are attempting to edit.
|
|
473
|
-
*
|
|
474
|
-
* Even if provided, the implementation should allow the user
|
|
475
|
-
* to log in as a different actor if they choose.
|
|
476
|
-
*/
|
|
477
|
-
actor?: string;
|
|
478
|
-
/**
|
|
479
|
-
* A yet to be defined permissions scope. An application may use
|
|
480
|
-
* this to indicate the minimum necessary scope needed to
|
|
481
|
-
* operate. For example, it may need to be able read private
|
|
482
|
-
* messages from a certain set of channels, or write messages that
|
|
483
|
-
* follow a particular schema.
|
|
484
|
-
*
|
|
485
|
-
* The login process should make it clear what scope an application
|
|
486
|
-
* is requesting and allow the user to enhance or reduce that
|
|
487
|
-
* scope as necessary.
|
|
488
|
-
*/
|
|
489
|
-
scope?: {};
|
|
490
|
-
}): Promise<void>;
|
|
357
|
+
actor?: string): Promise<void>;
|
|
491
358
|
/**
|
|
492
|
-
* Begins the logout process. Depending on the implementation, this may
|
|
359
|
+
* Begins the logout process for a particular {@link GraffitiSession | session}. Depending on the implementation, this may
|
|
493
360
|
* involve redirecting the user to a logout page or opening a popup,
|
|
494
|
-
* so it should always be called in response to a
|
|
361
|
+
* so it should always be called in response to a gesture, such as clicking
|
|
362
|
+
* a button, due to the [feature-gating browser security feature](https://developer.mozilla.org/en-US/docs/Web/Security/User_activation).
|
|
495
363
|
*
|
|
496
364
|
* A confirmation will be returned asynchronously via
|
|
497
365
|
* {@link Graffiti.sessionEvents | sessionEvents}
|
|
498
366
|
* as a {@link GraffitiLogoutEvent} as event type `logout`.
|
|
499
367
|
*
|
|
500
|
-
* @group Session Management
|
|
368
|
+
* @group 4 - Session Management
|
|
501
369
|
*/
|
|
502
370
|
abstract logout(
|
|
503
371
|
/**
|
|
@@ -506,12 +374,12 @@ export declare abstract class Graffiti {
|
|
|
506
374
|
session: GraffitiSession): Promise<void>;
|
|
507
375
|
/**
|
|
508
376
|
* An event target that can be used to listen for the following
|
|
509
|
-
* events and
|
|
377
|
+
* events and their corresponding event types:
|
|
510
378
|
* - `login` - {@link GraffitiLoginEvent}
|
|
511
379
|
* - `logout` - {@link GraffitiLogoutEvent}
|
|
512
380
|
* - `initialized` - {@link GraffitiSessionInitializedEvent}
|
|
513
381
|
*
|
|
514
|
-
* @group Session Management
|
|
382
|
+
* @group 4 - Session Management
|
|
515
383
|
*/
|
|
516
384
|
abstract readonly sessionEvents: EventTarget;
|
|
517
385
|
}
|