@sockethub/platform-caldav 1.0.0-beta.3 → 1.0.0-beta.5
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 +76 -10
- package/dist/dav.d.ts +6 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +296 -63
- package/dist/index.js.map +6 -6
- package/dist/schema.d.ts +612 -0
- package/dist/types.d.ts +9 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ it is used.
|
|
|
18
18
|
|
|
19
19
|
## Discovery cache
|
|
20
20
|
|
|
21
|
-
Each `query`, `create`, `update`, and `delete` needs the account's calendar list to
|
|
21
|
+
Each `query`, `sync`, `create`, `update`, and `delete` needs the account's calendar list to
|
|
22
22
|
check the target. The platform caches that discovery result in memory for
|
|
23
23
|
`packageConfig.discoveryCacheTtlMs` (default `300000`, 5 minutes; `0`
|
|
24
24
|
disables the cache). Entries are keyed by an HMAC of the protocol, service URL,
|
|
@@ -82,6 +82,8 @@ never forwarded to another origin.
|
|
|
82
82
|
- `fetch`: discover calendars and their event/task support.
|
|
83
83
|
- `query`: read items from one discovered calendar, optionally filtering by
|
|
84
84
|
component type or UTC date range.
|
|
85
|
+
- `sync`: report what changed in one discovered calendar since a sync token
|
|
86
|
+
(RFC 6578 WebDAV Sync).
|
|
85
87
|
- `read`: list the items in a published `.ics` feed without credentials,
|
|
86
88
|
with the same optional filters as `query`.
|
|
87
89
|
- `create`: create an event or task with collision protection.
|
|
@@ -134,6 +136,71 @@ Each returned item contains its resource `id`, `uid`, `etag`, and
|
|
|
134
136
|
`updateSupported`. Keep the ETag for later update or delete requests. Use date
|
|
135
137
|
ranges for large calendars; responses larger than 10 MiB are rejected.
|
|
136
138
|
|
|
139
|
+
### Sync changes
|
|
140
|
+
|
|
141
|
+
`sync` reports changes without downloading the whole calendar each time. Send
|
|
142
|
+
it without an `object` (or without `object.syncToken`) for the initial sync:
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{
|
|
146
|
+
"type": "sync",
|
|
147
|
+
"actor": { "id": "caldav:alice", "type": "person" },
|
|
148
|
+
"target": {
|
|
149
|
+
"id": "https://calendar.example/calendars/alice/personal/",
|
|
150
|
+
"type": "calendar"
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The response is a collection with every event and task, plus a token:
|
|
156
|
+
|
|
157
|
+
```json
|
|
158
|
+
{
|
|
159
|
+
"type": "collection",
|
|
160
|
+
"summary": "CalDAV changes",
|
|
161
|
+
"totalItems": 1,
|
|
162
|
+
"items": [
|
|
163
|
+
{
|
|
164
|
+
"id": "https://calendar.example/calendars/alice/personal/a.ics",
|
|
165
|
+
"type": "task",
|
|
166
|
+
"uid": "a",
|
|
167
|
+
"name": "Pay rent",
|
|
168
|
+
"etag": "\"2\"",
|
|
169
|
+
"updateSupported": true
|
|
170
|
+
}
|
|
171
|
+
],
|
|
172
|
+
"removed": [],
|
|
173
|
+
"syncToken": "http://sabre.io/ns/sync/42",
|
|
174
|
+
"truncated": false
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Store `syncToken` as an opaque string per calendar and send it back next time
|
|
179
|
+
as `"object": { "syncToken": "..." }`. The response then holds only the items
|
|
180
|
+
added or changed since that token, with their current ETag and content, and
|
|
181
|
+
`removed` lists the ids of items deleted since then. Items in the same shape
|
|
182
|
+
as `query` results replace the stored copy with the same `id`.
|
|
183
|
+
|
|
184
|
+
When `truncated` is `true`, the server limited the result. The returned token
|
|
185
|
+
covers exactly the changes delivered, so store it and sync again until
|
|
186
|
+
`truncated` is `false`.
|
|
187
|
+
|
|
188
|
+
Calendar resources that hold neither an event nor a task, such as journals, are
|
|
189
|
+
left out of `items`.
|
|
190
|
+
|
|
191
|
+
Handle these errors:
|
|
192
|
+
|
|
193
|
+
- `caldav:sync-token-invalid`: the server no longer accepts the token (it
|
|
194
|
+
expired, or the calendar was reset). Drop the stored token and sync again
|
|
195
|
+
without one.
|
|
196
|
+
- `caldav:sync-unsupported`: the server does not offer WebDAV Sync. Fall back
|
|
197
|
+
to `query`, which returns a full snapshot.
|
|
198
|
+
- `caldav:sync-failed`: any other sync error.
|
|
199
|
+
|
|
200
|
+
When a server rejects a token without saying why (a 400, 409, or 412 with
|
|
201
|
+
no `DAV:` precondition), the platform reports `caldav:sync-token-invalid`. A
|
|
202
|
+
retry without a token then reports the real cause.
|
|
203
|
+
|
|
137
204
|
### Read a published iCalendar feed
|
|
138
205
|
|
|
139
206
|
Many calendars are shared as a read-only `.ics` link (often shown as a
|
|
@@ -257,7 +324,8 @@ Query again, reconcile the change, and retry with the new ETag.
|
|
|
257
324
|
## Interoperability and security
|
|
258
325
|
|
|
259
326
|
The implementation follows WebDAV/CalDAV discovery, calendar-query REPORT,
|
|
260
|
-
iCalendar content-line escaping/folding,
|
|
327
|
+
iCalendar content-line escaping/folding, conditional PUT/DELETE semantics, and
|
|
328
|
+
WebDAV Sync (RFC 6578).
|
|
261
329
|
|
|
262
330
|
### Server and provider compatibility
|
|
263
331
|
|
|
@@ -269,8 +337,8 @@ until they are included in automated or repeatable manual testing.
|
|
|
269
337
|
|
|
270
338
|
| Service | Deployment | Verification | Authentication exercised | Notes |
|
|
271
339
|
| --- | --- | --- | --- | --- |
|
|
272
|
-
| Radicale 3.7.7 | Self-hosted | Automated integration | Basic | Complete discovery and event/task create, query, update, and delete lifecycle. |
|
|
273
|
-
| Baïkal 0.10.1 | Self-hosted | Automated integration | Digest MD5 with `qop=auth` | Complete lifecycle through Baïkal's `dav.php/` endpoint, including its encoded ETags. |
|
|
340
|
+
| Radicale 3.7.7 | Self-hosted | Automated integration | Basic | Complete discovery and event/task create, query, update, and delete lifecycle, and incremental sync. |
|
|
341
|
+
| Baïkal 0.10.1 | Self-hosted | Automated integration | Digest MD5 with `qop=auth` | Complete lifecycle and incremental sync through Baïkal's `dav.php/` endpoint, including its encoded ETags. |
|
|
274
342
|
| Nextcloud | Self-hosted or hosted | Manually verified during initial development | Basic with username and password or app password | Use the final `/remote.php/dav/` endpoint when cross-origin discovery redirects are involved. OAuth is not covered by this verification. |
|
|
275
343
|
| ownCloud | Self-hosted or hosted | Not yet verified | Not yet verified | Expected to work when standard discovery and a supported authentication method are enabled. |
|
|
276
344
|
| DAViCal | Self-hosted | Not yet verified | Not yet verified | Expected to work when standard discovery and a supported authentication method are enabled. |
|
|
@@ -300,17 +368,15 @@ administrator must explicitly enable `allowPrivateAddresses` or
|
|
|
300
368
|
| Shared and delegated calendars | Read-only discovery only | Calendars returned from the user's calendar home can be queried, but creating shares, accepting invitations, proxy delegation, and ACL management are not implemented. |
|
|
301
369
|
| Calendar collection management | Not supported | The platform does not create, rename, or delete calendar collections. |
|
|
302
370
|
| Free/busy queries | Not supported | CalDAV free-busy REPORT and scheduling availability are not implemented. |
|
|
303
|
-
| Incremental sync |
|
|
371
|
+
| Incremental sync | Supported | `sync` uses RFC 6578 WebDAV Sync tokens, including truncated results. Members returned without calendar data are fetched with one `calendar-multiget`. |
|
|
304
372
|
| Managed attachments | Not supported | iCalendar URL and inline attachment properties are supported, but CalDAV managed attachments are not. |
|
|
305
373
|
|
|
306
374
|
<!-- markdownlint-enable MD013 -->
|
|
307
375
|
|
|
308
|
-
Queries currently return calendar snapshots. CalDAV sync tokens (RFC 6578) are
|
|
309
|
-
the intended follow-up for efficient incremental synchronization.
|
|
310
|
-
|
|
311
376
|
Stable errors include `caldav:authentication-failed`,
|
|
312
377
|
`caldav:unsupported-authentication`,
|
|
313
378
|
`caldav:connection-failed`, `caldav:invalid-calendar`,
|
|
314
379
|
`caldav:invalid-resource`, `caldav:unsupported-component`,
|
|
315
|
-
`caldav:conflict`, `caldav:not-found`, `caldav:invalid-feed`,
|
|
316
|
-
`caldav:feed-failed
|
|
380
|
+
`caldav:conflict`, `caldav:not-found`, `caldav:invalid-feed`,
|
|
381
|
+
`caldav:feed-failed`, `caldav:sync-token-invalid`,
|
|
382
|
+
`caldav:sync-unsupported`, and `caldav:sync-failed`.
|
package/dist/dav.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type DavAuthentication, DavClient, DavFailure, type DavNetworkOptions } from "@sockethub/dav";
|
|
2
|
-
import type { CalendarDescription, CalendarItem, QueryInput } from "./types.js";
|
|
2
|
+
import type { CalendarDescription, CalendarItem, CalendarSyncResult, QueryInput } from "./types.js";
|
|
3
3
|
export declare const CalDavFailure: typeof DavFailure;
|
|
4
4
|
export declare class CalDavClient extends DavClient {
|
|
5
5
|
constructor(url: string, authentication: DavAuthentication, timeoutMs?: number, networkOptions?: DavNetworkOptions);
|
|
@@ -10,6 +10,11 @@ export declare class CalDavClient extends DavClient {
|
|
|
10
10
|
etag?: string;
|
|
11
11
|
}>;
|
|
12
12
|
query(calendar: CalendarDescription, query?: QueryInput): Promise<CalendarItem[]>;
|
|
13
|
+
/**
|
|
14
|
+
* Incremental sync (RFC 6578). Without `syncToken`, lists every event and
|
|
15
|
+
* task in the calendar; with one, lists only what changed since then.
|
|
16
|
+
*/
|
|
17
|
+
sync(calendar: CalendarDescription, syncToken?: string): Promise<CalendarSyncResult>;
|
|
13
18
|
update(id: string, etag: string, body: string): Promise<{
|
|
14
19
|
id: string;
|
|
15
20
|
etag?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -30,6 +30,17 @@ export default class CalDav implements PlatformInterface {
|
|
|
30
30
|
read(job: ActivityStream, done: PlatformCallback): void;
|
|
31
31
|
create(job: ActivityStream, credentials: CalDavCredentials, done: PlatformCallback): void;
|
|
32
32
|
query(job: ActivityStream, credentials: CalDavCredentials, done: PlatformCallback): void;
|
|
33
|
+
/**
|
|
34
|
+
* Incremental calendar sync (RFC 6578 WebDAV Sync). Without
|
|
35
|
+
* `object.syncToken`, returns every event and task plus a token; with
|
|
36
|
+
* one, returns only items changed and ids removed since that token.
|
|
37
|
+
* Store the returned `syncToken` opaquely and send it next time. When
|
|
38
|
+
* `truncated` is true, sync again with the new token before relying on
|
|
39
|
+
* the result being complete. `caldav:sync-token-invalid` means start
|
|
40
|
+
* over without a token; `caldav:sync-unsupported` means fall back to
|
|
41
|
+
* `query`.
|
|
42
|
+
*/
|
|
43
|
+
sync(job: ActivityStream, credentials: CalDavCredentials, done: PlatformCallback): void;
|
|
33
44
|
update(job: ActivityStream, credentials: CalDavCredentials, done: PlatformCallback): void;
|
|
34
45
|
delete(job: ActivityStream, credentials: CalDavCredentials, done: PlatformCallback): void;
|
|
35
46
|
private client;
|