mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-04-26 04:45:22 -04:00
convert APIs to edge functions (#1648)
This commit is contained in:
parent
62419f1380
commit
aa64279dd8
@ -1,5 +1,6 @@
|
||||
AIRTABLE_API_KEY=
|
||||
AIRTABLE_BASE=
|
||||
DATABASE_URL=
|
||||
GH_PUBLIC_TOKEN=
|
||||
HCAPTCHA_SECRET_KEY=
|
||||
NEXT_PUBLIC_HCAPTCHA_SITE_KEY=
|
||||
@ -10,8 +11,6 @@ POSTGRES_PRISMA_URL=
|
||||
POSTGRES_URL=
|
||||
POSTGRES_URL_NON_POOLING=
|
||||
POSTGRES_USER=
|
||||
SENTRY_AUTH_TOKEN=
|
||||
SENTRY_DSN=
|
||||
SPOTIFY_CLIENT_ID=
|
||||
SPOTIFY_CLIENT_SECRET=
|
||||
SPOTIFY_REFRESH_TOKEN=
|
||||
|
@ -1,22 +1,17 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import { IS_DEV_SERVER } from "../config/constants";
|
||||
import { PrismaClient } from "@prisma/client/edge";
|
||||
|
||||
// PrismaClient is attached to the `global` object in development to prevent
|
||||
// exhausting your database connection limit.
|
||||
//
|
||||
// Learn more:
|
||||
// creating PrismaClient here prevents next.js from starting too many concurrent prisma instances and exhausting the
|
||||
// number of connection pools available (especially when hot reloading from `next dev`).
|
||||
// https://pris.ly/d/help/next-js-best-practices
|
||||
|
||||
declare global {
|
||||
// allow global `var` declarations
|
||||
// eslint-disable-next-line no-var
|
||||
var prisma: PrismaClient | undefined;
|
||||
}
|
||||
const globalForPrisma = globalThis as unknown as {
|
||||
prisma: PrismaClient | undefined;
|
||||
};
|
||||
|
||||
export const prisma =
|
||||
global.prisma ||
|
||||
globalForPrisma.prisma ??
|
||||
new PrismaClient({
|
||||
log: ["query"],
|
||||
});
|
||||
|
||||
if (IS_DEV_SERVER) global.prisma = prisma;
|
||||
if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;
|
||||
|
@ -1,38 +0,0 @@
|
||||
import * as Sentry from "@sentry/node";
|
||||
import "@sentry/tracing";
|
||||
import { BUILD_ENV } from "../config/constants";
|
||||
|
||||
const IsomorphicSentry = () => {
|
||||
// https://docs.sentry.io/platforms/node/configuration/options/
|
||||
Sentry.init({
|
||||
dsn: process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN || "",
|
||||
environment: BUILD_ENV,
|
||||
tracesSampleRate: 1.0,
|
||||
});
|
||||
|
||||
return Sentry;
|
||||
};
|
||||
|
||||
export const logServerError = async (error: unknown) => {
|
||||
try {
|
||||
const sentryInstance = IsomorphicSentry();
|
||||
|
||||
// log error to sentry
|
||||
sentryInstance.captureException(error);
|
||||
|
||||
// give it 2 seconds to finish sending:
|
||||
// https://docs.sentry.io/platforms/node/configuration/draining/
|
||||
await sentryInstance.flush(2000);
|
||||
} catch (sentryError) {
|
||||
// cue inception bong
|
||||
console.error("Encountered an error logging an error... We are doomed.", sentryError);
|
||||
}
|
||||
|
||||
// also log the error normally to the Vercel console; will get picked up by log drain
|
||||
console.error(error);
|
||||
|
||||
// we really don't want to return *any* error from logging an error, so just keep it on the dl
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
export default IsomorphicSentry;
|
397
package-lock.json
generated
397
package-lock.json
generated
@ -16,10 +16,9 @@
|
||||
"@primer/octicons": "^19.4.0",
|
||||
"@prisma/client": "^4.16.1",
|
||||
"@react-spring/web": "^9.7.2",
|
||||
"@sentry/node": "^7.56.0",
|
||||
"@sentry/tracing": "^7.56.0",
|
||||
"@stitches/react": "^1.2.8",
|
||||
"@vercel/analytics": "^1.0.1",
|
||||
"@vercel/postgres": "^0.4.0",
|
||||
"comma-number": "^2.1.0",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"dayjs": "^1.11.8",
|
||||
@ -50,13 +49,13 @@
|
||||
"react-player": "~2.10.1",
|
||||
"react-textarea-autosize": "^8.5.0",
|
||||
"react-twitter-embed": "^4.0.4",
|
||||
"rehype-prism-plus": "^1.5.1",
|
||||
"rehype-prism-plus": "^1.6.1",
|
||||
"rehype-slug": "^5.1.0",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"remark-smartypants": "^2.0.0",
|
||||
"remark-unwrap-images": "^3.0.1",
|
||||
"remove-markdown": "^0.5.0",
|
||||
"simple-icons": "^9.2.0",
|
||||
"simple-icons": "^9.3.0",
|
||||
"sitemap": "^7.1.1",
|
||||
"stitches-normalize": "^2.0.0",
|
||||
"swr": "^2.2.0"
|
||||
@ -69,7 +68,7 @@
|
||||
"@types/node": "*",
|
||||
"@types/novnc__novnc": "^1.3.0",
|
||||
"@types/prop-types": "^15.7.5",
|
||||
"@types/react": "^18.2.13",
|
||||
"@types/react": "^18.2.14",
|
||||
"@types/react-dom": "^18.2.6",
|
||||
"@types/react-is": "^18.2.1",
|
||||
"@types/remove-markdown": "^0.3.1",
|
||||
@ -2281,6 +2280,14 @@
|
||||
"react": ">=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@neondatabase/serverless": {
|
||||
"version": "0.4.19",
|
||||
"resolved": "https://registry.npmjs.org/@neondatabase/serverless/-/serverless-0.4.19.tgz",
|
||||
"integrity": "sha512-atzpP9uBLrWPokXZdVy2iNPmmxVx51HXhrEObDb4KXmsyGEkGhCcb6cs51LA/oyXwjJUeB4AreOoVgMcPAIv5g==",
|
||||
"dependencies": {
|
||||
"@types/pg": "8.6.6"
|
||||
}
|
||||
},
|
||||
"node_modules/@next/env": {
|
||||
"version": "13.4.7",
|
||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.7.tgz",
|
||||
@ -2576,9 +2583,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@npmcli/map-workspaces/node_modules/minimatch": {
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz",
|
||||
"integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==",
|
||||
"version": "9.0.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.2.tgz",
|
||||
"integrity": "sha512-PZOT9g5v2ojiTL7r1xF6plNHLtOeTpSlDI007As2NlA2aYBMfVom17yqa6QzhmDP8QOhn7LjHTg7DFCVSSa6yg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
@ -2705,12 +2712,6 @@
|
||||
"url": "https://opencollective.com/unts"
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgr/utils/node_modules/tslib": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
||||
"integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@primer/octicons": {
|
||||
"version": "19.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-19.4.0.tgz",
|
||||
@ -2824,82 +2825,6 @@
|
||||
"integrity": "sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@sentry-internal/tracing": {
|
||||
"version": "7.56.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.56.0.tgz",
|
||||
"integrity": "sha512-OKI4Pz/O13gng8hT9rNc+gRV3+P7nnk1HnHlV8fgaQydS6DsRxoDL1sHa42tZGbh7K9jqNAP3TC6VjBOsr2tXA==",
|
||||
"dependencies": {
|
||||
"@sentry/core": "7.56.0",
|
||||
"@sentry/types": "7.56.0",
|
||||
"@sentry/utils": "7.56.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "7.56.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.56.0.tgz",
|
||||
"integrity": "sha512-Nuyyfh09Yz27kPo74fXHlrdmZeK6zrlJVtxQ6LkwuoaTBcNcesNXVaOtr6gjvUGUmsfriVPP3Jero5LXufV7GQ==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "7.56.0",
|
||||
"@sentry/utils": "7.56.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/node": {
|
||||
"version": "7.56.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.56.0.tgz",
|
||||
"integrity": "sha512-QXbWy/ypRxfFd8iP6zLvHInYZyjGKPrkVNYt43mhKAZHm764NxX/29vDfj1FztgG9Z6lVLIG2eyqTvLruYmsWw==",
|
||||
"dependencies": {
|
||||
"@sentry-internal/tracing": "7.56.0",
|
||||
"@sentry/core": "7.56.0",
|
||||
"@sentry/types": "7.56.0",
|
||||
"@sentry/utils": "7.56.0",
|
||||
"cookie": "^0.4.1",
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"lru_map": "^0.3.3",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/tracing": {
|
||||
"version": "7.56.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.56.0.tgz",
|
||||
"integrity": "sha512-Qy7lJdC2YBk9T8JFt4da7xHB3pTZH6yUiIwo5edmSBv2cY6MQ0QZgLzsjJurjf47+/WecVYYKdye9q4twsBlDA==",
|
||||
"dependencies": {
|
||||
"@sentry-internal/tracing": "7.56.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/types": {
|
||||
"version": "7.56.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.56.0.tgz",
|
||||
"integrity": "sha512-5WjhVOQm75ItOytOx2jTx+5yw8/qJ316+g1Di8dS9+kgIi1zniqdMcX00C2yYe3FMUgFB49PegCUYulm9Evapw==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/utils": {
|
||||
"version": "7.56.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.56.0.tgz",
|
||||
"integrity": "sha512-wgeX7bufxc//TjjSIE+gCMm8hVId7Jzvc+f441bYrWnNZBuzPIDW2BummCcPrKzSYe5GeYZDTZGV8YZGMLGBjw==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "7.56.0",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@stitches/react": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@stitches/react/-/react-1.2.8.tgz",
|
||||
@ -3173,11 +3098,6 @@
|
||||
"tslib": "^2.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/helpers/node_modules/tslib": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
||||
"integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w=="
|
||||
},
|
||||
"node_modules/@trysound/sax": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
|
||||
@ -3305,6 +3225,16 @@
|
||||
"integrity": "sha512-IiNumU7H5ezJhJlhFEUk8ouQ4z+DOX6Ldvlh2MwQ+fsN03FMLHJyAIBLVMaC+1pC43BMAqmTNMTK85sFlq0ADw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/pg": {
|
||||
"version": "8.6.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.6.6.tgz",
|
||||
"integrity": "sha512-O2xNmXebtwVekJDD+02udOncjVcMZQuTEQEMpKJ0ZRf5E7/9JJX3izhKUcUifBkyKpljyUM6BTgy2trmviKlpw==",
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"pg-protocol": "*",
|
||||
"pg-types": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/prismjs": {
|
||||
"version": "1.26.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.0.tgz",
|
||||
@ -3316,9 +3246,9 @@
|
||||
"integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w=="
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "18.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.13.tgz",
|
||||
"integrity": "sha512-vJ+zElvi/Zn9cVXB5slX2xL8PZodPCwPRDpittQdw43JR2AJ5k3vKdgJJyneV/cYgIbLQUwXa9JVDvUZXGba+Q==",
|
||||
"version": "18.2.14",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.14.tgz",
|
||||
"integrity": "sha512-A0zjq+QN/O0Kpe30hA1GidzyFjatVvrpIvWLxD+xv67Vt91TWWgco9IvrJBkeyHm1trGaFS/FSGqPlhyeZRm0g==",
|
||||
"dependencies": {
|
||||
"@types/prop-types": "*",
|
||||
"@types/scheduler": "*",
|
||||
@ -3685,6 +3615,20 @@
|
||||
"resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.0.1.tgz",
|
||||
"integrity": "sha512-Ux0c9qUfkcPqng3vrR0GTrlQdqNJ2JREn/2ydrVuKwM3RtMfF2mWX31Ijqo1opSjNAq6rK76PwtANw6kl6TAow=="
|
||||
},
|
||||
"node_modules/@vercel/postgres": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@vercel/postgres/-/postgres-0.4.0.tgz",
|
||||
"integrity": "sha512-GemRRKvLi90BC511WQzt5tfVLPNOQ9eNbbbaPquSgasm5ogfWLtjJSbNUD4jYEbs9IxbNovKqr0H0CAjJzOAyw==",
|
||||
"dependencies": {
|
||||
"@neondatabase/serverless": "0.4.19",
|
||||
"bufferutil": "4.0.7",
|
||||
"utf-8-validate": "6.0.3",
|
||||
"ws": "8.13.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.6"
|
||||
}
|
||||
},
|
||||
"node_modules/abbrev": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
|
||||
@ -3713,17 +3657,6 @@
|
||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
|
||||
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
|
||||
"dependencies": {
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/aggregate-error": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
|
||||
@ -3800,9 +3733,9 @@
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
|
||||
},
|
||||
"node_modules/aria-query": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.2.1.tgz",
|
||||
"integrity": "sha512-7uFg4b+lETFgdaJyETnILsXgnnzVnkHcgRbwbPwevm5x/LmUlt3MjczMRe1zg824iBgXZNRPTBftNYyRSKLp2g==",
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
|
||||
"integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"dequal": "^2.0.3"
|
||||
@ -4155,6 +4088,18 @@
|
||||
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/bufferutil": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.7.tgz",
|
||||
"integrity": "sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.14.2"
|
||||
}
|
||||
},
|
||||
"node_modules/bundle-name": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz",
|
||||
@ -4475,14 +4420,6 @@
|
||||
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz",
|
||||
"integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/copy-to-clipboard": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
|
||||
@ -4909,12 +4846,6 @@
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/dot-case/node_modules/tslib": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
||||
"integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/eastasianwidth": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
@ -4922,9 +4853,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.439",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.439.tgz",
|
||||
"integrity": "sha512-BHpErPSNhb9FB25+OwQP6mCAf3ZXfGbmuvc4LzBNVJwpCcXQJm++LerimocYRG9FRxUVRKZqaB7d0+pImSTPSg==",
|
||||
"version": "1.4.440",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.440.tgz",
|
||||
"integrity": "sha512-r6dCgNpRhPwiWlxbHzZQ/d9swfPaEJGi8ekqRBwQYaR3WmA5VkqQfBWSDDjuJU1ntO+W9tHx8OHV/96Q8e0dVw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
@ -5285,12 +5216,6 @@
|
||||
"eslint": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-mdx/node_modules/tslib": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
||||
"integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/eslint-module-utils": {
|
||||
"version": "2.8.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
|
||||
@ -5438,12 +5363,6 @@
|
||||
"eslint": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-mdx/node_modules/tslib": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
||||
"integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/eslint-plugin-prettier": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
|
||||
@ -6133,11 +6052,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/formik/node_modules/tslib": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
||||
"integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w=="
|
||||
},
|
||||
"node_modules/fs-constants": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
@ -6398,11 +6312,6 @@
|
||||
"graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/graphql-tag/node_modules/tslib": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
||||
"integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w=="
|
||||
},
|
||||
"node_modules/gray-matter": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz",
|
||||
@ -6645,18 +6554,6 @@
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
|
||||
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
|
||||
"dependencies": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
},
|
||||
"node_modules/human-signals": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
|
||||
@ -7764,17 +7661,6 @@
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/lower-case/node_modules/tslib": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
||||
"integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/lru_map": {
|
||||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz",
|
||||
"integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ=="
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
@ -9588,12 +9474,6 @@
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/no-case/node_modules/tslib": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
||||
"integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/node-abi": {
|
||||
"version": "3.45.0",
|
||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.45.0.tgz",
|
||||
@ -9645,6 +9525,16 @@
|
||||
"integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/node-gyp-build": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz",
|
||||
"integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==",
|
||||
"bin": {
|
||||
"node-gyp-build": "bin.js",
|
||||
"node-gyp-build-optional": "optional.js",
|
||||
"node-gyp-build-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"node_modules/node-releases": {
|
||||
"version": "2.0.12",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz",
|
||||
@ -10120,6 +10010,34 @@
|
||||
"is-reference": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pg-int8": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
|
||||
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pg-protocol": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz",
|
||||
"integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q=="
|
||||
},
|
||||
"node_modules/pg-types": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
|
||||
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
|
||||
"dependencies": {
|
||||
"pg-int8": "1.0.1",
|
||||
"postgres-array": "~2.0.0",
|
||||
"postgres-bytea": "~1.0.0",
|
||||
"postgres-date": "~1.0.4",
|
||||
"postgres-interval": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
@ -10182,6 +10100,41 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/postgres-array": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
|
||||
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/postgres-bytea": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
|
||||
"integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/postgres-date": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
|
||||
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/postgres-interval": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
|
||||
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
|
||||
"dependencies": {
|
||||
"xtend": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prebuild-install": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
|
||||
@ -10723,13 +10676,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rehype-prism-plus": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/rehype-prism-plus/-/rehype-prism-plus-1.5.1.tgz",
|
||||
"integrity": "sha512-mowYefSfrIkMMxkb0fwuEXlvc5nA9b1vQ6mzujM81Qx28RI0mo7jCHsBZ2tJ4eIJKXdFn+EdPkZZBGB10K02vg==",
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/rehype-prism-plus/-/rehype-prism-plus-1.6.1.tgz",
|
||||
"integrity": "sha512-HCLGvrbn9J1FSvsHo3/mJstToVJGe8czeUULpgPZhc3X21XJHCjYlZSBL4dH784WPUz/sW4PCATf8J1o7fgblA==",
|
||||
"dependencies": {
|
||||
"hast-util-to-string": "^2.0.0",
|
||||
"parse-numeric-range": "^1.3.0",
|
||||
"refractor": "^4.7.0",
|
||||
"refractor": "^4.8.0",
|
||||
"rehype-parse": "^8.0.2",
|
||||
"unist-util-filter": "^4.0.0",
|
||||
"unist-util-visit": "^4.0.0"
|
||||
@ -11235,12 +11188,6 @@
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rxjs/node_modules/tslib": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
||||
"integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/sade": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz",
|
||||
@ -11478,9 +11425,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/simple-icons": {
|
||||
"version": "9.2.0",
|
||||
"resolved": "https://registry.npmjs.org/simple-icons/-/simple-icons-9.2.0.tgz",
|
||||
"integrity": "sha512-BwLa76uMHBZKN1+L7Qmboj47mcFADiA/dfAePOd3arSPv6JMRNptJ2FNDBLuqkKliWG2W9XuBKhunuv+GzPpLA==",
|
||||
"version": "9.3.0",
|
||||
"resolved": "https://registry.npmjs.org/simple-icons/-/simple-icons-9.3.0.tgz",
|
||||
"integrity": "sha512-T6x3teIpPdMc8nibYvE56Va1eF+l8Puk//1YYtCxQP4wbGRzYxgwZTl18YCjoFLnu/0exehwyR2hMEFZV3lflg==",
|
||||
"engines": {
|
||||
"node": ">=0.12.18"
|
||||
},
|
||||
@ -11583,12 +11530,6 @@
|
||||
"tslib": "^2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/snake-case/node_modules/tslib": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
||||
"integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
@ -12016,12 +11957,6 @@
|
||||
"url": "https://opencollective.com/unts"
|
||||
}
|
||||
},
|
||||
"node_modules/synckit/node_modules/tslib": {
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
||||
"integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
||||
@ -12170,9 +12105,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
"version": "2.5.3",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
|
||||
"integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w=="
|
||||
},
|
||||
"node_modules/tsutils": {
|
||||
"version": "3.21.0",
|
||||
@ -12189,6 +12124,12 @@
|
||||
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
|
||||
}
|
||||
},
|
||||
"node_modules/tsutils/node_modules/tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/tunnel-agent": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||
@ -12703,6 +12644,18 @@
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/utf-8-validate": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-6.0.3.tgz",
|
||||
"integrity": "sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"node-gyp-build": "^4.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.14.2"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
@ -13129,6 +13082,26 @@
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
|
||||
"integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"bufferutil": "^4.0.1",
|
||||
"utf-8-validate": ">=5.0.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"bufferutil": {
|
||||
"optional": true
|
||||
},
|
||||
"utf-8-validate": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/xml-js": {
|
||||
"version": "1.6.11",
|
||||
"resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz",
|
||||
@ -13140,6 +13113,14 @@
|
||||
"xml-js": "bin/cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/xtend": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
||||
"engines": {
|
||||
"node": ">=0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||
|
11
package.json
11
package.json
@ -15,7 +15,7 @@
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint . --ext js,jsx,ts,tsx,md,mdx",
|
||||
"postinstall": "prisma generate"
|
||||
"postinstall": "prisma generate --data-proxy"
|
||||
},
|
||||
"dependencies": {
|
||||
"@giscus/react": "^2.2.8",
|
||||
@ -26,10 +26,9 @@
|
||||
"@primer/octicons": "^19.4.0",
|
||||
"@prisma/client": "^4.16.1",
|
||||
"@react-spring/web": "^9.7.2",
|
||||
"@sentry/node": "^7.56.0",
|
||||
"@sentry/tracing": "^7.56.0",
|
||||
"@stitches/react": "^1.2.8",
|
||||
"@vercel/analytics": "^1.0.1",
|
||||
"@vercel/postgres": "^0.4.0",
|
||||
"comma-number": "^2.1.0",
|
||||
"copy-to-clipboard": "^3.3.3",
|
||||
"dayjs": "^1.11.8",
|
||||
@ -60,13 +59,13 @@
|
||||
"react-player": "~2.10.1",
|
||||
"react-textarea-autosize": "^8.5.0",
|
||||
"react-twitter-embed": "^4.0.4",
|
||||
"rehype-prism-plus": "^1.5.1",
|
||||
"rehype-prism-plus": "^1.6.1",
|
||||
"rehype-slug": "^5.1.0",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"remark-smartypants": "^2.0.0",
|
||||
"remark-unwrap-images": "^3.0.1",
|
||||
"remove-markdown": "^0.5.0",
|
||||
"simple-icons": "^9.2.0",
|
||||
"simple-icons": "^9.3.0",
|
||||
"sitemap": "^7.1.1",
|
||||
"stitches-normalize": "^2.0.0",
|
||||
"swr": "^2.2.0"
|
||||
@ -79,7 +78,7 @@
|
||||
"@types/node": "*",
|
||||
"@types/novnc__novnc": "^1.3.0",
|
||||
"@types/prop-types": "^15.7.5",
|
||||
"@types/react": "^18.2.13",
|
||||
"@types/react": "^18.2.14",
|
||||
"@types/react-dom": "^18.2.6",
|
||||
"@types/react-is": "^18.2.1",
|
||||
"@types/remove-markdown": "^0.3.1",
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import queryString from "query-string";
|
||||
import { logServerError } from "../../lib/helpers/sentry";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { baseUrl } from "../../lib/config";
|
||||
import type { NextRequest } from "next/server";
|
||||
|
||||
// fallback to dummy secret for testing: https://docs.hcaptcha.com/#integration-testing-test-keys
|
||||
const HCAPTCHA_SITE_KEY =
|
||||
@ -11,56 +12,55 @@ const HCAPTCHA_API_ENDPOINT = "https://hcaptcha.com/siteverify";
|
||||
const { AIRTABLE_API_KEY, AIRTABLE_BASE } = process.env;
|
||||
const AIRTABLE_API_ENDPOINT = "https://api.airtable.com/v0/";
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
try {
|
||||
// disable caching on both ends
|
||||
res.setHeader("Cache-Control", "private, no-cache, no-store, must-revalidate");
|
||||
res.setHeader("Pragma", "no-cache");
|
||||
export const config = {
|
||||
runtime: "edge",
|
||||
};
|
||||
|
||||
// redirect GET requests to this endpoint to the contact form itself
|
||||
if (req.method === "GET") {
|
||||
return res.redirect(302, "/contact/");
|
||||
}
|
||||
|
||||
const { body } = req;
|
||||
|
||||
// these are both backups to client-side validations just in case someone squeezes through without them. the codes
|
||||
// are identical so they're caught in the same fashion.
|
||||
if (!body.name || !body.email || !body.message) {
|
||||
// all fields are required
|
||||
throw new Error("USER_MISSING_DATA");
|
||||
}
|
||||
if (!body["h-captcha-response"] || !(await validateCaptcha(body["h-captcha-response"]))) {
|
||||
// either the captcha is wrong or completely missing
|
||||
throw new Error("USER_INVALID_CAPTCHA");
|
||||
}
|
||||
|
||||
// sent directly to airtable
|
||||
const airtableResult = await sendToAirtable({
|
||||
Name: body.name,
|
||||
Email: body.email,
|
||||
Message: body.message,
|
||||
});
|
||||
|
||||
// throw an internal error, not user's fault
|
||||
if (airtableResult !== true) {
|
||||
throw new Error("AIRTABLE_API_ERROR");
|
||||
}
|
||||
|
||||
// success! let the client know
|
||||
return res.status(200).json({ success: true });
|
||||
} catch (error) {
|
||||
// extract just the error message to send back to client
|
||||
const message = error instanceof Error ? error.message : "UNKNOWN_EXCEPTION";
|
||||
|
||||
// log errors (except PEBCAK) to console and sentry
|
||||
if (!message.startsWith("USER_")) {
|
||||
await logServerError(error);
|
||||
}
|
||||
|
||||
// 500 Internal Server Error
|
||||
return res.status(500).json({ success: false, message });
|
||||
// eslint-disable-next-line import/no-anonymous-default-export
|
||||
export default async (req: NextRequest) => {
|
||||
// redirect GET requests to this endpoint to the contact form itself
|
||||
if (req.method === "GET") {
|
||||
return NextResponse.redirect(`${baseUrl}/contact/`);
|
||||
}
|
||||
|
||||
// possible weirdness? https://github.com/orgs/vercel/discussions/78#discussioncomment-5089059
|
||||
const data = await req.json();
|
||||
|
||||
// these are both backups to client-side validations just in case someone squeezes through without them. the codes
|
||||
// are identical so they're caught in the same fashion.
|
||||
if (!data.name || !data.email || !data.message) {
|
||||
// all fields are required
|
||||
throw new Error("MISSING_DATA");
|
||||
}
|
||||
if (!data["h-captcha-response"] || !(await validateCaptcha(data["h-captcha-response"]))) {
|
||||
// either the captcha is wrong or completely missing
|
||||
throw new Error("INVALID_CAPTCHA");
|
||||
}
|
||||
|
||||
// sent directly to airtable
|
||||
const airtableResult = await sendToAirtable({
|
||||
Name: data.name,
|
||||
Email: data.email,
|
||||
Message: data.message,
|
||||
});
|
||||
|
||||
// throw an internal error, not user's fault
|
||||
if (airtableResult !== true) {
|
||||
throw new Error("AIRTABLE_API_ERROR");
|
||||
}
|
||||
|
||||
// success! let the client know
|
||||
return NextResponse.json(
|
||||
{ success: true },
|
||||
{
|
||||
status: 201,
|
||||
headers: {
|
||||
// disable caching on both ends. see:
|
||||
// https://vercel.com/docs/concepts/functions/edge-functions/edge-caching
|
||||
"Cache-Control": "private, no-cache, no-store, must-revalidate",
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
const validateCaptcha = async (formResponse: unknown): Promise<unknown> => {
|
||||
@ -95,5 +95,3 @@ const sendToAirtable = async (data: unknown): Promise<boolean> => {
|
||||
|
||||
return response.ok;
|
||||
};
|
||||
|
||||
export default handler;
|
||||
|
@ -1,32 +1,30 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { prisma } from "../../lib/helpers/prisma";
|
||||
import { logServerError } from "../../lib/helpers/sentry";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import type { NextRequest } from "next/server";
|
||||
import type { PageStats } from "../../types";
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
try {
|
||||
if (!req.query?.slug) {
|
||||
return res.status(400).json({ message: "Missing `slug` parameter." });
|
||||
}
|
||||
export const config = {
|
||||
runtime: "edge",
|
||||
regions: ["iad1"], // the vercel postgres database lives in DC
|
||||
};
|
||||
|
||||
// add one to this page's count and return the new number
|
||||
const result = await incrementPageHits(req.query.slug as string);
|
||||
// eslint-disable-next-line import/no-anonymous-default-export
|
||||
export default async (req: NextRequest) => {
|
||||
const slug = req.nextUrl.searchParams.get("slug");
|
||||
|
||||
// disable caching on both ends
|
||||
res.setHeader("Cache-Control", "private, no-cache, no-store, must-revalidate");
|
||||
|
||||
// send result as JSON
|
||||
return res.status(200).json(result);
|
||||
} catch (error) {
|
||||
// extract just the error message to send back to client
|
||||
const message = error instanceof Error ? error.message : error;
|
||||
|
||||
// log full error to console and sentry
|
||||
await logServerError(error);
|
||||
|
||||
// 500 Internal Server Error
|
||||
return res.status(500).json({ message });
|
||||
if (!slug) {
|
||||
return NextResponse.json({ message: "Missing `slug` parameter." }, { status: 400 });
|
||||
}
|
||||
|
||||
// add one to this page's count and return the new number
|
||||
return NextResponse.json(await incrementPageHits(slug), {
|
||||
status: 200,
|
||||
headers: {
|
||||
// disable caching on both ends. see:
|
||||
// https://vercel.com/docs/concepts/functions/edge-functions/edge-caching
|
||||
"Cache-Control": "private, no-cache, no-store, must-revalidate",
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const incrementPageHits = async (slug: string): Promise<PageStats> => {
|
||||
@ -43,5 +41,3 @@ const incrementPageHits = async (slug: string): Promise<PageStats> => {
|
||||
// send client the *new* hit count
|
||||
return { hits };
|
||||
};
|
||||
|
||||
export default handler;
|
||||
|
@ -1,71 +1,29 @@
|
||||
import { prisma } from "../../lib/helpers/prisma";
|
||||
import { getAllNotes } from "../../lib/helpers/parse-notes";
|
||||
import { logServerError } from "../../lib/helpers/sentry";
|
||||
import { NOTES_DIR } from "../../lib/config/constants";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import type { DetailedPageStats, SiteStats } from "../../types";
|
||||
import { NextResponse } from "next/server";
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
try {
|
||||
// return overall site stats
|
||||
const result = await getSiteStats();
|
||||
|
||||
// let Vercel edge cache results for 15 mins
|
||||
res.setHeader("Cache-Control", "public, max-age=0, s-maxage=900, stale-while-revalidate");
|
||||
|
||||
// send result as JSON
|
||||
return res.status(200).json(result);
|
||||
} catch (error) {
|
||||
// extract just the error message to send back to client
|
||||
const message = error instanceof Error ? error.message : error;
|
||||
|
||||
// log full error to console and sentry
|
||||
await logServerError(error);
|
||||
|
||||
// 500 Internal Server Error
|
||||
return res.status(500).json({ message });
|
||||
}
|
||||
export const config = {
|
||||
runtime: "edge",
|
||||
regions: ["iad1"], // the vercel postgres database lives in DC
|
||||
};
|
||||
|
||||
const getSiteStats = async (): Promise<SiteStats> => {
|
||||
// eslint-disable-next-line import/no-anonymous-default-export
|
||||
export default async () => {
|
||||
// simultaneously fetch the entire hits db and notes from the filesystem
|
||||
const [hits, notes] = await Promise.all([
|
||||
prisma.hits.findMany({
|
||||
orderBy: [
|
||||
{
|
||||
hits: "desc",
|
||||
},
|
||||
],
|
||||
}),
|
||||
getAllNotes(),
|
||||
]);
|
||||
|
||||
const pages: DetailedPageStats[] = [];
|
||||
const total = { hits: 0 };
|
||||
|
||||
hits.forEach((record) => {
|
||||
// match slugs from getAllNotes() with db results to populate some metadata
|
||||
// TODO: add support for pages other than notes.
|
||||
const match = notes.find((note) => `${NOTES_DIR}/${note.slug}` === record.slug);
|
||||
|
||||
// don't reveal via API if the db entry doesn't belong to a valid page
|
||||
if (!match) {
|
||||
return;
|
||||
}
|
||||
|
||||
// merge record with its matching front matter data
|
||||
pages.push({
|
||||
...record,
|
||||
title: match.title,
|
||||
url: match.permalink,
|
||||
date: match.date,
|
||||
});
|
||||
|
||||
// add these hits to running tally
|
||||
total.hits += record.hits;
|
||||
const pages = await prisma.hits.findMany({
|
||||
orderBy: [
|
||||
{
|
||||
hits: "desc",
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
return { total, pages };
|
||||
};
|
||||
const total = { hits: 0 };
|
||||
|
||||
export default handler;
|
||||
// calculate total hits
|
||||
pages.forEach((page) => {
|
||||
// add these hits to running tally
|
||||
total.hits += page.hits;
|
||||
});
|
||||
|
||||
return NextResponse.json({ total, pages }, { status: 200 });
|
||||
};
|
||||
|
@ -2,8 +2,7 @@
|
||||
// Heavily inspired by @leerob: https://leerob.io/snippets/spotify
|
||||
|
||||
import queryString from "query-string";
|
||||
import { logServerError } from "../../lib/helpers/sentry";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { NextResponse } from "next/server";
|
||||
import type { Track } from "../../types";
|
||||
|
||||
const { SPOTIFY_CLIENT_ID, SPOTIFY_CLIENT_SECRET, SPOTIFY_REFRESH_TOKEN } = process.env;
|
||||
@ -32,25 +31,16 @@ type SpotifyTrackSchema = {
|
||||
};
|
||||
};
|
||||
|
||||
const handler = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
try {
|
||||
// let Vercel edge cache results for 5 mins
|
||||
res.setHeader("Cache-Control", "public, max-age=0, s-maxage=300, stale-while-revalidate");
|
||||
export const config = {
|
||||
runtime: "edge",
|
||||
};
|
||||
|
||||
const token = await getAccessToken();
|
||||
const playing = await getNowPlaying(token);
|
||||
const top = await getTopTracks(token);
|
||||
// eslint-disable-next-line import/no-anonymous-default-export
|
||||
export default async () => {
|
||||
const token = await getAccessToken();
|
||||
const [playing, top] = await Promise.all([getNowPlaying(token), getTopTracks(token)]);
|
||||
|
||||
return res.status(200).json({ playing, top });
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Unknown error.";
|
||||
|
||||
// log full error to console and sentry
|
||||
await logServerError(error);
|
||||
|
||||
// 500 Internal Server Error
|
||||
return res.status(500).json({ message });
|
||||
}
|
||||
return NextResponse.json({ playing, top }, { status: 200 });
|
||||
};
|
||||
|
||||
const getAccessToken = async () => {
|
||||
@ -125,5 +115,3 @@ const getTopTracks = async (token: string): Promise<Track[]> => {
|
||||
|
||||
return tracks;
|
||||
};
|
||||
|
||||
export default handler;
|
||||
|
@ -5,7 +5,7 @@ generator client {
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("POSTGRES_PRISMA_URL")
|
||||
url = env("DATABASE_URL")
|
||||
directUrl = env("POSTGRES_URL_NON_POOLING")
|
||||
shadowDatabaseUrl = env("POSTGRES_URL_NON_POOLING")
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user