diff --git a/client/src/utilities/confetti.ts b/client/src/utilities/confetti.ts index 0f2a28f3..19c75829 100644 --- a/client/src/utilities/confetti.ts +++ b/client/src/utilities/confetti.ts @@ -5,17 +5,19 @@ export const fireConfetti = () => { jsConfetti.addConfetti({ emojis: [ - '👏', - '🙌', - '🎉', - 'đŸĒŠ', - '🎊', - 'đŸĒ…', - 'đŸĒ„', - '✨', - '🌟', - '🎇', - '🎆', + '💀', + '🍁', + '🎃', + 'đŸĻ‡', + '🧛', + '🔮', + 'đŸ‘ģ', + '🧙', + '🕷', + '🕸', + 'đŸĻ‰', + '🌙', + '🧟', ], }) } diff --git a/server/package-lock.json b/server/package-lock.json index c4aa2574..7ab82af7 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -10,8 +10,6 @@ "dependencies": { "@jhwelch/made-with": "^0.0.3", "@notionhq/client": "^2.2.5", - "@types/express": "^4.17.17", - "@types/node": "^20.0.0", "body-parser": "^1.20.2", "dotenv": "^16.0.3", "ejs": "^3.1.10", @@ -27,7 +25,9 @@ "devDependencies": { "@jest-mock/express": "^2.0.2", "@jest/globals": "^29.5.0", + "@types/express": "^5.0.0", "@types/luxon": "^3.4.2", + "@types/node": "^22.7.5", "jest": "^29.5.0", "mockdate": "^3.0.5", "nodemon": "^3.0.1", @@ -1828,6 +1828,32 @@ "@types/express": "^4.17.21" } }, + "node_modules/@jest-mock/express/node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@jest-mock/express/node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, "node_modules/@jest/console": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", @@ -2423,21 +2449,23 @@ } }, "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.0.tgz", + "integrity": "sha512-DvZriSMehGHL1ZNLzi6MidnsDhUZM/x2pRdDIKdwbUNqqwHxMlRdkxtn6/EPKyqKpHqTl/4nRZsRNLpZxZRpPQ==", + "dev": true, "license": "MIT", "dependencies": { "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", + "@types/express-serve-static-core": "^5.0.0", "@types/qs": "*", "@types/serve-static": "*" } }, "node_modules/@types/express-serve-static-core": { - "version": "4.19.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", - "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.0.tgz", + "integrity": "sha512-AbXMTZGt40T+KON9/Fdxx0B2WK5hsgxcfXJLr5bFpZ7b4JCex2WyQPTEKdXqfHiY5nKKBScZ7yCoO6Pvgxfvnw==", + "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", @@ -2519,9 +2547,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.16.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.10.tgz", - "integrity": "sha512-vQUKgWTjEIRFCvK6CyriPH3MZYiYlNy0fKiEYHWbcoWLEgs4opurGGKlebrTLqdSMIbXImH6XExNiIyNUv3WpA==", + "version": "22.7.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", + "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", "license": "MIT", "dependencies": { "undici-types": "~6.19.2" @@ -4058,15 +4086,6 @@ "@google-cloud/storage": "^7.7.0" } }, - "node_modules/firebase-admin/node_modules/@types/node": { - "version": "22.7.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz", - "integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==", - "license": "MIT", - "dependencies": { - "undici-types": "~6.19.2" - } - }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -5727,6 +5746,30 @@ "node": ">=14" } }, + "node_modules/jwks-rsa/node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/jwks-rsa/node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, "node_modules/jwks-rsa/node_modules/debug": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", diff --git a/server/package.json b/server/package.json index 8cbce37b..6ed945f0 100644 --- a/server/package.json +++ b/server/package.json @@ -24,8 +24,6 @@ "dependencies": { "@jhwelch/made-with": "^0.0.3", "@notionhq/client": "^2.2.5", - "@types/express": "^4.17.17", - "@types/node": "^20.0.0", "body-parser": "^1.20.2", "dotenv": "^16.0.3", "ejs": "^3.1.10", @@ -41,7 +39,9 @@ "devDependencies": { "@jest-mock/express": "^2.0.2", "@jest/globals": "^29.5.0", + "@types/express": "^5.0.0", "@types/luxon": "^3.4.2", + "@types/node": "^22.7.5", "jest": "^29.5.0", "mockdate": "^3.0.5", "nodemon": "^3.0.1", diff --git a/server/src/controllers/cacheController.ts b/server/src/controllers/cacheController.ts index 2f3e3c5f..f6ea8429 100644 --- a/server/src/controllers/cacheController.ts +++ b/server/src/controllers/cacheController.ts @@ -13,11 +13,6 @@ import { Week } from '@server/models/week' import { minutesAsTimeString, timeStringAsMinutes } from '@server/helpers/timeStrings' export default class CacheController { - static PATHS = { - weeks: '/api/cache/weeks', - emailTemplates: '/api/cache/email-templates', - } - constructor ( private firestore: FirestoreAdapter, private notionAdapter: NotionAdapter, diff --git a/server/src/controllers/calendarController.ts b/server/src/controllers/calendarController.ts index 6c23b929..f6122520 100644 --- a/server/src/controllers/calendarController.ts +++ b/server/src/controllers/calendarController.ts @@ -2,8 +2,6 @@ import { Request, Response } from 'express' import Config from '@server/config/config' export default class CalendarController { - static PATH = '/calendar' - constructor ( private config: Config, ) {} diff --git a/server/src/controllers/cronController.ts b/server/src/controllers/cronController.ts index b8f02644..e020c683 100644 --- a/server/src/controllers/cronController.ts +++ b/server/src/controllers/cronController.ts @@ -4,10 +4,6 @@ import Config from '@server/config/config' import { tomorrow } from '@server/data/dateUtils' class CronController { - static PATHS = { - reminders: '/cron/reminders', - } - constructor ( protected config: Config, protected firestore: FirestoreAdapter, diff --git a/server/src/controllers/healthCheckController.ts b/server/src/controllers/healthCheckController.ts index 298f5461..3133a786 100644 --- a/server/src/controllers/healthCheckController.ts +++ b/server/src/controllers/healthCheckController.ts @@ -1,10 +1,6 @@ import { type Request, type Response } from 'express' export default class HealthCheckController { - static PATHS = { - index: '/health_check', - } - static async index (_req: Request, res: Response): Promise { res.status(200).send('ok') } diff --git a/server/src/controllers/rsvpController.ts b/server/src/controllers/rsvpController.ts index a623fadb..e65e4ac2 100644 --- a/server/src/controllers/rsvpController.ts +++ b/server/src/controllers/rsvpController.ts @@ -5,10 +5,6 @@ import { validate } from '@server/helpers/validation' import { Week } from '@server/models/week' export default class RsvpController { - static PATHS = { - store: '/api/weeks/:weekId/rsvp', - } - constructor ( private firestore: FirestoreAdapter, ) {} diff --git a/server/src/controllers/subscriptionController.ts b/server/src/controllers/subscriptionController.ts index 531ad12b..8b0b84ee 100644 --- a/server/src/controllers/subscriptionController.ts +++ b/server/src/controllers/subscriptionController.ts @@ -5,11 +5,6 @@ import { validate } from '@server/helpers/validation' import { withMessage } from '@server/helpers/messageBuilder' export default class SubscriptionController { - static PATHS = { - store: '/api/subscriptions', - destroy: '/unsubscribe', - } - static readonly SUCCESS_MESSAGE = { message: 'Thank you for signing up! See you soon.', } diff --git a/server/src/controllers/suggestionController.ts b/server/src/controllers/suggestionController.ts index 51202fe1..e10dcbfe 100644 --- a/server/src/controllers/suggestionController.ts +++ b/server/src/controllers/suggestionController.ts @@ -8,10 +8,6 @@ export default class SuggestionController { private notion: NotionAdapter, ) {} - static PATHS = { - store: '/suggestions', - } - store = async (req: Request, res: Response): Promise => { if (!this.validate(req, res)) return diff --git a/server/src/controllers/weekEventController.ts b/server/src/controllers/weekEventController.ts index a50f96f8..4c64d75c 100644 --- a/server/src/controllers/weekEventController.ts +++ b/server/src/controllers/weekEventController.ts @@ -3,10 +3,6 @@ import FirestoreAdapter from '@server/data/firestore/firestoreAdapter' import { icalGenerator } from '@server/data/icalGenerator' export default class WeekEventController { - static PATHS = { - show: '/weeks/:weekId/event', - } - constructor ( private firestore: FirestoreAdapter, ) {} diff --git a/server/src/models/user.ts b/server/src/models/user.ts index 83260712..c0c90bf8 100644 --- a/server/src/models/user.ts +++ b/server/src/models/user.ts @@ -1,5 +1,4 @@ import { DocumentData, QueryDocumentSnapshot } from 'firebase/firestore' -import SubscriptionController from '@server/controllers/subscriptionController' export default class User { constructor ( @@ -21,6 +20,5 @@ export default class User { reminders: this.reminders, }) - unsubscribeUrl = (): string => - SubscriptionController.PATHS.destroy + `?token=${this.id}` + unsubscribeUrl = (): string => `/unsubscribe?token=${this.id}` } diff --git a/server/src/routers/appRouter.ts b/server/src/routers/appRouter.ts index 33f2895e..df0d797e 100644 --- a/server/src/routers/appRouter.ts +++ b/server/src/routers/appRouter.ts @@ -55,33 +55,16 @@ function routes ( const weekEventController = new WeekEventController(firestore) return [ - new Route(HealthCheckController.PATHS.index, HealthCheckController.index), + new Route('/health_check', HealthCheckController.index), new Route('/api/weeks', weekController.index), - new Route(RsvpController.PATHS.store, rsvpController.store, HttpVerb.POST), - new Route(CacheController.PATHS.weeks, cacheController.cacheWeeks), - new Route( - CacheController.PATHS.emailTemplates, - cacheController.cacheEmailTemplates, - ), - new Route( - SuggestionController.PATHS.store, - suggestionController.store, - HttpVerb.POST, - ), - new Route( - CalendarController.PATH, - calendarController.index, - ), - new Route( - SubscriptionController.PATHS.store, - subscriptionController.store, - HttpVerb.POST, - ), - new Route( - SubscriptionController.PATHS.destroy, - subscriptionController.destroy, - ), - new Route(CronController.PATHS.reminders, cronController.reminders), - new Route(WeekEventController.PATHS.show, weekEventController.show), + new Route('/api/weeks/:weekId/rsvp', rsvpController.store, HttpVerb.POST), + new Route('/api/cache/weeks', cacheController.cacheWeeks), + new Route('/api/cache/email-templates', cacheController.cacheEmailTemplates), + new Route('/suggestions', suggestionController.store, HttpVerb.POST), + new Route('/calendar', calendarController.index), + new Route('/api/subscriptions', subscriptionController.store, HttpVerb.POST), + new Route('/unsubscribe', subscriptionController.destroy), + new Route('/cron/reminders', cronController.reminders), + new Route('/weeks/:weekId/event', weekEventController.show), ] }