Bug fixes, code cleanup, made root dir /
@ -1,2 +1,35 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# production env
|
||||
.env
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
drift.sqlite
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"typescript.tsdk": "src/node_modules/.pnpm/typescript@4.6.4/node_modules/typescript/lib",
|
||||
"typescript.tsdk": "node_modules/.pnpm/typescript@4.6.4/node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"dotenv.enableAutocloaking": false
|
||||
}
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 653 B After Width: | Height: | Size: 653 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 930 B After Width: | Height: | Size: 930 B |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
@ -1,35 +0,0 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# production env
|
||||
.env
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
@ -1,4 +0,0 @@
|
||||
{
|
||||
"typescript.tsdk": "node_modules/.pnpm/typescript@4.6.4/node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
|
||||
|
||||
## Getting Started
|
||||
|
||||
First, run the development server:
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
|
||||
You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
|
||||
|
||||
[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
|
||||
|
||||
The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
|
||||
|
||||
## Learn More
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
|
||||
|
||||
## Deploy on Vercel
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
|
@ -0,0 +1,73 @@
|
||||
import { ApiToken } from "@prisma/client"
|
||||
import useSWR from "swr"
|
||||
|
||||
type ConvertDateToString<T> = {
|
||||
[P in keyof T]: T[P] extends Date ? string : T[P]
|
||||
}
|
||||
|
||||
export type SerializedApiToken = ConvertDateToString<ApiToken>
|
||||
|
||||
type UseApiTokens = {
|
||||
userId?: string
|
||||
initialTokens?: SerializedApiToken[]
|
||||
}
|
||||
|
||||
const TOKENS_ENDPOINT = "/api/user/tokens"
|
||||
|
||||
export function useApiTokens({ userId, initialTokens }: UseApiTokens) {
|
||||
const { data, mutate, error, isLoading } = useSWR<SerializedApiToken[]>(
|
||||
"/api/user/tokens?userId=" + userId,
|
||||
async (url: string) => {
|
||||
return fetch(url).then(async (res) => {
|
||||
const data = await res.json()
|
||||
if (data.error) {
|
||||
throw new Error(data.error)
|
||||
}
|
||||
|
||||
return data
|
||||
})
|
||||
},
|
||||
{
|
||||
refreshInterval: 10000,
|
||||
fallbackData: initialTokens
|
||||
}
|
||||
)
|
||||
|
||||
async function createToken(newToken: string) {
|
||||
if (!newToken) {
|
||||
throw new Error("Token name is required")
|
||||
}
|
||||
|
||||
const res = await fetch(
|
||||
`${TOKENS_ENDPOINT}?userId=${userId}&name=${newToken}`,
|
||||
{
|
||||
method: "POST"
|
||||
}
|
||||
)
|
||||
|
||||
const response = await res.json()
|
||||
if (response.error) {
|
||||
throw new Error(response.error)
|
||||
return
|
||||
}
|
||||
|
||||
mutate([...(data || []), response])
|
||||
|
||||
return response as SerializedApiToken
|
||||
}
|
||||
|
||||
const expireToken = async (id: string) => {
|
||||
await fetch(`${TOKENS_ENDPOINT}?userId=${userId}&tokenId=${id}`, {
|
||||
method: "DELETE"
|
||||
})
|
||||
mutate(data?.filter((token) => token.id !== id))
|
||||
}
|
||||
|
||||
return {
|
||||
data,
|
||||
isLoading,
|
||||
error,
|
||||
createToken,
|
||||
expireToken
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
export async function copyToClipboard(text: string ) {
|
||||
await navigator.clipboard.writeText(text)
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
// A wrapper around next-auth/use-session that refreshes the page if the session changes
|
||||
|
||||
import { useEffect } from "react"
|
||||
import { useSession as useSessionOriginal } from "next-auth/react"
|
||||
import { useRouter } from "next/navigation"
|
||||
|
||||
|
||||
export function useSession() {
|
||||
const { data: session, status } = useSessionOriginal()
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
router.refresh();
|
||||
}, [router, status])
|
||||
|
||||
return { session, status }
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
import config from "./config"
|
||||
|
||||
export const revalidatePage = async (path: string) => {
|
||||
const res = await fetch(
|
||||
`${process.env.DRIFT_URL}/api/revalidate?secret=${config.nextauth_secret}&path=${path}`
|
||||
)
|
||||
const json = await res.json()
|
||||
return json
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
// https://beta.nextjs.org/docs/data-fetching/revalidating#on-demand-revalidation
|
||||
|
||||
import config from "@lib/config"
|
||||
import { parseQueryParam } from "@lib/server/parse-query-param"
|
||||
import type { NextApiRequest, NextApiResponse } from "next"
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
) {
|
||||
// TODO: create a new secret?
|
||||
if (req.query.secret !== config.nextauth_secret) {
|
||||
return res.status(401).json({ message: "Invalid token" })
|
||||
}
|
||||
|
||||
const path = parseQueryParam(req.query.path)
|
||||
|
||||
try {
|
||||
if (path) {
|
||||
await res.revalidate(path)
|
||||
return res.json({ revalidated: true })
|
||||
}
|
||||
} catch (err) {
|
||||
// If there was an error, Next.js will continue
|
||||
// to show the last successfully generated page
|
||||
return res.status(500).send("Error revalidating")
|
||||
}
|
||||
}
|