diff --git a/package.json b/package.json index 4f50e70..0318202 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,8 @@ "@types/node": "18.14.0", "@types/react": "18.0.28", "@types/react-dom": "18.0.11", + "date-fns": "^2.29.3", + "ioredis": "^5.3.1", "life360-node-api": "^0.0.10", "next": "13.1.6", "react": "18.2.0", diff --git a/src/env/schema.mjs b/src/env/schema.mjs index 9df5544..20bcca0 100644 --- a/src/env/schema.mjs +++ b/src/env/schema.mjs @@ -1,19 +1,20 @@ // @ts-check -import { z } from "zod"; +import { z } from 'zod'; /** * Specify your server-side environment variables schema here. * This way you can ensure the app isn't built with invalid env vars. */ export const serverSchema = z.object({ - API_KEY: z.string(), - CRONITOR_ACCOUNT_ID: z.string(), - CRONITOR_JOB_ID: z.string(), - LIFE360_USERNAME: z.string(), - LIFE360_PASSWORD: z.string(), - LIFE360_MEMBER_ID: z.string(), - MAX_DISTANCE: z.coerce.number().positive(), - CENTER_LATITUDE: z.coerce.number().min(-90).max(90), - CENTER_LONGITUDE: z.coerce.number().min(-180).max(180), - EDGE_CACHE_TIME_SECONDS: z.coerce.number().int().nonnegative().default(60), + API_KEY: z.string(), + CRONITOR_ACCOUNT_ID: z.string(), + CRONITOR_JOB_ID: z.string(), + LIFE360_USERNAME: z.string(), + LIFE360_PASSWORD: z.string(), + LIFE360_MEMBER_ID: z.string(), + MAX_DISTANCE: z.coerce.number().positive(), + CENTER_LATITUDE: z.coerce.number().min(-90).max(90), + CENTER_LONGITUDE: z.coerce.number().min(-180).max(180), + EDGE_CACHE_TIME_SECONDS: z.coerce.number().int().nonnegative().default(60), + REDIS_URL: z.string().url() }); diff --git a/src/env/server.mjs b/src/env/server.mjs index 6a324aa..bad2e2e 100644 --- a/src/env/server.mjs +++ b/src/env/server.mjs @@ -3,39 +3,40 @@ * This file is included in `/next.config.mjs` which ensures the app isn't built with invalid env vars. * It has to be a `.mjs`-file to be imported there. */ -import { serverSchema } from "./schema.mjs"; -import { formatErrors } from "./util.mjs"; +import { serverSchema } from './schema.mjs'; +import { formatErrors } from './util.mjs'; const _serverEnv = serverSchema.safeParse({ - API_KEY: process.env.API_KEY, - CRONITOR_ACCOUNT_ID: process.env.CRONITOR_ACCOUNT_ID, - CRONITOR_JOB_ID: process.env.CRONITOR_JOB_ID, - LIFE360_USERNAME: process.env.LIFE360_USERNAME, - LIFE360_PASSWORD: process.env.LIFE360_PASSWORD, - LIFE360_MEMBER_ID: process.env.LIFE360_MEMBER_ID, - MAX_DISTANCE: process.env.MAX_DISTANCE, - CENTER_LATITUDE: process.env.CENTER_LATITUDE, - CENTER_LONGITUDE: process.env.CENTER_LONGITUDE, - EDGE_CACHE_TIME_SECONDS: process.env.EDGE_CACHE_TIME_SECONDS, + API_KEY: process.env.API_KEY, + CRONITOR_ACCOUNT_ID: process.env.CRONITOR_ACCOUNT_ID, + CRONITOR_JOB_ID: process.env.CRONITOR_JOB_ID, + LIFE360_USERNAME: process.env.LIFE360_USERNAME, + LIFE360_PASSWORD: process.env.LIFE360_PASSWORD, + LIFE360_MEMBER_ID: process.env.LIFE360_MEMBER_ID, + MAX_DISTANCE: process.env.MAX_DISTANCE, + CENTER_LATITUDE: process.env.CENTER_LATITUDE, + CENTER_LONGITUDE: process.env.CENTER_LONGITUDE, + EDGE_CACHE_TIME_SECONDS: process.env.EDGE_CACHE_TIME_SECONDS, + REDIS_URL: process.env.REDIS_URL }); if (_serverEnv.success === false) { - console.error( - "❌ Invalid environment variables:\n", - ...formatErrors(_serverEnv.error.format()) - ); - throw new Error("Invalid environment variables"); + console.error( + '❌ Invalid environment variables:\n', + ...formatErrors(_serverEnv.error.format()) + ); + throw new Error('Invalid environment variables'); } /** * Validate that server-side environment variables are not exposed to the client. */ for (let key of Object.keys(_serverEnv.data)) { - if (key.startsWith("NEXT_PUBLIC_")) { - console.warn("❌ You are exposing a server-side env-variable:", key); + if (key.startsWith('NEXT_PUBLIC_')) { + console.warn('❌ You are exposing a server-side env-variable:', key); - throw new Error("You are exposing a server-side env-variable"); - } + throw new Error('You are exposing a server-side env-variable'); + } } export const env = { ..._serverEnv.data }; diff --git a/yarn.lock b/yarn.lock index 85fc0c3..6872f25 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@ioredis/commands@^1.1.1": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" + integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg== + "@next/env@13.1.6": version "13.1.6" resolved "https://registry.yarnpkg.com/@next/env/-/env-13.1.6.tgz#c4925609f16142ded1a5cb833359ab17359b7a93" @@ -125,16 +130,53 @@ client-only@0.0.1: resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== +cluster-key-slot@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" + integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== + csstype@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== +date-fns@^2.29.3: + version "2.29.3" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" + integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== + +debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +denque@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" + integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== + https@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/https/-/https-1.0.0.tgz#3c37c7ae1a8eeb966904a2ad1e975a194b7ed3a4" integrity sha512-4EC57ddXrkaF0x83Oj8sM6SLQHAWXw90Skqu2M4AEWENZ3F02dFJE/GARA8igO79tcgYqGrD7ae4f5L3um2lgg== +ioredis@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.3.1.tgz#55d394a51258cee3af9e96c21c863b1a97bf951f" + integrity sha512-C+IBcMysM6v52pTLItYMeV4Hz7uriGtoJdz7SSBDX6u+zwSYGirLdQh3L7t/OItWITcw3gTFMjJReYUwS4zihg== + dependencies: + "@ioredis/commands" "^1.1.1" + cluster-key-slot "^1.1.0" + debug "^4.3.4" + denque "^2.1.0" + lodash.defaults "^4.2.0" + lodash.isarguments "^3.1.0" + redis-errors "^1.2.0" + redis-parser "^3.0.0" + standard-as-callback "^2.1.0" + "js-tokens@^3.0.0 || ^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -149,6 +191,16 @@ life360-node-api@^0.0.10: https "^1.0.0" querystring "^0.2.0" +lodash.defaults@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== + +lodash.isarguments@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== + loose-envify@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -156,6 +208,11 @@ loose-envify@^1.1.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + nanoid@^3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" @@ -225,6 +282,18 @@ react@18.2.0: dependencies: loose-envify "^1.1.0" +redis-errors@^1.0.0, redis-errors@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" + integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w== + +redis-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" + integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A== + dependencies: + redis-errors "^1.0.0" + scheduler@^0.23.0: version "0.23.0" resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" @@ -237,6 +306,11 @@ source-map-js@^1.0.2: resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== +standard-as-callback@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" + integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== + styled-jsx@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f"