rrule-ts 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 ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CodeWithAgents
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,50 @@
1
+ # rrule-ts
2
+
3
+ [![npm](https://img.shields.io/npm/v/rrule-ts.svg)](https://npmjs.com/package/rrule-ts)
4
+ [![CI](https://github.com/codewithagents/rrule/actions/workflows/ci.yml/badge.svg)](https://github.com/codewithagents/rrule/actions/workflows/ci.yml)
5
+
6
+ **RFC 5545 RRULE parser, validator, stringifier, and expander. Temporal-native, zero runtime dependencies.**
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install rrule-ts
12
+ ```
13
+
14
+ On Node.js < 26, inject a Temporal polyfill before using date-expansion features:
15
+
16
+ ```ts
17
+ import { setTemporal } from 'rrule-ts'
18
+ import { Temporal } from 'temporal-polyfill'
19
+ setTemporal(Temporal)
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```ts
25
+ import { parse, validate, stringify } from 'rrule-ts'
26
+
27
+ const result = parse('RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR;COUNT=10')
28
+ if (!result.ok) throw new Error(result.error)
29
+
30
+ const validated = validate(result.value)
31
+ if (!validated.ok) {
32
+ for (const e of validated.error) console.error(e.message)
33
+ }
34
+
35
+ console.log(stringify(result.value))
36
+ // RRULE:FREQ=WEEKLY;COUNT=10;BYDAY=MO,WE,FR
37
+ ```
38
+
39
+ ## Subpath exports
40
+
41
+ | Import | What you get |
42
+ |---|---|
43
+ | `rrule-ts` | parse, validate, stringify, getTemporal, setTemporal, Result helpers |
44
+ | `rrule-ts/text` | toText, fromText (human-readable; planned) |
45
+ | `rrule-ts/locales/en` | English locale pack (planned) |
46
+ | `rrule-ts/locales/de` | German locale pack (planned) |
47
+
48
+ ## License
49
+
50
+ MIT
@@ -0,0 +1,31 @@
1
+ export { parse } from './parse.js';
2
+ export { stringify } from './stringify.js';
3
+ export { validate } from './validate.js';
4
+ export { getTemporal, setTemporal } from './temporal.js';
5
+ export { ok, err } from './result.js';
6
+ export type { Ok, Err, Result } from './result.js';
7
+ export type { Frequency, Weekday, WeekdayNum, RRuleOptions, RRuleDtstart, RRuleUntil, ValidationError, } from './types.js';
8
+ /**
9
+ * Expand an RRULE into a bounded list of occurrence instants.
10
+ *
11
+ * @stub Not yet implemented. Throws at runtime.
12
+ * TODO(expansion-phase): implement RRULE occurrence expansion.
13
+ */
14
+ export declare function expand(_options: import('./types.js').RRuleOptions, _limit?: number): never;
15
+ /**
16
+ * Iterate over RRULE occurrences lazily.
17
+ *
18
+ * @stub Not yet implemented. Throws at runtime.
19
+ * TODO(expansion-phase): implement RRULE async iterator.
20
+ */
21
+ export declare function iterate(_options: import('./types.js').RRuleOptions): never;
22
+ /**
23
+ * Combine multiple RRULEs, EXRULEs, RDATEs, and EXDATEs.
24
+ *
25
+ * @stub Not yet implemented. Throws at construction time.
26
+ * TODO(expansion-phase): implement RRuleSet.
27
+ */
28
+ export declare class RRuleSet {
29
+ constructor();
30
+ }
31
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AACxD,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AACrC,YAAY,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAClD,YAAY,EACV,SAAS,EACT,OAAO,EACP,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,eAAe,GAChB,MAAM,YAAY,CAAA;AAOnB;;;;;GAKG;AAEH,wBAAgB,MAAM,CAAC,QAAQ,EAAE,OAAO,YAAY,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAE1F;AAED;;;;;GAKG;AAEH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,OAAO,YAAY,EAAE,YAAY,GAAG,KAAK,CAE1E;AAED;;;;;GAKG;AAEH,qBAAa,QAAQ;;CAIpB"}
package/dist/index.js ADDED
@@ -0,0 +1,52 @@
1
+ // Public API surface for the rrule-ts core subpath (import 'rrule-ts').
2
+ //
3
+ // This phase implements: parse, stringify, validate, Temporal accessor, and
4
+ // the Result type helpers.
5
+ //
6
+ // expand(), iterate(), and RRuleSet are stubs that throw 'not implemented'.
7
+ // They are excluded from coverage thresholds (see vitest.config.ts include list
8
+ // and the /* v8 ignore */ annotations below) so thresholds reflect only the
9
+ // code that is genuinely exercised in this phase.
10
+ // TODO(expansion-phase): remove stubs and wire the real implementations.
11
+ export { parse } from './parse.js';
12
+ export { stringify } from './stringify.js';
13
+ export { validate } from './validate.js';
14
+ export { getTemporal, setTemporal } from './temporal.js';
15
+ export { ok, err } from './result.js';
16
+ // ---------------------------------------------------------------------------
17
+ // Stubs for the expansion phase
18
+ // TODO(expansion-phase): implement these in a follow-up PR.
19
+ // ---------------------------------------------------------------------------
20
+ /**
21
+ * Expand an RRULE into a bounded list of occurrence instants.
22
+ *
23
+ * @stub Not yet implemented. Throws at runtime.
24
+ * TODO(expansion-phase): implement RRULE occurrence expansion.
25
+ */
26
+ // v8 ignore next 3
27
+ export function expand(_options, _limit) {
28
+ throw new Error('not implemented: expand (coming in expansion phase)');
29
+ }
30
+ /**
31
+ * Iterate over RRULE occurrences lazily.
32
+ *
33
+ * @stub Not yet implemented. Throws at runtime.
34
+ * TODO(expansion-phase): implement RRULE async iterator.
35
+ */
36
+ // v8 ignore next 3
37
+ export function iterate(_options) {
38
+ throw new Error('not implemented: iterate (coming in expansion phase)');
39
+ }
40
+ /**
41
+ * Combine multiple RRULEs, EXRULEs, RDATEs, and EXDATEs.
42
+ *
43
+ * @stub Not yet implemented. Throws at construction time.
44
+ * TODO(expansion-phase): implement RRuleSet.
45
+ */
46
+ // v8 ignore next 3
47
+ export class RRuleSet {
48
+ constructor() {
49
+ throw new Error('not implemented: RRuleSet (coming in expansion phase)');
50
+ }
51
+ }
52
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,EAAE;AACF,4EAA4E;AAC5E,2BAA2B;AAC3B,EAAE;AACF,4EAA4E;AAC5E,gFAAgF;AAChF,4EAA4E;AAC5E,kDAAkD;AAClD,yEAAyE;AAEzE,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AACxD,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAYrC,8EAA8E;AAC9E,gCAAgC;AAChC,4DAA4D;AAC5D,8EAA8E;AAE9E;;;;;GAKG;AACH,mBAAmB;AACnB,MAAM,UAAU,MAAM,CAAC,QAA2C,EAAE,MAAe;IACjF,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAA;AACxE,CAAC;AAED;;;;;GAKG;AACH,mBAAmB;AACnB,MAAM,UAAU,OAAO,CAAC,QAA2C;IACjE,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAA;AACzE,CAAC;AAED;;;;;GAKG;AACH,mBAAmB;AACnB,MAAM,OAAO,QAAQ;IACnB;QACE,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAA;IAC1E,CAAC;CACF"}
@@ -0,0 +1,10 @@
1
+ import type { LocalePack } from './en.js';
2
+ export type { LocalePack };
3
+ /**
4
+ * German locale pack.
5
+ *
6
+ * @stub Partial data. The full locale will be populated in the expansion phase.
7
+ * TODO(expansion-phase): fill all strings and wire into toText.
8
+ */
9
+ export declare const de: LocalePack;
10
+ //# sourceMappingURL=de.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"de.d.ts","sourceRoot":"","sources":["../../src/locales/de.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzC,YAAY,EAAE,UAAU,EAAE,CAAA;AAE1B;;;;;GAKG;AACH,eAAO,MAAM,EAAE,EAAE,UA0BhB,CAAA"}
@@ -0,0 +1,38 @@
1
+ // German locale pack for rrule-ts/text (import 'rrule-ts/locales/de').
2
+ //
3
+ // Stub for the expansion phase.
4
+ // TODO(expansion-phase): provide full German locale strings for toText.
5
+ /**
6
+ * German locale pack.
7
+ *
8
+ * @stub Partial data. The full locale will be populated in the expansion phase.
9
+ * TODO(expansion-phase): fill all strings and wire into toText.
10
+ */
11
+ export const de = {
12
+ id: 'de',
13
+ weekdays: ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag'],
14
+ months: [
15
+ 'Januar',
16
+ 'Februar',
17
+ 'März',
18
+ 'April',
19
+ 'Mai',
20
+ 'Juni',
21
+ 'Juli',
22
+ 'August',
23
+ 'September',
24
+ 'Oktober',
25
+ 'November',
26
+ 'Dezember',
27
+ ],
28
+ frequencies: {
29
+ SECONDLY: 'jede Sekunde',
30
+ MINUTELY: 'jede Minute',
31
+ HOURLY: 'jede Stunde',
32
+ DAILY: 'täglich',
33
+ WEEKLY: 'wöchentlich',
34
+ MONTHLY: 'monatlich',
35
+ YEARLY: 'jährlich',
36
+ },
37
+ };
38
+ //# sourceMappingURL=de.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"de.js","sourceRoot":"","sources":["../../src/locales/de.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,EAAE;AACF,gCAAgC;AAChC,wEAAwE;AAMxE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,EAAE,GAAe;IAC5B,EAAE,EAAE,IAAI;IACR,QAAQ,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC;IAC3F,MAAM,EAAE;QACN,QAAQ;QACR,SAAS;QACT,MAAM;QACN,OAAO;QACP,KAAK;QACL,MAAM;QACN,MAAM;QACN,QAAQ;QACR,WAAW;QACX,SAAS;QACT,UAAU;QACV,UAAU;KACX;IACD,WAAW,EAAE;QACX,QAAQ,EAAE,cAAc;QACxB,QAAQ,EAAE,aAAa;QACvB,MAAM,EAAE,aAAa;QACrB,KAAK,EAAE,SAAS;QAChB,MAAM,EAAE,aAAa;QACrB,OAAO,EAAE,WAAW;QACpB,MAAM,EAAE,UAAU;KACnB;CACF,CAAA"}
@@ -0,0 +1,32 @@
1
+ /** Shape of a locale pack used by toText. */
2
+ export interface LocalePack {
3
+ /** Locale identifier. */
4
+ id: string;
5
+ /** Weekday names, indexed 0=Monday ... 6=Sunday. */
6
+ weekdays: [string, string, string, string, string, string, string];
7
+ /** Month names, indexed 0=January ... 11=December. */
8
+ months: [
9
+ string,
10
+ string,
11
+ string,
12
+ string,
13
+ string,
14
+ string,
15
+ string,
16
+ string,
17
+ string,
18
+ string,
19
+ string,
20
+ string
21
+ ];
22
+ /** Frequency labels. */
23
+ frequencies: Record<string, string>;
24
+ }
25
+ /**
26
+ * English locale pack.
27
+ *
28
+ * @stub Partial data. The full locale will be populated in the expansion phase.
29
+ * TODO(expansion-phase): fill all strings and wire into toText.
30
+ */
31
+ export declare const en: LocalePack;
32
+ //# sourceMappingURL=en.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/locales/en.ts"],"names":[],"mappings":"AAKA,6CAA6C;AAC7C,MAAM,WAAW,UAAU;IACzB,yBAAyB;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,oDAAoD;IACpD,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;IAClE,sDAAsD;IACtD,MAAM,EAAE;QACN,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;QACN,MAAM;KACP,CAAA;IACD,wBAAwB;IACxB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACpC;AAED;;;;;GAKG;AACH,eAAO,MAAM,EAAE,EAAE,UA0BhB,CAAA"}
@@ -0,0 +1,38 @@
1
+ // English locale pack for rrule-ts/text (import 'rrule-ts/locales/en').
2
+ //
3
+ // Stub for the expansion phase.
4
+ // TODO(expansion-phase): provide full English locale strings for toText.
5
+ /**
6
+ * English locale pack.
7
+ *
8
+ * @stub Partial data. The full locale will be populated in the expansion phase.
9
+ * TODO(expansion-phase): fill all strings and wire into toText.
10
+ */
11
+ export const en = {
12
+ id: 'en',
13
+ weekdays: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'],
14
+ months: [
15
+ 'January',
16
+ 'February',
17
+ 'March',
18
+ 'April',
19
+ 'May',
20
+ 'June',
21
+ 'July',
22
+ 'August',
23
+ 'September',
24
+ 'October',
25
+ 'November',
26
+ 'December',
27
+ ],
28
+ frequencies: {
29
+ SECONDLY: 'every second',
30
+ MINUTELY: 'every minute',
31
+ HOURLY: 'every hour',
32
+ DAILY: 'every day',
33
+ WEEKLY: 'every week',
34
+ MONTHLY: 'every month',
35
+ YEARLY: 'every year',
36
+ },
37
+ };
38
+ //# sourceMappingURL=en.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"en.js","sourceRoot":"","sources":["../../src/locales/en.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,EAAE;AACF,gCAAgC;AAChC,yEAAyE;AA2BzE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,EAAE,GAAe;IAC5B,EAAE,EAAE,IAAI;IACR,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,CAAC;IACxF,MAAM,EAAE;QACN,SAAS;QACT,UAAU;QACV,OAAO;QACP,OAAO;QACP,KAAK;QACL,MAAM;QACN,MAAM;QACN,QAAQ;QACR,WAAW;QACX,SAAS;QACT,UAAU;QACV,UAAU;KACX;IACD,WAAW,EAAE;QACX,QAAQ,EAAE,cAAc;QACxB,QAAQ,EAAE,cAAc;QACxB,MAAM,EAAE,YAAY;QACpB,KAAK,EAAE,WAAW;QAClB,MAAM,EAAE,YAAY;QACpB,OAAO,EAAE,aAAa;QACtB,MAAM,EAAE,YAAY;KACrB;CACF,CAAA"}
@@ -0,0 +1,18 @@
1
+ import type { RRuleOptions } from './types.js';
2
+ import type { Result } from './result.js';
3
+ /**
4
+ * Parse an RFC 5545 RRULE string into typed `RRuleOptions`.
5
+ *
6
+ * The input may be:
7
+ * - A bare RRULE value string: `FREQ=WEEKLY;BYDAY=MO`
8
+ * - With RRULE: prefix: `RRULE:FREQ=WEEKLY;BYDAY=MO`
9
+ * - Multiline with DTSTART:
10
+ * ```
11
+ * DTSTART:20240101T090000Z
12
+ * RRULE:FREQ=WEEKLY;BYDAY=MO
13
+ * ```
14
+ *
15
+ * Returns `{ ok: false, error }` on any parse failure; never throws.
16
+ */
17
+ export declare function parse(input: string): Result<RRuleOptions, string>;
18
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAGV,YAAY,EAIb,MAAM,YAAY,CAAA;AAEnB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAgIzC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CA2KjE"}
package/dist/parse.js ADDED
@@ -0,0 +1,316 @@
1
+ // RFC 5545 RRULE parser.
2
+ //
3
+ // Accepts:
4
+ // - A bare RRULE value: "FREQ=WEEKLY;BYDAY=MO,WE"
5
+ // - With RRULE: prefix: "RRULE:FREQ=WEEKLY;BYDAY=MO,WE"
6
+ // - With optional DTSTART lines:
7
+ // "DTSTART:20240101T090000Z\nRRULE:FREQ=WEEKLY"
8
+ // "DTSTART;TZID=America/New_York:20240101T090000\nRRULE:FREQ=WEEKLY"
9
+ //
10
+ // Returns a typed Result so callers never have to catch exceptions from user input.
11
+ import { getTemporal } from './temporal.js';
12
+ import { err, ok } from './result.js';
13
+ // ---------------------------------------------------------------------------
14
+ // iCalendar date/datetime string converters
15
+ // ---------------------------------------------------------------------------
16
+ /**
17
+ * Convert an iCalendar basic-format date string to an ISO 8601 extended string
18
+ * that Temporal parsers accept.
19
+ *
20
+ * Handles:
21
+ * YYYYMMDD -> YYYY-MM-DD
22
+ * YYYYMMDDTHHmmss -> YYYY-MM-DDTHH:mm:ss
23
+ * YYYYMMDDTHHmmssZ -> YYYY-MM-DDTHH:mm:ssZ
24
+ */
25
+ function icalToIso(value) {
26
+ const datePart = value.slice(0, 8);
27
+ const iso = `${datePart.slice(0, 4)}-${datePart.slice(4, 6)}-${datePart.slice(6, 8)}`;
28
+ if (value.length === 8)
29
+ return iso;
30
+ const tPos = value.indexOf('T');
31
+ if (tPos === -1)
32
+ return iso;
33
+ const timePart = value.slice(tPos + 1).replace('Z', '');
34
+ const hh = timePart.slice(0, 2);
35
+ const mm = timePart.slice(2, 4);
36
+ const ss = timePart.slice(4, 6);
37
+ const z = value.endsWith('Z') ? 'Z' : '';
38
+ return `${iso}T${hh}:${mm}:${ss}${z}`;
39
+ }
40
+ /** Parse a DTSTART value string (with optional TZID) into a typed Temporal value. */
41
+ function parseDtstart(value, tzid) {
42
+ const T = getTemporal();
43
+ const iso = icalToIso(value);
44
+ try {
45
+ if (tzid !== undefined) {
46
+ return ok(T.ZonedDateTime.from(`${iso}[${tzid}]`));
47
+ }
48
+ if (value.length === 8) {
49
+ return ok(T.PlainDate.from(iso));
50
+ }
51
+ if (value.endsWith('Z')) {
52
+ return ok(T.Instant.from(iso));
53
+ }
54
+ return ok(T.PlainDateTime.from(iso));
55
+ }
56
+ catch (e) {
57
+ return err(`invalid DTSTART value "${value}": ${String(e)}`);
58
+ }
59
+ }
60
+ /** Parse an UNTIL value string into a typed Temporal value. */
61
+ function parseUntil(value) {
62
+ const T = getTemporal();
63
+ const iso = icalToIso(value);
64
+ try {
65
+ if (value.length === 8) {
66
+ return ok(T.PlainDate.from(iso));
67
+ }
68
+ if (value.endsWith('Z')) {
69
+ return ok(T.Instant.from(iso));
70
+ }
71
+ return ok(T.PlainDateTime.from(iso));
72
+ }
73
+ catch (e) {
74
+ return err(`invalid UNTIL value "${value}": ${String(e)}`);
75
+ }
76
+ }
77
+ // ---------------------------------------------------------------------------
78
+ // RRULE part parsers
79
+ // ---------------------------------------------------------------------------
80
+ const VALID_FREQUENCIES = new Set([
81
+ 'SECONDLY',
82
+ 'MINUTELY',
83
+ 'HOURLY',
84
+ 'DAILY',
85
+ 'WEEKLY',
86
+ 'MONTHLY',
87
+ 'YEARLY',
88
+ ]);
89
+ const VALID_WEEKDAYS = new Set(['MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU']);
90
+ function parseFreq(value) {
91
+ if (VALID_FREQUENCIES.has(value))
92
+ return ok(value);
93
+ return err(`invalid FREQ value "${value}"`);
94
+ }
95
+ function parseWeekday(value) {
96
+ if (VALID_WEEKDAYS.has(value))
97
+ return ok(value);
98
+ return err(`invalid weekday "${value}"`);
99
+ }
100
+ /** Parse a BYDAY entry such as "MO", "3MO", or "-1FR". */
101
+ function parseWeekdayNum(raw) {
102
+ const upper = raw.toUpperCase();
103
+ // Weekday-only: MO, TU, etc.
104
+ if (VALID_WEEKDAYS.has(upper)) {
105
+ return ok({ ordinal: undefined, weekday: upper });
106
+ }
107
+ // Ordinal prefix: optional sign + digits + 2-char weekday
108
+ const match = /^([+-]?\d+)(MO|TU|WE|TH|FR|SA|SU)$/.exec(upper);
109
+ if (match) {
110
+ const ordinal = parseInt(match[1], 10);
111
+ if (ordinal === 0)
112
+ return err(`BYDAY ordinal must not be zero: "${raw}"`);
113
+ return ok({ ordinal, weekday: match[2] });
114
+ }
115
+ return err(`invalid BYDAY entry "${raw}"`);
116
+ }
117
+ function parseIntList(value, part) {
118
+ const items = value.split(',');
119
+ const nums = [];
120
+ for (const item of items) {
121
+ const n = Number(item);
122
+ if (!Number.isInteger(n) || String(n) !== item.trim()) {
123
+ return err(`${part} contains non-integer value "${item}"`);
124
+ }
125
+ nums.push(n);
126
+ }
127
+ return ok(nums);
128
+ }
129
+ // ---------------------------------------------------------------------------
130
+ // Main parser
131
+ // ---------------------------------------------------------------------------
132
+ /**
133
+ * Parse an RFC 5545 RRULE string into typed `RRuleOptions`.
134
+ *
135
+ * The input may be:
136
+ * - A bare RRULE value string: `FREQ=WEEKLY;BYDAY=MO`
137
+ * - With RRULE: prefix: `RRULE:FREQ=WEEKLY;BYDAY=MO`
138
+ * - Multiline with DTSTART:
139
+ * ```
140
+ * DTSTART:20240101T090000Z
141
+ * RRULE:FREQ=WEEKLY;BYDAY=MO
142
+ * ```
143
+ *
144
+ * Returns `{ ok: false, error }` on any parse failure; never throws.
145
+ */
146
+ export function parse(input) {
147
+ const lines = input.trim().split(/\r?\n/);
148
+ let rruleValue;
149
+ let dtstartRaw;
150
+ let tzid;
151
+ for (const rawLine of lines) {
152
+ const line = rawLine.trim();
153
+ if (line === '')
154
+ continue;
155
+ if (line.startsWith('DTSTART;TZID=')) {
156
+ const colonIdx = line.indexOf(':');
157
+ if (colonIdx === -1)
158
+ return err(`invalid DTSTART line: "${line}"`);
159
+ tzid = line.slice('DTSTART;TZID='.length, colonIdx);
160
+ dtstartRaw = line.slice(colonIdx + 1);
161
+ }
162
+ else if (line.startsWith('DTSTART:')) {
163
+ dtstartRaw = line.slice('DTSTART:'.length);
164
+ }
165
+ else if (line.startsWith('RRULE:')) {
166
+ rruleValue = line.slice('RRULE:'.length);
167
+ }
168
+ else if (line.includes(';') || line.startsWith('FREQ=')) {
169
+ // Bare RRULE value without the "RRULE:" prefix
170
+ rruleValue = line;
171
+ }
172
+ else {
173
+ return err(`unknown or unsupported content line: "${line}"`);
174
+ }
175
+ }
176
+ if (rruleValue === undefined) {
177
+ return err('no RRULE found in input');
178
+ }
179
+ // Parse individual RRULE parts
180
+ const parts = rruleValue.split(';');
181
+ const options = {};
182
+ const seenKeys = new Set();
183
+ for (const part of parts) {
184
+ if (part.trim() === '')
185
+ continue;
186
+ const eqIdx = part.indexOf('=');
187
+ if (eqIdx === -1)
188
+ return err(`invalid RRULE part (missing "="): "${part}"`);
189
+ const key = part.slice(0, eqIdx).toUpperCase();
190
+ const value = part.slice(eqIdx + 1);
191
+ if (seenKeys.has(key))
192
+ return err(`duplicate RRULE part: "${key}"`);
193
+ seenKeys.add(key);
194
+ switch (key) {
195
+ case 'FREQ': {
196
+ const r = parseFreq(value);
197
+ if (!r.ok)
198
+ return err(r.error);
199
+ options.freq = r.value;
200
+ break;
201
+ }
202
+ case 'INTERVAL': {
203
+ const n = parseInt(value, 10);
204
+ if (isNaN(n) || String(n) !== value)
205
+ return err(`invalid INTERVAL value: "${value}"`);
206
+ options.interval = n;
207
+ break;
208
+ }
209
+ case 'COUNT': {
210
+ const n = parseInt(value, 10);
211
+ if (isNaN(n) || String(n) !== value)
212
+ return err(`invalid COUNT value: "${value}"`);
213
+ options.count = n;
214
+ break;
215
+ }
216
+ case 'UNTIL': {
217
+ const r = parseUntil(value);
218
+ if (!r.ok)
219
+ return err(r.error);
220
+ options.until = r.value;
221
+ break;
222
+ }
223
+ case 'WKST': {
224
+ const r = parseWeekday(value);
225
+ if (!r.ok)
226
+ return err(`invalid WKST value: ${r.error}`);
227
+ options.wkst = r.value;
228
+ break;
229
+ }
230
+ case 'BYDAY': {
231
+ const entries = value.split(',');
232
+ const days = [];
233
+ for (const entry of entries) {
234
+ const r = parseWeekdayNum(entry);
235
+ if (!r.ok)
236
+ return err(r.error);
237
+ days.push(r.value);
238
+ }
239
+ options.byDay = days;
240
+ break;
241
+ }
242
+ case 'BYMONTH': {
243
+ const r = parseIntList(value, 'BYMONTH');
244
+ if (!r.ok)
245
+ return err(r.error);
246
+ options.byMonth = r.value;
247
+ break;
248
+ }
249
+ case 'BYMONTHDAY': {
250
+ const r = parseIntList(value, 'BYMONTHDAY');
251
+ if (!r.ok)
252
+ return err(r.error);
253
+ options.byMonthDay = r.value;
254
+ break;
255
+ }
256
+ case 'BYYEARDAY': {
257
+ const r = parseIntList(value, 'BYYEARDAY');
258
+ if (!r.ok)
259
+ return err(r.error);
260
+ options.byYearDay = r.value;
261
+ break;
262
+ }
263
+ case 'BYWEEKNO': {
264
+ const r = parseIntList(value, 'BYWEEKNO');
265
+ if (!r.ok)
266
+ return err(r.error);
267
+ options.byWeekNo = r.value;
268
+ break;
269
+ }
270
+ case 'BYHOUR': {
271
+ const r = parseIntList(value, 'BYHOUR');
272
+ if (!r.ok)
273
+ return err(r.error);
274
+ options.byHour = r.value;
275
+ break;
276
+ }
277
+ case 'BYMINUTE': {
278
+ const r = parseIntList(value, 'BYMINUTE');
279
+ if (!r.ok)
280
+ return err(r.error);
281
+ options.byMinute = r.value;
282
+ break;
283
+ }
284
+ case 'BYSECOND': {
285
+ const r = parseIntList(value, 'BYSECOND');
286
+ if (!r.ok)
287
+ return err(r.error);
288
+ options.bySecond = r.value;
289
+ break;
290
+ }
291
+ case 'BYSETPOS': {
292
+ const r = parseIntList(value, 'BYSETPOS');
293
+ if (!r.ok)
294
+ return err(r.error);
295
+ options.bySetPos = r.value;
296
+ break;
297
+ }
298
+ default:
299
+ return err(`unknown RRULE part: "${key}"`);
300
+ }
301
+ }
302
+ if (options.freq === undefined) {
303
+ return err('RRULE must contain FREQ');
304
+ }
305
+ // Parse DTSTART if present
306
+ if (dtstartRaw !== undefined) {
307
+ const r = parseDtstart(dtstartRaw, tzid);
308
+ if (!r.ok)
309
+ return err(r.error);
310
+ options.dtstart = r.value;
311
+ if (tzid !== undefined)
312
+ options.tzid = tzid;
313
+ }
314
+ return ok(options);
315
+ }
316
+ //# sourceMappingURL=parse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"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"}