diff --git a/.eslintrc.json b/.eslintrc.json index 5138e58..99fa606 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -7,11 +7,18 @@ "plugin:drizzle/recommended" ], "parser": "@typescript-eslint/parser", - "plugins": ["@typescript-eslint", "drizzle"], + "plugins": ["@typescript-eslint", "tsdoc", "drizzle"], + "rules": { + "tsdoc/syntax": "warn" + }, "overrides": [ { "files": ["**/*.js", "**/*.jsx", "**/*.cjs", "**/*.mjs"], - "extends": ["plugin:@typescript-eslint/disable-type-checked"] + "extends": ["plugin:@typescript-eslint/disable-type-checked"], + "rules": { + "@typescript-eslint/no-var-requires": "off", + "tsdoc/syntax": "off" + } } ], "root": true diff --git a/package.json b/package.json index 60fca81..000bfd1 100644 --- a/package.json +++ b/package.json @@ -37,8 +37,8 @@ }, "dependencies": { "@ark-ui/react": "^1.3.0", - "@auth/core": "^0.23.0", - "@auth/drizzle-adapter": "^0.3.17", + "@auth/core": "^0.24.0", + "@auth/drizzle-adapter": "^0.4.0", "@next/bundle-analyzer": "canary", "@react-aria/datepicker": "^3.9.1", "@react-aria/i18n": "^3.10.0", @@ -71,7 +71,7 @@ "@pandacss/types": "^0.28.0", "@park-ui/panda-preset": "^0.31.0", "@types/luxon": "^3.4.2", - "@types/node": "^20.11.7", + "@types/node": "^20.11.8", "@types/pg": "^8.11.0", "@types/react": "^18.2.48", "@types/react-dom": "^18.2.18", @@ -83,6 +83,7 @@ "eslint": "^8.56.0", "eslint-config-next": "14.1.0", "eslint-plugin-drizzle": "^0.2.3", + "eslint-plugin-tsdoc": "^0.2.17", "husky": "^9.0.6", "lint-staged": "^15.2.0", "postcss": "^8.4.33", diff --git a/prettier.config.js b/prettier.config.js index 278366b..ffbc20d 100644 --- a/prettier.config.js +++ b/prettier.config.js @@ -11,7 +11,7 @@ module.exports = { "^(next/(.*)$)|^(next$)", "", "", - "^@/(components|lib|utils|interfaces)/(.*)$", + "^@/(components|hooks|interfaces|lib|utils)/(.*)$", "^@/(.*)$", "^[./]", ], diff --git a/src/components/calendar/Calendar.tsx b/src/components/calendar/Calendar.tsx index e74094b..fecb8b4 100644 --- a/src/components/calendar/Calendar.tsx +++ b/src/components/calendar/Calendar.tsx @@ -1,10 +1,9 @@ import React, { type CSSProperties } from "react"; import { Info } from "luxon"; -import { CalendarEvent, CurrentTime } from "@/components/calendar"; -import { Text } from "@/components/ui"; +import { CalendarEvent, CalendarHeader, CalendarTimes, CurrentTime } from "@/components/calendar"; import { Grid, GridItem, type GridProps } from "@/lib/styled/jsx"; -import { getTimeRange, getWeekdaysIndex, sortWeekdays, TIME_NARROW } from "@/utils/time"; +import { hoursFromIntervals, reorderWeekdaysByStart, WEEKDAY_NUMBERS } from "@/utils/time"; import type { Event } from "@/interfaces"; type CalendarProps = { @@ -12,43 +11,12 @@ type CalendarProps = { } & GridProps; export const Calendar = ({ events, ...rest }: CalendarProps) => { - const timeRange = getTimeRange(events.map((event) => event.interval)); - const [start, end] = [timeRange[0], timeRange.at(-1)]; - - // end is undefined, or start or end times are invalid - if (!end || !start.isValid || !end.isValid) return null; + const timeRange = hoursFromIntervals(events.map((event) => event.interval)); return ( - - {sortWeekdays(Info.weekdays("short")).map((day) => ( - - {day} - - ))} - - - - {timeRange.map((time) => ( - - - {time.toFormat(TIME_NARROW)} - - - ))} - + + { bg="border.muted" // using outline here since border would misalign the grid outline="muted" - grid="repeat(var(--rows), token(sizes.12)) / repeat(7, 1fr)" + grid="[main-start] repeat(var(--rows), token(sizes.12)) [main-end] / [main-start] repeat(7, 1fr) [main-end]" style={{ "--rows": timeRange.length } as CSSProperties} > - {/* Current time indicator */} - + {/* Indicates current time */} + {/* Events */} - - {events.map((event) => - event.weekdays.map((day) => ( - - )) - )} - + {events.map((event) => + event.weekdays.map((day) => ( + + )) + )} {/* Decorative elements, creates borders between cells */} - {/* Using subgrid here to allow grid to auto place elements while overlapping */} - - {sortWeekdays(getWeekdaysIndex()).map((day) => + {/* Using subgrid here to allow subgrid to auto place elements while above elements + /* can overlap, which is impossible on an implicit grid */} + + {reorderWeekdaysByStart(WEEKDAY_NUMBERS).map((day) => timeRange.map((time) => ( )) )} diff --git a/src/components/calendar/CalendarEvent.tsx b/src/components/calendar/CalendarEvent.tsx index c6c047a..88ae186 100644 --- a/src/components/calendar/CalendarEvent.tsx +++ b/src/components/calendar/CalendarEvent.tsx @@ -1,13 +1,14 @@ -import { Info, type WeekdayNumbers } from "luxon"; +import type { DateTime, WeekdayNumbers } from "luxon"; import { Text } from "@/components/ui"; import type { Event } from "@/interfaces/time"; import { Flex, GridItem } from "@/lib/styled/jsx"; import { hexToRgb, rgbToYIQ } from "@/utils/colors"; import { getPercentage } from "@/utils/common"; +import { getWeekdayOffset } from "@/utils/time"; type CalendarEventProps = { - startHour: number; + timeRange: DateTime[]; weekday: WeekdayNumbers; } & Omit; @@ -15,15 +16,15 @@ export const CalendarEvent = ({ name, interval, weekday, - startHour, + timeRange, color, }: CalendarEventProps) => { const duration = Math.ceil(interval.length("hour")); if (!interval.start?.isValid) return; - const startOfWeek = Info.getStartOfWeek(); + const startHour = timeRange[0].hour; // offset by the start of the week - const col = ((weekday - startOfWeek + 7) % 7) + 1; + const col = getWeekdayOffset(weekday); const row = interval.start.hour - startHour + 2; const offset = interval.start.minute / 60; diff --git a/src/components/calendar/CalendarHeader.tsx b/src/components/calendar/CalendarHeader.tsx new file mode 100644 index 0000000..c10641d --- /dev/null +++ b/src/components/calendar/CalendarHeader.tsx @@ -0,0 +1,16 @@ +import { Info } from "luxon"; + +import { Grid, GridItem, type GridProps } from "@/lib/styled/jsx"; +import { reorderWeekdaysByStart } from "@/utils/time"; + +export const CalendarHeader = (props: GridProps) => { + return ( + + {reorderWeekdaysByStart(Info.weekdays("short")).map((day) => ( + + {day} + + ))} + + ); +}; diff --git a/src/components/calendar/CalendarTimes.tsx b/src/components/calendar/CalendarTimes.tsx new file mode 100644 index 0000000..4fc189b --- /dev/null +++ b/src/components/calendar/CalendarTimes.tsx @@ -0,0 +1,37 @@ +import type { DateTimeMaybeValid } from "luxon"; + +import { Text } from "@/components/ui"; +import { Grid, GridProps } from "@/lib/styled/jsx"; +import { TIME_NARROW } from "@/utils/time"; + +type CalendarTimesProps = { + timeRange: DateTimeMaybeValid[]; +} & GridProps; + +export const CalendarTimes = ({ timeRange, ...rest }: CalendarTimesProps) => { + return ( + + {timeRange.map((time) => ( + + + {time.toFormat(TIME_NARROW)} + + + ))} + + ); +}; diff --git a/src/components/calendar/CurrentTime.tsx b/src/components/calendar/CurrentTime.tsx index 7455e5e..ab842e1 100644 --- a/src/components/calendar/CurrentTime.tsx +++ b/src/components/calendar/CurrentTime.tsx @@ -1,11 +1,12 @@ "use client"; -import React, { useEffect, useState, type CSSProperties } from "react"; -import { DateTime, type HourNumbers } from "luxon"; +import React, { useState } from "react"; +import { useLocale } from "@react-aria/i18n"; +import { DateTime, Info, type HourNumbers } from "luxon"; import { Box, GridItem } from "@/lib/styled/jsx"; import { getPercentage } from "@/utils/common"; -import { getWeekdayOffset } from "@/utils/time"; +import { useInterval } from "@/hooks"; type CurrentTimeProps = { startHour: HourNumbers; @@ -13,35 +14,27 @@ type CurrentTimeProps = { }; export const CurrentTime = ({ startHour, endHour }: CurrentTimeProps) => { - const [curr, setCurr] = useState(DateTime.now()); + const { locale } = useLocale(); + const [curr, setCurr] = useState(DateTime.now().setLocale(locale)); - useEffect(() => { - const interval = setInterval(() => { - setCurr(DateTime.now()); - // update every minute - }, 60 * 1000); + // update every minute + useInterval(() => setCurr(DateTime.now().setLocale(locale)), 60 * 1000); - return () => clearInterval(interval); - }, []); + if (!Info.features().localeWeek) return null; // time indicator would not be visible since it is outside of the calendar if (startHour > curr.hour || endHour < curr.hour) return null; - const offset = curr.minute / 60; - - // z-index so above any events - // visibility hidden so user can interact with events return ( ); diff --git a/src/components/calendar/index.ts b/src/components/calendar/index.ts index fc9e2d8..c0f8287 100644 --- a/src/components/calendar/index.ts +++ b/src/components/calendar/index.ts @@ -1,3 +1,5 @@ export * from "./Calendar"; export * from "./CalendarEvent"; export * from "./CurrentTime"; +export * from "./CalendarHeader"; +export * from "./CalendarTimes"; diff --git a/src/components/form/Form.tsx b/src/components/form/Form.tsx index 4a54034..eccb597 100644 --- a/src/components/form/Form.tsx +++ b/src/components/form/Form.tsx @@ -17,9 +17,9 @@ type FormProps = { * A wrapper around the native form element that handles form submission and error handling. For * all errors, a toast notification is shown. * - * @param children The form elements - * @param action The form action (with state) that is used in `useFormState()` - * @param onSubmitSuccess A callback that is called when the form is successfully submitted + * @param children - The form elements + * @param action - The form action (with state) that is used in `useFormState()` + * @param onSubmitSuccess - A callback that is called when the form is successfully submitted * (i.e. state.status === "ok") */ export const Form = ({ children, action, onSubmitSuccess, ...rest }: FormProps) => { diff --git a/src/components/form/FormButton.tsx b/src/components/form/FormButton.tsx index b3324e1..664b821 100644 --- a/src/components/form/FormButton.tsx +++ b/src/components/form/FormButton.tsx @@ -8,7 +8,7 @@ type FormButtonProps = { * Button wrapped in a form, useful for server actions that don't require input * but still need to be submitted as a form. * - * @param action The action to perform when the button is clicked. + * @param action - The action to perform when the button is clicked. * @returns A button wrapped in a form. */ export const FormButton = ({ action, children, ...rest }: FormButtonProps) => { diff --git a/src/components/form/Prompt.tsx b/src/components/form/Prompt.tsx index 50ebc94..48dfd4c 100644 --- a/src/components/form/Prompt.tsx +++ b/src/components/form/Prompt.tsx @@ -19,10 +19,10 @@ type PromptProps = { * A wrapper around the Dialog component that handles form submission and error handling. For all * errors, a toast notification is shown. * - * @param title The title of the dialog - * @param description The description of the dialog - * @param children The form elements - * @param action The form action (with state) + * @param title - The title of the dialog + * @param description - The description of the dialog + * @param children - The form elements + * @param action - The form action (with state) */ export const Prompt = ({ title, description, children, action, ...props }: PromptProps) => { const [isOpen, setIsOpen] = useState(false); diff --git a/src/components/ui/Progress.tsx b/src/components/ui/Progress.tsx index 12cfc65..112783a 100644 --- a/src/components/ui/Progress.tsx +++ b/src/components/ui/Progress.tsx @@ -15,7 +15,7 @@ export interface ProgressProps children?: ReactNode; /** * The type of progress to render. - * @default linear + * @defaultValue linear */ type?: "linear" | "circular"; } diff --git a/src/hooks/index.ts b/src/hooks/index.ts new file mode 100644 index 0000000..4a32083 --- /dev/null +++ b/src/hooks/index.ts @@ -0,0 +1 @@ +export * from "./useInterval"; diff --git a/src/hooks/useInterval.ts b/src/hooks/useInterval.ts new file mode 100644 index 0000000..78c7f20 --- /dev/null +++ b/src/hooks/useInterval.ts @@ -0,0 +1,32 @@ +"use client"; + +import { useEffect, useRef } from "react"; + +/** + * See {@link https://overreacted.io/making-setinterval-declarative-with-react-hooks/} + * + * @param callback - Function to execute at most every `delay` milliseconds + * @param delay - Milliseconds between calls to `callback`. `null` to disable the interval. + */ +export const useInterval = ReturnType>( + callback: T, + delay: number | null +): void => { + const savedCallback = useRef(); + + useEffect(() => { + savedCallback.current = callback; + }, [callback]); + + useEffect(() => { + if (delay === null) return; + + const id = setInterval(() => { + if (savedCallback.current) { + savedCallback.current(); + } + }, delay); + + return () => clearInterval(id); + }, [delay]); +}; diff --git a/src/utils/time.ts b/src/utils/time.ts index 278c737..0f67a14 100644 --- a/src/utils/time.ts +++ b/src/utils/time.ts @@ -1,4 +1,14 @@ -import { DateTime, Info, InfoUnitOptions, Interval, type WeekdayNumbers } from "luxon"; +import { + DateTime, + DateTimeJSOptions, + Info, + Interval, + type IntervalMaybeValid, + type WeekdayNumbers, +} from "luxon"; + +// ISO 8601 weekday numbers, starting with Monday (1) and ending with Sunday (7) +export const WEEKDAY_NUMBERS: WeekdayNumbers[] = [1, 2, 3, 4, 5, 6, 7]; export const { TIME_SIMPLE } = DateTime; export const TIME_NARROW = "h a"; @@ -6,48 +16,69 @@ export const TIME_NARROW = "h a"; // Given two ISO strings, return an Interval export const getInterval = (start: string, end: string) => Interval.fromISO(`${start}/${end}`); -// indexed by 1-7, starting with Monday, based on ISO 8601 -// is own function, since the isoIndex and array index may get confusing +// Given an ISO weekday number, return the corresponding weekday name export const getWeekday = (isoIndex: WeekdayNumbers, ...rest: Parameters) => Info.weekdays(...rest)[isoIndex - 1]; -// Given an array of either weekday numbers or weekday names (sorted by ISO index 1-7 or Mon - Sun), -// return a new array such that the array is sorted by the start of the week (Sunday in the US). -export const sortWeekdays = (weekdays: T[]) => { - const start = Info.getStartOfWeek(); +/** + * Reorders an array of weekdays so that it starts from the weekday specified by the start of the week in the given locale. + * + * @example + * ``` + * // Returns [Sun, Mon, Tue, Wed, Thu, Fri, Sat] + * reorderWeekdaysByStart([Mon, Tue, Wed, Thu, Fri, Sat, Sun], "en-US") + * ``` + * + * @typeParam T - The type of the weekday array + * @param weekdays - The array of weekdays to reorder (e.g. [Mon, Tue, Wed, Thu, Fri, Sat, Sun] or [1, 2, 3, 4, 5, 6, 7]) + * @param input - Optional locale input to determine the start of the week + * @returns The reordered array of weekdays + */ +export const reorderWeekdaysByStart = ( + weekdays: T[], + input?: Info.LocaleInput +): T[] => { + if (!weekdays.length) return weekdays; + if (weekdays.length !== 7) throw new Error("Invalid array length"); + const start = Info.getStartOfWeek(input); return [...weekdays.slice(start - 1), ...weekdays.slice(0, start - 1)]; }; -// Return an array of the weekday indices, starting with Monday (1) and ending with Sunday (7) -export const getWeekdaysIndex = (opts?: InfoUnitOptions) => - Info.weekdays(undefined, opts).map((_, i) => (i + 1) as WeekdayNumbers); - -// Given an ISO weekday index, return the weekday index where start of week is 1, and end of week is 7 -export const getWeekdayOffset = (isoIndex: WeekdayNumbers) => - ((isoIndex - Info.getStartOfWeek() + 7) % 7) + 1; - /** - * Given an array of intervals, return an array of DateTime objects from the start to - * the end of the intervals, padded by an hour on each side. + * Converts an ISO weekday number where Monday is 1 and Sunday is 7 to a weekday number where the + * start of the week is 1 and the end of the week is 7. + * + * @example + * ``` + * // Returns 2, since Monday (1) is the 2nd day of the week in the en-US locale + * getWeekdayOffset(1, { locale: "en-US" }) + * ``` + * + * @param isoIndex - The ISO weekday index (1 for Monday, 7 for Sunday). + * @param input - Optional locale input to determine the start of the week. + * @returns The adjusted weekday index based on the custom start of the week. */ -export const getTimeRange = (intervals: Interval[]) => { - // merge overlapping intervals, and combine the first and last interval to - // get the full range - const merged = Interval.merge(intervals); - const [first, last] = [merged.at(0), merged.at(-1)]; - - if (!first || !last) throw new Error("Invalid interval"); +export const getWeekdayOffset = (isoIndex: WeekdayNumbers, input?: Info.LocaleInput) => + ((isoIndex - Info.getStartOfWeek(input) + 7) % 7) + 1; - const combinedInterval = first.union(last); - if (!combinedInterval.isValid) throw new Error("Invalid interval"); +/** + * Returns an array of DateTime objects spaced one hour apart, starting at the start of + * the given intervals and ending at the rounded-up end hour of the given intervals. + * + * @param intervals - The intervals to get the time range of + * @returns An array of DateTime objects spaced one hour apart + * @throws If the merged interval is invalid + */ +export const hoursFromIntervals = (intervals: IntervalMaybeValid[], opts?: DateTimeJSOptions) => { + const merged = intervals.reduce((merged, current) => merged.union(current)); + if (!merged.isValid) throw new Error("Invalid interval"); - // pad by an hour on each side - const startHour = Math.max(0, combinedInterval.start.hour - 1); - const endHour = Math.min(23, combinedInterval.end.hour + 1); + const duration = Math.ceil(merged.toDuration("hours").hours); - // create an array of hours from the start to the end - return Array.from({ length: endHour - startHour + 1 }, (_, i) => - DateTime.fromObject({ hour: startHour + i }) - ); + // length is duration + 1, since labels are rendered at end of grid, meaning + // there must be an extra grid row + return Array.from({ length: duration + 1 }, (_, i) => + DateTime.fromObject({ hour: merged.start.hour + i }, opts) + ).filter((dt): dt is DateTime => dt.isValid); }; diff --git a/tsconfig.json b/tsconfig.json index 1c61143..d8cc928 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,9 +17,9 @@ "plugins": [{ "name": "next" }], "paths": { "@/*": ["./src/*"], - "@/lib/styled/*": ["./styled-system/*"] - } + "@/lib/styled/*": ["./styled-system/*"], + }, }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "exclude": ["node_modules"], } diff --git a/yarn.lock b/yarn.lock index 1ff0d56..dad6be0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -128,9 +128,9 @@ __metadata: languageName: node linkType: hard -"@auth/core@npm:0.23.0, @auth/core@npm:^0.23.0": - version: 0.23.0 - resolution: "@auth/core@npm:0.23.0" +"@auth/core@npm:0.24.0, @auth/core@npm:^0.24.0": + version: 0.24.0 + resolution: "@auth/core@npm:0.24.0" dependencies: "@panva/hkdf": "npm:^1.1.1" "@types/cookie": "npm:0.6.0" @@ -144,16 +144,16 @@ __metadata: peerDependenciesMeta: nodemailer: optional: true - checksum: 70e998fabaaa8ecb710272f40a5bec0874e47f5b105a36d6be36547ec08dfbec8fb330c6ca91559bfe24575bed9a4ab5eee3bac0a038e3f3a13d9d6cb8b10b6e + checksum: b8d8c66bc35d18a6ffa80e21b122747cb0c40826f68eb8c22a1b4dda01aba62c2050a1d5e4997e92a6756edad4103faafe8d9a49c7278d991e690c3ebbdb6035 languageName: node linkType: hard -"@auth/drizzle-adapter@npm:^0.3.17": - version: 0.3.17 - resolution: "@auth/drizzle-adapter@npm:0.3.17" +"@auth/drizzle-adapter@npm:^0.4.0": + version: 0.4.0 + resolution: "@auth/drizzle-adapter@npm:0.4.0" dependencies: - "@auth/core": "npm:0.23.0" - checksum: becafb828f74f925865f483e1b6508e8aa2c610e4448068ab1a3cf71349813701ca40250e34be219cb1d8e33794a5adc99cca0330e2f706fb1147329476c2fd4 + "@auth/core": "npm:0.24.0" + checksum: 7badd709de35f85ab3d8dc0d35c1888092a116ab1f4605900e8976a89c2a8b382b442034439f3eb9d55e500b390556540180f9fde1180a56a15aeb1655336694 languageName: node linkType: hard @@ -1341,6 +1341,25 @@ __metadata: languageName: node linkType: hard +"@microsoft/tsdoc-config@npm:0.16.2": + version: 0.16.2 + resolution: "@microsoft/tsdoc-config@npm:0.16.2" + dependencies: + "@microsoft/tsdoc": "npm:0.14.2" + ajv: "npm:~6.12.6" + jju: "npm:~1.4.0" + resolve: "npm:~1.19.0" + checksum: 9e8c176b68f01c8bb38e6365d5b543e471bba59fced6070d9bd35b32461fbd650c2e1a6f686e8dca0cf22bc5e7d796e4213e66bce4426c8cb9864c1f6ca6836c + languageName: node + linkType: hard + +"@microsoft/tsdoc@npm:0.14.2": + version: 0.14.2 + resolution: "@microsoft/tsdoc@npm:0.14.2" + checksum: c018857ad439144559ce34a397a29ace7cf5b24b999b8e3c1b88d878338088b3a453eaac4435beaf2c7eae13c4c0aac81e42f96f0f1d48e8d4eeb438eb3bb82f + languageName: node + linkType: hard + "@next/bundle-analyzer@npm:canary": version: 14.1.1-canary.9 resolution: "@next/bundle-analyzer@npm:14.1.1-canary.9" @@ -2472,12 +2491,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^20.11.7": - version: 20.11.7 - resolution: "@types/node@npm:20.11.7" +"@types/node@npm:^20.11.8": + version: 20.11.8 + resolution: "@types/node@npm:20.11.8" dependencies: undici-types: "npm:~5.26.4" - checksum: ba4b41542b64f21a881a277189e761c553d00af0b1c02f2d8a47ebe8bc29a00ed21b45adf0bf9af2cf8ea6c92a443853d4f7b690081ceaecc150719cc574e9ea + checksum: cd4eff91ff2291b909cf8ce81f3117effcfd59c435a9d42a9a085f5de8f414eabfbe4558f53a275eedc280a97393d71084812d91cf31fba436a01369d80133b5 languageName: node linkType: hard @@ -3686,7 +3705,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^6.12.4": +"ajv@npm:^6.12.4, ajv@npm:~6.12.6": version: 6.12.6 resolution: "ajv@npm:6.12.6" dependencies: @@ -5556,6 +5575,16 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-tsdoc@npm:^0.2.17": + version: 0.2.17 + resolution: "eslint-plugin-tsdoc@npm:0.2.17" + dependencies: + "@microsoft/tsdoc": "npm:0.14.2" + "@microsoft/tsdoc-config": "npm:0.16.2" + checksum: 26cad40b22f3dc0adfb06b1ea12f7d3c9cb257ac8bb56ad6a023e3b3bdfc6144d95a8b01323563e75283cca90baaf4d68816f5cea6994c6cd660a642e820847a + languageName: node + linkType: hard + "eslint-scope@npm:^7.2.2": version: 7.2.2 resolution: "eslint-scope@npm:7.2.2" @@ -6440,8 +6469,8 @@ __metadata: resolution: "inkhorn@workspace:." dependencies: "@ark-ui/react": "npm:^1.3.0" - "@auth/core": "npm:^0.23.0" - "@auth/drizzle-adapter": "npm:^0.3.17" + "@auth/core": "npm:^0.24.0" + "@auth/drizzle-adapter": "npm:^0.4.0" "@ianvs/prettier-plugin-sort-imports": "npm:^4.1.1" "@next/bundle-analyzer": "npm:canary" "@pandacss/dev": "npm:^0.28.0" @@ -6456,7 +6485,7 @@ __metadata: "@tiptap/react": "npm:^2.1.16" "@tiptap/starter-kit": "npm:^2.1.16" "@types/luxon": "npm:^3.4.2" - "@types/node": "npm:^20.11.7" + "@types/node": "npm:^20.11.8" "@types/pg": "npm:^8.11.0" "@types/react": "npm:^18.2.48" "@types/react-dom": "npm:^18.2.18" @@ -6474,6 +6503,7 @@ __metadata: eslint: "npm:^8.56.0" eslint-config-next: "npm:14.1.0" eslint-plugin-drizzle: "npm:^0.2.3" + eslint-plugin-tsdoc: "npm:^0.2.17" husky: "npm:^9.0.6" lint-staged: "npm:^15.2.0" lucide-react: "npm:^0.316.0" @@ -6581,7 +6611,7 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.11.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1": +"is-core-module@npm:^2.1.0, is-core-module@npm:^2.11.0, is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1": version: 2.13.1 resolution: "is-core-module@npm:2.13.1" dependencies: @@ -6893,6 +6923,13 @@ __metadata: languageName: node linkType: hard +"jju@npm:~1.4.0": + version: 1.4.0 + resolution: "jju@npm:1.4.0" + checksum: f3f444557e4364cfc06b1abf8331bf3778b26c0c8552ca54429bc0092652172fdea26cbffe33e1017b303d5aa506f7ede8571857400efe459cb7439180e2acad + languageName: node + linkType: hard + "jose@npm:^5.1.3": version: 5.1.3 resolution: "jose@npm:5.1.3" @@ -8322,7 +8359,7 @@ __metadata: languageName: node linkType: hard -"path-parse@npm:^1.0.7": +"path-parse@npm:^1.0.6, path-parse@npm:^1.0.7": version: 1.0.7 resolution: "path-parse@npm:1.0.7" checksum: 11ce261f9d294cc7a58d6a574b7f1b935842355ec66fba3c3fd79e0f036462eaf07d0aa95bb74ff432f9afef97ce1926c720988c6a7451d8a584930ae7de86e1 @@ -9132,6 +9169,16 @@ __metadata: languageName: node linkType: hard +"resolve@npm:~1.19.0": + version: 1.19.0 + resolution: "resolve@npm:1.19.0" + dependencies: + is-core-module: "npm:^2.1.0" + path-parse: "npm:^1.0.6" + checksum: 1c8afdfb88c9adab0a19b6f16756d47f5917f64047bf5a38c17aa543aae5ccca2a0631671b19ce8460a7a3e65ead98ee70e046d3056ec173d3377a27487848a8 + languageName: node + linkType: hard + "resolve@patch:resolve@npm%3A^1.22.4#optional!builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" @@ -9158,6 +9205,16 @@ __metadata: languageName: node linkType: hard +"resolve@patch:resolve@npm%3A~1.19.0#optional!builtin": + version: 1.19.0 + resolution: "resolve@patch:resolve@npm%3A1.19.0#optional!builtin::version=1.19.0&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.1.0" + path-parse: "npm:^1.0.6" + checksum: 254980f60dd9fdb28b34a511e70df6e3027d9627efce86a40757eea9b87252d172829c84517554560c4541ebfe207868270c19a0f086997b41209367aa8ef74f + languageName: node + linkType: hard + "restore-cursor@npm:^4.0.0": version: 4.0.0 resolution: "restore-cursor@npm:4.0.0"