@craftguild/jscalendar 0.2.0 → 0.3.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/README.md +63 -0
- package/dist/__tests__/builders.test.d.ts +1 -0
- package/dist/__tests__/builders.test.js +82 -0
- package/dist/__tests__/calendar-extra.test.js +36 -0
- package/dist/__tests__/recurrence.test.js +123 -0
- package/dist/__tests__/search.test.js +27 -0
- package/dist/__tests__/utils.test.js +3 -0
- package/dist/__tests__/validation.test.js +113 -0
- package/dist/ical.d.ts +6 -0
- package/dist/ical.js +71 -3
- package/dist/jscal/base.d.ts +90 -0
- package/dist/jscal/base.js +181 -0
- package/dist/jscal/builders.d.ts +135 -0
- package/dist/jscal/builders.js +220 -0
- package/dist/jscal/constants.d.ts +11 -0
- package/dist/jscal/constants.js +11 -0
- package/dist/jscal/datetime.d.ts +14 -0
- package/dist/jscal/datetime.js +42 -0
- package/dist/jscal/defaults.d.ts +31 -0
- package/dist/jscal/defaults.js +102 -0
- package/dist/jscal/duration.d.ts +43 -0
- package/dist/jscal/duration.js +72 -0
- package/dist/jscal/event.d.ts +17 -0
- package/dist/jscal/event.js +71 -0
- package/dist/jscal/group.d.ts +25 -0
- package/dist/jscal/group.js +62 -0
- package/dist/jscal/guards.d.ts +19 -0
- package/dist/jscal/guards.js +25 -0
- package/dist/jscal/ids.d.ts +11 -0
- package/dist/jscal/ids.js +77 -0
- package/dist/jscal/normalize.d.ts +32 -0
- package/dist/jscal/normalize.js +45 -0
- package/dist/jscal/task.d.ts +17 -0
- package/dist/jscal/task.js +60 -0
- package/dist/jscal/types.d.ts +38 -0
- package/dist/jscal/types.js +1 -0
- package/dist/jscal.d.ts +77 -70
- package/dist/jscal.js +77 -465
- package/dist/patch.d.ts +13 -0
- package/dist/patch.js +166 -41
- package/dist/recurrence/constants.d.ts +13 -0
- package/dist/recurrence/constants.js +13 -0
- package/dist/recurrence/date-utils.d.ts +125 -0
- package/dist/recurrence/date-utils.js +259 -0
- package/dist/recurrence/expand.d.ts +23 -0
- package/dist/recurrence/expand.js +294 -0
- package/dist/recurrence/rule-candidates.d.ts +21 -0
- package/dist/recurrence/rule-candidates.js +120 -0
- package/dist/recurrence/rule-generate.d.ts +11 -0
- package/dist/recurrence/rule-generate.js +36 -0
- package/dist/recurrence/rule-matchers.d.ts +34 -0
- package/dist/recurrence/rule-matchers.js +120 -0
- package/dist/recurrence/rule-normalize.d.ts +9 -0
- package/dist/recurrence/rule-normalize.js +57 -0
- package/dist/recurrence/rule-selectors.d.ts +7 -0
- package/dist/recurrence/rule-selectors.js +21 -0
- package/dist/recurrence/rules.d.ts +14 -0
- package/dist/recurrence/rules.js +57 -0
- package/dist/recurrence/types.d.ts +27 -0
- package/dist/recurrence/types.js +1 -0
- package/dist/recurrence.d.ts +2 -15
- package/dist/recurrence.js +1 -674
- package/dist/search.d.ts +30 -0
- package/dist/search.js +92 -8
- package/dist/timezones/chunk_1.d.ts +2 -0
- package/dist/timezones/chunk_1.js +72 -0
- package/dist/timezones/chunk_2.d.ts +2 -0
- package/dist/timezones/chunk_2.js +72 -0
- package/dist/timezones/chunk_3.d.ts +2 -0
- package/dist/timezones/chunk_3.js +72 -0
- package/dist/timezones/chunk_4.d.ts +2 -0
- package/dist/timezones/chunk_4.js +72 -0
- package/dist/timezones/chunk_5.d.ts +2 -0
- package/dist/timezones/chunk_5.js +72 -0
- package/dist/timezones/chunk_6.d.ts +2 -0
- package/dist/timezones/chunk_6.js +72 -0
- package/dist/timezones/chunk_7.d.ts +2 -0
- package/dist/timezones/chunk_7.js +6 -0
- package/dist/timezones.d.ts +5 -0
- package/dist/timezones.js +14 -3
- package/dist/utils.d.ts +72 -0
- package/dist/utils.js +85 -1
- package/dist/validate/asserts.d.ts +155 -0
- package/dist/validate/asserts.js +381 -0
- package/dist/validate/constants.d.ts +25 -0
- package/dist/validate/constants.js +33 -0
- package/dist/validate/error.d.ts +19 -0
- package/dist/validate/error.js +25 -0
- package/dist/validate/validators-common.d.ts +64 -0
- package/dist/validate/validators-common.js +385 -0
- package/dist/validate/validators-objects.d.ts +8 -0
- package/dist/validate/validators-objects.js +70 -0
- package/dist/validate/validators-recurrence.d.ts +15 -0
- package/dist/validate/validators-recurrence.js +115 -0
- package/dist/validate/validators.d.ts +1 -0
- package/dist/validate/validators.js +1 -0
- package/dist/validate.d.ts +2 -6
- package/dist/validate.js +2 -745
- package/package.json +1 -1
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
import { TimeZones } from "../timezones.js";
|
|
2
|
+
import { fail } from "./error.js";
|
|
3
|
+
import { CHARSET_KEY, DATE_TIME, DURATION, ID_PATTERN, UTF8, Z_SUFFIX } from "./constants.js";
|
|
4
|
+
import { isBooleanValue, isNumberValue, isObjectValue, isStringValue } from "../utils.js";
|
|
5
|
+
const TYPEOF_UNDEFINED = "undefined";
|
|
6
|
+
/**
|
|
7
|
+
* Get the UTF-8 byte length of a string.
|
|
8
|
+
* @param value Input string.
|
|
9
|
+
* @return Byte length.
|
|
10
|
+
*/
|
|
11
|
+
export function utf8Length(value) {
|
|
12
|
+
if (typeof TextEncoder !== TYPEOF_UNDEFINED) {
|
|
13
|
+
return new TextEncoder().encode(value).length;
|
|
14
|
+
}
|
|
15
|
+
return value.length;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Check whether a value is a plain record.
|
|
19
|
+
* @param value Input value.
|
|
20
|
+
* @return True if the value is a record.
|
|
21
|
+
*/
|
|
22
|
+
export function isRecord(value) {
|
|
23
|
+
return !!value && isObjectValue(value) && !Array.isArray(value);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Assert a value is a string when defined.
|
|
27
|
+
* @param value Value to check.
|
|
28
|
+
* @param path Validation path.
|
|
29
|
+
* @return Nothing.
|
|
30
|
+
*/
|
|
31
|
+
export function assertString(value, path) {
|
|
32
|
+
if (value === undefined || value === null)
|
|
33
|
+
return;
|
|
34
|
+
if (!isStringValue(value))
|
|
35
|
+
fail(path, "must be a string");
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Assert a value is a non-empty string when defined.
|
|
39
|
+
* @param value Value to check.
|
|
40
|
+
* @param path Validation path.
|
|
41
|
+
* @return Nothing.
|
|
42
|
+
*/
|
|
43
|
+
export function assertNonEmptyString(value, path) {
|
|
44
|
+
if (value === undefined)
|
|
45
|
+
return;
|
|
46
|
+
if (!isStringValue(value))
|
|
47
|
+
fail(path, "must be a string");
|
|
48
|
+
if (value.length === 0)
|
|
49
|
+
fail(path, "must not be empty");
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Assert a value is a valid Id when defined.
|
|
53
|
+
* @param value Value to check.
|
|
54
|
+
* @param path Validation path.
|
|
55
|
+
* @return Nothing.
|
|
56
|
+
*/
|
|
57
|
+
export function assertId(value, path) {
|
|
58
|
+
if (value === undefined)
|
|
59
|
+
return;
|
|
60
|
+
if (!isStringValue(value))
|
|
61
|
+
fail(path, "must be an Id");
|
|
62
|
+
const length = utf8Length(value);
|
|
63
|
+
if (length < 1 || length > 255)
|
|
64
|
+
fail(path, "must be between 1 and 255 octets");
|
|
65
|
+
if (!ID_PATTERN.test(value))
|
|
66
|
+
fail(path, "must use base64url characters");
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Assert a value is boolean when defined.
|
|
70
|
+
* @param value Value to check.
|
|
71
|
+
* @param path Validation path.
|
|
72
|
+
* @return Nothing.
|
|
73
|
+
*/
|
|
74
|
+
export function assertBoolean(value, path) {
|
|
75
|
+
if (value === undefined || value === null)
|
|
76
|
+
return;
|
|
77
|
+
if (!isBooleanValue(value))
|
|
78
|
+
fail(path, "must be a boolean");
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Assert a value is an integer when defined.
|
|
82
|
+
* @param value Value to check.
|
|
83
|
+
* @param path Validation path.
|
|
84
|
+
* @return Nothing.
|
|
85
|
+
*/
|
|
86
|
+
export function assertInteger(value, path) {
|
|
87
|
+
if (value === undefined || value === null)
|
|
88
|
+
return;
|
|
89
|
+
if (!isNumberValue(value) || !Number.isInteger(value))
|
|
90
|
+
fail(path, "must be an integer");
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Assert a value is a non-negative integer when defined.
|
|
94
|
+
* @param value Value to check.
|
|
95
|
+
* @param path Validation path.
|
|
96
|
+
* @return Nothing.
|
|
97
|
+
*/
|
|
98
|
+
export function assertUnsignedInt(value, path) {
|
|
99
|
+
if (value === undefined || value === null)
|
|
100
|
+
return;
|
|
101
|
+
if (!isNumberValue(value) || !Number.isInteger(value) || value < 0) {
|
|
102
|
+
fail(path, "must be a non-negative integer");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Assert a date-time string matches the expected format.
|
|
107
|
+
* @param value Date-time string.
|
|
108
|
+
* @param path Validation path.
|
|
109
|
+
* @param requireZ Whether a Z suffix is required.
|
|
110
|
+
* @return Nothing.
|
|
111
|
+
*/
|
|
112
|
+
export function assertDateTime(value, path, requireZ) {
|
|
113
|
+
if (value === undefined)
|
|
114
|
+
return;
|
|
115
|
+
if (!isStringValue(value))
|
|
116
|
+
fail(path, "must be a date-time string");
|
|
117
|
+
const match = value.match(DATE_TIME);
|
|
118
|
+
if (!match) {
|
|
119
|
+
fail(path, requireZ ? "must be a UTCDateTime (YYYY-MM-DDTHH:mm:ssZ)" : "must be a LocalDateTime (YYYY-MM-DDTHH:mm:ss)");
|
|
120
|
+
}
|
|
121
|
+
const [, year, month, day, hour, minute, second, fraction, zFlag] = match;
|
|
122
|
+
if (requireZ && zFlag !== Z_SUFFIX)
|
|
123
|
+
fail(path, "must use Z suffix");
|
|
124
|
+
if (!requireZ && zFlag)
|
|
125
|
+
fail(path, "must not include time zone offset");
|
|
126
|
+
const monthNum = Number.parseInt(month ?? "0", 10);
|
|
127
|
+
const dayNum = Number.parseInt(day ?? "0", 10);
|
|
128
|
+
const hourNum = Number.parseInt(hour ?? "0", 10);
|
|
129
|
+
const minuteNum = Number.parseInt(minute ?? "0", 10);
|
|
130
|
+
const secondNum = Number.parseInt(second ?? "0", 10);
|
|
131
|
+
if (monthNum < 1 || monthNum > 12)
|
|
132
|
+
fail(path, "month must be 01-12");
|
|
133
|
+
if (dayNum < 1 || dayNum > 31)
|
|
134
|
+
fail(path, "day must be 01-31");
|
|
135
|
+
if (hourNum < 0 || hourNum > 23)
|
|
136
|
+
fail(path, "hour must be 00-23");
|
|
137
|
+
if (minuteNum < 0 || minuteNum > 59)
|
|
138
|
+
fail(path, "minute must be 00-59");
|
|
139
|
+
if (secondNum < 0 || secondNum > 59)
|
|
140
|
+
fail(path, "second must be 00-59");
|
|
141
|
+
if (fraction !== undefined) {
|
|
142
|
+
if (fraction.length > 9)
|
|
143
|
+
fail(path, "fractional seconds must be 1-9 digits");
|
|
144
|
+
if (/^0+$/.test(fraction))
|
|
145
|
+
fail(path, "fractional seconds must be non-zero");
|
|
146
|
+
if (fraction.endsWith("0"))
|
|
147
|
+
fail(path, "fractional seconds must not have trailing zeros");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Assert local date time when provided.
|
|
152
|
+
* @param value LocalDateTime string.
|
|
153
|
+
* @param path Validation path.
|
|
154
|
+
* @return Nothing.
|
|
155
|
+
*/
|
|
156
|
+
export function assertLocalDateTime(value, path) {
|
|
157
|
+
return assertDateTime(value, path, false);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Assert utc date time when provided.
|
|
161
|
+
* @param value UTCDateTime string.
|
|
162
|
+
* @param path Validation path.
|
|
163
|
+
* @return Nothing.
|
|
164
|
+
*/
|
|
165
|
+
export function assertUtcDateTime(value, path) {
|
|
166
|
+
return assertDateTime(value, path, true);
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Assert duration like when provided.
|
|
170
|
+
* @param value Duration string.
|
|
171
|
+
* @param path Validation path.
|
|
172
|
+
* @param signed Whether negative values are allowed.
|
|
173
|
+
* @return Nothing.
|
|
174
|
+
*/
|
|
175
|
+
export function assertDurationLike(value, path, signed) {
|
|
176
|
+
if (value === undefined)
|
|
177
|
+
return;
|
|
178
|
+
if (!isStringValue(value))
|
|
179
|
+
fail(path, "must be a duration string");
|
|
180
|
+
if (!signed && value.startsWith("-"))
|
|
181
|
+
fail(path, "must not be negative");
|
|
182
|
+
const match = value.match(DURATION);
|
|
183
|
+
if (!match)
|
|
184
|
+
fail(path, "must be an ISO 8601 duration");
|
|
185
|
+
const week = match[1];
|
|
186
|
+
const dayFromWeek = match[2];
|
|
187
|
+
const day = match[3];
|
|
188
|
+
const hour = match[4];
|
|
189
|
+
const minute = match[5];
|
|
190
|
+
const second = match[6];
|
|
191
|
+
const fraction = match[7];
|
|
192
|
+
const hasDate = !!week || !!dayFromWeek || !!day;
|
|
193
|
+
const hasTime = !!hour || !!minute || !!second;
|
|
194
|
+
if (!hasDate && !hasTime)
|
|
195
|
+
fail(path, "must include at least one duration component");
|
|
196
|
+
if (fraction !== undefined) {
|
|
197
|
+
if (fraction.length > 9)
|
|
198
|
+
fail(path, "fractional seconds must be 1-9 digits");
|
|
199
|
+
if (/^0+$/.test(fraction))
|
|
200
|
+
fail(path, "fractional seconds must be non-zero");
|
|
201
|
+
if (fraction.endsWith("0"))
|
|
202
|
+
fail(path, "fractional seconds must not have trailing zeros");
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Assert duration when provided.
|
|
207
|
+
* @param value Duration string.
|
|
208
|
+
* @param path Validation path.
|
|
209
|
+
* @return Nothing.
|
|
210
|
+
*/
|
|
211
|
+
export function assertDuration(value, path) {
|
|
212
|
+
return assertDurationLike(value, path, false);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Assert signed duration when provided.
|
|
216
|
+
* @param value Duration string.
|
|
217
|
+
* @param path Validation path.
|
|
218
|
+
* @return Nothing.
|
|
219
|
+
*/
|
|
220
|
+
export function assertSignedDuration(value, path) {
|
|
221
|
+
return assertDurationLike(value, path, true);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Assert boolean map when provided.
|
|
225
|
+
* @param value Boolean map object.
|
|
226
|
+
* @param path Validation path.
|
|
227
|
+
* @return Nothing.
|
|
228
|
+
*/
|
|
229
|
+
export function assertBooleanMap(value, path) {
|
|
230
|
+
if (value === undefined)
|
|
231
|
+
return;
|
|
232
|
+
if (!isRecord(value))
|
|
233
|
+
fail(path, "must be a boolean map object");
|
|
234
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
235
|
+
if (entry !== true)
|
|
236
|
+
fail(`${path}.${key}`, "must be true");
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Assert ID boolean map when provided.
|
|
241
|
+
* @param value Boolean map object keyed by Ids.
|
|
242
|
+
* @param path Validation path.
|
|
243
|
+
* @return Nothing.
|
|
244
|
+
*/
|
|
245
|
+
export function assertIdBooleanMap(value, path) {
|
|
246
|
+
if (value === undefined)
|
|
247
|
+
return;
|
|
248
|
+
if (!isRecord(value))
|
|
249
|
+
fail(path, "must be a boolean map object");
|
|
250
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
251
|
+
assertId(key, `${path}.${key}`);
|
|
252
|
+
if (entry !== true)
|
|
253
|
+
fail(`${path}.${key}`, "must be true");
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Assert media type when provided.
|
|
258
|
+
* @param value Media type string.
|
|
259
|
+
* @param path Validation path.
|
|
260
|
+
* @return Nothing.
|
|
261
|
+
*/
|
|
262
|
+
export function assertMediaType(value, path) {
|
|
263
|
+
if (value === undefined)
|
|
264
|
+
return;
|
|
265
|
+
if (!isStringValue(value))
|
|
266
|
+
fail(path, "must be a media type string");
|
|
267
|
+
const [typePart, ...params] = value.split(";");
|
|
268
|
+
const mediaType = (typePart ?? "").trim();
|
|
269
|
+
if (!/^[a-zA-Z0-9!#$&^_.+-]+\/[a-zA-Z0-9!#$&^_.+-]+$/.test(mediaType)) {
|
|
270
|
+
fail(path, "must be a valid media type");
|
|
271
|
+
}
|
|
272
|
+
for (const param of params) {
|
|
273
|
+
const [rawKey, rawValue] = param.split("=");
|
|
274
|
+
if (!rawKey || !rawValue)
|
|
275
|
+
continue;
|
|
276
|
+
const key = rawKey.trim().toLowerCase();
|
|
277
|
+
const valuePart = rawValue.trim().toLowerCase();
|
|
278
|
+
if (key === CHARSET_KEY && valuePart !== UTF8) {
|
|
279
|
+
fail(path, "charset parameter must be utf-8");
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Assert text content type when provided.
|
|
285
|
+
* @param value Media type string.
|
|
286
|
+
* @param path Validation path.
|
|
287
|
+
* @return Nothing.
|
|
288
|
+
*/
|
|
289
|
+
export function assertTextContentType(value, path) {
|
|
290
|
+
if (value === undefined)
|
|
291
|
+
return;
|
|
292
|
+
if (!isStringValue(value))
|
|
293
|
+
fail(path, "must be a media type string");
|
|
294
|
+
const [typePart] = value.split(";");
|
|
295
|
+
const mediaType = (typePart ?? "").trim();
|
|
296
|
+
if (!mediaType.startsWith("text/"))
|
|
297
|
+
fail(path, "must be a text/* media type");
|
|
298
|
+
assertMediaType(value, path);
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Assert content ID when provided.
|
|
302
|
+
* @param value Content-ID string.
|
|
303
|
+
* @param path Validation path.
|
|
304
|
+
* @return Nothing.
|
|
305
|
+
*/
|
|
306
|
+
export function assertContentId(value, path) {
|
|
307
|
+
if (value === undefined)
|
|
308
|
+
return;
|
|
309
|
+
if (!isStringValue(value))
|
|
310
|
+
fail(path, "must be a content-id");
|
|
311
|
+
const trimmed = value.trim();
|
|
312
|
+
const hasBrackets = trimmed.startsWith("<") || trimmed.endsWith(">");
|
|
313
|
+
if (hasBrackets && !(trimmed.startsWith("<") && trimmed.endsWith(">"))) {
|
|
314
|
+
fail(path, "must use matching angle brackets");
|
|
315
|
+
}
|
|
316
|
+
const raw = hasBrackets ? trimmed.slice(1, -1) : trimmed;
|
|
317
|
+
if (!/^[^\s<>@]+@[^\s<>@]+$/.test(raw)) {
|
|
318
|
+
fail(path, "must be a content-id");
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Assert time zone when provided.
|
|
323
|
+
* @param value Time zone ID.
|
|
324
|
+
* @param path Validation path.
|
|
325
|
+
* @return Nothing.
|
|
326
|
+
*/
|
|
327
|
+
export function assertTimeZone(value, path) {
|
|
328
|
+
if (value === undefined || value === null)
|
|
329
|
+
return;
|
|
330
|
+
if (!isStringValue(value))
|
|
331
|
+
fail(path, "must be a time zone ID");
|
|
332
|
+
for (const tz of TimeZones) {
|
|
333
|
+
if (tz === value)
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
fail(path, "must be a supported time zone ID");
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Assert json value when provided.
|
|
340
|
+
* @param value JSON value.
|
|
341
|
+
* @param path Validation path.
|
|
342
|
+
* @return Nothing.
|
|
343
|
+
*/
|
|
344
|
+
export function assertJsonValue(value, path) {
|
|
345
|
+
if (value === undefined)
|
|
346
|
+
fail(path, "must be a JSON value");
|
|
347
|
+
if (value === null)
|
|
348
|
+
return;
|
|
349
|
+
if (isStringValue(value) || isNumberValue(value) || isBooleanValue(value))
|
|
350
|
+
return;
|
|
351
|
+
if (Array.isArray(value)) {
|
|
352
|
+
value.forEach((entry, index) => assertJsonValue(entry, `${path}[${index}]`));
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
if (isObjectValue(value)) {
|
|
356
|
+
if (!isRecord(value))
|
|
357
|
+
fail(path, "must be a JSON object");
|
|
358
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
359
|
+
assertJsonValue(entry, `${path}.${key}`);
|
|
360
|
+
}
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
fail(path, "must be a JSON value");
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Assert patch object when provided.
|
|
367
|
+
* @param value PatchObject.
|
|
368
|
+
* @param path Validation path.
|
|
369
|
+
* @return Nothing.
|
|
370
|
+
*/
|
|
371
|
+
export function assertPatchObject(value, path) {
|
|
372
|
+
if (value === undefined)
|
|
373
|
+
return;
|
|
374
|
+
if (!isRecord(value))
|
|
375
|
+
fail(path, "must be a PatchObject");
|
|
376
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
377
|
+
if (entry === null)
|
|
378
|
+
continue;
|
|
379
|
+
assertJsonValue(entry, `${path}.${key}`);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export declare const Z_SUFFIX = "Z";
|
|
2
|
+
export declare const CHARSET_KEY = "charset";
|
|
3
|
+
export declare const UTF8 = "utf-8";
|
|
4
|
+
export declare const RSCALE_GREGORIAN = "gregorian";
|
|
5
|
+
export declare const TYPE_NDAY = "NDay";
|
|
6
|
+
export declare const TYPE_RECURRENCE_RULE = "RecurrenceRule";
|
|
7
|
+
export declare const TYPE_ALERT = "Alert";
|
|
8
|
+
export declare const TYPE_OFFSET_TRIGGER = "OffsetTrigger";
|
|
9
|
+
export declare const TYPE_ABSOLUTE_TRIGGER = "AbsoluteTrigger";
|
|
10
|
+
export declare const TYPE_RELATION = "Relation";
|
|
11
|
+
export declare const TYPE_LINK = "Link";
|
|
12
|
+
export declare const TYPE_LOCATION = "Location";
|
|
13
|
+
export declare const TYPE_VIRTUAL_LOCATION = "VirtualLocation";
|
|
14
|
+
export declare const TYPE_TIME_ZONE_RULE = "TimeZoneRule";
|
|
15
|
+
export declare const TYPE_TIME_ZONE = "TimeZone";
|
|
16
|
+
export declare const TYPE_PARTICIPANT = "Participant";
|
|
17
|
+
export declare const TYPE_EVENT = "Event";
|
|
18
|
+
export declare const TYPE_TASK = "Task";
|
|
19
|
+
export declare const TYPE_GROUP = "Group";
|
|
20
|
+
export declare const DATE_TIME: RegExp;
|
|
21
|
+
export declare const DURATION: RegExp;
|
|
22
|
+
export declare const DAY_OF_WEEK: Set<string>;
|
|
23
|
+
export declare const RECURRENCE_FREQUENCY: Set<string>;
|
|
24
|
+
export declare const SKIP: Set<string>;
|
|
25
|
+
export declare const ID_PATTERN: RegExp;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const Z_SUFFIX = "Z";
|
|
2
|
+
export const CHARSET_KEY = "charset";
|
|
3
|
+
export const UTF8 = "utf-8";
|
|
4
|
+
export const RSCALE_GREGORIAN = "gregorian";
|
|
5
|
+
export const TYPE_NDAY = "NDay";
|
|
6
|
+
export const TYPE_RECURRENCE_RULE = "RecurrenceRule";
|
|
7
|
+
export const TYPE_ALERT = "Alert";
|
|
8
|
+
export const TYPE_OFFSET_TRIGGER = "OffsetTrigger";
|
|
9
|
+
export const TYPE_ABSOLUTE_TRIGGER = "AbsoluteTrigger";
|
|
10
|
+
export const TYPE_RELATION = "Relation";
|
|
11
|
+
export const TYPE_LINK = "Link";
|
|
12
|
+
export const TYPE_LOCATION = "Location";
|
|
13
|
+
export const TYPE_VIRTUAL_LOCATION = "VirtualLocation";
|
|
14
|
+
export const TYPE_TIME_ZONE_RULE = "TimeZoneRule";
|
|
15
|
+
export const TYPE_TIME_ZONE = "TimeZone";
|
|
16
|
+
export const TYPE_PARTICIPANT = "Participant";
|
|
17
|
+
export const TYPE_EVENT = "Event";
|
|
18
|
+
export const TYPE_TASK = "Task";
|
|
19
|
+
export const TYPE_GROUP = "Group";
|
|
20
|
+
export const DATE_TIME = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?(Z)?$/;
|
|
21
|
+
export const DURATION = /^-?P(?:(\d+)W(?:(\d+)D)?|(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)(?:\.(\d+))?S)?)?$/;
|
|
22
|
+
export const DAY_OF_WEEK = new Set(["mo", "tu", "we", "th", "fr", "sa", "su"]);
|
|
23
|
+
export const RECURRENCE_FREQUENCY = new Set([
|
|
24
|
+
"yearly",
|
|
25
|
+
"monthly",
|
|
26
|
+
"weekly",
|
|
27
|
+
"daily",
|
|
28
|
+
"hourly",
|
|
29
|
+
"minutely",
|
|
30
|
+
"secondly",
|
|
31
|
+
]);
|
|
32
|
+
export const SKIP = new Set(["omit", "backward", "forward"]);
|
|
33
|
+
export const ID_PATTERN = /^[A-Za-z0-9_-]+$/;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error thrown when validation fails.
|
|
3
|
+
*/
|
|
4
|
+
export declare class ValidationError extends Error {
|
|
5
|
+
path: string;
|
|
6
|
+
/**
|
|
7
|
+
* Create a new ValidationError.
|
|
8
|
+
* @param path Validation path.
|
|
9
|
+
* @param message Error message.
|
|
10
|
+
*/
|
|
11
|
+
constructor(path: string, message: string);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Throw a ValidationError.
|
|
15
|
+
* @param path Validation path.
|
|
16
|
+
* @param message Error message.
|
|
17
|
+
* @return Never returns.
|
|
18
|
+
*/
|
|
19
|
+
export declare function fail(path: string, message: string): never;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error thrown when validation fails.
|
|
3
|
+
*/
|
|
4
|
+
export class ValidationError extends Error {
|
|
5
|
+
path;
|
|
6
|
+
/**
|
|
7
|
+
* Create a new ValidationError.
|
|
8
|
+
* @param path Validation path.
|
|
9
|
+
* @param message Error message.
|
|
10
|
+
*/
|
|
11
|
+
constructor(path, message) {
|
|
12
|
+
super(`${path}: ${message}`);
|
|
13
|
+
this.name = "ValidationError";
|
|
14
|
+
this.path = path;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Throw a ValidationError.
|
|
19
|
+
* @param path Validation path.
|
|
20
|
+
* @param message Error message.
|
|
21
|
+
* @return Never returns.
|
|
22
|
+
*/
|
|
23
|
+
export function fail(path, message) {
|
|
24
|
+
throw new ValidationError(path, message);
|
|
25
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Alert, JSCalendarObject, Link, Location, Participant, Relation, TimeZone, TimeZoneRule, VirtualLocation } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Validate alert structure.
|
|
4
|
+
* @param value Alert object to validate.
|
|
5
|
+
* @param path JSON pointer path for error messages.
|
|
6
|
+
* @return Nothing.
|
|
7
|
+
*/
|
|
8
|
+
export declare function validateAlert(value: Alert, path: string): void;
|
|
9
|
+
/**
|
|
10
|
+
* Validate relation structure.
|
|
11
|
+
* @param value Relation object to validate.
|
|
12
|
+
* @param path JSON pointer path for error messages.
|
|
13
|
+
* @return Nothing.
|
|
14
|
+
*/
|
|
15
|
+
export declare function validateRelation(value: Relation, path: string): void;
|
|
16
|
+
/**
|
|
17
|
+
* Validate link structure.
|
|
18
|
+
* @param value Link object to validate.
|
|
19
|
+
* @param path JSON pointer path for error messages.
|
|
20
|
+
* @return Nothing.
|
|
21
|
+
*/
|
|
22
|
+
export declare function validateLink(value: Link, path: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Validate location structure.
|
|
25
|
+
* @param value Location object to validate.
|
|
26
|
+
* @param path JSON pointer path for error messages.
|
|
27
|
+
* @return Nothing.
|
|
28
|
+
*/
|
|
29
|
+
export declare function validateLocation(value: Location, path: string): void;
|
|
30
|
+
/**
|
|
31
|
+
* Validate virtual location structure.
|
|
32
|
+
* @param value VirtualLocation object to validate.
|
|
33
|
+
* @param path JSON pointer path for error messages.
|
|
34
|
+
* @return Nothing.
|
|
35
|
+
*/
|
|
36
|
+
export declare function validateVirtualLocation(value: VirtualLocation, path: string): void;
|
|
37
|
+
/**
|
|
38
|
+
* Validate time zone rule structure.
|
|
39
|
+
* @param value TimeZoneRule object to validate.
|
|
40
|
+
* @param path JSON pointer path for error messages.
|
|
41
|
+
* @return Nothing.
|
|
42
|
+
*/
|
|
43
|
+
export declare function validateTimeZoneRule(value: TimeZoneRule, path: string): void;
|
|
44
|
+
/**
|
|
45
|
+
* Validate time zone object structure.
|
|
46
|
+
* @param value TimeZone object to validate.
|
|
47
|
+
* @param path JSON pointer path for error messages.
|
|
48
|
+
* @return Nothing.
|
|
49
|
+
*/
|
|
50
|
+
export declare function validateTimeZoneObject(value: TimeZone, path: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Validate participant structure.
|
|
53
|
+
* @param value Participant object to validate.
|
|
54
|
+
* @param path JSON pointer path for error messages.
|
|
55
|
+
* @return Nothing.
|
|
56
|
+
*/
|
|
57
|
+
export declare function validateParticipant(value: Participant, path: string): void;
|
|
58
|
+
/**
|
|
59
|
+
* Validate common structure.
|
|
60
|
+
* @param value JSCalendar object to validate.
|
|
61
|
+
* @param path JSON pointer path for error messages.
|
|
62
|
+
* @return Nothing.
|
|
63
|
+
*/
|
|
64
|
+
export declare function validateCommon(value: JSCalendarObject, path: string): void;
|