From 2f5da6f771d7c5d8c293cb60c464ab15e37449a5 Mon Sep 17 00:00:00 2001 From: Davis Haupt Date: Sun, 26 Mar 2023 14:56:44 -0400 Subject: [PATCH] added zod --- package-lock.json | 16 ++++++++- package.json | 3 +- src/types/schema.ts | 83 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 src/types/schema.ts diff --git a/package-lock.json b/package-lock.json index 0ad32b6..f57afb7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,7 +30,8 @@ "obsidian-daily-notes-interface": "^0.9.4", "react": "^17.0.2", "react-dom": "^17.0.2", - "rrule": "^2.7.2" + "rrule": "^2.7.2", + "zod": "^3.21.4" }, "devDependencies": { "@types/co": "^4.6.3", @@ -9557,6 +9558,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zod": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", + "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", @@ -16183,6 +16192,11 @@ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true }, + "zod": { + "version": "3.21.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz", + "integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==" + }, "zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/package.json b/package.json index 0990394..5c0c187 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "obsidian-daily-notes-interface": "^0.9.4", "react": "^17.0.2", "react-dom": "^17.0.2", - "rrule": "^2.7.2" + "rrule": "^2.7.2", + "zod": "^3.21.4" } } diff --git a/src/types/schema.ts b/src/types/schema.ts new file mode 100644 index 0000000..23e6da0 --- /dev/null +++ b/src/types/schema.ts @@ -0,0 +1,83 @@ +import { z, ZodError } from "zod"; +import { DateTime, Duration } from "luxon"; + +const parsedDate = () => + z.string().transform((val) => DateTime.fromFormat(val, "yyyy-MM-dd")); +const parsedTime = () => + z.string().transform((val, ctx) => { + let parsed = DateTime.fromFormat(val, "h:mm a"); + if (parsed.invalidReason) { + parsed = DateTime.fromFormat(val, "HH:mm"); + } + + if (parsed.invalidReason) { + ctx.addIssue({ + code: z.ZodIssueCode.custom, + message: parsed.invalidReason, + }); + return z.NEVER; + } + + return Duration.fromISOTime( + parsed.toISOTime({ + includeOffset: false, + includePrefix: false, + }) + ); + }); + +const TimeSchema = z.discriminatedUnion("allDay", [ + z.object({ allDay: z.literal(true) }), + z.object({ + allDay: z.literal(false).optional(), + startTime: parsedTime(), + endTime: parsedTime(), + }), +]); + +const CommonSchema = z.object({ title: z.string(), id: z.string().optional() }); + +const EventSchema = z.discriminatedUnion("type", [ + z + .object({ + type: z.literal("single").default("single"), + date: parsedDate(), + endDate: parsedDate().optional(), + completed: z.date().or(z.literal(false)).or(z.literal(null)), + }) + .merge(CommonSchema), + z + .object({ + type: z.literal("recurring"), + daysOfWeek: z.array(z.enum(["U", "M", "T", "W", "R", "F", "S"])), + startRecur: parsedDate().optional(), + endRecur: parsedDate().optional(), + }) + .merge(CommonSchema), + z + .object({ + type: z.literal("rrule"), + startDate: parsedDate(), + rrule: z.string(), + skipDates: z.array(parsedDate()), + }) + .merge(CommonSchema), +]); + +type EventType = z.infer; +type TimeType = z.infer; + +export type OFCEvent = EventType & TimeType; + +export function parseEvent(obj: any): OFCEvent | null { + try { + const timeInfo = TimeSchema.parse(obj); + const eventInfo = EventSchema.parse(obj); + return { ...eventInfo, ...timeInfo }; + } catch (e) { + if (e instanceof ZodError) { + console.debug("Parsing failed with errors", e.errors); + } + return null; + } +}