@craftguild/jscalendar 0.5.3 → 0.5.4
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 +128 -92
- package/dist/index.cjs +3923 -0
- package/dist/index.d.cts +802 -0
- package/dist/index.d.mts +802 -0
- package/dist/index.mjs +3927 -0
- package/package.json +46 -31
- package/dist/__tests__/builders.test.d.ts +0 -1
- package/dist/__tests__/builders.test.js +0 -101
- package/dist/__tests__/calendar-extra.test.d.ts +0 -1
- package/dist/__tests__/calendar-extra.test.js +0 -221
- package/dist/__tests__/calendar.test.d.ts +0 -1
- package/dist/__tests__/calendar.test.js +0 -97
- package/dist/__tests__/ical-extra.test.d.ts +0 -1
- package/dist/__tests__/ical-extra.test.js +0 -87
- package/dist/__tests__/ical.test.d.ts +0 -1
- package/dist/__tests__/ical.test.js +0 -72
- package/dist/__tests__/index.test.d.ts +0 -1
- package/dist/__tests__/index.test.js +0 -9
- package/dist/__tests__/patch.test.d.ts +0 -1
- package/dist/__tests__/patch.test.js +0 -47
- package/dist/__tests__/recurrence.test.d.ts +0 -1
- package/dist/__tests__/recurrence.test.js +0 -640
- package/dist/__tests__/search.test.d.ts +0 -1
- package/dist/__tests__/search.test.js +0 -264
- package/dist/__tests__/timezones.test.d.ts +0 -1
- package/dist/__tests__/timezones.test.js +0 -12
- package/dist/__tests__/utils.test.d.ts +0 -1
- package/dist/__tests__/utils.test.js +0 -127
- package/dist/__tests__/validation.test.d.ts +0 -1
- package/dist/__tests__/validation.test.js +0 -224
- package/dist/ical.d.ts +0 -13
- package/dist/ical.js +0 -270
- package/dist/index.d.ts +0 -3
- package/dist/index.js +0 -2
- package/dist/jscal/base.d.ts +0 -89
- package/dist/jscal/base.js +0 -173
- package/dist/jscal/builders.d.ts +0 -183
- package/dist/jscal/builders.js +0 -287
- package/dist/jscal/constants.d.ts +0 -11
- package/dist/jscal/constants.js +0 -11
- package/dist/jscal/datetime.d.ts +0 -14
- package/dist/jscal/datetime.js +0 -42
- package/dist/jscal/defaults.d.ts +0 -31
- package/dist/jscal/defaults.js +0 -102
- package/dist/jscal/duration.d.ts +0 -43
- package/dist/jscal/duration.js +0 -75
- package/dist/jscal/event.d.ts +0 -23
- package/dist/jscal/event.js +0 -78
- package/dist/jscal/group.d.ts +0 -31
- package/dist/jscal/group.js +0 -69
- package/dist/jscal/guards.d.ts +0 -19
- package/dist/jscal/guards.js +0 -25
- package/dist/jscal/ids.d.ts +0 -11
- package/dist/jscal/ids.js +0 -77
- package/dist/jscal/normalize.d.ts +0 -32
- package/dist/jscal/normalize.js +0 -45
- package/dist/jscal/task.d.ts +0 -23
- package/dist/jscal/task.js +0 -67
- package/dist/jscal/types.d.ts +0 -38
- package/dist/jscal/types.js +0 -1
- package/dist/jscal.d.ts +0 -145
- package/dist/jscal.js +0 -126
- package/dist/patch.d.ts +0 -18
- package/dist/patch.js +0 -216
- package/dist/recurrence/constants.d.ts +0 -13
- package/dist/recurrence/constants.js +0 -13
- package/dist/recurrence/date-utils.d.ts +0 -125
- package/dist/recurrence/date-utils.js +0 -259
- package/dist/recurrence/expand.d.ts +0 -23
- package/dist/recurrence/expand.js +0 -315
- package/dist/recurrence/rule-candidates.d.ts +0 -21
- package/dist/recurrence/rule-candidates.js +0 -120
- package/dist/recurrence/rule-generate.d.ts +0 -11
- package/dist/recurrence/rule-generate.js +0 -36
- package/dist/recurrence/rule-matchers.d.ts +0 -34
- package/dist/recurrence/rule-matchers.js +0 -120
- package/dist/recurrence/rule-normalize.d.ts +0 -9
- package/dist/recurrence/rule-normalize.js +0 -57
- package/dist/recurrence/rule-selectors.d.ts +0 -7
- package/dist/recurrence/rule-selectors.js +0 -21
- package/dist/recurrence/rules.d.ts +0 -14
- package/dist/recurrence/rules.js +0 -57
- package/dist/recurrence/types.d.ts +0 -27
- package/dist/recurrence/types.js +0 -1
- package/dist/recurrence.d.ts +0 -2
- package/dist/recurrence.js +0 -1
- package/dist/search.d.ts +0 -44
- package/dist/search.js +0 -292
- package/dist/timezones/chunk_1.d.ts +0 -2
- package/dist/timezones/chunk_1.js +0 -72
- package/dist/timezones/chunk_2.d.ts +0 -2
- package/dist/timezones/chunk_2.js +0 -72
- package/dist/timezones/chunk_3.d.ts +0 -2
- package/dist/timezones/chunk_3.js +0 -72
- package/dist/timezones/chunk_4.d.ts +0 -2
- package/dist/timezones/chunk_4.js +0 -72
- package/dist/timezones/chunk_5.d.ts +0 -2
- package/dist/timezones/chunk_5.js +0 -72
- package/dist/timezones/chunk_6.d.ts +0 -2
- package/dist/timezones/chunk_6.js +0 -72
- package/dist/timezones/chunk_7.d.ts +0 -2
- package/dist/timezones/chunk_7.js +0 -6
- package/dist/timezones.d.ts +0 -9
- package/dist/timezones.js +0 -452
- package/dist/types.d.ts +0 -246
- package/dist/types.js +0 -1
- package/dist/utils.d.ts +0 -82
- package/dist/utils.js +0 -164
- package/dist/validate/asserts.d.ts +0 -155
- package/dist/validate/asserts.js +0 -381
- package/dist/validate/constants.d.ts +0 -25
- package/dist/validate/constants.js +0 -33
- package/dist/validate/error.d.ts +0 -19
- package/dist/validate/error.js +0 -25
- package/dist/validate/validators-common.d.ts +0 -64
- package/dist/validate/validators-common.js +0 -390
- package/dist/validate/validators-objects.d.ts +0 -8
- package/dist/validate/validators-objects.js +0 -70
- package/dist/validate/validators-recurrence.d.ts +0 -15
- package/dist/validate/validators-recurrence.js +0 -115
- package/dist/validate/validators.d.ts +0 -1
- package/dist/validate/validators.js +0 -1
- package/dist/validate.d.ts +0 -2
- package/dist/validate.js +0 -2
package/README.md
CHANGED
|
@@ -34,19 +34,19 @@ import { JsCal } from "@craftguild/jscalendar";
|
|
|
34
34
|
|
|
35
35
|
// Create a recurring event and a simple task, then expand occurrences.
|
|
36
36
|
const event = new JsCal.Event({
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
title: "Weekly Sync",
|
|
38
|
+
start: new Date(2026, 0, 1, 0, 0, 0, 0),
|
|
39
|
+
recurrenceRules: [
|
|
40
|
+
JsCal.RecurrenceRule({
|
|
41
|
+
frequency: "weekly",
|
|
42
|
+
byDay: [JsCal.ByDay({ day: "th" })],
|
|
43
|
+
}),
|
|
44
|
+
],
|
|
45
45
|
});
|
|
46
46
|
|
|
47
47
|
const task = new JsCal.Task({
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
title: "Prepare Notes",
|
|
49
|
+
start: new Date(2026, 0, 1, 0, 0, 0, 0),
|
|
50
50
|
});
|
|
51
51
|
|
|
52
52
|
const from = new Date(2026, 0, 1, 0, 0, 0, 0);
|
|
@@ -54,12 +54,13 @@ const to = new Date(2026, 0, 31, 0, 0, 0, 0);
|
|
|
54
54
|
const generator = JsCal.expandRecurrence([event, task], { from, to });
|
|
55
55
|
|
|
56
56
|
for (const item of generator) {
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
// Expanded JSCalendar objects for events and tasks in the range.
|
|
58
|
+
console.log(JSON.stringify(item));
|
|
59
59
|
}
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
Sample output (truncated):
|
|
63
|
+
|
|
63
64
|
```txt
|
|
64
65
|
{"title":"Weekly Sync","@type":"Event","start":"2026-01-01T00:00:00",...}
|
|
65
66
|
{"title":"Prepare Notes","@type":"Task","start":"2026-01-01T00:00:00",...}
|
|
@@ -76,10 +77,10 @@ object and normalizes required fields (e.g., `uid`, `updated`).
|
|
|
76
77
|
|
|
77
78
|
```ts
|
|
78
79
|
const event = new JsCal.Event({
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
title: "Team Sync",
|
|
81
|
+
start: "2026-02-10T10:00:00",
|
|
82
|
+
timeZone: "America/New_York",
|
|
83
|
+
duration: "PT30M",
|
|
83
84
|
});
|
|
84
85
|
```
|
|
85
86
|
|
|
@@ -87,10 +88,10 @@ const event = new JsCal.Event({
|
|
|
87
88
|
|
|
88
89
|
```ts
|
|
89
90
|
const task = new JsCal.Task({
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
title: "Write report",
|
|
92
|
+
start: "2026-02-11T09:00:00",
|
|
93
|
+
due: "2026-02-11T17:00:00",
|
|
94
|
+
percentComplete: 10,
|
|
94
95
|
});
|
|
95
96
|
```
|
|
96
97
|
|
|
@@ -101,8 +102,8 @@ or `JsCal.Event`/`JsCal.Task` instances.
|
|
|
101
102
|
|
|
102
103
|
```ts
|
|
103
104
|
const group = new JsCal.Group({
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
title: "Project A",
|
|
106
|
+
entries: [event, task.eject()],
|
|
106
107
|
});
|
|
107
108
|
```
|
|
108
109
|
|
|
@@ -124,18 +125,33 @@ your database), but builders offer a safer, clearer option for app code.
|
|
|
124
125
|
|
|
125
126
|
```ts
|
|
126
127
|
const task = new JsCal.Task({
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
128
|
+
title: "Write report",
|
|
129
|
+
start: "2026-02-11T09:00:00",
|
|
130
|
+
participants: JsCal.participants([
|
|
131
|
+
{
|
|
132
|
+
value: JsCal.Participant({
|
|
133
|
+
name: "Alice",
|
|
134
|
+
email: "a@example.com",
|
|
135
|
+
roles: { attendee: true },
|
|
136
|
+
}),
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
value: JsCal.Participant({
|
|
140
|
+
name: "Bob",
|
|
141
|
+
roles: { attendee: true },
|
|
142
|
+
}),
|
|
143
|
+
},
|
|
144
|
+
]),
|
|
145
|
+
locations: JsCal.locations([{ value: JsCal.Location({ name: "Room A" }) }]),
|
|
146
|
+
alerts: JsCal.alerts([
|
|
147
|
+
{
|
|
148
|
+
value: JsCal.Alert({
|
|
149
|
+
trigger: JsCal.OffsetTrigger({
|
|
150
|
+
offset: JsCal.duration.minutes(-15),
|
|
151
|
+
}),
|
|
152
|
+
}),
|
|
153
|
+
},
|
|
154
|
+
]),
|
|
139
155
|
});
|
|
140
156
|
```
|
|
141
157
|
|
|
@@ -143,17 +159,25 @@ const task = new JsCal.Task({
|
|
|
143
159
|
|
|
144
160
|
```ts
|
|
145
161
|
const task = new JsCal.Task({
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
162
|
+
title: "Imported task",
|
|
163
|
+
start: "2026-02-11T09:00:00",
|
|
164
|
+
participants: {
|
|
165
|
+
p1: {
|
|
166
|
+
"@type": "Participant",
|
|
167
|
+
name: "Alice",
|
|
168
|
+
email: "a@example.com",
|
|
169
|
+
roles: { attendee: true },
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
locations: {
|
|
173
|
+
l1: { "@type": "Location", name: "Room A" },
|
|
174
|
+
},
|
|
175
|
+
alerts: {
|
|
176
|
+
a1: {
|
|
177
|
+
"@type": "Alert",
|
|
178
|
+
trigger: { "@type": "OffsetTrigger", offset: "-PT15M" },
|
|
179
|
+
},
|
|
180
|
+
},
|
|
157
181
|
});
|
|
158
182
|
```
|
|
159
183
|
|
|
@@ -177,6 +201,7 @@ clone of that underlying JSCalendar object for serialization, storage,
|
|
|
177
201
|
or passing across app boundaries.
|
|
178
202
|
|
|
179
203
|
Why `eject()` exists:
|
|
204
|
+
|
|
180
205
|
- Class instances are convenient for building and updating objects with
|
|
181
206
|
helpers like `patch`.
|
|
182
207
|
- External APIs, storage layers, and JSON stringify expect plain objects.
|
|
@@ -184,12 +209,16 @@ Why `eject()` exists:
|
|
|
184
209
|
from the original instance (and vice versa).
|
|
185
210
|
|
|
186
211
|
What changes after `eject()`:
|
|
212
|
+
|
|
187
213
|
- You lose helper methods; the result is just a plain JSCalendar object.
|
|
188
214
|
- Mutating the plain object does not affect the original instance.
|
|
189
215
|
- The instance can still be used and updated independently.
|
|
190
216
|
|
|
191
217
|
```ts
|
|
192
|
-
const event = new JsCal.Event({
|
|
218
|
+
const event = new JsCal.Event({
|
|
219
|
+
title: "Kickoff",
|
|
220
|
+
start: "2026-02-02T10:00:00",
|
|
221
|
+
});
|
|
193
222
|
const plain = event.eject();
|
|
194
223
|
|
|
195
224
|
// Plain object is ready for JSON / storage / network.
|
|
@@ -216,40 +245,47 @@ You can also patch nested maps by replacing the full map in one call:
|
|
|
216
245
|
|
|
217
246
|
```ts
|
|
218
247
|
const withParticipants = event.patch({
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
248
|
+
participants: {
|
|
249
|
+
p1: {
|
|
250
|
+
"@type": "Participant",
|
|
251
|
+
roles: { attendee: true },
|
|
252
|
+
email: "a@example.com",
|
|
253
|
+
},
|
|
254
|
+
},
|
|
222
255
|
});
|
|
223
256
|
```
|
|
224
257
|
|
|
225
258
|
Two common patterns for nested patches:
|
|
226
259
|
|
|
227
|
-
1
|
|
260
|
+
1. Set raw values directly
|
|
261
|
+
|
|
228
262
|
```ts
|
|
229
263
|
const withLocations = event.patch({
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
264
|
+
locations: {
|
|
265
|
+
l1: { "@type": "Location", name: "Room A" },
|
|
266
|
+
},
|
|
233
267
|
});
|
|
234
268
|
```
|
|
235
269
|
|
|
236
|
-
2
|
|
270
|
+
2. Use helpers to build or merge map values
|
|
271
|
+
|
|
237
272
|
```ts
|
|
238
273
|
const withLocations = event.patch({
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
274
|
+
locations: JsCal.locations([
|
|
275
|
+
{ id: "l1", value: JsCal.Location({ name: "Room A" }) },
|
|
276
|
+
{ value: JsCal.Location({ name: "Room B" }) },
|
|
277
|
+
]),
|
|
243
278
|
});
|
|
244
279
|
```
|
|
245
280
|
|
|
246
281
|
To merge into an existing map, pass the current map as the second argument:
|
|
282
|
+
|
|
247
283
|
```ts
|
|
248
284
|
const withLocations = event.patch({
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
285
|
+
locations: JsCal.locations(
|
|
286
|
+
[{ value: JsCal.Location({ name: "Room C" }) }],
|
|
287
|
+
event.data.locations,
|
|
288
|
+
),
|
|
253
289
|
});
|
|
254
290
|
```
|
|
255
291
|
|
|
@@ -264,20 +300,20 @@ Date fields accept either RFC 8984 strings or JavaScript `Date`. When a
|
|
|
264
300
|
|
|
265
301
|
```ts
|
|
266
302
|
const eventFromDate = new JsCal.Event({
|
|
267
|
-
|
|
268
|
-
|
|
303
|
+
title: "Kickoff",
|
|
304
|
+
start: new Date(),
|
|
269
305
|
});
|
|
270
306
|
|
|
271
307
|
const eventWithSeconds = new JsCal.Event({
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
308
|
+
title: "Kickoff",
|
|
309
|
+
start: new Date(),
|
|
310
|
+
duration: 90 * 60, // seconds
|
|
275
311
|
});
|
|
276
312
|
|
|
277
313
|
const eventWithZone = new JsCal.Event({
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
314
|
+
title: "Kickoff",
|
|
315
|
+
start: new Date(),
|
|
316
|
+
timeZone: JsCal.timeZone("asia/tokyo"), // => Asia/Tokyo
|
|
281
317
|
});
|
|
282
318
|
```
|
|
283
319
|
|
|
@@ -292,8 +328,8 @@ query engine or build a custom index.
|
|
|
292
328
|
|
|
293
329
|
```ts
|
|
294
330
|
const results = JsCal.filterByDateRange(items, {
|
|
295
|
-
|
|
296
|
-
|
|
331
|
+
start: "2026-02-01T00:00:00Z",
|
|
332
|
+
end: "2026-02-28T23:59:59Z",
|
|
297
333
|
});
|
|
298
334
|
|
|
299
335
|
const found = JsCal.findByUid(items, "uid-123");
|
|
@@ -320,11 +356,11 @@ overrides and exclusions. The output instances contain `recurrenceId`
|
|
|
320
356
|
and preserve the base object’s data unless a patch modifies fields.
|
|
321
357
|
|
|
322
358
|
```ts
|
|
323
|
-
for (const occ of JsCal.expandRecurrence(
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
)) {
|
|
327
|
-
|
|
359
|
+
for (const occ of JsCal.expandRecurrence([event], {
|
|
360
|
+
from: new Date("2026-02-01"),
|
|
361
|
+
to: new Date("2026-03-01"),
|
|
362
|
+
})) {
|
|
363
|
+
console.log(occ);
|
|
328
364
|
}
|
|
329
365
|
```
|
|
330
366
|
|
|
@@ -336,15 +372,15 @@ scrolling or an infinite feed.
|
|
|
336
372
|
|
|
337
373
|
```ts
|
|
338
374
|
const page1 = JsCal.expandRecurrencePaged(
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
375
|
+
[event],
|
|
376
|
+
{ from: new Date("2026-02-01"), to: new Date("2026-03-01") },
|
|
377
|
+
{ limit: 50 },
|
|
342
378
|
);
|
|
343
379
|
|
|
344
380
|
const page2 = JsCal.expandRecurrencePaged(
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
381
|
+
[event],
|
|
382
|
+
{ from: new Date("2026-02-01"), to: new Date("2026-03-01") },
|
|
383
|
+
{ limit: 50, cursor: page1.nextCursor },
|
|
348
384
|
);
|
|
349
385
|
```
|
|
350
386
|
|
|
@@ -360,15 +396,15 @@ compared as simple strings.
|
|
|
360
396
|
|
|
361
397
|
```ts
|
|
362
398
|
const event = new JsCal.Event({
|
|
363
|
-
|
|
364
|
-
|
|
399
|
+
start: "2026-02-01T10:00:00",
|
|
400
|
+
timeZone: "Asia/Tokyo",
|
|
365
401
|
});
|
|
366
402
|
|
|
367
403
|
// 2026-02-01T01:00:00Z is 10:00 in Asia/Tokyo
|
|
368
|
-
const results = JsCal.filterByDateRange(
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
);
|
|
404
|
+
const results = JsCal.filterByDateRange([event], {
|
|
405
|
+
start: new Date("2026-02-01T01:00:00Z"),
|
|
406
|
+
end: new Date("2026-02-01T01:00:00Z"),
|
|
407
|
+
});
|
|
372
408
|
console.log(results.length); // 1
|
|
373
409
|
```
|
|
374
410
|
|
|
@@ -413,9 +449,9 @@ and this library’s behavior.
|
|
|
413
449
|
- **Validation**: strict type/format validation is enforced by default (RFC-style date/time and duration rules),
|
|
414
450
|
but can be disabled with `{ validate: false }` in create/update/patch.
|
|
415
451
|
- **Time zone and DST**:
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
452
|
+
- Range filtering and recurrence comparisons use `date-fns-tz`.
|
|
453
|
+
- Recurrence generation still operates on LocalDateTime arithmetic and does not fully normalize
|
|
454
|
+
DST gaps/overlaps into canonical UTC instants for all cases.
|
|
419
455
|
- **iCalendar export**: minimal mapping + `X-JSCALENDAR`; no VTIMEZONE generation.
|
|
420
456
|
|
|
421
457
|
If you require strict, formal compliance, please treat this as a foundation
|