@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/src/2-types.ts CHANGED
@@ -1,23 +1,23 @@
1
1
  import type { JSONSchema, FromSchema } from "json-schema-to-ts";
2
- import type { Operation as JSONPatchOperation } from "fast-json-patch";
3
2
 
4
3
  /**
5
4
  * Objects are the atomic unit in Graffiti that can represent both data (*e.g.* a social media post or profile)
6
5
  * and activities (*e.g.* a like or follow).
7
- * Objects are created and modified by a single {@link actor | `actor`}.
8
6
  *
9
- * Most of an object's content is stored in its {@link value | `value`} property, which can be any JSON
10
- * object. However, we recommend using properties from the
7
+ * Each object embeds the {@link actor | `actor`} that created it.
8
+ * Object content and metadata are static but an object may be deleted by
9
+ * its creating {@link actor | `actor`}.
10
+ *
11
+ * An object's content is stored in its {@link value | `value`} property, which can be any JSON
12
+ * object. However, it is recommended to use properties from the
11
13
  * [Activity Vocabulary](https://www.w3.org/TR/activitystreams-vocabulary/)
12
14
  * or properties that emerge in the Graffiti [folksonomy](https://en.wikipedia.org/wiki/Folksonomy)
13
15
  * to promote interoperability.
14
16
  *
15
- * The object is globally addressable via its {@link url | `url`}.
16
- *
17
- * The {@link channels | `channels`} and {@link allowed | `allowed`} properties
18
- * enable the object's creator to shape the visibility of and access to their object.
17
+ * Each object is globally addressable via its {@link url | `url`}.
19
18
  *
20
- * The {@link lastModified | `lastModified`} property can be used to compare object versions.
19
+ * An object's {@link channels | `channels`} and {@link allowed | `allowed`} properties
20
+ * are set by an objects creator to shape the visibility of and access to their object.
21
21
  */
