@craftguild/jscalendar 0.1.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/LICENSE.md +7 -0
- package/README.md +295 -0
- package/dist/__tests__/calendar-extra.test.d.ts +1 -0
- package/dist/__tests__/calendar-extra.test.js +185 -0
- package/dist/__tests__/calendar.test.d.ts +1 -0
- package/dist/__tests__/calendar.test.js +104 -0
- package/dist/__tests__/ical-extra.test.d.ts +1 -0
- package/dist/__tests__/ical-extra.test.js +87 -0
- package/dist/__tests__/ical.test.d.ts +1 -0
- package/dist/__tests__/ical.test.js +72 -0
- package/dist/__tests__/index.test.d.ts +1 -0
- package/dist/__tests__/index.test.js +9 -0
- package/dist/__tests__/patch.test.d.ts +1 -0
- package/dist/__tests__/patch.test.js +47 -0
- package/dist/__tests__/recurrence.test.d.ts +1 -0
- package/dist/__tests__/recurrence.test.js +498 -0
- package/dist/__tests__/search.test.d.ts +1 -0
- package/dist/__tests__/search.test.js +237 -0
- package/dist/__tests__/timezones.test.d.ts +1 -0
- package/dist/__tests__/timezones.test.js +12 -0
- package/dist/__tests__/utils.test.d.ts +1 -0
- package/dist/__tests__/utils.test.js +116 -0
- package/dist/__tests__/validation.test.d.ts +1 -0
- package/dist/__tests__/validation.test.js +91 -0
- package/dist/ical.d.ts +7 -0
- package/dist/ical.js +202 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/jscal.d.ts +129 -0
- package/dist/jscal.js +504 -0
- package/dist/patch.d.ts +5 -0
- package/dist/patch.js +91 -0
- package/dist/recurrence.d.ts +15 -0
- package/dist/recurrence.js +674 -0
- package/dist/search.d.ts +14 -0
- package/dist/search.js +208 -0
- package/dist/timezones.d.ts +4 -0
- package/dist/timezones.js +441 -0
- package/dist/types.d.ts +219 -0
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +10 -0
- package/dist/utils.js +80 -0
- package/dist/validate.d.ts +6 -0
- package/dist/validate.js +745 -0
- package/package.json +33 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import type { TimeZoneId } from "./timezones.js";
|
|
2
|
+
export { TimeZoneId, TimeZoneInput } from "./timezones.js";
|
|
3
|
+
export type Id = string;
|
|
4
|
+
export type Int = number;
|
|
5
|
+
export type UnsignedInt = number;
|
|
6
|
+
export type UTCDateTime = string;
|
|
7
|
+
export type LocalDateTime = string;
|
|
8
|
+
export type Duration = string;
|
|
9
|
+
export type SignedDuration = string;
|
|
10
|
+
export type BooleanMap = Record<string, true>;
|
|
11
|
+
export type JsonPrimitive = string | number | boolean | null;
|
|
12
|
+
export type JsonValue = JsonPrimitive | JsonValue[] | {
|
|
13
|
+
[key: string]: JsonValue;
|
|
14
|
+
};
|
|
15
|
+
export type PatchObject = Record<string, JsonValue | null>;
|
|
16
|
+
export interface Relation {
|
|
17
|
+
"@type": "Relation";
|
|
18
|
+
relation?: BooleanMap;
|
|
19
|
+
}
|
|
20
|
+
export interface Link {
|
|
21
|
+
"@type": "Link";
|
|
22
|
+
href: string;
|
|
23
|
+
cid?: string;
|
|
24
|
+
contentType?: string;
|
|
25
|
+
size?: UnsignedInt;
|
|
26
|
+
rel?: string;
|
|
27
|
+
display?: string;
|
|
28
|
+
title?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface Location {
|
|
31
|
+
"@type": "Location";
|
|
32
|
+
name?: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
locationTypes?: BooleanMap;
|
|
35
|
+
relativeTo?: string;
|
|
36
|
+
timeZone?: TimeZoneId;
|
|
37
|
+
coordinates?: string;
|
|
38
|
+
links?: Record<Id, Link>;
|
|
39
|
+
}
|
|
40
|
+
export interface VirtualLocation {
|
|
41
|
+
"@type": "VirtualLocation";
|
|
42
|
+
name?: string;
|
|
43
|
+
description?: string;
|
|
44
|
+
uri: string;
|
|
45
|
+
features?: BooleanMap;
|
|
46
|
+
}
|
|
47
|
+
export interface Participant {
|
|
48
|
+
"@type": "Participant";
|
|
49
|
+
name?: string;
|
|
50
|
+
email?: string;
|
|
51
|
+
description?: string;
|
|
52
|
+
sendTo?: Record<string, string>;
|
|
53
|
+
kind?: string;
|
|
54
|
+
roles: BooleanMap;
|
|
55
|
+
locationId?: Id;
|
|
56
|
+
language?: string;
|
|
57
|
+
participationStatus?: string;
|
|
58
|
+
participationComment?: string;
|
|
59
|
+
expectReply?: boolean;
|
|
60
|
+
scheduleAgent?: string;
|
|
61
|
+
scheduleForceSend?: boolean;
|
|
62
|
+
scheduleSequence?: UnsignedInt;
|
|
63
|
+
scheduleStatus?: string[];
|
|
64
|
+
scheduleUpdated?: UTCDateTime;
|
|
65
|
+
sentBy?: string;
|
|
66
|
+
invitedBy?: Id;
|
|
67
|
+
delegatedTo?: Record<Id, true>;
|
|
68
|
+
delegatedFrom?: Record<Id, true>;
|
|
69
|
+
memberOf?: Record<Id, true>;
|
|
70
|
+
links?: Record<Id, Link>;
|
|
71
|
+
progress?: string;
|
|
72
|
+
progressUpdated?: UTCDateTime;
|
|
73
|
+
percentComplete?: UnsignedInt;
|
|
74
|
+
}
|
|
75
|
+
export interface OffsetTrigger {
|
|
76
|
+
"@type": "OffsetTrigger";
|
|
77
|
+
offset: SignedDuration;
|
|
78
|
+
relativeTo?: "start" | "end" | string;
|
|
79
|
+
}
|
|
80
|
+
export interface AbsoluteTrigger {
|
|
81
|
+
"@type": "AbsoluteTrigger";
|
|
82
|
+
when: UTCDateTime;
|
|
83
|
+
}
|
|
84
|
+
export interface UnknownTrigger {
|
|
85
|
+
"@type": string;
|
|
86
|
+
[key: string]: JsonValue;
|
|
87
|
+
}
|
|
88
|
+
export type Trigger = OffsetTrigger | AbsoluteTrigger | UnknownTrigger;
|
|
89
|
+
export interface Alert {
|
|
90
|
+
"@type": "Alert";
|
|
91
|
+
trigger: Trigger;
|
|
92
|
+
acknowledged?: UTCDateTime;
|
|
93
|
+
relatedTo?: Record<string, Relation>;
|
|
94
|
+
action?: string;
|
|
95
|
+
}
|
|
96
|
+
export type DayOfWeek = "mo" | "tu" | "we" | "th" | "fr" | "sa" | "su";
|
|
97
|
+
export interface NDay {
|
|
98
|
+
"@type": "NDay";
|
|
99
|
+
day: DayOfWeek;
|
|
100
|
+
nthOfPeriod?: Int;
|
|
101
|
+
}
|
|
102
|
+
export interface RecurrenceRule {
|
|
103
|
+
"@type": "RecurrenceRule";
|
|
104
|
+
frequency: "yearly" | "monthly" | "weekly" | "daily" | "hourly" | "minutely" | "secondly";
|
|
105
|
+
interval?: UnsignedInt;
|
|
106
|
+
rscale?: string;
|
|
107
|
+
skip?: "omit" | "backward" | "forward";
|
|
108
|
+
firstDayOfWeek?: DayOfWeek;
|
|
109
|
+
byDay?: NDay[];
|
|
110
|
+
byMonthDay?: Int[];
|
|
111
|
+
byMonth?: string[];
|
|
112
|
+
byYearDay?: Int[];
|
|
113
|
+
byWeekNo?: Int[];
|
|
114
|
+
byHour?: UnsignedInt[];
|
|
115
|
+
byMinute?: UnsignedInt[];
|
|
116
|
+
bySecond?: UnsignedInt[];
|
|
117
|
+
bySetPosition?: Int[];
|
|
118
|
+
count?: UnsignedInt;
|
|
119
|
+
until?: LocalDateTime;
|
|
120
|
+
}
|
|
121
|
+
export interface TimeZoneRule {
|
|
122
|
+
"@type": "TimeZoneRule";
|
|
123
|
+
start: LocalDateTime;
|
|
124
|
+
offsetFrom: string;
|
|
125
|
+
offsetTo: string;
|
|
126
|
+
recurrenceRules?: RecurrenceRule[];
|
|
127
|
+
recurrenceOverrides?: Record<LocalDateTime, PatchObject>;
|
|
128
|
+
names?: BooleanMap;
|
|
129
|
+
comments?: string[];
|
|
130
|
+
}
|
|
131
|
+
export interface TimeZone {
|
|
132
|
+
"@type": "TimeZone";
|
|
133
|
+
tzId: string;
|
|
134
|
+
updated?: UTCDateTime;
|
|
135
|
+
url?: string;
|
|
136
|
+
validUntil?: UTCDateTime;
|
|
137
|
+
aliases?: BooleanMap;
|
|
138
|
+
standard?: TimeZoneRule[];
|
|
139
|
+
daylight?: TimeZoneRule[];
|
|
140
|
+
}
|
|
141
|
+
export interface JSCalendarCommon {
|
|
142
|
+
"@type": string;
|
|
143
|
+
uid: string;
|
|
144
|
+
relatedTo?: Record<string, Relation>;
|
|
145
|
+
prodId?: string;
|
|
146
|
+
created?: UTCDateTime;
|
|
147
|
+
updated: UTCDateTime;
|
|
148
|
+
sequence?: UnsignedInt;
|
|
149
|
+
method?: string;
|
|
150
|
+
title?: string;
|
|
151
|
+
description?: string;
|
|
152
|
+
descriptionContentType?: string;
|
|
153
|
+
showWithoutTime?: boolean;
|
|
154
|
+
locations?: Record<Id, Location>;
|
|
155
|
+
virtualLocations?: Record<Id, VirtualLocation>;
|
|
156
|
+
links?: Record<Id, Link>;
|
|
157
|
+
locale?: string;
|
|
158
|
+
keywords?: BooleanMap;
|
|
159
|
+
categories?: BooleanMap;
|
|
160
|
+
color?: string;
|
|
161
|
+
recurrenceId?: LocalDateTime;
|
|
162
|
+
recurrenceIdTimeZone?: TimeZoneId | null;
|
|
163
|
+
recurrenceRules?: RecurrenceRule[];
|
|
164
|
+
excludedRecurrenceRules?: RecurrenceRule[];
|
|
165
|
+
recurrenceOverrides?: Record<LocalDateTime, PatchObject>;
|
|
166
|
+
excluded?: boolean;
|
|
167
|
+
priority?: Int;
|
|
168
|
+
freeBusyStatus?: string;
|
|
169
|
+
privacy?: string;
|
|
170
|
+
replyTo?: Record<string, string>;
|
|
171
|
+
sentBy?: string;
|
|
172
|
+
participants?: Record<Id, Participant>;
|
|
173
|
+
requestStatus?: string;
|
|
174
|
+
useDefaultAlerts?: boolean;
|
|
175
|
+
alerts?: Record<Id, Alert>;
|
|
176
|
+
localizations?: Record<string, PatchObject>;
|
|
177
|
+
timeZone?: TimeZoneId | null;
|
|
178
|
+
timeZones?: Partial<Record<TimeZoneId, TimeZone>>;
|
|
179
|
+
}
|
|
180
|
+
export interface Event extends JSCalendarCommon {
|
|
181
|
+
"@type": "Event";
|
|
182
|
+
start: LocalDateTime;
|
|
183
|
+
duration?: Duration;
|
|
184
|
+
status?: string;
|
|
185
|
+
}
|
|
186
|
+
export interface Task extends JSCalendarCommon {
|
|
187
|
+
"@type": "Task";
|
|
188
|
+
due?: LocalDateTime;
|
|
189
|
+
start?: LocalDateTime;
|
|
190
|
+
estimatedDuration?: Duration;
|
|
191
|
+
percentComplete?: UnsignedInt;
|
|
192
|
+
progress?: string;
|
|
193
|
+
progressUpdated?: UTCDateTime;
|
|
194
|
+
}
|
|
195
|
+
export interface Group extends JSCalendarCommon {
|
|
196
|
+
"@type": "Group";
|
|
197
|
+
entries: Array<Event | Task>;
|
|
198
|
+
source?: string;
|
|
199
|
+
}
|
|
200
|
+
export type JSCalendarObject = Event | Task | Group;
|
|
201
|
+
export type CalendarType = JSCalendarObject["@type"];
|
|
202
|
+
export type CreateInput<TType extends CalendarType> = TType extends "Event" ? Omit<Event, "@type" | "uid" | "updated"> & {
|
|
203
|
+
type?: "Event" | "event";
|
|
204
|
+
"@type"?: "Event";
|
|
205
|
+
uid?: string;
|
|
206
|
+
updated?: UTCDateTime;
|
|
207
|
+
} : TType extends "Task" ? Omit<Task, "@type" | "uid" | "updated"> & {
|
|
208
|
+
type?: "Task" | "task";
|
|
209
|
+
"@type"?: "Task";
|
|
210
|
+
uid?: string;
|
|
211
|
+
updated?: UTCDateTime;
|
|
212
|
+
} : Omit<Group, "@type" | "uid" | "updated"> & {
|
|
213
|
+
type?: "Group" | "group";
|
|
214
|
+
"@type"?: "Group";
|
|
215
|
+
uid?: string;
|
|
216
|
+
updated?: UTCDateTime;
|
|
217
|
+
};
|
|
218
|
+
export type AnyCreateInput = CreateInput<"Event"> | CreateInput<"Task"> | CreateInput<"Group">;
|
|
219
|
+
export type CalendarLike = JSCalendarObject | PatchObject | JsonValue;
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Duration, UTCDateTime } from "./types.js";
|
|
2
|
+
export declare function nowUtc(): UTCDateTime;
|
|
3
|
+
export declare function deepClone<T>(value: T): T;
|
|
4
|
+
export declare function isUtcDateTime(value: string): boolean;
|
|
5
|
+
export declare function compareDateTime(a: string, b: string): number | null;
|
|
6
|
+
export declare function durationToMilliseconds(duration: Duration): number | null;
|
|
7
|
+
export declare function normalizeUtcDateTime(value: string): UTCDateTime;
|
|
8
|
+
export declare function localDateTimeFromDate(value: Date): string;
|
|
9
|
+
export declare function dateTimeInTimeZone(value: Date, timeZone: string): string;
|
|
10
|
+
export declare function localDateTimeToUtcDate(value: string, timeZone: string): Date;
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { format } from "date-fns";
|
|
2
|
+
import { formatInTimeZone, fromZonedTime } from "date-fns-tz";
|
|
3
|
+
export function nowUtc() {
|
|
4
|
+
return normalizeUtcDateTime(new Date().toISOString());
|
|
5
|
+
}
|
|
6
|
+
export function deepClone(value) {
|
|
7
|
+
if (typeof structuredClone === "function") {
|
|
8
|
+
return structuredClone(value);
|
|
9
|
+
}
|
|
10
|
+
throw new Error("structuredClone is not available in this environment");
|
|
11
|
+
}
|
|
12
|
+
export function isUtcDateTime(value) {
|
|
13
|
+
return /Z$/.test(value);
|
|
14
|
+
}
|
|
15
|
+
export function compareDateTime(a, b) {
|
|
16
|
+
const aUtc = isUtcDateTime(a);
|
|
17
|
+
const bUtc = isUtcDateTime(b);
|
|
18
|
+
if (aUtc && bUtc) {
|
|
19
|
+
const aMs = Date.parse(a);
|
|
20
|
+
const bMs = Date.parse(b);
|
|
21
|
+
if (Number.isNaN(aMs) || Number.isNaN(bMs))
|
|
22
|
+
return null;
|
|
23
|
+
return aMs === bMs ? 0 : aMs < bMs ? -1 : 1;
|
|
24
|
+
}
|
|
25
|
+
if (!aUtc && !bUtc) {
|
|
26
|
+
if (a === b)
|
|
27
|
+
return 0;
|
|
28
|
+
return a < b ? -1 : 1;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
export function durationToMilliseconds(duration) {
|
|
33
|
+
const re = /^P(?:(\d+)W)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d+)?)S)?)?$/;
|
|
34
|
+
const match = re.exec(duration);
|
|
35
|
+
if (!match)
|
|
36
|
+
return null;
|
|
37
|
+
const weeks = Number(match[1] || 0);
|
|
38
|
+
const days = Number(match[2] || 0);
|
|
39
|
+
const hours = Number(match[3] || 0);
|
|
40
|
+
const minutes = Number(match[4] || 0);
|
|
41
|
+
const seconds = Number(match[5] || 0);
|
|
42
|
+
const totalSeconds = weeks * 7 * 24 * 60 * 60 +
|
|
43
|
+
days * 24 * 60 * 60 +
|
|
44
|
+
hours * 60 * 60 +
|
|
45
|
+
minutes * 60 +
|
|
46
|
+
seconds;
|
|
47
|
+
return totalSeconds * 1000;
|
|
48
|
+
}
|
|
49
|
+
export function normalizeUtcDateTime(value) {
|
|
50
|
+
const match = value.match(/^(.*)\.(\d+)Z$/);
|
|
51
|
+
if (!match)
|
|
52
|
+
return value;
|
|
53
|
+
const prefix = match[1] ?? value;
|
|
54
|
+
const fraction = match[2] ?? "";
|
|
55
|
+
const trimmed = fraction.replace(/0+$/, "");
|
|
56
|
+
if (trimmed.length === 0) {
|
|
57
|
+
return `${prefix}Z`;
|
|
58
|
+
}
|
|
59
|
+
return `${prefix}.${trimmed}Z`;
|
|
60
|
+
}
|
|
61
|
+
export function localDateTimeFromDate(value) {
|
|
62
|
+
return format(value, "yyyy-MM-dd'T'HH:mm:ss");
|
|
63
|
+
}
|
|
64
|
+
export function dateTimeInTimeZone(value, timeZone) {
|
|
65
|
+
return formatInTimeZone(value, timeZone, "yyyy-MM-dd'T'HH:mm:ss");
|
|
66
|
+
}
|
|
67
|
+
export function localDateTimeToUtcDate(value, timeZone) {
|
|
68
|
+
const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})/.exec(value);
|
|
69
|
+
if (!match) {
|
|
70
|
+
throw new Error(`Invalid LocalDateTime: ${value}`);
|
|
71
|
+
}
|
|
72
|
+
const year = Number(match[1]);
|
|
73
|
+
const month = Number(match[2]);
|
|
74
|
+
const day = Number(match[3]);
|
|
75
|
+
const hour = Number(match[4]);
|
|
76
|
+
const minute = Number(match[5]);
|
|
77
|
+
const second = Number(match[6]);
|
|
78
|
+
const local = new Date(year, month - 1, day, hour, minute, second);
|
|
79
|
+
return fromZonedTime(local, timeZone);
|
|
80
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { JSCalendarObject } from "./types.js";
|
|
2
|
+
export declare class ValidationError extends Error {
|
|
3
|
+
path: string;
|
|
4
|
+
constructor(path: string, message: string);
|
|
5
|
+
}
|
|
6
|
+
export declare function validateJsCalendarObject(value: JSCalendarObject, path?: string): void;
|