@cocoar/vue-calendar 1.18.0 → 2.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/dist/builders/calendar-builder.d.ts +179 -2
- package/dist/builders/calendar-builder.d.ts.map +1 -1
- package/dist/builders/types.d.ts +41 -0
- package/dist/builders/types.d.ts.map +1 -1
- package/dist/components/CoarAgendaView.vue.d.ts.map +1 -1
- package/dist/components/CoarCalendar.vue.d.ts.map +1 -1
- package/dist/components/CoarMonthView.vue.d.ts.map +1 -1
- package/dist/components/CoarTimeGrid.vue.d.ts.map +1 -1
- package/dist/components/CoarTimelineView.vue.d.ts +68 -0
- package/dist/components/CoarTimelineView.vue.d.ts.map +1 -0
- package/dist/components/CoarWorkWeekView.vue.d.ts +53 -0
- package/dist/components/CoarWorkWeekView.vue.d.ts.map +1 -0
- package/dist/components/internal/CoarEventDecorations.vue.d.ts +1 -1
- package/dist/components/internal/CoarEventDecorations.vue.d.ts.map +1 -1
- package/dist/composables/useViewWindow.d.ts.map +1 -1
- package/dist/core/dnd/move-math.d.ts +23 -0
- package/dist/core/dnd/move-math.d.ts.map +1 -1
- package/dist/core/index.d.ts +8 -15
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/temporal.d.ts +13 -0
- package/dist/core/temporal.d.ts.map +1 -1
- package/dist/core/timelineLayout.d.ts +77 -0
- package/dist/core/timelineLayout.d.ts.map +1 -0
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/viewWindow.d.ts +8 -1
- package/dist/core/viewWindow.d.ts.map +1 -1
- package/dist/{core-DK63eHat.js → core-D-gBBiQ5.js} +276 -400
- package/dist/core.js +3 -2
- package/dist/index.d.ts +5 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1739 -1232
- package/dist/move-math-vYSpEW-r.js +215 -0
- package/dist/recurrence/index.d.ts +70 -0
- package/dist/recurrence/index.d.ts.map +1 -0
- package/dist/recurrence/internal/default-engine.d.ts +20 -0
- package/dist/recurrence/internal/default-engine.d.ts.map +1 -0
- package/dist/recurrence/internal/dst-resolve.d.ts +12 -0
- package/dist/recurrence/internal/dst-resolve.d.ts.map +1 -0
- package/dist/recurrence/internal/engine-to-events.d.ts +38 -0
- package/dist/recurrence/internal/engine-to-events.d.ts.map +1 -0
- package/dist/recurrence/internal/series-to-engine.d.ts +4 -0
- package/dist/recurrence/internal/series-to-engine.d.ts.map +1 -0
- package/dist/recurrence/types.d.ts +252 -0
- package/dist/recurrence/types.d.ts.map +1 -0
- package/dist/recurrence-rrule-temporal/index.d.ts +12 -0
- package/dist/recurrence-rrule-temporal/index.d.ts.map +1 -0
- package/dist/recurrence-rrule-temporal.js +158 -0
- package/dist/recurrence.js +225 -0
- package/dist/types-fzCER_SC.js +4 -0
- package/dist/useTimelineView.d.ts +6 -0
- package/dist/useTimelineView.d.ts.map +1 -0
- package/dist/useWorkWeekView.d.ts +6 -0
- package/dist/useWorkWeekView.d.ts.map +1 -0
- package/dist/vue-calendar.css +1 -1
- package/package.json +12 -7
- package/dist/core/recurrence-public.d.ts +0 -59
- package/dist/core/recurrence-public.d.ts.map +0 -1
- package/dist/core/recurrence.d.ts +0 -112
- package/dist/core/recurrence.d.ts.map +0 -1
- package/dist/core/recurrenceWorker.d.ts +0 -62
- package/dist/core/recurrenceWorker.d.ts.map +0 -1
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { Temporal as e } from "@js-temporal/polyfill";
|
|
2
|
+
//#region src/core/types.ts
|
|
3
|
+
function t(e) {
|
|
4
|
+
return "timeZoneId" in e.start;
|
|
5
|
+
}
|
|
6
|
+
function n(e) {
|
|
7
|
+
return !("timeZoneId" in e.start);
|
|
8
|
+
}
|
|
9
|
+
function r(t) {
|
|
10
|
+
let { id: n, start: r, end: a } = t, o = r instanceof e.ZonedDateTime, s = r instanceof e.PlainDate;
|
|
11
|
+
if (!o && !s) throw TypeError(`[CalendarEvent ${n}] start must be Temporal.ZonedDateTime or Temporal.PlainDate. Got ${r?.constructor?.name ?? typeof r}.`);
|
|
12
|
+
if (o) try {
|
|
13
|
+
r.toInstant();
|
|
14
|
+
} catch (e) {
|
|
15
|
+
let t = r.timeZoneId;
|
|
16
|
+
throw TypeError(`[CalendarEvent ${n}] start.timeZoneId='${t}' is not a recognised IANA zone (Temporal threw '${e.message}'). Use a real IANA name like 'Europe/Vienna' / 'America/Los_Angeles'.`, { cause: e });
|
|
17
|
+
}
|
|
18
|
+
if (a !== void 0) {
|
|
19
|
+
let t = a instanceof e.ZonedDateTime, i = a instanceof e.PlainDate;
|
|
20
|
+
if (!t && !i) throw TypeError(`[CalendarEvent ${n}] end must be Temporal.ZonedDateTime or Temporal.PlainDate. Got ${a?.constructor?.name ?? typeof a}.`);
|
|
21
|
+
if (o !== t) throw TypeError(`[CalendarEvent ${n}] start and end must be the same shape. Got start=${o ? "ZonedDateTime" : "PlainDate"}, end=${t ? "ZonedDateTime" : "PlainDate"}.`);
|
|
22
|
+
if (o) {
|
|
23
|
+
if (e.Instant.compare(r.toInstant(), a.toInstant()) >= 0) throw RangeError(`[CalendarEvent ${n}] end must be strictly after start.`);
|
|
24
|
+
} else if (e.PlainDate.compare(r, a) >= 0) throw RangeError(`[CalendarEvent ${n}] end must be strictly after start.`);
|
|
25
|
+
}
|
|
26
|
+
let c = t.meta;
|
|
27
|
+
if ((c?.rrule !== void 0 || c?.rdate !== void 0 || c?.exdate !== void 0 || c?.recurrenceId !== void 0) && !i.has(n)) {
|
|
28
|
+
i.add(n);
|
|
29
|
+
let e = `[@cocoar/vue-calendar] [CalendarEvent ${n}] meta.rrule / .rdate / .exdate / .recurrenceId is set, but recurrence is not yet wired (Phase 4). The event will render only as a single occurrence at \`start\`. Construct a \`RecurringSeries\` and use \`expandSeries()\` (when available) instead of stuffing rrule into meta.`;
|
|
30
|
+
typeof console < "u" && console.warn(e);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
var i = /* @__PURE__ */ new Set(), a = 15, o = class extends Error {
|
|
34
|
+
disambiguation;
|
|
35
|
+
constructor(e, t) {
|
|
36
|
+
super(t), this.name = "DstResolutionError", this.disambiguation = e;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
function s(t, n) {
|
|
40
|
+
let r;
|
|
41
|
+
try {
|
|
42
|
+
r = e.PlainDateTime.from({
|
|
43
|
+
year: n.year,
|
|
44
|
+
month: n.month,
|
|
45
|
+
day: n.day,
|
|
46
|
+
hour: n.hour,
|
|
47
|
+
minute: n.minute,
|
|
48
|
+
second: n.second ?? 0
|
|
49
|
+
});
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
return r.toZonedDateTime(t, { disambiguation: "reject" }), null;
|
|
55
|
+
} catch {}
|
|
56
|
+
let i;
|
|
57
|
+
try {
|
|
58
|
+
i = r.toZonedDateTime(t, { disambiguation: "earlier" });
|
|
59
|
+
} catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
let a = i.toPlainDateTime();
|
|
63
|
+
return e.PlainDateTime.compare(a, r) === 0 ? "overlap" : "gap";
|
|
64
|
+
}
|
|
65
|
+
function c(e, t, n, r, i, a) {
|
|
66
|
+
let o = l(t, r, i, e);
|
|
67
|
+
return {
|
|
68
|
+
event: t,
|
|
69
|
+
original: {
|
|
70
|
+
start: n.start,
|
|
71
|
+
...n.end === void 0 ? {} : { end: n.end },
|
|
72
|
+
displayZone: n.displayZone
|
|
73
|
+
},
|
|
74
|
+
next: o,
|
|
75
|
+
target: {
|
|
76
|
+
...r,
|
|
77
|
+
date: r.date,
|
|
78
|
+
minutes: r.minutes,
|
|
79
|
+
displayZone: r.displayZone,
|
|
80
|
+
disambiguation: o.disambiguation ?? null
|
|
81
|
+
},
|
|
82
|
+
native: a
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function l(r, i, a, c = "compatible") {
|
|
86
|
+
if (n(r)) {
|
|
87
|
+
let t = r.start, n = r.end ?? t.add({ days: 1 }), o = e.PlainDate.from(i.date);
|
|
88
|
+
if (a === "allDay-resize-start" || a === "month-resize-start") {
|
|
89
|
+
let t = n.subtract({ days: 1 });
|
|
90
|
+
return {
|
|
91
|
+
start: e.PlainDate.compare(o, t) > 0 ? t : o,
|
|
92
|
+
end: n
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
if (a === "allDay-resize-end" || a === "month-resize-end") {
|
|
96
|
+
let n = t.add({ days: 1 }), r = o.add({ days: 1 });
|
|
97
|
+
return {
|
|
98
|
+
start: t,
|
|
99
|
+
end: e.PlainDate.compare(r, n) < 0 ? n : r
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
let s = t.until(n).total({ unit: "days" }), c = o, l = c.add({ days: s });
|
|
103
|
+
return r.end ? {
|
|
104
|
+
start: c,
|
|
105
|
+
end: l
|
|
106
|
+
} : { start: c };
|
|
107
|
+
}
|
|
108
|
+
if (!t(r)) throw TypeError(`[applyMoveToEvent] event ${r.id} has unrecognised start shape`);
|
|
109
|
+
let l = r.start.timeZoneId, u = r.end?.timeZoneId ?? l, d = r.start, f = r.end ?? null, p = e.PlainDate.from(i.date);
|
|
110
|
+
if (i.minutes === null && (a === "timed" || a === "timed-resize-start" || a === "timed-resize-end")) throw TypeError(`[applyMoveToEvent] timed event ${r.id} cannot be dropped onto an all-day target (target.minutes === null). To convert a timed event to all-day, change the event's start to a Temporal.PlainDate explicitly in your event-source — the drop API does not auto-convert.`);
|
|
111
|
+
let m = e.PlainTime.from({
|
|
112
|
+
hour: Math.floor(i.minutes / 60),
|
|
113
|
+
minute: i.minutes % 60
|
|
114
|
+
}), h = s(i.displayZone, {
|
|
115
|
+
year: p.year,
|
|
116
|
+
month: p.month,
|
|
117
|
+
day: p.day,
|
|
118
|
+
hour: m.hour,
|
|
119
|
+
minute: m.minute
|
|
120
|
+
});
|
|
121
|
+
if (h && c === "reject") throw new o(h, `[applyMoveToEvent] target ${i.date}T${String(m.hour).padStart(2, "0")}:${String(m.minute).padStart(2, "0")} is a DST ${h} in ${i.displayZone}; policy='reject'.`);
|
|
122
|
+
let g = c === "reject" ? "compatible" : c, _ = e.PlainDateTime.from({
|
|
123
|
+
year: p.year,
|
|
124
|
+
month: p.month,
|
|
125
|
+
day: p.day,
|
|
126
|
+
hour: m.hour,
|
|
127
|
+
minute: m.minute
|
|
128
|
+
}).toZonedDateTime(i.displayZone, { disambiguation: g }), v = _.withTimeZone(l), y = _.withTimeZone(u), b = h;
|
|
129
|
+
if (a === "timed-resize-start") {
|
|
130
|
+
let t = v;
|
|
131
|
+
if (f) {
|
|
132
|
+
let n = f.subtract({ minutes: 15 }).withTimeZone(l);
|
|
133
|
+
e.Instant.compare(t.toInstant(), n.toInstant()) > 0 && (t = n);
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
start: t,
|
|
137
|
+
...f ? { end: f } : {},
|
|
138
|
+
disambiguation: b
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
if (a === "timed-resize-end") {
|
|
142
|
+
let t = d.add({ minutes: 15 }).withTimeZone(u), n = y;
|
|
143
|
+
return e.Instant.compare(n.toInstant(), t.toInstant()) < 0 && (n = t), {
|
|
144
|
+
start: d,
|
|
145
|
+
end: n,
|
|
146
|
+
disambiguation: b
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
if (a === "month-resize-start") {
|
|
150
|
+
let t = d.withTimeZone(i.displayZone), n = s(i.displayZone, {
|
|
151
|
+
year: p.year,
|
|
152
|
+
month: p.month,
|
|
153
|
+
day: p.day,
|
|
154
|
+
hour: t.hour,
|
|
155
|
+
minute: t.minute,
|
|
156
|
+
second: t.second
|
|
157
|
+
});
|
|
158
|
+
if (n && c === "reject") throw new o(n, `[applyMoveToEvent] month-resize-start lands in a DST ${n} in ${i.displayZone}; policy='reject'.`);
|
|
159
|
+
let r = c === "reject" ? "compatible" : c, a = e.PlainDateTime.from({
|
|
160
|
+
year: p.year,
|
|
161
|
+
month: p.month,
|
|
162
|
+
day: p.day,
|
|
163
|
+
hour: t.hour,
|
|
164
|
+
minute: t.minute,
|
|
165
|
+
second: t.second
|
|
166
|
+
}).toZonedDateTime(i.displayZone, { disambiguation: r }).withTimeZone(l);
|
|
167
|
+
if (f) {
|
|
168
|
+
let t = f.subtract({ minutes: 15 }).withTimeZone(l);
|
|
169
|
+
e.Instant.compare(a.toInstant(), t.toInstant()) > 0 && (a = t);
|
|
170
|
+
}
|
|
171
|
+
return {
|
|
172
|
+
start: a,
|
|
173
|
+
...f ? { end: f } : {},
|
|
174
|
+
disambiguation: n
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
if (a === "month-resize-end") {
|
|
178
|
+
let t = f ?? d, n = f ? u : l, r = t.withTimeZone(i.displayZone), a = s(i.displayZone, {
|
|
179
|
+
year: p.year,
|
|
180
|
+
month: p.month,
|
|
181
|
+
day: p.day,
|
|
182
|
+
hour: r.hour,
|
|
183
|
+
minute: r.minute,
|
|
184
|
+
second: r.second
|
|
185
|
+
});
|
|
186
|
+
if (a && c === "reject") throw new o(a, `[applyMoveToEvent] month-resize-end lands in a DST ${a} in ${i.displayZone}; policy='reject'.`);
|
|
187
|
+
let m = c === "reject" ? "compatible" : c, h = e.PlainDateTime.from({
|
|
188
|
+
year: p.year,
|
|
189
|
+
month: p.month,
|
|
190
|
+
day: p.day,
|
|
191
|
+
hour: r.hour,
|
|
192
|
+
minute: r.minute,
|
|
193
|
+
second: r.second
|
|
194
|
+
}).toZonedDateTime(i.displayZone, { disambiguation: m }).withTimeZone(n), g = d.add({ minutes: 15 }).withTimeZone(n);
|
|
195
|
+
return e.Instant.compare(h.toInstant(), g.toInstant()) < 0 && (h = g), {
|
|
196
|
+
start: d,
|
|
197
|
+
end: h,
|
|
198
|
+
disambiguation: a
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
if (f) {
|
|
202
|
+
let e = f.epochMilliseconds - d.epochMilliseconds;
|
|
203
|
+
return {
|
|
204
|
+
start: v,
|
|
205
|
+
end: v.add({ milliseconds: e }).withTimeZone(u),
|
|
206
|
+
disambiguation: b
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
start: v,
|
|
211
|
+
disambiguation: b
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
//#endregion
|
|
215
|
+
export { s as a, r as c, c as i, a as n, n as o, l as r, t as s, o as t };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { Temporal } from '@js-temporal/polyfill';
|
|
2
|
+
import { CalendarEvent, RecurringSeries, RecurrenceExpansionWindow } from '../core/types';
|
|
3
|
+
import { DstPolicy } from '../core/dnd/move-math';
|
|
4
|
+
import { RecurrenceEngine } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* Expand a `RecurringSeries` into the concrete occurrences that fall
|
|
7
|
+
* within `window`.
|
|
8
|
+
*
|
|
9
|
+
* **Inputs**
|
|
10
|
+
* - `series` — the rule + dtstart + optional duration / rdate /
|
|
11
|
+
* exdate.
|
|
12
|
+
* - `window` — inclusive-start / exclusive-end. Typically the
|
|
13
|
+
* calendar's `_visibleRange` plus a small overscan.
|
|
14
|
+
* - `dstPolicy` — required (C4). Same options as the drag pipeline:
|
|
15
|
+
* `'compatible' | 'reject' | 'earlier' | 'later'`. **Step 2:
|
|
16
|
+
* accepted but not yet applied — engine-default disambiguation
|
|
17
|
+
* wins.** Step 3 wires the post-processing layer that enforces
|
|
18
|
+
* the policy uniformly across engines.
|
|
19
|
+
* - `engine` — optional. Defaults to a lazy-constructed
|
|
20
|
+
* rrule-temporal adapter from
|
|
21
|
+
* `@cocoar/vue-calendar/recurrence-rrule-temporal`.
|
|
22
|
+
*
|
|
23
|
+
* **Output**
|
|
24
|
+
*
|
|
25
|
+
* `CalendarEvent<TMeta>[]` where every occurrence:
|
|
26
|
+
* - has a UNIQUE synthetic `id` of shape
|
|
27
|
+
* `${series.id}__${recurrenceId}` so the layout pipeline can
|
|
28
|
+
* distinguish occurrences (it dedupes by `event.id`). The
|
|
29
|
+
* original series identifier is in `meta.__recurrence.seriesId`
|
|
30
|
+
* — read via `getRecurrenceMeta(event)`.
|
|
31
|
+
* - has `start` typed identically to `series.dtstart` (timed → ZDT,
|
|
32
|
+
* all-day → PD).
|
|
33
|
+
* - has `start.timeZoneId === series.dtstart.timeZoneId` for
|
|
34
|
+
* timed series — the engine never collapses to UTC or to the
|
|
35
|
+
* calendar's display zone (C3).
|
|
36
|
+
* - has `end` computed from `series.duration` if present.
|
|
37
|
+
* - carries provenance under `meta.__recurrence` (A4) — read via
|
|
38
|
+
* `getRecurrenceMeta(event)`.
|
|
39
|
+
*
|
|
40
|
+
* **Throws**
|
|
41
|
+
*
|
|
42
|
+
* - `TypeError` for shape mismatches (PlainDate RDATE on a timed
|
|
43
|
+
* series, etc.).
|
|
44
|
+
* - Step 3: `DstResolutionError` when `dstPolicy === 'reject'` and
|
|
45
|
+
* any occurrence falls in a DST gap.
|
|
46
|
+
*/
|
|
47
|
+
export declare function expandSeries<TMeta extends Record<string, unknown> = Record<string, unknown>>(series: RecurringSeries<TMeta>, window: RecurrenceExpansionWindow, dstPolicy: DstPolicy, engine?: RecurrenceEngine): Promise<CalendarEvent<TMeta>[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Public accessor for the lib-managed recurrence metadata on an
|
|
50
|
+
* expanded occurrence. Returns `null` for non-recurring events.
|
|
51
|
+
*
|
|
52
|
+
* Use this instead of reading `event.meta.__recurrence` directly —
|
|
53
|
+
* the storage key is library-managed and may change between minor
|
|
54
|
+
* versions.
|
|
55
|
+
*/
|
|
56
|
+
export { getRecurrenceMeta } from './internal/engine-to-events';
|
|
57
|
+
export type { RecurrenceMeta } from './internal/engine-to-events';
|
|
58
|
+
/**
|
|
59
|
+
* Type-only re-exports — single-import ergonomics for consumers who
|
|
60
|
+
* `import { ... } from '@cocoar/vue-calendar/recurrence'`.
|
|
61
|
+
*/
|
|
62
|
+
export type { RecurringSeries, RecurrencePattern, RecurrenceExpansionWindow, } from '../core/types';
|
|
63
|
+
export type { RecurrenceEngine, EngineRequest, EngineResponse, EngineResult, EngineResultTimed, EngineResultAllDay, EngineSeries, EngineSeriesTimed, EngineSeriesAllDay, EngineWindow, EngineSeriesError, RuleSpec, WallclockTimed, WallclockDate, OriginCode, } from './types';
|
|
64
|
+
export { ORIGIN_RRULE, ORIGIN_RDATE } from './types';
|
|
65
|
+
export type { DstPolicy } from '../core/dnd/move-math';
|
|
66
|
+
/**
|
|
67
|
+
* Re-exported `Temporal` for convenience when constructing series.
|
|
68
|
+
*/
|
|
69
|
+
export type { Temporal };
|
|
70
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/recurrence/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,yBAAyB,EAC1B,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAKvD,OAAO,KAAK,EAAE,gBAAgB,EAAgB,MAAM,SAAS,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAsB,YAAY,CAChC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAE/D,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC,EAC9B,MAAM,EAAE,yBAAyB,EACjC,SAAS,EAAE,SAAS,EACpB,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC,CAwBjC;AAED;;;;;;;GAOG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,YAAY,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAElE;;;GAGG;AACH,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,yBAAyB,GAC1B,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,iBAAiB,EACjB,QAAQ,EACR,cAAc,EACd,aAAa,EACb,UAAU,GACX,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAErD,YAAY,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD;;GAEG;AACH,YAAY,EAAE,QAAQ,EAAE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { RecurrenceEngine } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the default engine. Dynamic-imports
|
|
4
|
+
* `recurrence-rrule-temporal` once, then caches the instance for
|
|
5
|
+
* subsequent calls.
|
|
6
|
+
*
|
|
7
|
+
* The loader is process-global by design — the engine is stateless
|
|
8
|
+
* and reuse is safe. Builders that want a different engine pass it
|
|
9
|
+
* explicitly via `builder.recurrenceEngine(...)`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function getDefaultEngine(): Promise<RecurrenceEngine>;
|
|
12
|
+
/**
|
|
13
|
+
* Test-only helper: clear the cached engine. Lets test suites
|
|
14
|
+
* inject engines without leaking across tests.
|
|
15
|
+
*
|
|
16
|
+
* Not part of the public API surface (re-exported only from the
|
|
17
|
+
* recurrence subpath for internal test use).
|
|
18
|
+
*/
|
|
19
|
+
export declare function _resetDefaultEngineForTests(): void;
|
|
20
|
+
//# sourceMappingURL=default-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"default-engine.d.ts","sourceRoot":"","sources":["../../../src/recurrence/internal/default-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAKjD;;;;;;;;GAQG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAsBlE;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,IAAI,IAAI,CAGlD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { DstPolicy } from '../../core/dnd/move-math';
|
|
2
|
+
import { CalendarEvent, RecurringSeries } from '../../core/types';
|
|
3
|
+
/**
|
|
4
|
+
* Apply `dstPolicy` to every timed rule-generated occurrence in
|
|
5
|
+
* `events`, in place of returning the engine's native DST behavior.
|
|
6
|
+
* All-day events and RDATE-originated occurrences pass through.
|
|
7
|
+
*
|
|
8
|
+
* Throws `DstResolutionError` if any occurrence falls in a DST
|
|
9
|
+
* gap/overlap and `dstPolicy === 'reject'`.
|
|
10
|
+
*/
|
|
11
|
+
export declare function applyDstPolicy<TMeta extends Record<string, unknown>>(events: CalendarEvent<TMeta>[], series: RecurringSeries<TMeta>, dstPolicy: DstPolicy): CalendarEvent<TMeta>[];
|
|
12
|
+
//# sourceMappingURL=dst-resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dst-resolve.d.ts","sourceRoot":"","sources":["../../../src/recurrence/internal/dst-resolve.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAGH,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGvE;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,EAC9B,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC,EAC9B,SAAS,EAAE,SAAS,GACnB,aAAa,CAAC,KAAK,CAAC,EAAE,CA+ExB"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Temporal } from '@js-temporal/polyfill';
|
|
2
|
+
import { CalendarEvent, RecurringSeries } from '../../core/types';
|
|
3
|
+
import { EngineResult } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* Internal provenance attached to every expanded `CalendarEvent`
|
|
6
|
+
* under `meta.__recurrence`. Public consumers read it via
|
|
7
|
+
* `getRecurrenceMeta(event)`.
|
|
8
|
+
*
|
|
9
|
+
* The double-underscore prefix marks the key as library-managed.
|
|
10
|
+
* Consumers MUST NOT read or write it directly — that contract may
|
|
11
|
+
* change between minor versions.
|
|
12
|
+
*/
|
|
13
|
+
export interface RecurrenceMeta {
|
|
14
|
+
/** Stable id of the source `RecurringSeries`. */
|
|
15
|
+
readonly seriesId: string;
|
|
16
|
+
/**
|
|
17
|
+
* RECURRENCE-ID per RFC 5545 — the original wallclock value of
|
|
18
|
+
* this occurrence. For unmodified occurrences `recurrenceId`
|
|
19
|
+
* equals `event.start`; Phase-5 single-instance edits will let
|
|
20
|
+
* `event.start` differ while `recurrenceId` keeps pointing at
|
|
21
|
+
* the original slot.
|
|
22
|
+
*/
|
|
23
|
+
readonly recurrenceId: Temporal.ZonedDateTime | Temporal.PlainDate;
|
|
24
|
+
/** Where this occurrence came from in the source series. */
|
|
25
|
+
readonly source: 'rrule' | 'rdate';
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The lib-managed key under `event.meta`. Consumers should treat it
|
|
29
|
+
* as opaque — read via `getRecurrenceMeta(event)`.
|
|
30
|
+
*/
|
|
31
|
+
export declare const RECURRENCE_META_KEY: "__recurrence";
|
|
32
|
+
export declare function decodeEngineResult<TMeta extends Record<string, unknown>>(result: EngineResult, series: RecurringSeries<TMeta>): CalendarEvent<TMeta>[];
|
|
33
|
+
/**
|
|
34
|
+
* Public helper to read the lib-managed recurrence metadata off an
|
|
35
|
+
* expanded occurrence. Returns `null` for non-recurring events.
|
|
36
|
+
*/
|
|
37
|
+
export declare function getRecurrenceMeta<TMeta extends Record<string, unknown>>(event: CalendarEvent<TMeta>): RecurrenceMeta | null;
|
|
38
|
+
//# sourceMappingURL=engine-to-events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine-to-events.d.ts","sourceRoot":"","sources":["../../../src/recurrence/internal/engine-to-events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7C;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,aAAa,GAAG,QAAQ,CAAC,SAAS,CAAC;IACnE,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;CACpC;AAED;;;GAGG;AACH,eAAO,MAAM,mBAAmB,EAAG,cAAuB,CAAC;AAE3D,wBAAgB,kBAAkB,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtE,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC,GAC7B,aAAa,CAAC,KAAK,CAAC,EAAE,CAKxB;AA2HD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrE,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,GAC1B,cAAc,GAAG,IAAI,CAMvB"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { RecurringSeries } from '../../core/types';
|
|
2
|
+
import { EngineSeries } from '../types';
|
|
3
|
+
export declare function seriesToEngineSeries<TMeta extends Record<string, unknown>>(series: RecurringSeries<TMeta>): EngineSeries;
|
|
4
|
+
//# sourceMappingURL=series-to-engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"series-to-engine.d.ts","sourceRoot":"","sources":["../../../src/recurrence/internal/series-to-engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EACV,YAAY,EAGb,MAAM,UAAU,CAAC;AAElB,wBAAgB,oBAAoB,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxE,MAAM,EAAE,eAAe,CAAC,KAAK,CAAC,GAC7B,YAAY,CAWd"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public engine interface for recurrence expansion (Phase 4 §A5).
|
|
3
|
+
*
|
|
4
|
+
* Engines implement `RecurrenceEngine`; consumers can replace the
|
|
5
|
+
* default engine via `builder.recurrenceEngine(custom)` or by
|
|
6
|
+
* passing a 4th arg to `expandSeries(...)`. The contract
|
|
7
|
+
* intentionally stays small and stable: the lib does the heavy
|
|
8
|
+
* lifting (RecurringSeries → EngineSeries conversion, source-zone
|
|
9
|
+
* preservation, DstPolicy post-processing, provenance) so engines
|
|
10
|
+
* focus only on RRULE expansion.
|
|
11
|
+
*
|
|
12
|
+
* One engine adapter ships in-tree:
|
|
13
|
+
* - `@cocoar/vue-calendar/recurrence-rrule-temporal` — pure JS,
|
|
14
|
+
* Temporal-native, the lazy default.
|
|
15
|
+
*
|
|
16
|
+
* Custom engines (e.g. WASM-backed for high-volume workloads,
|
|
17
|
+
* server-side delegation, or test mocks) implement `RecurrenceEngine`
|
|
18
|
+
* in consumer code and register via `builder.recurrenceEngine(...)`.
|
|
19
|
+
*
|
|
20
|
+
* **Wire format invariants**
|
|
21
|
+
* - All times travel as numeric components (year/month/day/hour
|
|
22
|
+
* /minute/second). No `Date`, no `Temporal` objects in the wire —
|
|
23
|
+
* so Worker postMessage stays cheap and structured-clone friendly.
|
|
24
|
+
* - Source zones travel per-endpoint (DTSTART, each RDATE, each
|
|
25
|
+
* EXDATE). The library NEVER collapses to one zone before calling
|
|
26
|
+
* the engine — C3.
|
|
27
|
+
* - Output `timestamps` are unix-ms (UTC instants). The library
|
|
28
|
+
* reconstructs each occurrence's `Temporal.ZonedDateTime` in its
|
|
29
|
+
* source zone using the parallel `seriesTzid` + `occurrenceTzids`
|
|
30
|
+
* fields — no zone identity is lost.
|
|
31
|
+
* - All-day series travel through a separate `kind: 'allDay'`
|
|
32
|
+
* branch with packed `Int32Array` dates. No instants exist for
|
|
33
|
+
* all-day events (Article 4) so `timestamps` would be a category
|
|
34
|
+
* error.
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* Components of a wallclock time. Used for DTSTART, RDATE, EXDATE,
|
|
38
|
+
* and the `UNTIL` field of an RRULE in the timed path. Plain numbers
|
|
39
|
+
* so the structure clones cheaply across the worker boundary.
|
|
40
|
+
*/
|
|
41
|
+
export interface WallclockTimed {
|
|
42
|
+
readonly year: number;
|
|
43
|
+
readonly month: number;
|
|
44
|
+
readonly day: number;
|
|
45
|
+
readonly hour: number;
|
|
46
|
+
readonly minute: number;
|
|
47
|
+
readonly second: number;
|
|
48
|
+
readonly tzid: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Components of a wallclock date (no time, no zone). Used for
|
|
52
|
+
* DTSTART, RDATE, EXDATE, and `UNTIL` of an RRULE in the all-day
|
|
53
|
+
* path. Article 4: a date is not a point in time.
|
|
54
|
+
*/
|
|
55
|
+
export interface WallclockDate {
|
|
56
|
+
readonly year: number;
|
|
57
|
+
readonly month: number;
|
|
58
|
+
readonly day: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* RFC-5545 RRULE in string form, e.g. `'FREQ=WEEKLY;BYDAY=MO,WE,FR'`.
|
|
62
|
+
*
|
|
63
|
+
* Stored as a string because:
|
|
64
|
+
* - Engines parse RRULE natively; pre-parsing into a structured
|
|
65
|
+
* form would require us to re-emit RFC-compliant syntax for any
|
|
66
|
+
* engine using a typed constructor.
|
|
67
|
+
* - Adding a structured representation here would lock the lib
|
|
68
|
+
* into a specific RRULE-feature subset; the string form lets
|
|
69
|
+
* each engine accept whatever RFC features it supports natively.
|
|
70
|
+
*
|
|
71
|
+
* The optional `until` is split out so the lib can pass it as a
|
|
72
|
+
* properly-typed value (matching DTSTART's value class) instead of
|
|
73
|
+
* embedding it in the string.
|
|
74
|
+
*/
|
|
75
|
+
export interface RuleSpec {
|
|
76
|
+
readonly rrule: string;
|
|
77
|
+
/**
|
|
78
|
+
* Optional override for `UNTIL` from the rrule string. When set,
|
|
79
|
+
* adapters use this typed value instead of parsing the embedded
|
|
80
|
+
* `UNTIL` from the string. Lets the lib enforce value-class
|
|
81
|
+
* matching with DTSTART (per A6).
|
|
82
|
+
*/
|
|
83
|
+
readonly until?: WallclockTimed | WallclockDate;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Engine-side representation of a `RecurringSeries`.
|
|
87
|
+
*
|
|
88
|
+
* Discriminated by `kind` so timed and all-day series travel through
|
|
89
|
+
* separate code paths inside the engine — no synthetic 00:00 in a
|
|
90
|
+
* zone (per A6).
|
|
91
|
+
*/
|
|
92
|
+
export type EngineSeries = EngineSeriesTimed | EngineSeriesAllDay;
|
|
93
|
+
export interface EngineSeriesTimed {
|
|
94
|
+
readonly seriesId: string;
|
|
95
|
+
readonly kind: 'timed';
|
|
96
|
+
readonly dtstart: WallclockTimed;
|
|
97
|
+
readonly rules: readonly RuleSpec[];
|
|
98
|
+
readonly rdates: readonly WallclockTimed[];
|
|
99
|
+
readonly exdates: readonly WallclockTimed[];
|
|
100
|
+
}
|
|
101
|
+
export interface EngineSeriesAllDay {
|
|
102
|
+
readonly seriesId: string;
|
|
103
|
+
readonly kind: 'allDay';
|
|
104
|
+
readonly dtstart: WallclockDate;
|
|
105
|
+
readonly rules: readonly RuleSpec[];
|
|
106
|
+
readonly rdates: readonly WallclockDate[];
|
|
107
|
+
readonly exdates: readonly WallclockDate[];
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Window for the engine call. Bounds are absolute instants (unix-ms);
|
|
111
|
+
* the engine clips occurrences to `[start, end)`. Inclusive-start /
|
|
112
|
+
* exclusive-end (same convention as `RecurrenceExpansionWindow` and
|
|
113
|
+
* `ViewWindow`).
|
|
114
|
+
*
|
|
115
|
+
* For all-day series the lib still passes instants — the engine
|
|
116
|
+
* computes the date-only window by taking each date's UTC-midnight
|
|
117
|
+
* instant. The bounds are wide enough that DST near the edge can't
|
|
118
|
+
* flip an occurrence out of the window.
|
|
119
|
+
*/
|
|
120
|
+
export interface EngineWindow {
|
|
121
|
+
readonly startMs: number;
|
|
122
|
+
readonly endMs: number;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Batched engine request. The library collects all visible series,
|
|
126
|
+
* dispatches once. Engines that can parallelize (worker-backed) get
|
|
127
|
+
* the most leverage from large batches.
|
|
128
|
+
*/
|
|
129
|
+
export interface EngineRequest {
|
|
130
|
+
readonly window: EngineWindow;
|
|
131
|
+
readonly series: readonly EngineSeries[];
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Origin marker for one occurrence. Packed into a `Uint8Array` per
|
|
135
|
+
* series-result for transferable round-trip. Used by Step 3 to set
|
|
136
|
+
* `__recurrence.source` on each `CalendarEvent`.
|
|
137
|
+
*/
|
|
138
|
+
export declare const ORIGIN_RRULE = 0;
|
|
139
|
+
export declare const ORIGIN_RDATE = 1;
|
|
140
|
+
export type OriginCode = typeof ORIGIN_RRULE | typeof ORIGIN_RDATE;
|
|
141
|
+
/**
|
|
142
|
+
* Engine result — discriminated union mirroring `EngineSeries.kind`.
|
|
143
|
+
*
|
|
144
|
+
* `Float64Array` / `Int32Array` / `Uint16Array` / `Uint8Array` are
|
|
145
|
+
* all Transferable; the worker round-trip stays zero-copy.
|
|
146
|
+
*/
|
|
147
|
+
export type EngineResult = EngineResultTimed | EngineResultAllDay;
|
|
148
|
+
export interface EngineResultTimed {
|
|
149
|
+
readonly seriesId: string;
|
|
150
|
+
readonly kind: 'timed';
|
|
151
|
+
/** Unix-ms instants of every occurrence inside the window. */
|
|
152
|
+
readonly timestamps: Float64Array;
|
|
153
|
+
/**
|
|
154
|
+
* The series source zone (matches `EngineSeriesTimed.dtstart.tzid`).
|
|
155
|
+
* Set unconditionally so the library can reconstruct
|
|
156
|
+
* `Temporal.ZonedDateTime` for rule-generated occurrences without
|
|
157
|
+
* looking elsewhere.
|
|
158
|
+
*/
|
|
159
|
+
readonly seriesTzid: string;
|
|
160
|
+
/**
|
|
161
|
+
* Per-occurrence zone overrides — used only when at least one
|
|
162
|
+
* RDATE has a different `tzid` than `seriesTzid`. When present,
|
|
163
|
+
* `indices[i]` is the index into `pool` for the i-th occurrence.
|
|
164
|
+
* When omitted, every occurrence uses `seriesTzid`.
|
|
165
|
+
*
|
|
166
|
+
* Hot-path optimization (A1 fast-path): the homogeneous-zone case
|
|
167
|
+
* pays no extra bytes.
|
|
168
|
+
*/
|
|
169
|
+
readonly occurrenceTzids?: {
|
|
170
|
+
readonly pool: readonly string[];
|
|
171
|
+
readonly indices: Uint16Array;
|
|
172
|
+
};
|
|
173
|
+
/**
|
|
174
|
+
* One byte per occurrence — `ORIGIN_RRULE` or `ORIGIN_RDATE`. Step
|
|
175
|
+
* 3 uses this to populate `__recurrence.source`.
|
|
176
|
+
*/
|
|
177
|
+
readonly origins: Uint8Array;
|
|
178
|
+
}
|
|
179
|
+
export interface EngineResultAllDay {
|
|
180
|
+
readonly seriesId: string;
|
|
181
|
+
readonly kind: 'allDay';
|
|
182
|
+
/**
|
|
183
|
+
* Packed dates: each entry is `(year * 512 + month * 32 + day)`.
|
|
184
|
+
* Decoded by the library into `Temporal.PlainDate`.
|
|
185
|
+
*
|
|
186
|
+
* Why packed: instants don't exist for all-day events (Article 4),
|
|
187
|
+
* but a numeric encoding still rides the transferable fast-path.
|
|
188
|
+
* The `512 * 32` packing fits 11 bits of year + 4 bits of month +
|
|
189
|
+
* 5 bits of day in 20 bits — well inside Int32.
|
|
190
|
+
*/
|
|
191
|
+
readonly dates: Int32Array;
|
|
192
|
+
readonly origins: Uint8Array;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Batched engine response — one result per input series, in the same
|
|
196
|
+
* order. Errors are surfaced per-series so a single bad rule doesn't
|
|
197
|
+
* fail the whole batch.
|
|
198
|
+
*/
|
|
199
|
+
export interface EngineResponse {
|
|
200
|
+
readonly results: readonly EngineResult[];
|
|
201
|
+
/**
|
|
202
|
+
* Per-series errors. Empty on full success. When non-empty, the
|
|
203
|
+
* corresponding entry in `results` may be missing (engines may
|
|
204
|
+
* skip failed series rather than emitting an empty result).
|
|
205
|
+
*/
|
|
206
|
+
readonly errors: readonly EngineSeriesError[];
|
|
207
|
+
}
|
|
208
|
+
export interface EngineSeriesError {
|
|
209
|
+
readonly seriesId: string;
|
|
210
|
+
readonly message: string;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Recurrence engine contract.
|
|
214
|
+
*
|
|
215
|
+
* Implementations parse + expand RRULE/RDATE/EXDATE for a batch of
|
|
216
|
+
* series over a window. The library does NOT expect the engine to
|
|
217
|
+
* apply `DstPolicy` — that's post-processing in `dst-resolve.ts`
|
|
218
|
+
* (Step 3) so engine-swap never changes observable semantics.
|
|
219
|
+
*
|
|
220
|
+
* The interface is `async` so worker-backed engines fit the same
|
|
221
|
+
* shape as in-thread engines. Consumers always `await`.
|
|
222
|
+
*
|
|
223
|
+
* **Engine implementer responsibilities:**
|
|
224
|
+
* - Use the `series.dtstart.tzid` (or per-RDATE/EXDATE `tzid`) for
|
|
225
|
+
* wallclock interpretation. Never collapse to one zone.
|
|
226
|
+
* - For timed `EngineResultTimed`: emit `timestamps` as unix-ms
|
|
227
|
+
* UTC instants, and populate `seriesTzid` + optional
|
|
228
|
+
* `occurrenceTzids` so the lib can reconstruct ZDTs in the
|
|
229
|
+
* correct zone per occurrence.
|
|
230
|
+
* - For all-day `EngineResultAllDay`: emit packed `dates`. Never
|
|
231
|
+
* pass through an `Instant` for all-day series (Article 4).
|
|
232
|
+
* - EXDATE matching: against the series source zone (A7).
|
|
233
|
+
* - `origins`: set `ORIGIN_RRULE` for rule-generated occurrences
|
|
234
|
+
* and `ORIGIN_RDATE` for occurrences originating from an RDATE.
|
|
235
|
+
*
|
|
236
|
+
* **What engines MUST NOT do:**
|
|
237
|
+
* - Apply `DstPolicy` — that's the lib's job (Step 3).
|
|
238
|
+
* - Add `meta.__recurrence` provenance — that's the lib's job
|
|
239
|
+
* (Step 3).
|
|
240
|
+
* - Reorder occurrences inside one series-result. Within each
|
|
241
|
+
* `EngineResult.timestamps` (or `dates`), occurrences must be
|
|
242
|
+
* sorted ascending. The lib relies on this.
|
|
243
|
+
*/
|
|
244
|
+
export interface RecurrenceEngine {
|
|
245
|
+
/**
|
|
246
|
+
* Expand a batch of recurring series over a window.
|
|
247
|
+
* Always async. Consumers await regardless of whether the engine
|
|
248
|
+
* is in-thread or worker-backed.
|
|
249
|
+
*/
|
|
250
|
+
expand(request: EngineRequest): Promise<EngineResponse>;
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/recurrence/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { EngineRequest, EngineResponse, RecurrenceEngine } from '../recurrence/types';
|
|
2
|
+
/**
|
|
3
|
+
* Default recurrence engine — pure JS, Temporal-native.
|
|
4
|
+
*
|
|
5
|
+
* Stateless. Construction is cheap (no module init). Reuse one
|
|
6
|
+
* instance per builder; the lib does that automatically when no
|
|
7
|
+
* explicit engine is configured.
|
|
8
|
+
*/
|
|
9
|
+
export declare class RruleTemporalEngine implements RecurrenceEngine {
|
|
10
|
+
expand(request: EngineRequest): Promise<EngineResponse>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/recurrence-rrule-temporal/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAIH,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EAMd,gBAAgB,EAGjB,MAAM,qBAAqB,CAAC;AAK7B;;;;;;GAMG;AACH,qBAAa,mBAAoB,YAAW,gBAAgB;IACpD,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,cAAc,CAAC;CAkB9D"}
|