22
22
  export interface GraffitiObjectBase {
23
23
  /**
@@ -34,11 +34,11 @@ export interface GraffitiObjectBase {
34
34
  * {@link Graffiti.discover} method. This allows creators to express the intended audience of their object
35
35
  * which helps to prevent [context collapse](https://en.wikipedia.org/wiki/Context_collapse) even
36
36
  * in the highly interoperable ecosystem that Graffiti envisions. For example, channel URIs may be:
37
- * - A user's own {@link actor | `actor`} URI. Putting an object in this channel is a way to broadcast
38
- * the object to the user's followers, like posting a tweet.
39
- * - The URL of a Graffiti post. Putting an object in this channel is a way to broadcast to anyone viewing
37
+ * - A actor's own {@link actor | `actor`} URI. Posting an object to this channel is a way to broadcast
38
+ * the object to the actor's followers, like posting a tweet.
39
+ * - The URL of a Graffiti post. Posting an object to this channel is a way to broadcast to anyone viewing
40
40
  * the post, like commenting on a tweet.
41
- * - A URI representing a topic. Putting an object in this channel is a way to broadcast to anyone interested
41
+ * - A URI representing a topic. Posting an object to this channel is a way to broadcast to anyone interested
42
42
  * in that topic, like posting in a subreddit.
43
43
  */
44
44
  channels: string[];
@@ -49,19 +49,20 @@ export interface GraffitiObjectBase {
49
49
  * also know the right {@link channels | `channel` } to look in). An object can always be accessed by its creator, even if
50
50
  * the `allowed` array is empty.
51
51
  *
52
- * The `allowed` array is not revealed to users other than the creator, like
53
- * a BCC email. A user may choose to add a `to` property to the object's {@link value | `value`} to indicate
52
+ * The `allowed` array is not revealed to actors other than the creator, like
53
+ * a BCC email. An actor may choose to add a `to` property to the object's {@link value | `value`} to indicate
54
54
  * other recipients, however this is not enforced by Graffiti and may not accurately reflect the actual `allowed` array.
55
55
  *
56
56
  * `allowed` can be combined with {@link channels | `channels`}. For example, to send someone a direct message
57
- * the sender should put their object in the channel of the recipient's {@link actor | `actor`} URI to notify them of the message and also add
57
+ * the sender should post their object to the channel of the recipient's {@link actor | `actor`} URI to notify them of the message and also add
58
58
  * the recipient's {@link actor | `actor`} URI to the `allowed` array to prevent others from seeing the message.
59
59
  */
60
60
  allowed?: string[] | null;
61
61
 
62
62
  /**
63
- * The URI of the `actor` that {@link Graffiti.put | created } the object. This `actor` also has the unique permission to
64
- * {@link Graffiti.patch | modify} or {@link Graffiti.delete | delete} the object.
63
+ * The URI of the `actor` that {@link Graffiti.post | created } the object.
64
+ * This `actor` has the unique permission to
65
+ * {@link Graffiti.delete | delete} the object.
65
66
  *
66
67
  * We borrow the term actor from the ActivityPub because
67
68
  * [like in ActivityPub](https://www.w3.org/TR/activitypub/#h-note-0)
@@ -77,8 +78,6 @@ export interface GraffitiObjectBase {
77
78
  /**
78
79
  * A globally unique identifier and locator for the object. It can be used to point to
79
80
  * an object or to retrieve the object directly with {@link Graffiti.get}.
80
- * If an object is {@link Graffiti.put | put} with the same URL
81
- * as an existing object, the existing object will be replaced with the new object.
82
81
  *
83
82
  * An object's URL is generated when the object is first created and
84
83
  * should include sufficient randomness to prevent collisions
@@ -87,25 +86,11 @@ export interface GraffitiObjectBase {
87
86
  * to pull from multiple coexisting Graffiti implementations without collision.
88
87
  * Existing schemes include `graffiti:local:` for objects stored locally
89
88
  * (see the [local implementation](https://github.com/graffiti-garden/implementation-local))
90
- * and `graffiti:remote:` for objects stored on Graffiti-specific web servers (see the
91
- * [remote implementation](https://github.com/graffiti-garden/implementation-remote)).
89
+ * and `graffiti:remote:` for objects stored on Graffiti-specific web servers (see the [remote implementation](https://github.com/graffiti-garden/implementation-remote))
92
90
  * Options available in the future might include `graffiti:solid:` for objects stored on Solid servers
93
91
  * or `graffiti:p2p:` for objects stored on a peer-to-peer network.
94
92
  */
95
93
  url: string;
96
-
97
- /**
98
- * The time the object was last modified, measured in milliseconds since January 1, 1970.
99
- * It can be used to compare object versions.
100
- * A number, rather than an ISO string or Date object, is used for easy comparison, sorting,
101
- * and JSON Schema [range queries](https://json-schema.org/understanding-json-schema/reference/numeric#range).
102
- *
103
- * It is possible to use this value to sort objects in a user's interface but in many cases it would be better to
104
- * use a [`published`](https://www.w3.org/TR/activitystreams-vocabulary/#dfn-published)
105
- * property in the object's {@link value | `value`} to indicate when the object was created
106
- * rather than when it was modified.
107
- */
108
- lastModified: number;
109
94
  }
110
95
 
111
96
  /**
@@ -132,61 +117,55 @@ export const GraffitiObjectJSONSchema = {
132
117
  allowed: { type: "array", items: { type: "string" }, nullable: true },
133
118
  url: { type: "string" },
134
119
  actor: { type: "string" },
135
- lastModified: { type: "number" },
136
120
  },
137
121
  additionalProperties: false,
138
- required: ["value", "channels", "actor", "url", "lastModified"],
122
+ required: ["value", "channels", "actor", "url"],
139
123
  } as const satisfies JSONSchema;
140
124
 
141
125
  /**
142
126
  * This is an object containing only the {@link GraffitiObjectBase.url | `url`}
143
127
  * property of a {@link GraffitiObjectBase | GraffitiObject}.
144
- * It is used as a utility type so that users can call {@link Graffiti.get},
145
- * {@link Graffiti.patch}, or {@link Graffiti.delete} directly on an object
128
+ * It is used as a utility type so that applications can call
129
+ * {@link Graffiti.delete} directly on an object
146
130
  * rather than on `object.url`.
147
131
  */
148
132
  export type GraffitiObjectUrl = Pick<GraffitiObjectBase, "url">;
149
133
 
