@craftguild/jscalendar 0.5.0 → 0.5.2
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 +60 -42
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,15 +1,25 @@
|
|
|
1
|
+
<p style="text-align: center;">
|
|
2
|
+
<img src="assets/d97d4d10-44f9-4b49-9fc2-5aaf33c667ef.png" alt="JSCalendar logo" style="max-height: 320px; height: auto; width: auto;" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
# RFC 8984 (JSCalendar) TypeScript Library
|
|
2
6
|
|
|
3
7
|
This library provides a thin, practical TypeScript API for working with
|
|
4
|
-
RFC 8984 (JSCalendar) objects
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
RFC 8984 (JSCalendar) objects while staying close to the spec. It focuses
|
|
9
|
+
on creation, patching, recurrence expansion, search, and iCalendar export.
|
|
10
|
+
It does **not** implement a calendar application or server; it is a data
|
|
11
|
+
model toolkit you can use in web apps, CLIs, or services.
|
|
8
12
|
|
|
9
13
|
Primary object types are **Event**, **Task**, and **Group**. A **Group**
|
|
10
14
|
acts as a container when you want to bundle multiple objects. The API is
|
|
11
|
-
intentionally small
|
|
12
|
-
|
|
15
|
+
intentionally small but opinionated: constructors normalize required
|
|
16
|
+
fields, validation is strict by default, and `patch` applies RFC 8984
|
|
17
|
+
PatchObject semantics.
|
|
18
|
+
|
|
19
|
+
For developer experience, the library offers builder helpers that fill
|
|
20
|
+
`@type` fields and validate nested structures (participants, locations,
|
|
21
|
+
alerts, recurrence rules, and more). You can still pass raw, typed
|
|
22
|
+
JSCalendar objects directly when your data already matches the spec.
|
|
13
23
|
|
|
14
24
|
## Installation
|
|
15
25
|
|
|
@@ -84,20 +94,6 @@ const task = new JsCal.Task({
|
|
|
84
94
|
});
|
|
85
95
|
```
|
|
86
96
|
|
|
87
|
-
Id maps use `{ id, value }` entries. If you need to merge into an
|
|
88
|
-
existing map, pass it as the second argument. Entries with `id` overwrite
|
|
89
|
-
matching ids; entries without `id` get new generated ids.
|
|
90
|
-
|
|
91
|
-
```ts
|
|
92
|
-
const mergedLocations = JsCal.locations(
|
|
93
|
-
[
|
|
94
|
-
{ id: "l1", value: { name: "Room A Updated" } },
|
|
95
|
-
{ value: { name: "Room B" } },
|
|
96
|
-
],
|
|
97
|
-
existingLocations,
|
|
98
|
-
);
|
|
99
|
-
```
|
|
100
|
-
|
|
101
97
|
### Group
|
|
102
98
|
|
|
103
99
|
`entries` accepts either plain JSCalendar objects (including `eject()` results)
|
|
@@ -204,17 +200,59 @@ plain.title = "Exported";
|
|
|
204
200
|
const updated = event.patch({ title: "Live" });
|
|
205
201
|
```
|
|
206
202
|
|
|
207
|
-
##
|
|
203
|
+
## Patch Usage
|
|
208
204
|
|
|
209
205
|
Patch helpers return new instances and keep metadata such as
|
|
210
206
|
`updated` and `sequence` consistent. Use `patch` for RFC 8984 PatchObject
|
|
211
|
-
semantics.
|
|
207
|
+
semantics. You can set raw values directly, or use helper methods if you
|
|
208
|
+
prefer validated, type-safe inputs.
|
|
212
209
|
|
|
213
210
|
```ts
|
|
214
211
|
const patchedEvent = event.patch({ title: "Updated title" });
|
|
215
212
|
const patchedAgain = patchedEvent.patch({ title: "Patched title" });
|
|
216
213
|
```
|
|
217
214
|
|
|
215
|
+
You can also patch nested maps by replacing the full map in one call:
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
const withParticipants = event.patch({
|
|
219
|
+
participants: {
|
|
220
|
+
p1: { "@type": "Participant", roles: { attendee: true }, email: "a@example.com" },
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Two common patterns for nested patches:
|
|
226
|
+
|
|
227
|
+
1) Set raw values directly
|
|
228
|
+
```ts
|
|
229
|
+
const withLocations = event.patch({
|
|
230
|
+
locations: {
|
|
231
|
+
l1: { "@type": "Location", name: "Room A" },
|
|
232
|
+
},
|
|
233
|
+
});
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
2) Use helpers to build or merge map values
|
|
237
|
+
```ts
|
|
238
|
+
const withLocations = event.patch({
|
|
239
|
+
locations: JsCal.locations([
|
|
240
|
+
{ id: "l1", value: JsCal.Location({ name: "Room A" }) },
|
|
241
|
+
{ value: JsCal.Location({ name: "Room B" }) },
|
|
242
|
+
]),
|
|
243
|
+
});
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
To merge into an existing map, pass the current map as the second argument:
|
|
247
|
+
```ts
|
|
248
|
+
const withLocations = event.patch({
|
|
249
|
+
locations: JsCal.locations(
|
|
250
|
+
[{ value: JsCal.Location({ name: "Room C" }) }],
|
|
251
|
+
event.data.locations,
|
|
252
|
+
),
|
|
253
|
+
});
|
|
254
|
+
```
|
|
255
|
+
|
|
218
256
|
## Date Inputs and Time Zones
|
|
219
257
|
|
|
220
258
|
Date fields accept either RFC 8984 strings or JavaScript `Date`. When a
|
|
@@ -351,26 +389,6 @@ const icalMany = JsCal.toICal([event, task], { includeXJSCalendar: true });
|
|
|
351
389
|
console.log(icalMany);
|
|
352
390
|
```
|
|
353
391
|
|
|
354
|
-
## Practical Example
|
|
355
|
-
|
|
356
|
-
**Weekly engineering sync (every Wednesday 10:30, 1 hour)**
|
|
357
|
-
|
|
358
|
-
```ts
|
|
359
|
-
const weekly = new JsCal.Event({
|
|
360
|
-
title: "Engineering Sync",
|
|
361
|
-
start: "2026-02-04T10:30:00",
|
|
362
|
-
timeZone: "Asia/Tokyo",
|
|
363
|
-
duration: JsCal.duration.hours(1),
|
|
364
|
-
recurrenceRules: [
|
|
365
|
-
{
|
|
366
|
-
"@type": "RecurrenceRule",
|
|
367
|
-
frequency: "weekly",
|
|
368
|
-
byDay: [{ "@type": "NDay", day: "we" }],
|
|
369
|
-
},
|
|
370
|
-
],
|
|
371
|
-
});
|
|
372
|
-
```
|
|
373
|
-
|
|
374
392
|
## Compliance and Deviations
|
|
375
393
|
|
|
376
394
|
### RFC 8984 Conformance (Implemented)
|
package/package.json
CHANGED