@webamoki/web-svelte 1.2.3 → 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/README.md +3 -1
- package/dist/components/showcase/CodeBlock.svelte +1 -1
- package/dist/{components → shared/components}/form/Button.svelte +2 -2
- package/dist/{components → shared/components}/form/Button.svelte.d.ts +2 -2
- package/dist/{components → shared/components}/form/Errors.svelte +1 -1
- package/dist/{components → shared/components}/form/FieldWrapper.svelte +1 -1
- package/dist/{components → shared/components}/form/fields/ChoiceMultiField.svelte +3 -1
- package/dist/{components → shared/components}/form/fields/DateField.svelte +2 -2
- package/dist/{components → shared/components}/form/fields/MessageField.svelte +2 -2
- package/dist/{components → shared/components}/form/fields/NumberField.svelte +2 -2
- package/dist/{components → shared/components}/form/fields/PasswordField.svelte +2 -2
- package/dist/{components → shared/components}/form/fields/SelectField.svelte +3 -3
- package/dist/{components → shared/components}/form/fields/SelectMultiField.svelte +3 -3
- package/dist/{components → shared/components}/form/fields/TextField.svelte +2 -2
- package/dist/{components → shared/components}/form/fields/TextFieldNullable.svelte +2 -2
- package/dist/{components → shared/components}/form/fields/TimeField.svelte +2 -2
- package/dist/{components → shared/components}/ui/choice/ChoiceInternal.svelte +1 -1
- package/dist/{components → shared/components}/ui/choice/WeekdayChoice.svelte +6 -3
- package/dist/{components → shared/components}/ui/choice/WeekdayChoice.svelte.d.ts +1 -1
- package/dist/{components → shared/components}/ui/choice/WeekdayChoiceMulti.svelte +6 -3
- package/dist/{components → shared/components}/ui/choice/WeekdayChoiceMulti.svelte.d.ts +1 -1
- package/dist/{components → shared/components}/ui/context-menu/ContextMenuContent.svelte +1 -1
- package/dist/{components → shared/components}/ui/context-menu/ContextMenuItem.svelte +1 -1
- package/dist/{components → shared/components}/ui/search/SearchBar.svelte +2 -2
- package/dist/{utils/types → shared/utils}/arktype.d.ts +4 -12
- package/dist/shared/utils/arktype.js +40 -0
- package/dist/{utils → shared/utils}/datetime/datetime.spec.js +39 -26
- package/dist/{utils → shared/utils}/datetime/index.d.ts +52 -34
- package/dist/{utils → shared/utils}/datetime/index.js +105 -78
- package/dist/{utils → shared/utils}/email/README.md +5 -5
- package/dist/{utils → shared/utils}/email/ses.js +17 -9
- package/dist/shared/utils/functional/index.d.ts +2 -0
- package/dist/shared/utils/functional/index.js +2 -0
- package/dist/shared/utils/functional/result.d.ts +72 -0
- package/dist/shared/utils/functional/result.js +86 -0
- package/dist/shared/utils/functional/result.spec.d.ts +1 -0
- package/dist/shared/utils/functional/result.spec.js +96 -0
- package/dist/shared/utils/remote.d.ts +28 -0
- package/dist/shared/utils/remote.js +74 -0
- package/dist/{utils/search.d.ts → shared/utils/string.d.ts} +1 -0
- package/dist/{utils/search.js → shared/utils/string.js} +13 -4
- package/package.json +27 -30
- package/dist/utils/email/aws-signer.d.ts +0 -17
- package/dist/utils/email/aws-signer.js +0 -83
- package/dist/utils/string.d.ts +0 -1
- package/dist/utils/string.js +0 -4
- package/dist/utils/types/arktype.js +0 -92
- package/dist/utils/types/consts.d.ts +0 -5
- package/dist/utils/types/consts.js +0 -5
- package/dist/utils/types/db.d.ts +0 -57
- package/dist/utils/types/db.js +0 -34
- /package/dist/{components → shared/components}/form/Errors.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/FieldWrapper.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/Form.svelte +0 -0
- /package/dist/{components → shared/components}/form/Form.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/IconInputWrapper.svelte +0 -0
- /package/dist/{components → shared/components}/form/IconInputWrapper.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/fields/ChoiceField.svelte +0 -0
- /package/dist/{components → shared/components}/form/fields/ChoiceField.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/fields/ChoiceMultiField.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/fields/DateField.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/fields/HexColorField.svelte +0 -0
- /package/dist/{components → shared/components}/form/fields/HexColorField.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/fields/MessageField.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/fields/NumberField.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/fields/PasswordField.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/fields/SelectField.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/fields/SelectMultiField.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/fields/TextField.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/fields/TextFieldNullable.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/fields/TimeField.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/fields/WeekdayChoiceField.svelte +0 -0
- /package/dist/{components → shared/components}/form/fields/WeekdayChoiceField.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/fields/WeekdayChoiceMultiField.svelte +0 -0
- /package/dist/{components → shared/components}/form/fields/WeekdayChoiceMultiField.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/form/index.d.ts +0 -0
- /package/dist/{components → shared/components}/form/index.js +0 -0
- /package/dist/{components → shared/components}/ui/choice/Choice.svelte +0 -0
- /package/dist/{components → shared/components}/ui/choice/Choice.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/ui/choice/ChoiceInternal.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/ui/choice/ChoiceMulti.svelte +0 -0
- /package/dist/{components → shared/components}/ui/choice/ChoiceMulti.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/ui/context-menu/ContextMenu.svelte +0 -0
- /package/dist/{components → shared/components}/ui/context-menu/ContextMenu.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/ui/context-menu/ContextMenuContent.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/ui/context-menu/ContextMenuItem.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/ui/context-menu/ContextMenuSeparator.svelte +0 -0
- /package/dist/{components → shared/components}/ui/context-menu/ContextMenuSeparator.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/ui/context-menu/ContextMenuTrigger.svelte +0 -0
- /package/dist/{components → shared/components}/ui/context-menu/ContextMenuTrigger.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/ui/context-menu/context-menu-state.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/ui/context-menu/context-menu-state.svelte.js +0 -0
- /package/dist/{components → shared/components}/ui/drag-drop/Draggable.svelte +0 -0
- /package/dist/{components → shared/components}/ui/drag-drop/Draggable.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/ui/drag-drop/Dropzone.svelte +0 -0
- /package/dist/{components → shared/components}/ui/drag-drop/Dropzone.svelte.d.ts +0 -0
- /package/dist/{components → shared/components}/ui/drag-drop/drag-manager.d.ts +0 -0
- /package/dist/{components → shared/components}/ui/drag-drop/drag-manager.js +0 -0
- /package/dist/{components → shared/components}/ui/index.d.ts +0 -0
- /package/dist/{components → shared/components}/ui/index.js +0 -0
- /package/dist/{components → shared/components}/ui/search/SearchBar.svelte.d.ts +0 -0
- /package/dist/{server → shared/server}/form-handler.d.ts +0 -0
- /package/dist/{server → shared/server}/form-handler.js +0 -0
- /package/dist/{server → shared/server}/form-processor.d.ts +0 -0
- /package/dist/{server → shared/server}/form-processor.js +0 -0
- /package/dist/{utils → shared/utils}/datetime/datetime.spec.d.ts +0 -0
- /package/dist/{utils → shared/utils}/email/index.d.ts +0 -0
- /package/dist/{utils → shared/utils}/email/index.js +0 -0
- /package/dist/{utils → shared/utils}/email/ses.d.ts +0 -0
- /package/dist/{utils → shared/utils}/email/ses.test.d.ts +0 -0
- /package/dist/{utils → shared/utils}/email/ses.test.js +0 -0
- /package/dist/{utils → shared/utils}/form/index.d.ts +0 -0
- /package/dist/{utils → shared/utils}/form/index.js +0 -0
- /package/dist/{utils → shared/utils}/form/virtual-form.d.ts +0 -0
- /package/dist/{utils → shared/utils}/form/virtual-form.js +0 -0
- /package/dist/{highlight.d.ts → utils/highlight.d.ts} +0 -0
- /package/dist/{highlight.js → utils/highlight.js} +0 -0
|
@@ -1,15 +1,48 @@
|
|
|
1
1
|
import type { Transport } from '@sveltejs/kit';
|
|
2
2
|
import { CalendarDate, type DateDuration, Time, ZonedDateTime } from '@internationalized/date';
|
|
3
|
-
import type { Day } from '../types/arktype.js';
|
|
4
3
|
export declare const Days: readonly ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
|
|
4
|
+
export type Day = (typeof Days)[number];
|
|
5
5
|
export declare const DayIndex: Record<Day, number>;
|
|
6
|
+
export declare class LocalDateF {
|
|
7
|
+
private readonly timezone;
|
|
8
|
+
constructor(timezone: string);
|
|
9
|
+
/**
|
|
10
|
+
* Calculates the age from a date of birth.
|
|
11
|
+
* @param dob - The date of birth.
|
|
12
|
+
* @returns The age in years.
|
|
13
|
+
* @throws Error if the date of birth is in the future.
|
|
14
|
+
*/
|
|
15
|
+
ageFromDob(dob: CalendarDate): number;
|
|
16
|
+
/**
|
|
17
|
+
* Checks if a given date is today.
|
|
18
|
+
* @param date - The date to check.
|
|
19
|
+
* @returns True if the date is today, false otherwise.
|
|
20
|
+
*/
|
|
21
|
+
isDateToday(date: CalendarDate): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* @returns The current date and time.
|
|
24
|
+
*/
|
|
25
|
+
now(): ZonedDateTime;
|
|
26
|
+
/**
|
|
27
|
+
* @returns The current date.
|
|
28
|
+
*/
|
|
29
|
+
today(): CalendarDate;
|
|
30
|
+
}
|
|
31
|
+
/** Gets the day index of the date */
|
|
32
|
+
export declare function getDayIndexOfDate(date: CalendarDate): number;
|
|
6
33
|
/**
|
|
7
|
-
*
|
|
8
|
-
* @param
|
|
9
|
-
* @returns The
|
|
10
|
-
* @throws Error if the date of birth is in the future.
|
|
34
|
+
* Gets the day of the week for a given date.
|
|
35
|
+
* @param date - The date to get the day of the week for.
|
|
36
|
+
* @returns The day of the week
|
|
11
37
|
*/
|
|
12
|
-
export declare function
|
|
38
|
+
export declare function getDayOfDate(date: CalendarDate): Day;
|
|
39
|
+
/**
|
|
40
|
+
* Checks if a given date is a specific day of the week.
|
|
41
|
+
* @param date - The date to check.
|
|
42
|
+
* @param dayOfWeek - The day of the week to check against.
|
|
43
|
+
* @returns True if the date is the specified day, false otherwise.
|
|
44
|
+
*/
|
|
45
|
+
export declare function isDateDay(date: CalendarDate, dayOfWeek: Day): boolean;
|
|
13
46
|
/**
|
|
14
47
|
* Checks if two time ranges overlap, boundaries are not considered overlapping.
|
|
15
48
|
* @param start1 - The start time of the first range.
|
|
@@ -27,14 +60,6 @@ export declare function checkOverlap(start1: Time, end1: Time, start2: Time, end
|
|
|
27
60
|
* @returns True if the dates are within duration, false otherwise.
|
|
28
61
|
*/
|
|
29
62
|
export declare function datesWithin(date1: CalendarDate, date2: CalendarDate, duration: DateDuration): boolean;
|
|
30
|
-
/** Gets the day index of the date */
|
|
31
|
-
export declare function getDayIndex(date: CalendarDate): number;
|
|
32
|
-
/**
|
|
33
|
-
* Gets the day of the week for a given date.
|
|
34
|
-
* @param date - The date to get the day of the week for.
|
|
35
|
-
* @returns The day of the week
|
|
36
|
-
*/
|
|
37
|
-
export declare function getDayOfDate(date: CalendarDate): Day;
|
|
38
63
|
/**
|
|
39
64
|
* Gets the most recent occurrence of a day of the week.
|
|
40
65
|
* @param dayOfWeek - The day of the week
|
|
@@ -66,19 +91,6 @@ export declare function getLastMonths(count: number, startDate: CalendarDate): C
|
|
|
66
91
|
* @returns The date of the next occurrence of the specified day.
|
|
67
92
|
*/
|
|
68
93
|
export declare function getNextDateOfDay(dayOfWeek: Day, startDate: CalendarDate): CalendarDate;
|
|
69
|
-
/**
|
|
70
|
-
* Checks if a given date is a specific day of the week.
|
|
71
|
-
* @param date - The date to check.
|
|
72
|
-
* @param dayOfWeek - The day of the week to check against.
|
|
73
|
-
* @returns True if the date is the specified day, false otherwise.
|
|
74
|
-
*/
|
|
75
|
-
export declare function isDateDay(date: CalendarDate, dayOfWeek: Day): boolean;
|
|
76
|
-
/**
|
|
77
|
-
* Checks if a given date is today.
|
|
78
|
-
* @param date - The date to check.
|
|
79
|
-
* @returns True if the date is today, false otherwise.
|
|
80
|
-
*/
|
|
81
|
-
export declare function isDateToday(date: CalendarDate, timezone: string): boolean;
|
|
82
94
|
/**
|
|
83
95
|
* Calculates the difference in weeks between two dates.
|
|
84
96
|
* @param date1 - The first date in order.
|
|
@@ -135,9 +147,15 @@ export declare function formatDateShort(date: CalendarDate): string;
|
|
|
135
147
|
* Formats the month only.
|
|
136
148
|
* @param date - The date to format.
|
|
137
149
|
* @returns The formatted month string.
|
|
138
|
-
* @example "Oct"
|
|
150
|
+
* @example "Oct 23"
|
|
139
151
|
*/
|
|
140
152
|
export declare function formatMonth(date: CalendarDate): string;
|
|
153
|
+
/**
|
|
154
|
+
* Gives time in HH:MM format
|
|
155
|
+
* @param time
|
|
156
|
+
* @returns string of time in that format
|
|
157
|
+
*/
|
|
158
|
+
export declare function formatTime(time: Time): string;
|
|
141
159
|
/**
|
|
142
160
|
* Calculates the end time given a starting time and duration.
|
|
143
161
|
* @param timeStart starting time
|
|
@@ -151,12 +169,6 @@ export declare function formatTimeEnd(timeStart: Time, durationMinutes: number):
|
|
|
151
169
|
* @returns string of time in that format
|
|
152
170
|
*/
|
|
153
171
|
export declare function formatTimeFull(time: Time): string;
|
|
154
|
-
/**
|
|
155
|
-
* Gives time in HH:MM format
|
|
156
|
-
* @param time
|
|
157
|
-
* @returns string of time in that format
|
|
158
|
-
*/
|
|
159
|
-
export declare function formatTimeShort(time: Time): string;
|
|
160
172
|
/**
|
|
161
173
|
* Unfreezes a CalendarDate object from a snapshot.
|
|
162
174
|
* @param raw - The snapshot of the CalendarDate object.
|
|
@@ -169,4 +181,10 @@ export declare function unfreezeDate(raw: ReturnType<typeof $state.snapshot<Cale
|
|
|
169
181
|
* @returns The unfrozen Time object.
|
|
170
182
|
*/
|
|
171
183
|
export declare function unfreezeTime(raw: ReturnType<typeof $state.snapshot<Time>>): Time;
|
|
184
|
+
/**
|
|
185
|
+
* Unfreezes a ZonedDateTime object from a snapshot.
|
|
186
|
+
* @param date - The snapshot of the ZonedDateTime object.
|
|
187
|
+
* @returns The unfrozen ZonedDateTime object.
|
|
188
|
+
*/
|
|
189
|
+
export declare function unfreezeAbsoluteDate(date: ReturnType<typeof $state.snapshot<ZonedDateTime>>): ZonedDateTime;
|
|
172
190
|
export declare const dateTransport: Transport;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { CalendarDate, DateFormatter, fromDate, getDayOfWeek, getLocalTimeZone, startOfMonth, Time, toCalendarDate, today, toTime, ZonedDateTime } from '@internationalized/date';
|
|
1
|
+
import { CalendarDate, DateFormatter, fromDate, getDayOfWeek, getLocalTimeZone, now as nowFn, startOfMonth, Time, toCalendarDate, today as todayFn, toTime, ZonedDateTime } from '@internationalized/date';
|
|
2
2
|
import { map, range } from 'ramda';
|
|
3
|
-
const DEFAULT_TIME_ZONE = 'Europe/London';
|
|
4
3
|
const DEFAULT_LOCALE = 'en-GB';
|
|
5
4
|
// Day of the week
|
|
6
5
|
export const Days = [
|
|
@@ -13,26 +12,77 @@ export const Days = [
|
|
|
13
12
|
'Sunday'
|
|
14
13
|
];
|
|
15
14
|
export const DayIndex = Object.fromEntries(Days.map((day, index) => [day, index]));
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
// Date functions local to a timezone
|
|
16
|
+
export class LocalDateF {
|
|
17
|
+
timezone;
|
|
18
|
+
constructor(timezone) {
|
|
19
|
+
this.timezone = timezone;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Calculates the age from a date of birth.
|
|
23
|
+
* @param dob - The date of birth.
|
|
24
|
+
* @returns The age in years.
|
|
25
|
+
* @throws Error if the date of birth is in the future.
|
|
26
|
+
*/
|
|
27
|
+
ageFromDob(dob) {
|
|
28
|
+
const todayDate = this.today();
|
|
29
|
+
if (todayDate.compare(dob) < 0) {
|
|
30
|
+
throw new Error('Date of birth is in the future');
|
|
31
|
+
}
|
|
32
|
+
let years = todayDate.year - dob.year;
|
|
33
|
+
const monthDiff = todayDate.month - dob.month;
|
|
34
|
+
const dayDiff = todayDate.day - dob.day;
|
|
35
|
+
// Adjust years down if birthday hasn't occurred this year
|
|
36
|
+
if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) {
|
|
37
|
+
years--;
|
|
38
|
+
}
|
|
39
|
+
return years;
|
|
26
40
|
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Checks if a given date is today.
|
|
43
|
+
* @param date - The date to check.
|
|
44
|
+
* @returns True if the date is today, false otherwise.
|
|
45
|
+
*/
|
|
46
|
+
isDateToday(date) {
|
|
47
|
+
return this.today().compare(date) === 0;
|
|
33
48
|
}
|
|
34
|
-
|
|
49
|
+
/**
|
|
50
|
+
* @returns The current date and time.
|
|
51
|
+
*/
|
|
52
|
+
now() {
|
|
53
|
+
return nowFn(this.timezone);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* @returns The current date.
|
|
57
|
+
*/
|
|
58
|
+
today() {
|
|
59
|
+
return todayFn(this.timezone);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** Gets the day index of the date */
|
|
63
|
+
export function getDayIndexOfDate(date) {
|
|
64
|
+
// Always start 0 on Monday
|
|
65
|
+
return getDayOfWeek(date, DEFAULT_LOCALE, 'mon');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Gets the day of the week for a given date.
|
|
69
|
+
* @param date - The date to get the day of the week for.
|
|
70
|
+
* @returns The day of the week
|
|
71
|
+
*/
|
|
72
|
+
export function getDayOfDate(date) {
|
|
73
|
+
return Days[getDayIndexOfDate(date)];
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Checks if a given date is a specific day of the week.
|
|
77
|
+
* @param date - The date to check.
|
|
78
|
+
* @param dayOfWeek - The day of the week to check against.
|
|
79
|
+
* @returns True if the date is the specified day, false otherwise.
|
|
80
|
+
*/
|
|
81
|
+
export function isDateDay(date, dayOfWeek) {
|
|
82
|
+
const dateDay = getDayOfDate(date);
|
|
83
|
+
return dateDay === dayOfWeek;
|
|
35
84
|
}
|
|
85
|
+
/* Intervals */
|
|
36
86
|
/**
|
|
37
87
|
* Checks if two time ranges overlap, boundaries are not considered overlapping.
|
|
38
88
|
* @param start1 - The start time of the first range.
|
|
@@ -57,19 +107,6 @@ export function datesWithin(date1, date2, duration) {
|
|
|
57
107
|
return false;
|
|
58
108
|
return date1.add(duration).compare(date2) >= 0;
|
|
59
109
|
}
|
|
60
|
-
/** Gets the day index of the date */
|
|
61
|
-
export function getDayIndex(date) {
|
|
62
|
-
// Always start 0 on Monday
|
|
63
|
-
return getDayOfWeek(date, DEFAULT_LOCALE, 'mon');
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Gets the day of the week for a given date.
|
|
67
|
-
* @param date - The date to get the day of the week for.
|
|
68
|
-
* @returns The day of the week
|
|
69
|
-
*/
|
|
70
|
-
export function getDayOfDate(date) {
|
|
71
|
-
return Days[getDayIndex(date)];
|
|
72
|
-
}
|
|
73
110
|
/**
|
|
74
111
|
* Gets the most recent occurrence of a day of the week.
|
|
75
112
|
* @param dayOfWeek - The day of the week
|
|
@@ -79,7 +116,7 @@ export function getDayOfDate(date) {
|
|
|
79
116
|
*/
|
|
80
117
|
export function getLastDateOfDay(dayOfWeek, startDate) {
|
|
81
118
|
const dayIndex = DayIndex[dayOfWeek];
|
|
82
|
-
const startIndex =
|
|
119
|
+
const startIndex = getDayIndexOfDate(startDate);
|
|
83
120
|
// Already on the day
|
|
84
121
|
if (startIndex === dayIndex)
|
|
85
122
|
return startDate;
|
|
@@ -126,7 +163,7 @@ export function getLastMonths(count, startDate) {
|
|
|
126
163
|
*/
|
|
127
164
|
export function getNextDateOfDay(dayOfWeek, startDate) {
|
|
128
165
|
const dayIndex = DayIndex[dayOfWeek];
|
|
129
|
-
const startIndex =
|
|
166
|
+
const startIndex = getDayIndexOfDate(startDate);
|
|
130
167
|
// Already on the day
|
|
131
168
|
if (startIndex === dayIndex)
|
|
132
169
|
return startDate;
|
|
@@ -134,25 +171,6 @@ export function getNextDateOfDay(dayOfWeek, startDate) {
|
|
|
134
171
|
const addition = (dayIndex - startIndex + 7) % 7;
|
|
135
172
|
return startDate.add({ days: addition });
|
|
136
173
|
}
|
|
137
|
-
/* Intervals */
|
|
138
|
-
/**
|
|
139
|
-
* Checks if a given date is a specific day of the week.
|
|
140
|
-
* @param date - The date to check.
|
|
141
|
-
* @param dayOfWeek - The day of the week to check against.
|
|
142
|
-
* @returns True if the date is the specified day, false otherwise.
|
|
143
|
-
*/
|
|
144
|
-
export function isDateDay(date, dayOfWeek) {
|
|
145
|
-
const dateDay = getDayOfDate(date);
|
|
146
|
-
return dateDay === dayOfWeek;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Checks if a given date is today.
|
|
150
|
-
* @param date - The date to check.
|
|
151
|
-
* @returns True if the date is today, false otherwise.
|
|
152
|
-
*/
|
|
153
|
-
export function isDateToday(date, timezone) {
|
|
154
|
-
return today(timezone).compare(date) === 0;
|
|
155
|
-
}
|
|
156
174
|
const msPerWeek = 7 * 24 * 60 * 60 * 1000;
|
|
157
175
|
/**
|
|
158
176
|
* Calculates the difference in weeks between two dates.
|
|
@@ -160,9 +178,10 @@ const msPerWeek = 7 * 24 * 60 * 60 * 1000;
|
|
|
160
178
|
* @param date2 - The second date in order.
|
|
161
179
|
*/
|
|
162
180
|
export function dateDiffWeeks(date1, date2) {
|
|
163
|
-
const
|
|
164
|
-
const
|
|
165
|
-
|
|
181
|
+
const date1Ms = date1.toDate('UTC').getTime();
|
|
182
|
+
const date2Ms = date2.toDate('UTC').getTime();
|
|
183
|
+
const absDiff = Math.abs(date2Ms - date1Ms);
|
|
184
|
+
return Math.floor(absDiff / msPerWeek);
|
|
166
185
|
}
|
|
167
186
|
/* Formatting */
|
|
168
187
|
/* Day of the week*/
|
|
@@ -253,12 +272,22 @@ export function formatDateShort(date) {
|
|
|
253
272
|
* Formats the month only.
|
|
254
273
|
* @param date - The date to format.
|
|
255
274
|
* @returns The formatted month string.
|
|
256
|
-
* @example "Oct"
|
|
275
|
+
* @example "Oct 23"
|
|
257
276
|
*/
|
|
258
277
|
export function formatMonth(date) {
|
|
259
278
|
return formatDate(date, MonthFormatter);
|
|
260
279
|
}
|
|
261
280
|
/* Times */
|
|
281
|
+
/**
|
|
282
|
+
* Gives time in HH:MM format
|
|
283
|
+
* @param time
|
|
284
|
+
* @returns string of time in that format
|
|
285
|
+
*/
|
|
286
|
+
export function formatTime(time) {
|
|
287
|
+
const hours = padNum(time.hour, 2);
|
|
288
|
+
const minutes = padNum(time.minute, 2);
|
|
289
|
+
return `${hours}:${minutes}`;
|
|
290
|
+
}
|
|
262
291
|
/**
|
|
263
292
|
* Calculates the end time given a starting time and duration.
|
|
264
293
|
* @param timeStart starting time
|
|
@@ -267,7 +296,7 @@ export function formatMonth(date) {
|
|
|
267
296
|
*/
|
|
268
297
|
export function formatTimeEnd(timeStart, durationMinutes) {
|
|
269
298
|
const timeEnd = timeStart.add({ minutes: durationMinutes });
|
|
270
|
-
return
|
|
299
|
+
return formatTime(timeEnd);
|
|
271
300
|
}
|
|
272
301
|
/**
|
|
273
302
|
* Gives time in HH:MM:SS format
|
|
@@ -280,16 +309,18 @@ export function formatTimeFull(time) {
|
|
|
280
309
|
const seconds = padNum(time.second, 2);
|
|
281
310
|
return `${hours}:${minutes}:${seconds}`;
|
|
282
311
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
*/
|
|
288
|
-
export function formatTimeShort(time) {
|
|
289
|
-
const hours = padNum(time.hour, 2);
|
|
290
|
-
const minutes = padNum(time.minute, 2);
|
|
291
|
-
return `${hours}:${minutes}`;
|
|
312
|
+
/* Helpers */
|
|
313
|
+
function formatDate(date, formatter) {
|
|
314
|
+
const nativeDate = date.toDate(getLocalTimeZone());
|
|
315
|
+
return formatter.format(nativeDate);
|
|
292
316
|
}
|
|
317
|
+
// Pad number with zeroes to the left
|
|
318
|
+
function padNum(num, len) {
|
|
319
|
+
if (isNaN(num))
|
|
320
|
+
return '0'.repeat(len);
|
|
321
|
+
return num.toString().padStart(len, '0');
|
|
322
|
+
}
|
|
323
|
+
/* State handling */
|
|
293
324
|
/**
|
|
294
325
|
* Unfreezes a CalendarDate object from a snapshot.
|
|
295
326
|
* @param raw - The snapshot of the CalendarDate object.
|
|
@@ -306,17 +337,13 @@ export function unfreezeDate(raw) {
|
|
|
306
337
|
export function unfreezeTime(raw) {
|
|
307
338
|
return new Time(raw.hour, raw.minute, raw.second, raw.millisecond);
|
|
308
339
|
}
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
if (isNaN(num)) {
|
|
317
|
-
return '0'.repeat(len);
|
|
318
|
-
}
|
|
319
|
-
return num.toString().padStart(len, '0');
|
|
340
|
+
/**
|
|
341
|
+
* Unfreezes a ZonedDateTime object from a snapshot.
|
|
342
|
+
* @param date - The snapshot of the ZonedDateTime object.
|
|
343
|
+
* @returns The unfrozen ZonedDateTime object.
|
|
344
|
+
*/
|
|
345
|
+
export function unfreezeAbsoluteDate(date) {
|
|
346
|
+
return new ZonedDateTime(date.year, date.month, date.day, date.timeZone, date.offset, date.hour, date.minute, date.second, date.millisecond);
|
|
320
347
|
}
|
|
321
348
|
// SerDe
|
|
322
349
|
export const dateTransport = {
|
|
@@ -4,17 +4,17 @@ This package provides utilities for sending emails using AWS Simple Email Servic
|
|
|
4
4
|
|
|
5
5
|
## Key Features
|
|
6
6
|
|
|
7
|
-
- **Cloudflare Workers Compatible**: Uses direct AWS SES API calls
|
|
8
|
-
- **AWS Signature V4**:
|
|
7
|
+
- **Cloudflare Workers Compatible**: Uses `aws4fetch` for direct AWS SES API calls
|
|
8
|
+
- **AWS Signature V4**: Handled by `aws4fetch` for secure API requests
|
|
9
9
|
- **Zero Heavy Dependencies**: No AWS SDK required, works in any JavaScript runtime with fetch support
|
|
10
10
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
The implementation uses:
|
|
14
14
|
|
|
15
|
+
- `aws4fetch` for AWS Signature V4 signing and requests
|
|
15
16
|
- Native `fetch` API for HTTP requests
|
|
16
|
-
-
|
|
17
|
-
- Native `DOMParser` for XML response parsing
|
|
17
|
+
- Native `DOMParser` for XML response parsing (optional, used for error/response parsing)
|
|
18
18
|
|
|
19
19
|
## Configuration
|
|
20
20
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AwsClient } from 'aws4fetch';
|
|
2
2
|
/**
|
|
3
3
|
* Send an email using AWS SES API.
|
|
4
4
|
* Uses AWS Signature V4 signing and fetch API for Cloudflare Workers compatibility.
|
|
@@ -71,21 +71,29 @@ export async function sendEmail(options) {
|
|
|
71
71
|
const host = `email.${awsRegion}.amazonaws.com`;
|
|
72
72
|
const path = '/';
|
|
73
73
|
try {
|
|
74
|
-
|
|
75
|
-
const { headers } = await signRequest('POST', host, path, body, {
|
|
74
|
+
const aws = new AwsClient({
|
|
76
75
|
accessKeyId: awsAccessKeyId,
|
|
77
76
|
region: awsRegion,
|
|
78
|
-
secretAccessKey: awsSecretAccessKey
|
|
77
|
+
secretAccessKey: awsSecretAccessKey,
|
|
78
|
+
service: 'ses'
|
|
79
79
|
});
|
|
80
|
-
|
|
81
|
-
const
|
|
80
|
+
const url = `https://${host}${path}`;
|
|
81
|
+
const init = {
|
|
82
82
|
body,
|
|
83
83
|
headers: {
|
|
84
|
-
|
|
85
|
-
'Content-Length': body.length.toString(),
|
|
86
|
-
Host: host
|
|
84
|
+
'Content-Type': 'application/x-form-urlencoded'
|
|
87
85
|
},
|
|
88
86
|
method: 'POST'
|
|
87
|
+
};
|
|
88
|
+
// Sign the request and then use the global fetch.
|
|
89
|
+
// We avoid using aws.fetch() directly as it can cause issues in some test environments
|
|
90
|
+
// or when fetch is mocked/replaced after AwsClient instantiation.
|
|
91
|
+
const signedRequest = await aws.sign(url, init);
|
|
92
|
+
// Use two-argument fetch to satisfy tests that expect the second argument to be an options object
|
|
93
|
+
const response = await fetch(signedRequest.url, {
|
|
94
|
+
body: init.body,
|
|
95
|
+
headers: signedRequest.headers,
|
|
96
|
+
method: signedRequest.method
|
|
89
97
|
});
|
|
90
98
|
const responseText = await response.text();
|
|
91
99
|
if (!response.ok) {
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export type Result<T, E> = {
|
|
2
|
+
error: E;
|
|
3
|
+
ok: false;
|
|
4
|
+
} | {
|
|
5
|
+
ok: true;
|
|
6
|
+
value: T;
|
|
7
|
+
};
|
|
8
|
+
export declare const Result: {
|
|
9
|
+
/**
|
|
10
|
+
* Creates a failed result with the given error.
|
|
11
|
+
*/
|
|
12
|
+
err<E>(error: E): {
|
|
13
|
+
error: E;
|
|
14
|
+
ok: false;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Creates a successful result with the given value.
|
|
18
|
+
*/
|
|
19
|
+
ok<T>(value: T): {
|
|
20
|
+
ok: true;
|
|
21
|
+
value: T;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Returns true if the result is Ok.
|
|
25
|
+
*/
|
|
26
|
+
isOk<T, E>(result: Result<T, E>): result is {
|
|
27
|
+
ok: true;
|
|
28
|
+
value: T;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Returns true if the result is Err.
|
|
32
|
+
*/
|
|
33
|
+
isErr<T, E>(result: Result<T, E>): result is {
|
|
34
|
+
error: E;
|
|
35
|
+
ok: false;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Returns the contained Ok value or a provided default.
|
|
39
|
+
*/
|
|
40
|
+
unwrapOr<T, E>(result: Result<T, E>, defaultValue: T): T;
|
|
41
|
+
/**
|
|
42
|
+
* Returns the contained Ok value or computes it from the provided op.
|
|
43
|
+
* @param op - Computes value in error case or throws an error.
|
|
44
|
+
*/
|
|
45
|
+
unwrapOrElse<T, E>(result: Result<T, E>, op: (error: E) => T): T;
|
|
46
|
+
/**
|
|
47
|
+
* Maps a Result<T, E> to Result<U, E> by applying a function to a contained Ok value,
|
|
48
|
+
* leaving an Err value untouched.
|
|
49
|
+
*/
|
|
50
|
+
map<T, U, E>(result: Result<T, E>, fn: (val: T) => U): Result<U, E>;
|
|
51
|
+
/**
|
|
52
|
+
* Maps a Result<T, E> to Result<T, F> by applying a function to a contained Err value,
|
|
53
|
+
* leaving an Ok value untouched.
|
|
54
|
+
*/
|
|
55
|
+
mapErr<T, E, F>(result: Result<T, E>, fn: (err: E) => F): Result<T, F>;
|
|
56
|
+
/**
|
|
57
|
+
* Calls op if the result is Ok, otherwise returns the Err value of self.
|
|
58
|
+
* This function can be used for control flow based on Result values.
|
|
59
|
+
*/
|
|
60
|
+
andThen<T, U, E>(result: Result<T, E>, op: (val: T) => Result<U, E>): Result<U, E>;
|
|
61
|
+
/**
|
|
62
|
+
* Calls op if the result is Err, otherwise returns the Ok value of self.
|
|
63
|
+
*/
|
|
64
|
+
orElse<T, E, F>(result: Result<T, E>, op: (err: E) => Result<T, F>): Result<T, F>;
|
|
65
|
+
/**
|
|
66
|
+
* Pattern matches the Result and returns the result of the corresponding arm.
|
|
67
|
+
*/
|
|
68
|
+
match<T, E, R>(result: Result<T, E>, arms: {
|
|
69
|
+
err: (err: E) => R;
|
|
70
|
+
ok: (val: T) => R;
|
|
71
|
+
}): R;
|
|
72
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export const Result = {
|
|
2
|
+
/**
|
|
3
|
+
* Creates a failed result with the given error.
|
|
4
|
+
*/
|
|
5
|
+
err(error) {
|
|
6
|
+
return { error, ok: false };
|
|
7
|
+
},
|
|
8
|
+
/**
|
|
9
|
+
* Creates a successful result with the given value.
|
|
10
|
+
*/
|
|
11
|
+
ok(value) {
|
|
12
|
+
return { ok: true, value };
|
|
13
|
+
},
|
|
14
|
+
/**
|
|
15
|
+
* Returns true if the result is Ok.
|
|
16
|
+
*/
|
|
17
|
+
isOk(result) {
|
|
18
|
+
return result.ok;
|
|
19
|
+
},
|
|
20
|
+
/**
|
|
21
|
+
* Returns true if the result is Err.
|
|
22
|
+
*/
|
|
23
|
+
isErr(result) {
|
|
24
|
+
return !result.ok;
|
|
25
|
+
},
|
|
26
|
+
/**
|
|
27
|
+
* Returns the contained Ok value or a provided default.
|
|
28
|
+
*/
|
|
29
|
+
unwrapOr(result, defaultValue) {
|
|
30
|
+
if (result.ok)
|
|
31
|
+
return result.value;
|
|
32
|
+
return defaultValue;
|
|
33
|
+
},
|
|
34
|
+
/**
|
|
35
|
+
* Returns the contained Ok value or computes it from the provided op.
|
|
36
|
+
* @param op - Computes value in error case or throws an error.
|
|
37
|
+
*/
|
|
38
|
+
unwrapOrElse(result, op) {
|
|
39
|
+
if (result.ok)
|
|
40
|
+
return result.value;
|
|
41
|
+
return op(result.error);
|
|
42
|
+
},
|
|
43
|
+
/**
|
|
44
|
+
* Maps a Result<T, E> to Result<U, E> by applying a function to a contained Ok value,
|
|
45
|
+
* leaving an Err value untouched.
|
|
46
|
+
*/
|
|
47
|
+
map(result, fn) {
|
|
48
|
+
if (result.ok)
|
|
49
|
+
return Result.ok(fn(result.value));
|
|
50
|
+
return result;
|
|
51
|
+
},
|
|
52
|
+
/**
|
|
53
|
+
* Maps a Result<T, E> to Result<T, F> by applying a function to a contained Err value,
|
|
54
|
+
* leaving an Ok value untouched.
|
|
55
|
+
*/
|
|
56
|
+
mapErr(result, fn) {
|
|
57
|
+
if (!result.ok)
|
|
58
|
+
return Result.err(fn(result.error));
|
|
59
|
+
return result;
|
|
60
|
+
},
|
|
61
|
+
/**
|
|
62
|
+
* Calls op if the result is Ok, otherwise returns the Err value of self.
|
|
63
|
+
* This function can be used for control flow based on Result values.
|
|
64
|
+
*/
|
|
65
|
+
andThen(result, op) {
|
|
66
|
+
if (result.ok)
|
|
67
|
+
return op(result.value);
|
|
68
|
+
return result;
|
|
69
|
+
},
|
|
70
|
+
/**
|
|
71
|
+
* Calls op if the result is Err, otherwise returns the Ok value of self.
|
|
72
|
+
*/
|
|
73
|
+
orElse(result, op) {
|
|
74
|
+
if (!result.ok)
|
|
75
|
+
return op(result.error);
|
|
76
|
+
return result;
|
|
77
|
+
},
|
|
78
|
+
/**
|
|
79
|
+
* Pattern matches the Result and returns the result of the corresponding arm.
|
|
80
|
+
*/
|
|
81
|
+
match(result, arms) {
|
|
82
|
+
if (result.ok)
|
|
83
|
+
return arms.ok(result.value);
|
|
84
|
+
return arms.err(result.error);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|