150
134
  /**
151
- * This object is a subset of {@link GraffitiObjectBase} that a user must construct locally before calling {@link Graffiti.put}.
152
- * This local copy does not require system-generated properties and may be statically typed with
135
+ * This object is a subset of {@link GraffitiObjectBase} that must be constructed locally before calling {@link Graffiti.post}.
136
+ * This local copy ignores system-generated properties
137
+ * ({@link GraffitiObjectBase.url | `url`} and {@link GraffitiObjectBase.actor | `actor`}),
138
+ * and may be statically typed with
153
139
  * a [JSON schema](https://json-schema.org/) to prevent the accidental creation of erroneous objects.
154
140
  *
155
141
  * This local object must have a {@link GraffitiObjectBase.value | `value`} and {@link GraffitiObjectBase.channels | `channels`}
156
142
  * and may optionally have an {@link GraffitiObjectBase.allowed | `allowed`} property.
157
- *
158
- * It may also include a {@link GraffitiObjectBase.url | `url`} property to specify the
159
- * URL of an existing object to replace. If no `url` is provided, one will be generated during object creation.
160
- *
161
- * This object does not need a {@link GraffitiObjectBase.lastModified | `lastModified`}
162
- * property since it will be automatically generated by the Graffiti system.
163
143
  */
164
- export type GraffitiPutObject<Schema extends JSONSchema> = Pick<
144
+ export type GraffitiPostObject<Schema extends JSONSchema> = Pick<
165
145
  GraffitiObjectBase,
166
146
  "value" | "channels" | "allowed"
167
147
  > &
168
148
  Partial<GraffitiObjectBase> &
169
- FromSchema<Schema & typeof GraffitiPutObjectJSONSchema>;
149
+ FromSchema<Schema & typeof GraffitiPostObjectJSONSchema>;
170
150
 
171
151
  /**
172
- * A JSON Schema equivalent to the {@link GraffitiPutObject} type.
152
+ * A JSON Schema equivalent to the {@link GraffitiPostObject} type.
173
153
  * Needed internally for type inference of JSON Schemas, but can
174
154
  * be used by implementations to validate objects.
175
155
  */
176
- export const GraffitiPutObjectJSONSchema = {
156
+ export const GraffitiPostObjectJSONSchema = {
177
157
  ...GraffitiObjectJSONSchema,
178
158
  required: ["value", "channels"],
179
159
  } as const satisfies JSONSchema;
180
160
 
181
161
  /**
182
162
  * This object contains information that the underlying implementation can
183
- * use to verify that a user has permission to operate a
184
- * particular {@link GraffitiObjectBase.actor | `actor`}.
163
+ * use to authenticate a particular {@link GraffitiObjectBase.actor | `actor`}.
185
164
  * This object is required of all {@link Graffiti} methods
186
- * that modify objects and is optional for methods that read objects.
165
+ * that modify objects or media and is optional for methods that read objects.
187
166
  *
188
167
  * At a minimum the `session` object must contain the
189
- * {@link GraffitiSession.actor | `actor`} URI the user wants to authenticate with.
168
+ * {@link GraffitiSession.actor | `actor`} URI to authenticate with.
190
169
  * However it is likely that the `session` object must contain other
191
170
  * implementation-specific properties.
192
171
  * For example, a Solid implementation might include a
@@ -197,13 +176,10 @@ export const GraffitiPutObjectJSONSchema = {
197
176
  * As to why the `session` object is passed as an argument to every method
198
177
  * rather than being an internal property of the {@link Graffiti} instance,
199
178
  * this is primarily for type-checking to catch bugs related to login state.
200
- * Graffiti applications can expose some functionality to users who are not logged in
179
+ * Graffiti applications can expose some functionality to people who are not logged in
201
180
  * with {@link Graffiti.get} and {@link Graffiti.discover} but without type-checking
202
181
  * the `session` it can be easy to forget to hide buttons that trigger
203
182
  * other methods that require login.
204
- * In the future, `session` object may be updated to include scope information
205
- * and passing the `session` to each method can type-check whether the session provides the
206
- * necessary permissions.
207
183
  *
208
184
  * Passing the `session` object per-method also allows for multiple sessions
209
185
  * to be used within the same application, like an Email client fetching from
@@ -211,61 +187,20 @@ export const GraffitiPutObjectJSONSchema = {
211
187
  */
212
188
  export interface GraffitiSession {
213
189
  /**
214
- * The {@link GraffitiObjectBase.actor | `actor`} a user wants to authenticate with.
190
+ * The {@link GraffitiObjectBase.actor | `actor`} to authenticate with.
215
191
  */
216
192
  actor: string;
217
- /**
218
- * A yet undefined property detailing what operations the session
219
- * grants the user to perform. For example, to allow a user to
220
- * read private messages from a particular set of channels or
221
- * to allow the user to write object matching a particular schema.
222
- */
223
- scope?: {};
224
- }
225
-
226
- /**
227
- * This is the format for patches that modify {@link GraffitiObjectBase} objects
228
- * using the {@link Graffiti.patch} method. The patches must
229
- * be an array of [JSON Patch](https://jsonpatch.com) operations.
230
- * Patches can only be applied to the
231
- * {@link GraffitiObjectBase.value | `value`}, {@link GraffitiObjectBase.channels | `channels`},
232
- * and {@link GraffitiObjectBase.allowed | `allowed`} properties since the other
233
- * properties either describe the object's location or are automatically generated.
234
- * (See also {@link GraffitiPutObject}).
235
- */
236
- export interface GraffitiPatch {
237
- /**
238
- * An array of [JSON Patch](https://jsonpatch.com) operations to
239
- * modify the object's {@link GraffitiObjectBase.value | `value`}. The resulting
240
- * `value` must still be a JSON object.
241
- */
242
- value?: JSONPatchOperation[];
243
-
244
- /**
245
- * An array of [JSON Patch](https://jsonpatch.com) operations to
246
- * modify the object's {@link GraffitiObjectBase.channels | `channels`}. The resulting
247
- * `channels` must still be an array of strings.
248
- */
249
- channels?: JSONPatchOperation[];
250
-
251
- /**
252
- * An array of [JSON Patch](https://jsonpatch.com) operations to
253
- * modify the object's {@link GraffitiObjectBase.allowed | `allowed`} property. The resulting
254
- * `allowed` property must still be an array of strings or `undefined`.
255
- */
256
- allowed?: JSONPatchOperation[];
257
193
  }
258
194
 
259
195
  /**
260
- * A stream of data that are returned by Graffiti's query-like operations
261
- * {@link Graffiti.discover} and {@link Graffiti.recoverOrphans}.
196
+ * A stream of data that are returned by {@link Graffiti.discover}.
262
197
  *
263
198
  * Errors are returned within the stream rather than as
264
199
  * exceptions that would halt the entire stream. This is because
265
200
  * some implementations may pull data from multiple sources
266
201
  * including some that may be unreliable. In many cases,
267
202
  * these errors can be safely ignored.
268
- * See {@link GraffitiStreamError}.
203
+ * See {@link GraffitiObjectStreamError}.
269
204
  *
270
205
  * The stream is an [`AsyncGenerator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)
271
206
  * that can be iterated over using `for await` loops or calling `next` on the generator.
@@ -276,17 +211,16 @@ export interface GraffitiPatch {
276
211
  * each of which can be used to resume the stream from where it left off.
277
212
  */
278
213
  export type GraffitiObjectStream<Schema extends JSONSchema> = AsyncGenerator<
279
- GraffitiStreamError | GraffitiObjectStreamEntry<Schema>,
214
+ GraffitiObjectStreamError | GraffitiObjectStreamEntry<Schema>,
280
215
  GraffitiObjectStreamReturn<Schema>
281
216
  >;
282
217
 
283
218
  /**
284
- * An error that can occur in either the
285
- * {@link GraffitiObjectStream} or {@link GraffitiChannelStatsStream}.
219
+ * An error that can occur in a {@link GraffitiObjectStream}.
286
220
  *
287
221
  * @internal
288
222
  */
289
- export interface GraffitiStreamError {
223
+ export interface GraffitiObjectStreamError {
290
224
  /**
291
225
  * The error that occurred while streaming data.
292
226
  */
@@ -307,7 +241,7 @@ export interface GraffitiStreamError {
307
241
  */
308
242
  export interface GraffitiObjectStreamEntry<Schema extends JSONSchema> {
309
243
  /**
310
- * Empty property for compatibility with {@link GraffitiStreamError}
244
+ * Empty property for compatibility with {@link GraffitiObjectStreamError}
311
245
  */
312
246
  error?: undefined;
313
247
  /**
@@ -324,13 +258,13 @@ export interface GraffitiObjectStreamEntry<Schema extends JSONSchema> {
324
258
  * A result from a {@link GraffitiObjectStreamContinue} that indicated
325
259
  * an object has been deleted since the original stream was run.
326
260
  * Only sparse metadata about the deleted object is returned to respect
327
- * the deleting user's privacy.
261
+ * the deleting actor's privacy.
328
262
  *
329
263
  * @internal
330
264
  */
331
265
  export interface GraffitiObjectStreamContinueTombstone {
332
266
  /**
333
- * Empty property for compatibility with {@link GraffitiStreamError}
267
+ * Empty property for compatibility with {@link GraffitiObjectStreamError}
334
268
  */
335
269
  error?: undefined;
336
270
  /**
@@ -340,25 +274,13 @@ export interface GraffitiObjectStreamContinueTombstone {
340
274
  tombstone: true;
341
275
  /**
342
276
  * Sparse metadata about the deleted object. The full object is not returned
343
- * to respect a user's privacy.
277
+ * to respect an actor's privacy.
344
278
  */
345
279
  object: {
346
280
  /**
347
281
  * The {@link GraffitiObjectBase.url | `url`} of the deleted object.
348
282
  */
349
283
  url: string;
350
- /**
351
- * The time at which the object was deleted, comparable to
352
- * {@link GraffitiObjectBase.lastModified | `lastModified`}.
353
- *
354
- * While it is not possible to re-{@link Graffiti.put | put} objects that have been
355
- * {@link Graffiti.delete | deleted}, objects may appear deleted if
356
- * an {@link GraffitiObjectBase.actor | `actor`} is no longer
357
- * {@link GraffitiObjectBase.allowed | `allowed`} to access them.
358
- * Therefore the {@link GraffitiObjectBase.lastModified | `lastModified`} property
359
- * is necessary to compare object versions.
360
- */
361
- lastModified: number;
362
284
  };
363
285
  }
364
286
 
@@ -377,7 +299,7 @@ export type GraffitiObjectStreamContinueEntry<Schema extends JSONSchema> =
377
299
  * that allows the stream to be continued from where it left off.
378
300
  *
379
301
  * The {@link continue} function preserves the typing of the original stream,
380
- * where as the {@link cursor} string can be serialized for use after a user
302
+ * where as the {@link cursor} string can be serialized for use after a person
381
303
  * has closed and reopened an application.
382
304
  *
383
305
  * The continued stream may include `tombstone`s of objects that have been
@@ -396,7 +318,7 @@ export interface GraffitiObjectStreamReturn<Schema extends JSONSchema> {
396
318
  continue: () => GraffitiObjectStreamContinue<Schema>;
397
319
  /**
398
320
  * A string that can be serialized and stored to resume the stream later.
399
- * It must be passed to the {@link Graffiti.continueObjectStream} method
321
+ * It must be passed to the {@link Graffiti.continueDiscover} method
400
322
  * to resume the stream.
401
323
  */
402
324
  cursor: string;
@@ -405,7 +327,7 @@ export interface GraffitiObjectStreamReturn<Schema extends JSONSchema> {
405
327
  /**
406
328
  * A continutation of the {@link GraffitiObjectStream} type, as returned by
407
329
  * the {@link GraffitiObjectStreamReturn.continue} or by using
408
- * {@link GraffitiObjectStreamReturn.cursor} with {@link Graffiti.continueObjectStream}.
330
+ * {@link GraffitiObjectStreamReturn.cursor} with {@link Graffiti.continueDiscover}.
409
331
  *
410
332
  * The continued stream may include `tombstone`s of objects that have been
411
333
  * deleted since the original stream was run. See {@link GraffitiObjectStreamContinueTombstone}.
@@ -414,48 +336,13 @@ export interface GraffitiObjectStreamReturn<Schema extends JSONSchema> {
414
336
  */
415
337
  export type GraffitiObjectStreamContinue<Schema extends JSONSchema> =
416
338
  AsyncGenerator<
417
- GraffitiStreamError | GraffitiObjectStreamContinueEntry<Schema>,
339
+ GraffitiObjectStreamError | GraffitiObjectStreamContinueEntry<Schema>,
418
340
  GraffitiObjectStreamReturn<Schema>
419
341
  >;
420
342
 
421
- /**
422
- * Statistic about single channel returned by {@link Graffiti.channelStats}.
423
- * These statistics only account for contributions made by the
424
- * querying actor.
425
- */
426
- export type ChannelStats = {
427
- /**
428
- * The URI of the channel.
429
- */
430
- channel: string;
431
- /**
432
- * The number of objects that the actor has {@link Graffiti.put | put}
433
- * and not {@link Graffiti.delete | deleted} in the channel.
434
- */
435
- count: number;
436
- /**
437
- * The time that the actor {@link GraffitiObjectBase.lastModified | last modified} an object in the channel,
438
- * measured in milliseconds since January 1, 1970.
439
- * {@link Graffiti.delete | Deleted} objects do not effect this modification time.
440
- */
441
- lastModified: number;
442
- };
443
-
444
- /**
445
- * A stream of data that are returned by Graffiti's {@link Graffiti.channelStats} method.
446
- * See {@link GraffitiObjectStream} for more information on streams.
447
- */
448
- export type GraffitiChannelStatsStream = AsyncGenerator<
449
- | GraffitiStreamError
450
- | {
451
- error?: undefined;
452
- value: ChannelStats;
453
- }
454
- >;
455
-
456
343
  /**
457
344
  * The event type produced in {@link Graffiti.sessionEvents}
458
- * when a user logs in manually from {@link Graffiti.login}
345
+ * when a actor logs in manually from {@link Graffiti.login}
459
346
  * or when their session is restored from a previous login.
460
347
  * The event name to listen for is `login`.
461
348
  */
@@ -472,7 +359,7 @@ export type GraffitiLoginEvent = CustomEvent<
472
359
 
473
360
  /**
474
361
  * The event type produced in {@link Graffiti.sessionEvents}
475
- * when a user logs out either manually with {@link Graffiti.logout}
362
+ * when a actor logs out either manually with {@link Graffiti.logout}
476
363
  * or when their session times out or otherwise becomes invalid.
477
364
  * The event name to listen for is `logout`.
478
365
  */
@@ -495,8 +382,8 @@ export type GraffitiLogoutEvent = CustomEvent<
495
382
  * their own {@link GraffitiLoginEvent} events.
496
383
  *
497
384
  * This event optionally returns an `href` property
498
- * representing the URL the user originated a login request
499
- * from, which may be useful for redirecting the user back to
385
+ * representing the URL that originated a login request,
386
+ * which may be useful for redirecting the user back to
500
387
  * the page they were on after login.
501
388
  * The event name to listen for is `initialized`.
502
389
  */
package/src/3-errors.ts CHANGED
@@ -38,19 +38,19 @@ export class GraffitiErrorSchemaMismatch extends Error {
38
38
  }
39
39
  }
40
40
 
41
- export class GraffitiErrorPatchTestFailed extends Error {
41
+ export class GraffitiErrorTooLarge extends Error {
42
42
  constructor(message?: string) {
43
43
  super(message);
44
- this.name = "GraffitiErrorPatchTestFailed";
45
- Object.setPrototypeOf(this, GraffitiErrorPatchTestFailed.prototype);
44
+ this.name = "GraffitiErrorTooLarge";
45
+ Object.setPrototypeOf(this, GraffitiErrorTooLarge.prototype);
46
46
  }
47
47
  }
48
48
 
49
- export class GraffitiErrorPatchError extends Error {
49
+ export class GraffitiErrorNotAcceptable extends Error {
50
50
  constructor(message?: string) {
51
51
  super(message);
52
- this.name = "GraffitiErrorPatchError";
53
- Object.setPrototypeOf(this, GraffitiErrorPatchError.prototype);
52
+ this.name = "GraffitiErrorNotAcceptable";
53
+ Object.setPrototypeOf(this, GraffitiErrorNotAcceptable.prototype);
54
54
  }
55
55
  }
56
56