diff --git a/.changeset/eleven-pants-smash.md b/.changeset/eleven-pants-smash.md new file mode 100644 index 0000000000..8fdc9a69e7 --- /dev/null +++ b/.changeset/eleven-pants-smash.md @@ -0,0 +1,5 @@ +--- +"create-t3-app": patch +--- + +refactor: swap inquirer for clack diff --git a/.changeset/fast-teachers-explain.md b/.changeset/fast-teachers-explain.md new file mode 100644 index 0000000000..665327447f --- /dev/null +++ b/.changeset/fast-teachers-explain.md @@ -0,0 +1,22 @@ +--- +"create-t3-app": minor +--- + +feat: add drizzle + +This release adds a new option to use [`drizzle-orm`](https://orm.drizzle.team/docs/overview) as an alternative to Prisma. + +To make the different ORM options as similar as possible, some minor changes has also been made to the Prisma installer: + +- a new script `db:push` has been added and is included in both ORM options. +- the prisma client has been renamed to `db` in the trpc context - you now access your database client like + ```ts + examples: publicProcedure.query((opts) => { + // prisma + opts.ctx.db.example.findMany() + // drizzle + opts.ctx.db.query.example.findMany() + }), + ``` + +You cannot choose the two options in the same app. diff --git a/.eslintrc.cjs b/.eslintrc.cjs index a050858b18..c6d2a93195 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -46,6 +46,9 @@ const config = { // These lint rules don't make sense for us but are enabled in the preset configs "@typescript-eslint/no-confusing-void-expression": "off", "@typescript-eslint/restrict-template-expressions": "off", + + // This rule doesn't seem to be working properly + "@typescript-eslint/prefer-nullish-coalescing": "off", }, }; diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 33804e6fb8..fc6dc47b07 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -27,30 +27,40 @@ jobs: tailwind: ["true", "false"] nextAuth: ["true", "false"] prisma: ["true", "false"] + drizzle: ["true", "false"] - name: "Build and Start T3 App ${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.prisma }}" + name: "Build and Start T3 App ${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.prisma }}-${{ matrix.drizzle}}" steps: - uses: actions/checkout@v3 with: fetch-depth: 0 + - name: Check valid matrix + id: matrix-valid + run: | + echo "continue=${{ matrix.prisma == 'false' || matrix.drizzle == 'false' }}" >> $GITHUB_OUTPUT + - name: Install Node.js + if: ${{ steps.matrix-valid.outputs.continue == 'true' }}  uses: actions/setup-node@v3 with: node-version: 18 - uses: pnpm/action-setup@v2.2.4 + if: ${{ steps.matrix-valid.outputs.continue == 'true' }} name: Install pnpm id: pnpm-install with: run_install: false - name: Get pnpm store directory + if: ${{ steps.matrix-valid.outputs.continue == 'true' }} id: pnpm-cache run: | echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT - uses: actions/cache@v3 + if: ${{ steps.matrix-valid.outputs.continue == 'true' }} name: Setup pnpm cache with: path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} @@ -59,14 +69,19 @@ jobs: ${{ runner.os }}-pnpm-store- - name: Install dependencies + if: ${{ steps.matrix-valid.outputs.continue == 'true' }} run: pnpm install - run: pnpm turbo --filter=create-t3-app build + if: ${{ steps.matrix-valid.outputs.continue == 'true' }} + # has to be scaffolded outside the CLI project so that no lint/tsconfig are leaking # through. this way it ensures that it is the app's configs that are being used # FIXME: this is a bit hacky, would rather have --packages=trpc,tailwind,... but not sure how to setup the matrix for that - - run: cd cli && pnpm start ../../ci-${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.prisma }} --noGit --CI --trpc=${{ matrix.trpc }} --tailwind=${{ matrix.tailwind }} --nextAuth=${{ matrix.nextAuth }} --prisma=${{ matrix.prisma }} - - run: cd ../ci-${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.prisma }} && pnpm build + - run: cd cli && pnpm start ../../ci-${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.prisma }}-${{ matrix.drizzle}} --noGit --CI --trpc=${{ matrix.trpc }} --tailwind=${{ matrix.tailwind }} --nextAuth=${{ matrix.nextAuth }} --prisma=${{ matrix.prisma }} --drizzle=${{ matrix.drizzle }} + if: ${{ steps.matrix-valid.outputs.continue == 'true' }} + - run: cd ../ci-${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.prisma }}-${{ matrix.drizzle}} && pnpm build + if: ${{ steps.matrix-valid.outputs.continue == 'true' }} env: NEXTAUTH_SECRET: foo diff --git a/.vscode/settings.json b/.vscode/settings.json index 3c13149fd3..3d7a747030 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -24,5 +24,8 @@ "mdx.experimentalLanguageServer": true, "[astro]": { "editor.defaultFormatter": "astro-build.astro-vscode" + }, + "[prisma]": { + "editor.defaultFormatter": "Prisma.prisma" } } diff --git a/cli/package.json b/cli/package.json index cd08c724b0..d75a31d0c4 100644 --- a/cli/package.json +++ b/cli/package.json @@ -41,30 +41,36 @@ "pub:release": "pnpm build && npm publish" }, "dependencies": { + "@clack/core": "^0.3.2", + "@clack/prompts": "^0.6.3", "@ianvs/prettier-plugin-sort-imports": "^4.1.0", "chalk": "5.2.0", "commander": "^10.0.0", "execa": "^7.1.1", "fs-extra": "^11.1.1", "gradient-string": "^2.0.2", - "inquirer": "^9.2.3", "ora": "6.3.1", "sort-package-json": "^2.4.1" }, "devDependencies": { - "@prisma/client": "^4.14.0", + "@auth/drizzle-adapter": "^0.3.2", + "@next-auth/prisma-adapter": "^1.0.7", + "@planetscale/database": "^1.11.0", + "@prisma/client": "^5.1.1", "@t3-oss/env-nextjs": "^0.6.0", - "@tanstack/react-query": "^4.29.7", - "@trpc/client": "^10.26.0", - "@trpc/next": "^10.26.0", - "@trpc/react-query": "^10.26.0", - "@trpc/server": "^10.26.0", + "@tanstack/react-query": "^4.32.6", + "@trpc/client": "^10.37.1", + "@trpc/next": "^10.37.1", + "@trpc/react-query": "^10.37.1", + "@trpc/server": "^10.37.1", "@types/fs-extra": "^11.0.1", "@types/gradient-string": "^1.1.2", "@types/inquirer": "^9.0.3", "@types/node": "^18.16.0", - "next": "^13.4.1", - "next-auth": "^4.22.1", + "drizzle-kit": "^0.19.13", + "drizzle-orm": "^0.28.5", + "next": "^13.4.19", + "next-auth": "^4.23.1", "prettier": "^3.0.0", "prettier-plugin-tailwindcss": "^0.5.1", "prisma": "^4.14.0", diff --git a/cli/src/cli/index.ts b/cli/src/cli/index.ts index 8b66a80c8d..8f07b9a6d2 100644 --- a/cli/src/cli/index.ts +++ b/cli/src/cli/index.ts @@ -1,12 +1,9 @@ +import * as p from "@clack/prompts"; import chalk from "chalk"; import { Command } from "commander"; -import inquirer from "inquirer"; import { CREATE_T3_APP, DEFAULT_APP_NAME } from "~/consts.js"; -import { - availablePackages, - type AvailablePackages, -} from "~/installers/index.js"; +import { type AvailablePackages } from "~/installers/index.js"; import { getVersion } from "~/utils/getT3Version.js"; import { getUserPkgManager } from "~/utils/getUserPkgManager.js"; import { IsTTYError } from "~/utils/isTTYError.js"; @@ -29,6 +26,8 @@ interface CliFlags { /** @internal Used in CI. */ prisma: boolean; /** @internal Used in CI. */ + drizzle: boolean; + /** @internal Used in CI. */ nextAuth: boolean; } @@ -49,19 +48,17 @@ const defaultOptions: CliResults = { tailwind: false, trpc: false, prisma: false, + drizzle: false, nextAuth: false, importAlias: "~/", }, }; -export const runCli = async () => { +export const runCli = async (): Promise => { const cliResults = defaultOptions; - const program = new Command().name(CREATE_T3_APP); - - // TODO: This doesn't return anything typesafe. Research other options? - // Emulate from: https://github.com/Schniz/soundtype-commander - program + const program = new Command() + .name(CREATE_T3_APP) .description("A CLI for creating web applications with the t3 stack") .argument( "[dir]", @@ -107,6 +104,12 @@ export const runCli = async () => { (value) => !!value && value !== "false" ) /** @experimental - Used for CI E2E tests. Used in conjunction with `--CI` to skip prompting. */ + .option( + "--drizzle [boolean]", + "Experimental: Boolean value if we should install Drizzle. Must be used in conjunction with `--CI`.", + (value) => !!value && value !== "false" + ) + /** @experimental - Used for CI E2E tests. Used in conjunction with `--CI` to skip prompting. */ .option( "--trpc [boolean]", "Experimental: Boolean value if we should install tRPC. Must be used in conjunction with `--CI`.", @@ -149,14 +152,27 @@ export const runCli = async () => { cliResults.flags = program.opts(); /** @internal Used for CI E2E tests. */ - let CIMode = false; if (cliResults.flags.CI) { - CIMode = true; cliResults.packages = []; if (cliResults.flags.trpc) cliResults.packages.push("trpc"); if (cliResults.flags.tailwind) cliResults.packages.push("tailwind"); if (cliResults.flags.prisma) cliResults.packages.push("prisma"); + if (cliResults.flags.drizzle) cliResults.packages.push("drizzle"); if (cliResults.flags.nextAuth) cliResults.packages.push("nextAuth"); + + if (cliResults.flags.prisma && cliResults.flags.drizzle) { + // We test a matrix of all possible combination of packages in CI. Checking for impossible + // combinations here and exiting gracefully is easier than changing the CI matrix to exclude + // invalid combinations. We are using an "OK" exit code so CI continues with the next combination. + logger.warn("Incompatible combination Prisma + Drizzle. Exiting."); + process.exit(0); + } + + return cliResults; + } + + if (cliResults.flags.default) { + return cliResults; } // Explained below why this is in a try/catch block @@ -170,24 +186,118 @@ export const runCli = async () => { } // if --CI flag is set, we are running in CI mode and should not prompt the user - // if --default flag is set, we should not prompt the user - if (!cliResults.flags.default && !CIMode) { - if (!cliProvidedName) { - cliResults.appName = await promptAppName(); - } - - await promptLanguage(); - cliResults.packages = await promptPackages(); - if (!cliResults.flags.noGit) { - cliResults.flags.noGit = !(await promptGit()); - } - if (!cliResults.flags.noInstall) { - cliResults.flags.noInstall = !(await promptInstall()); + const pkgManager = getUserPkgManager(); + + const project = await p.group( + { + ...(!cliProvidedName && { + name: () => + p.text({ + message: "What will your project be called?", + defaultValue: cliProvidedName, + validate: validateAppName, + }), + }), + language: () => { + return p.select({ + message: "Will you be using TypeScript or JavaScript?", + options: [ + { value: "typescript", label: "TypeScript" }, + { value: "javascript", label: "JavaScript" }, + ], + initialValue: "typescript", + }); + }, + _: ({ results }) => + results.language === "javascript" + ? p.note(chalk.redBright("Wrong answer, using TypeScript instead")) + : undefined, + styling: () => { + return p.confirm({ + message: "Will you be using Tailwind CSS for styling?", + }); + }, + trpc: () => { + return p.confirm({ + message: "Would you like to use tRPC?", + }); + }, + authentication: () => { + return p.select({ + message: "What authentication provider would you like to use?", + options: [ + { value: "none", label: "None" }, + { value: "next-auth", label: "NextAuth.js" }, + // Maybe later + // { value: "clerk", label: "Clerk" }, + ], + initialValue: "none", + }); + }, + database: () => { + return p.select({ + message: "What database ORM would you like to use?", + options: [ + { value: "none", label: "None" }, + { value: "prisma", label: "Prisma" }, + { value: "drizzle", label: "Drizzle" }, + ], + initialValue: "none", + }); + }, + ...(!cliResults.flags.noGit && { + git: () => { + return p.confirm({ + message: + "Should we initialize a Git repository and stage the changes?", + initialValue: !defaultOptions.flags.noGit, + }); + }, + }), + ...(!cliResults.flags.noInstall && { + install: () => { + return p.confirm({ + message: + `Should we run '${pkgManager}` + + (pkgManager === "yarn" ? `'?` : ` install' for you?`), + initialValue: !defaultOptions.flags.noInstall, + }); + }, + }), + importAlias: () => { + return p.text({ + message: "What import alias would you like to use?", + defaultValue: defaultOptions.flags.importAlias, + placeholder: defaultOptions.flags.importAlias, + validate: validateImportAlias, + }); + }, + }, + { + onCancel() { + process.exit(1); + }, } - - cliResults.flags.importAlias = await promptImportAlias(); - } + ); + + const packages: AvailablePackages[] = []; + if (project.styling) packages.push("tailwind"); + if (project.trpc) packages.push("trpc"); + if (project.authentication === "next-auth") packages.push("nextAuth"); + if (project.database === "prisma") packages.push("prisma"); + if (project.database === "drizzle") packages.push("drizzle"); + + return { + appName: project.name ?? cliResults.appName, + packages, + flags: { + ...cliResults.flags, + noGit: !project.git ?? cliResults.flags.noGit, + noInstall: !project.install ?? cliResults.flags.noInstall, + importAlias: project.importAlias ?? cliResults.flags.importAlias, + }, + }; } catch (err) { // If the user is not calling create-t3-app from an interactive terminal, inquirer will throw an IsTTYError // If this happens, we catch the error, tell the user what has happened, and then continue to run the program with a default t3 app @@ -195,13 +305,9 @@ export const runCli = async () => { logger.warn(` ${CREATE_T3_APP} needs an interactive terminal to provide options`); - const { shouldContinue } = await inquirer.prompt<{ - shouldContinue: boolean; - }>({ - name: "shouldContinue", - type: "confirm", + const shouldContinue = await p.confirm({ message: `Continue scaffolding a default T3 app?`, - default: true, + initialValue: true, }); if (!shouldContinue) { @@ -217,114 +323,3 @@ export const runCli = async () => { return cliResults; }; - -const promptAppName = async (): Promise => { - const { appName } = await inquirer.prompt>({ - name: "appName", - type: "input", - message: "What will your project be called?", - default: defaultOptions.appName, - validate: validateAppName, - transformer: (input: string) => { - return input.trim(); - }, - }); - - return appName; -}; - -const promptLanguage = async (): Promise => { - const { language } = await inquirer.prompt<{ language: string }>({ - name: "language", - type: "list", - message: "Will you be using TypeScript or JavaScript?", - choices: [ - { name: "TypeScript", value: "typescript", short: "TypeScript" }, - { name: "JavaScript", value: "javascript", short: "JavaScript" }, - ], - default: "typescript", - }); - - if (language === "javascript") { - logger.error("Wrong answer, using TypeScript instead..."); - } else { - logger.success("Good choice! Using TypeScript!"); - } -}; - -const promptPackages = async (): Promise => { - const { packages } = await inquirer.prompt>({ - name: "packages", - type: "checkbox", - message: "Which packages would you like to enable?", - choices: availablePackages - .filter((pkg) => pkg !== "envVariables") // don't prompt for env-vars - .map((pkgName) => ({ - name: pkgName, - checked: false, - })), - }); - - return packages; -}; - -const promptGit = async (): Promise => { - const { git } = await inquirer.prompt<{ git: boolean }>({ - name: "git", - type: "confirm", - message: "Initialize a new git repository?", - default: true, - }); - - if (git) { - logger.success("Nice one! Initializing repository!"); - } else { - logger.info("Sounds good! You can come back and run git init later."); - } - - return git; -}; - -const promptInstall = async (): Promise => { - const pkgManager = getUserPkgManager(); - - const { install } = await inquirer.prompt<{ install: boolean }>({ - name: "install", - type: "confirm", - message: - `Would you like us to run '${pkgManager}` + - (pkgManager === "yarn" ? `'?` : ` install'?`), - default: true, - }); - - if (install) { - logger.success("Alright. We'll install the dependencies for you!"); - } else { - if (pkgManager === "yarn") { - logger.info( - `No worries. You can run '${pkgManager}' later to install the dependencies.` - ); - } else { - logger.info( - `No worries. You can run '${pkgManager} install' later to install the dependencies.` - ); - } - } - - return install; -}; - -const promptImportAlias = async (): Promise => { - const { importAlias } = await inquirer.prompt>({ - name: "importAlias", - type: "input", - message: "What import alias would you like configured?", - default: defaultOptions.flags.importAlias, - validate: validateImportAlias, - transformer: (input: string) => { - return input.trim(); - }, - }); - - return importAlias; -}; diff --git a/cli/src/helpers/createProject.ts b/cli/src/helpers/createProject.ts index 7eebc9bf02..74d768c8cd 100644 --- a/cli/src/helpers/createProject.ts +++ b/cli/src/helpers/createProject.ts @@ -9,12 +9,14 @@ import { getUserPkgManager } from "~/utils/getUserPkgManager.js"; interface CreateProjectOptions { projectName: string; packages: PkgInstallerMap; + scopedAppName: string; noInstall: boolean; importAlias: string; } export const createProject = async ({ projectName, + scopedAppName, packages, noInstall, }: CreateProjectOptions) => { @@ -26,11 +28,14 @@ export const createProject = async ({ projectName, projectDir, pkgManager, + scopedAppName, noInstall, }); // Install the selected packages installPackages({ + projectName, + scopedAppName, projectDir, pkgManager, packages, diff --git a/cli/src/helpers/git.ts b/cli/src/helpers/git.ts index 4ad2a9ab29..527c7fd460 100644 --- a/cli/src/helpers/git.ts +++ b/cli/src/helpers/git.ts @@ -1,9 +1,9 @@ import { execSync } from "child_process"; import path from "path"; +import * as p from "@clack/prompts"; import chalk from "chalk"; import { execa } from "execa"; import fs from "fs-extra"; -import inquirer from "inquirer"; import ora from "ora"; import { logger } from "~/utils/logger.js"; @@ -72,16 +72,13 @@ export const initializeGit = async (projectDir: string) => { if (isInside && isRoot) { // Dir is a root git repo spinner.stop(); - const { overwriteGit } = await inquirer.prompt<{ - overwriteGit: boolean; - }>({ - name: "overwriteGit", - type: "confirm", + const overwriteGit = await p.confirm({ message: `${chalk.redBright.bold( "Warning:" )} Git is already initialized in "${dirName}". Initializing a new git repository would delete the previous history. Would you like to continue anyways?`, - default: false, + initialValue: false, }); + if (!overwriteGit) { spinner.info("Skipping Git initialization."); return; @@ -91,15 +88,11 @@ export const initializeGit = async (projectDir: string) => { } else if (isInside && !isRoot) { // Dir is inside a git worktree spinner.stop(); - const { initializeChildGitRepo } = await inquirer.prompt<{ - initializeChildGitRepo: boolean; - }>({ - name: "initializeChildGitRepo", - type: "confirm", + const initializeChildGitRepo = await p.confirm({ message: `${chalk.redBright.bold( "Warning:" )} "${dirName}" is already in a git worktree. Would you still like to initialize a new git repository in this directory?`, - default: false, + initialValue: false, }); if (!initializeChildGitRepo) { spinner.info("Skipping Git initialization."); diff --git a/cli/src/helpers/logNextSteps.ts b/cli/src/helpers/logNextSteps.ts index 17919a102b..66f607e470 100644 --- a/cli/src/helpers/logNextSteps.ts +++ b/cli/src/helpers/logNextSteps.ts @@ -27,10 +27,12 @@ export const logNextSteps = async ({ } } - if (packages?.prisma.inUse) { - logger.info( - ` ${pkgManager === "npm" ? "npx" : pkgManager} prisma db push` - ); + if (packages?.prisma.inUse || packages?.drizzle.inUse) { + if (["npm", "bun"].includes(pkgManager)) { + logger.info(` ${pkgManager} run db:push`); + } else { + logger.info(` ${pkgManager} db:push`); + } } if (["npm", "bun"].includes(pkgManager)) { @@ -43,4 +45,11 @@ export const logNextSteps = async ({ logger.info(` git init`); } logger.info(` git commit -m "initial commit"`); + + if (packages?.drizzle.inUse) { + logger.warn( + `\nThank you for trying out the new Drizzle option. If you encounter any issues, please open an issue!`, + `\nNote: We use the PlanetScale driver so that you can query your data in edge runtimes. If you want to use a different driver, you'll need to change it yourself.` + ); + } }; diff --git a/cli/src/helpers/scaffoldProject.ts b/cli/src/helpers/scaffoldProject.ts index 62d8e92396..d4e6730798 100644 --- a/cli/src/helpers/scaffoldProject.ts +++ b/cli/src/helpers/scaffoldProject.ts @@ -1,7 +1,7 @@ import path from "path"; +import * as p from "@clack/prompts"; import chalk from "chalk"; import fs from "fs-extra"; -import inquirer from "inquirer"; import ora from "ora"; import { PKG_ROOT } from "~/consts.js"; @@ -33,32 +33,25 @@ export const scaffoldProject = async ({ ); } else { spinner.stopAndPersist(); - const { overwriteDir } = await inquirer.prompt<{ - overwriteDir: "abort" | "clear" | "overwrite"; - }>({ - name: "overwriteDir", - type: "list", + const overwriteDir = await p.select({ message: `${chalk.redBright.bold("Warning:")} ${chalk.cyan.bold( projectName )} already exists and isn't empty. How would you like to proceed?`, - choices: [ + options: [ { - name: "Abort installation (recommended)", + label: "Abort installation (recommended)", value: "abort", - short: "Abort", }, { - name: "Clear the directory and continue installation", + label: "Clear the directory and continue installation", value: "clear", - short: "Clear", }, { - name: "Continue installation and overwrite conflicting files", + label: "Continue installation and overwrite conflicting files", value: "overwrite", - short: "Overwrite", }, ], - default: "abort", + initialValue: "abort", }); if (overwriteDir === "abort") { spinner.fail("Aborting installation..."); @@ -70,13 +63,9 @@ export const scaffoldProject = async ({ ? "clear the directory" : "overwrite conflicting files"; - const { confirmOverwriteDir } = await inquirer.prompt<{ - confirmOverwriteDir: boolean; - }>({ - name: "confirmOverwriteDir", - type: "confirm", + const confirmOverwriteDir = await p.confirm({ message: `Are you sure you want to ${overwriteAction}?`, - default: false, + initialValue: false, }); if (!confirmOverwriteDir) { diff --git a/cli/src/index.ts b/cli/src/index.ts index 5541afa025..651f3cdb30 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -43,6 +43,7 @@ const main = async () => { const projectDir = await createProject({ projectName: appDir, + scopedAppName, packages: usePackages, importAlias: importAlias, noInstall, diff --git a/cli/src/installers/dependencyVersionMap.ts b/cli/src/installers/dependencyVersionMap.ts index 3f133a5924..11dc1f3877 100644 --- a/cli/src/installers/dependencyVersionMap.ts +++ b/cli/src/installers/dependencyVersionMap.ts @@ -4,13 +4,20 @@ */ export const dependencyVersionMap = { // NextAuth.js - "next-auth": "^4.22.4", + "next-auth": "^4.23.0", "@next-auth/prisma-adapter": "^1.0.7", + "@auth/drizzle-adapter": "^0.3.2", // Prisma prisma: "^5.1.1", "@prisma/client": "^5.1.1", + // Drizzle + "drizzle-orm": "^0.28.5", + "drizzle-kit": "^0.19.13", + "dotenv-cli": "^7.3.0", + "@planetscale/database": "^1.11.0", + // TailwindCSS tailwindcss: "^3.3.3", autoprefixer: "^10.4.14", @@ -19,11 +26,11 @@ export const dependencyVersionMap = { "prettier-plugin-tailwindcss": "^0.5.1", // tRPC - "@trpc/client": "^10.34.0", - "@trpc/server": "^10.34.0", - "@trpc/react-query": "^10.34.0", - "@trpc/next": "^10.34.0", - "@tanstack/react-query": "^4.29.25", + "@trpc/client": "^10.37.1", + "@trpc/server": "^10.37.1", + "@trpc/react-query": "^10.37.1", + "@trpc/next": "^10.37.1", + "@tanstack/react-query": "^4.32.6", superjson: "^1.13.1", } as const; export type AvailableDependencies = keyof typeof dependencyVersionMap; diff --git a/cli/src/installers/drizzle.ts b/cli/src/installers/drizzle.ts new file mode 100644 index 0000000000..f1de68e5d2 --- /dev/null +++ b/cli/src/installers/drizzle.ts @@ -0,0 +1,68 @@ +import path from "path"; +import fs from "fs-extra"; +import { type PackageJson } from "type-fest"; + +import { PKG_ROOT } from "~/consts.js"; +import { type Installer } from "~/installers/index.js"; +import { addPackageDependency } from "~/utils/addPackageDependency.js"; + +export const drizzleInstaller: Installer = ({ + projectDir, + packages, + scopedAppName, +}) => { + addPackageDependency({ + projectDir, + dependencies: ["drizzle-kit", "dotenv-cli"], + devMode: true, + }); + addPackageDependency({ + projectDir, + dependencies: ["drizzle-orm", "@planetscale/database"], + devMode: false, + }); + + const extrasDir = path.join(PKG_ROOT, "template/extras"); + + const configFile = path.join(extrasDir, "config/drizzle.config.ts"); + const configDest = path.join(projectDir, "drizzle.config.ts"); + + const schemaSrc = path.join( + extrasDir, + "src/server/db", + packages?.nextAuth.inUse + ? "drizzle-schema-auth.ts" + : "drizzle-schema-base.ts" + ); + const schemaDest = path.join(projectDir, "src/server/db/schema.ts"); + + // Replace placeholder table prefix with project name + let schemaContent = fs.readFileSync(schemaSrc, "utf-8"); + schemaContent = schemaContent.replace( + "project1_${name}", + `${scopedAppName}_\${name}` + ); + let configContent = fs.readFileSync(configFile, "utf-8"); + configContent = configContent.replace("project1_*", `${scopedAppName}_*`); + + const clientSrc = path.join(extrasDir, "src/server/db/index-drizzle.ts"); + const clientDest = path.join(projectDir, "src/server/db/index.ts"); + + // add db:push script to package.json + const packageJsonPath = path.join(projectDir, "package.json"); + + const packageJsonContent = fs.readJSONSync(packageJsonPath) as PackageJson; + packageJsonContent.scripts = { + ...packageJsonContent.scripts, + "db:push": "dotenv drizzle-kit push:mysql", + }; + + fs.copySync(configFile, configDest); + fs.mkdirSync(path.dirname(schemaDest), { recursive: true }); + fs.writeFileSync(schemaDest, schemaContent); + fs.writeFileSync(configDest, configContent); + fs.copySync(clientSrc, clientDest); + fs.writeJSONSync(packageJsonPath, packageJsonContent, { + spaces: 2, + }); +}; diff --git a/cli/src/installers/envVars.ts b/cli/src/installers/envVars.ts index ed59d3ab88..9b4e3a4233 100644 --- a/cli/src/installers/envVars.ts +++ b/cli/src/installers/envVars.ts @@ -7,16 +7,19 @@ import { type Installer } from "~/installers/index.js"; export const envVariablesInstaller: Installer = ({ projectDir, packages }) => { const usingAuth = packages?.nextAuth.inUse; const usingPrisma = packages?.prisma.inUse; + const usingDrizzle = packages?.drizzle.inUse; - const envContent = getEnvContent(!!usingAuth, !!usingPrisma); + const usingDb = usingPrisma || usingDrizzle; + + const envContent = getEnvContent(!!usingAuth, !!usingPrisma, !!usingDrizzle); const envFile = - usingAuth && usingPrisma - ? "with-auth-prisma.mjs" + usingAuth && usingDb + ? "with-auth-db.mjs" : usingAuth ? "with-auth.mjs" - : usingPrisma - ? "with-prisma.mjs" + : usingDb + ? "with-db.mjs" : ""; if (envFile !== "") { @@ -36,7 +39,11 @@ export const envVariablesInstaller: Installer = ({ projectDir, packages }) => { fs.writeFileSync(envExampleDest, exampleEnvContent + envContent, "utf-8"); }; -const getEnvContent = (usingAuth: boolean, usingPrisma: boolean) => { +const getEnvContent = ( + usingAuth: boolean, + usingPrisma: boolean, + usingDrizzle: boolean +) => { let content = ` # When adding additional environment variables, the schema in "/src/env.mjs" # should be updated accordingly. @@ -51,6 +58,15 @@ const getEnvContent = (usingAuth: boolean, usingPrisma: boolean) => { DATABASE_URL="file:./db.sqlite" `; + if (usingDrizzle) { + content += ` +# Drizzle +# Get the Database URL from the "prisma" dropdown selector in PlanetScale. +# Change the query params at the end of the URL to "?ssl={"rejectUnauthorized":true}" +DATABASE_URL='mysql://YOUR_MYSQL_URL_HERE?ssl={"rejectUnauthorized":true}' +`; + } + if (usingAuth) content += ` # Next Auth diff --git a/cli/src/installers/index.ts b/cli/src/installers/index.ts index 9fa144f5e4..45bef9ef14 100644 --- a/cli/src/installers/index.ts +++ b/cli/src/installers/index.ts @@ -4,12 +4,14 @@ import { prismaInstaller } from "~/installers/prisma.js"; import { tailwindInstaller } from "~/installers/tailwind.js"; import { trpcInstaller } from "~/installers/trpc.js"; import { type PackageManager } from "~/utils/getUserPkgManager.js"; +import { drizzleInstaller } from "./drizzle.js"; // Turning this into a const allows the list to be iterated over for programatically creating prompt options // Should increase extensability in the future export const availablePackages = [ "nextAuth", "prisma", + "drizzle", "tailwind", "trpc", "envVariables", @@ -21,7 +23,8 @@ export interface InstallerOptions { pkgManager: PackageManager; noInstall: boolean; packages?: PkgInstallerMap; - projectName?: string; + projectName: string; + scopedAppName: string; } export type Installer = (opts: InstallerOptions) => void; @@ -44,6 +47,10 @@ export const buildPkgInstallerMap = ( inUse: packages.includes("prisma"), installer: prismaInstaller, }, + drizzle: { + inUse: packages.includes("drizzle"), + installer: drizzleInstaller, + }, tailwind: { inUse: packages.includes("tailwind"), installer: tailwindInstaller, diff --git a/cli/src/installers/nextAuth.ts b/cli/src/installers/nextAuth.ts index a1ff4153bc..f4a27ebdfc 100644 --- a/cli/src/installers/nextAuth.ts +++ b/cli/src/installers/nextAuth.ts @@ -8,8 +8,11 @@ import { addPackageDependency } from "~/utils/addPackageDependency.js"; export const nextAuthInstaller: Installer = ({ projectDir, packages }) => { const usingPrisma = packages?.prisma.inUse; + const usingDrizzle = packages?.drizzle.inUse; + const deps: AvailableDependencies[] = ["next-auth"]; if (usingPrisma) deps.push("@next-auth/prisma-adapter"); + if (usingDrizzle) deps.push("@auth/drizzle-adapter"); addPackageDependency({ projectDir, @@ -26,7 +29,11 @@ export const nextAuthInstaller: Installer = ({ projectDir, packages }) => { const authConfigSrc = path.join( extrasDir, "src/server/auth", - usingPrisma ? "with-prisma.ts" : "base.ts" + usingPrisma + ? "with-prisma.ts" + : usingDrizzle + ? "with-drizzle.ts" + : "base.ts" ); const authConfigDest = path.join(projectDir, "src/server/auth.ts"); diff --git a/cli/src/installers/prisma.ts b/cli/src/installers/prisma.ts index f41d3b3de6..b31b23b541 100644 --- a/cli/src/installers/prisma.ts +++ b/cli/src/installers/prisma.ts @@ -27,16 +27,17 @@ export const prismaInstaller: Installer = ({ projectDir, packages }) => { ); const schemaDest = path.join(projectDir, "prisma/schema.prisma"); - const clientSrc = path.join(extrasDir, "src/server/db.ts"); + const clientSrc = path.join(extrasDir, "src/server/db/db-prisma.ts"); const clientDest = path.join(projectDir, "src/server/db.ts"); - // add postinstall script to package.json + // add postinstall and push script to package.json const packageJsonPath = path.join(projectDir, "package.json"); const packageJsonContent = fs.readJSONSync(packageJsonPath) as PackageJson; packageJsonContent.scripts = { ...packageJsonContent.scripts, postinstall: "prisma generate", + "db:push": "prisma db push", }; fs.copySync(schemaSrc, schemaDest); diff --git a/cli/src/installers/trpc.ts b/cli/src/installers/trpc.ts index 5089b736b9..4d1cd24141 100644 --- a/cli/src/installers/trpc.ts +++ b/cli/src/installers/trpc.ts @@ -21,6 +21,8 @@ export const trpcInstaller: Installer = ({ projectDir, packages }) => { const usingAuth = packages?.nextAuth.inUse; const usingPrisma = packages?.prisma.inUse; + const usingDrizzle = packages?.drizzle.inUse; + const usingDb = usingPrisma || usingDrizzle; const extrasDir = path.join(PKG_ROOT, "template/extras"); @@ -31,12 +33,12 @@ export const trpcInstaller: Installer = ({ projectDir, packages }) => { const utilsDest = path.join(projectDir, "src/utils/api.ts"); const trpcFile = - usingAuth && usingPrisma - ? "with-auth-prisma.ts" + usingAuth && usingDb + ? "with-auth-db.ts" : usingAuth ? "with-auth.ts" - : usingPrisma - ? "with-prisma.ts" + : usingDb + ? "with-db.ts" : "base.ts"; const trpcSrc = path.join(extrasDir, "src/server/api/trpc", trpcFile); const trpcDest = path.join(projectDir, "src/server/api/trpc.ts"); @@ -47,10 +49,14 @@ export const trpcInstaller: Installer = ({ projectDir, packages }) => { const exampleRouterFile = usingAuth && usingPrisma ? "with-auth-prisma.ts" + : usingAuth && usingDrizzle + ? "with-auth-drizzle.ts" : usingAuth ? "with-auth.ts" : usingPrisma ? "with-prisma.ts" + : usingDrizzle + ? "with-drizzle.ts" : "base.ts"; const exampleRouterSrc = path.join( diff --git a/cli/src/utils/parseNameAndPath.ts b/cli/src/utils/parseNameAndPath.ts index 92dd20108d..2f311f34a5 100644 --- a/cli/src/utils/parseNameAndPath.ts +++ b/cli/src/utils/parseNameAndPath.ts @@ -22,7 +22,7 @@ export const parseNameAndPath = (rawInput: string) => { const paths = input.split("/"); - let appName = paths[paths.length - 1]; + let appName = paths[paths.length - 1]!; // If the user ran `npx create-t3-app .` or similar, the appName should be the current directory if (appName === ".") { diff --git a/cli/src/utils/validateAppName.ts b/cli/src/utils/validateAppName.ts index 6dec344753..7f05949582 100644 --- a/cli/src/utils/validateAppName.ts +++ b/cli/src/utils/validateAppName.ts @@ -17,7 +17,7 @@ export const validateAppName = (rawInput: string) => { } if (input === "." || validationRegExp.test(appName ?? "")) { - return true; + return; } else { return "App name must consist of only lowercase alphanumeric characters, '-', and '_'"; } diff --git a/cli/src/utils/validateImportAlias.ts b/cli/src/utils/validateImportAlias.ts index d762a9c951..bd33ca6197 100644 --- a/cli/src/utils/validateImportAlias.ts +++ b/cli/src/utils/validateImportAlias.ts @@ -1,7 +1,6 @@ export const validateImportAlias = (input: string) => { if (input.startsWith(".") || input.startsWith("/")) { return "Import alias can't start with '.' or '/'"; - } else { - return true; } + return; }; diff --git a/cli/template/base/package.json b/cli/template/base/package.json index e5d71365b7..ff123eb4f5 100644 --- a/cli/template/base/package.json +++ b/cli/template/base/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@t3-oss/env-nextjs": "^0.6.0", - "next": "^13.4.13", + "next": "^13.4.19", "react": "18.2.0", "react-dom": "18.2.0", "zod": "^3.21.4" @@ -23,7 +23,7 @@ "@typescript-eslint/eslint-plugin": "^6.3.0", "@typescript-eslint/parser": "^6.3.0", "eslint": "^8.47.0", - "eslint-config-next": "^13.4.13", + "eslint-config-next": "^13.4.19", "typescript": "^5.1.6" } } diff --git a/cli/template/extras/config/drizzle.config.ts b/cli/template/extras/config/drizzle.config.ts new file mode 100644 index 0000000000..aaef4720f4 --- /dev/null +++ b/cli/template/extras/config/drizzle.config.ts @@ -0,0 +1,12 @@ +import { type Config } from "drizzle-kit"; + +import { env } from "~/env.mjs"; + +export default { + schema: "./src/server/db/schema.ts", + driver: "mysql2", + dbCredentials: { + connectionString: env.DATABASE_URL, + }, + tablesFilter: ["project1_*"], +} satisfies Config; diff --git a/cli/template/extras/prisma/schema/base.prisma b/cli/template/extras/prisma/schema/base.prisma index 6d43fd2ab6..c229b415fb 100644 --- a/cli/template/extras/prisma/schema/base.prisma +++ b/cli/template/extras/prisma/schema/base.prisma @@ -11,7 +11,10 @@ datasource db { } model Example { - id String @id @default(cuid()) + id Int @id @default(autoincrement()) + name String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt + + @@index([name]) } diff --git a/cli/template/extras/prisma/schema/with-auth.prisma b/cli/template/extras/prisma/schema/with-auth.prisma index 0001d809c5..935817c6ba 100644 --- a/cli/template/extras/prisma/schema/with-auth.prisma +++ b/cli/template/extras/prisma/schema/with-auth.prisma @@ -15,9 +15,12 @@ datasource db { } model Example { - id String @id @default(cuid()) + id Int @id @default(autoincrement()) + name String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt + + @@index([name]) } // Necessary for Next auth diff --git a/cli/template/extras/src/env/with-auth-prisma.mjs b/cli/template/extras/src/env/with-auth-db.mjs similarity index 95% rename from cli/template/extras/src/env/with-auth-prisma.mjs rename to cli/template/extras/src/env/with-auth-db.mjs index 58bc43a153..5363637a3a 100644 --- a/cli/template/extras/src/env/with-auth-prisma.mjs +++ b/cli/template/extras/src/env/with-auth-db.mjs @@ -8,7 +8,9 @@ export const env = createEnv({ */ server: { DATABASE_URL: z.string().url(), - NODE_ENV: z.enum(["development", "test", "production"]), + NODE_ENV: z + .enum(["development", "test", "production"]) + .default("development"), NEXTAUTH_SECRET: process.env.NODE_ENV === "production" ? z.string().min(1) diff --git a/cli/template/extras/src/env/with-auth.mjs b/cli/template/extras/src/env/with-auth.mjs index 71808934f2..da17aef134 100644 --- a/cli/template/extras/src/env/with-auth.mjs +++ b/cli/template/extras/src/env/with-auth.mjs @@ -7,7 +7,9 @@ export const env = createEnv({ * isn't built with invalid env vars. */ server: { - NODE_ENV: z.enum(["development", "test", "production"]), + NODE_ENV: z + .enum(["development", "test", "production"]) + .default("development"), NEXTAUTH_SECRET: process.env.NODE_ENV === "production" ? z.string().min(1) diff --git a/cli/template/extras/src/env/with-prisma.mjs b/cli/template/extras/src/env/with-db.mjs similarity index 86% rename from cli/template/extras/src/env/with-prisma.mjs rename to cli/template/extras/src/env/with-db.mjs index 67fa767443..d96eb5ce6c 100644 --- a/cli/template/extras/src/env/with-prisma.mjs +++ b/cli/template/extras/src/env/with-db.mjs @@ -8,7 +8,9 @@ export const env = createEnv({ */ server: { DATABASE_URL: z.string().url(), - NODE_ENV: z.enum(["development", "test", "production"]), + NODE_ENV: z + .enum(["development", "test", "production"]) + .default("development"), }, /** @@ -30,8 +32,8 @@ export const env = createEnv({ // NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR, }, /** - * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. - * This is especially useful for Docker builds. + * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially + * useful for Docker builds. */ skipValidation: !!process.env.SKIP_ENV_VALIDATION, }); diff --git a/cli/template/extras/src/server/api/routers/example/with-auth-drizzle.ts b/cli/template/extras/src/server/api/routers/example/with-auth-drizzle.ts new file mode 100644 index 0000000000..55a3189509 --- /dev/null +++ b/cli/template/extras/src/server/api/routers/example/with-auth-drizzle.ts @@ -0,0 +1,25 @@ +import { z } from "zod"; + +import { + createTRPCRouter, + protectedProcedure, + publicProcedure, +} from "~/server/api/trpc"; + +export const exampleRouter = createTRPCRouter({ + hello: publicProcedure + .input(z.object({ text: z.string() })) + .query(({ input }) => { + return { + greeting: `Hello ${input.text}`, + }; + }), + + getAll: publicProcedure.query(({ ctx }) => { + return ctx.db.query.example.findMany(); + }), + + getSecretMessage: protectedProcedure.query(() => { + return "you can now see this secret message!"; + }), +}); diff --git a/cli/template/extras/src/server/api/routers/example/with-auth-prisma.ts b/cli/template/extras/src/server/api/routers/example/with-auth-prisma.ts index 5b9da79b3e..ed0ce35ba1 100644 --- a/cli/template/extras/src/server/api/routers/example/with-auth-prisma.ts +++ b/cli/template/extras/src/server/api/routers/example/with-auth-prisma.ts @@ -16,7 +16,7 @@ export const exampleRouter = createTRPCRouter({ }), getAll: publicProcedure.query(({ ctx }) => { - return ctx.prisma.example.findMany(); + return ctx.db.example.findMany(); }), getSecretMessage: protectedProcedure.query(() => { diff --git a/cli/template/extras/src/server/api/routers/example/with-drizzle.ts b/cli/template/extras/src/server/api/routers/example/with-drizzle.ts new file mode 100644 index 0000000000..15f90c76b6 --- /dev/null +++ b/cli/template/extras/src/server/api/routers/example/with-drizzle.ts @@ -0,0 +1,16 @@ +import { z } from "zod"; + +import { createTRPCRouter, publicProcedure } from "~/server/api/trpc"; + +export const exampleRouter = createTRPCRouter({ + hello: publicProcedure + .input(z.object({ text: z.string() })) + .query(({ input }) => { + return { + greeting: `Hello ${input.text}`, + }; + }), + getAll: publicProcedure.query(({ ctx }) => { + return ctx.db.query.example.findMany(); + }), +}); diff --git a/cli/template/extras/src/server/api/routers/example/with-prisma.ts b/cli/template/extras/src/server/api/routers/example/with-prisma.ts index be8d0e1f95..de5d5c5b6e 100644 --- a/cli/template/extras/src/server/api/routers/example/with-prisma.ts +++ b/cli/template/extras/src/server/api/routers/example/with-prisma.ts @@ -11,6 +11,6 @@ export const exampleRouter = createTRPCRouter({ }; }), getAll: publicProcedure.query(({ ctx }) => { - return ctx.prisma.example.findMany(); + return ctx.db.example.findMany(); }), }); diff --git a/cli/template/extras/src/server/api/trpc/with-auth-prisma.ts b/cli/template/extras/src/server/api/trpc/with-auth-db.ts similarity index 98% rename from cli/template/extras/src/server/api/trpc/with-auth-prisma.ts rename to cli/template/extras/src/server/api/trpc/with-auth-db.ts index 231835d48e..87237ffc8f 100644 --- a/cli/template/extras/src/server/api/trpc/with-auth-prisma.ts +++ b/cli/template/extras/src/server/api/trpc/with-auth-db.ts @@ -14,7 +14,7 @@ import superjson from "superjson"; import { ZodError } from "zod"; import { getServerAuthSession } from "~/server/auth"; -import { prisma } from "~/server/db"; +import { db } from "~/server/db"; /** * 1. CONTEXT @@ -41,7 +41,7 @@ interface CreateContextOptions { const createInnerTRPCContext = (opts: CreateContextOptions) => { return { session: opts.session, - prisma, + db, }; }; diff --git a/cli/template/extras/src/server/api/trpc/with-prisma.ts b/cli/template/extras/src/server/api/trpc/with-db.ts similarity index 98% rename from cli/template/extras/src/server/api/trpc/with-prisma.ts rename to cli/template/extras/src/server/api/trpc/with-db.ts index 0088dde3c9..dc3b40b241 100644 --- a/cli/template/extras/src/server/api/trpc/with-prisma.ts +++ b/cli/template/extras/src/server/api/trpc/with-db.ts @@ -11,7 +11,7 @@ import { type CreateNextContextOptions } from "@trpc/server/adapters/next"; import superjson from "superjson"; import { ZodError } from "zod"; -import { prisma } from "~/server/db"; +import { db } from "~/server/db"; /** * 1. CONTEXT @@ -35,7 +35,7 @@ type CreateContextOptions = Record; */ const createInnerTRPCContext = (_opts: CreateContextOptions) => { return { - prisma, + db, }; }; diff --git a/cli/template/extras/src/server/auth/with-drizzle.ts b/cli/template/extras/src/server/auth/with-drizzle.ts new file mode 100644 index 0000000000..89391fd84a --- /dev/null +++ b/cli/template/extras/src/server/auth/with-drizzle.ts @@ -0,0 +1,78 @@ +import { DrizzleAdapter } from "@auth/drizzle-adapter"; +import { type GetServerSidePropsContext } from "next"; +import { + getServerSession, + type DefaultSession, + type NextAuthOptions, +} from "next-auth"; +import DiscordProvider from "next-auth/providers/discord"; + +import { env } from "~/env.mjs"; +import { db } from "~/server/db"; +import { mysqlTable } from "~/server/db/schema"; + +/** + * Module augmentation for `next-auth` types. Allows us to add custom properties to the `session` + * object and keep type safety. + * + * @see https://next-auth.js.org/getting-started/typescript#module-augmentation + */ +declare module "next-auth" { + interface Session extends DefaultSession { + user: { + id: string; + // ...other properties + // role: UserRole; + } & DefaultSession["user"]; + } + + // interface User { + // // ...other properties + // // role: UserRole; + // } +} + +/** + * Options for NextAuth.js used to configure adapters, providers, callbacks, etc. + * + * @see https://next-auth.js.org/configuration/options + */ +export const authOptions: NextAuthOptions = { + callbacks: { + session: ({ session, user }) => ({ + ...session, + user: { + ...session.user, + id: user.id, + }, + }), + }, + adapter: DrizzleAdapter(db, mysqlTable), + providers: [ + DiscordProvider({ + clientId: env.DISCORD_CLIENT_ID, + clientSecret: env.DISCORD_CLIENT_SECRET, + }), + /** + * ...add more providers here. + * + * Most other providers require a bit more work than the Discord provider. For example, the + * GitHub provider requires you to add the `refresh_token_expires_in` field to the Account + * model. Refer to the NextAuth.js docs for the provider you want to use. Example: + * + * @see https://next-auth.js.org/providers/github + */ + ], +}; + +/** + * Wrapper for `getServerSession` so that you don't need to import the `authOptions` in every file. + * + * @see https://next-auth.js.org/configuration/nextjs + */ +export const getServerAuthSession = (ctx: { + req: GetServerSidePropsContext["req"]; + res: GetServerSidePropsContext["res"]; +}) => { + return getServerSession(ctx.req, ctx.res, authOptions); +}; diff --git a/cli/template/extras/src/server/auth/with-prisma.ts b/cli/template/extras/src/server/auth/with-prisma.ts index f7cec72a1d..cec71fc803 100644 --- a/cli/template/extras/src/server/auth/with-prisma.ts +++ b/cli/template/extras/src/server/auth/with-prisma.ts @@ -8,7 +8,7 @@ import { import DiscordProvider from "next-auth/providers/discord"; import { env } from "~/env.mjs"; -import { prisma } from "~/server/db"; +import { db } from "~/server/db"; /** * Module augmentation for `next-auth` types. Allows us to add custom properties to the `session` @@ -46,7 +46,7 @@ export const authOptions: NextAuthOptions = { }, }), }, - adapter: PrismaAdapter(prisma), + adapter: PrismaAdapter(db), providers: [ DiscordProvider({ clientId: env.DISCORD_CLIENT_ID, diff --git a/cli/template/extras/src/server/db.ts b/cli/template/extras/src/server/db/db-prisma.ts similarity index 77% rename from cli/template/extras/src/server/db.ts rename to cli/template/extras/src/server/db/db-prisma.ts index 861093d2f7..a4753ca156 100644 --- a/cli/template/extras/src/server/db.ts +++ b/cli/template/extras/src/server/db/db-prisma.ts @@ -6,11 +6,11 @@ const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined; }; -export const prisma = +export const db = globalForPrisma.prisma ?? new PrismaClient({ log: env.NODE_ENV === "development" ? ["query", "error", "warn"] : ["error"], }); -if (env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; +if (env.NODE_ENV !== "production") globalForPrisma.prisma = db; diff --git a/cli/template/extras/src/server/db/drizzle-schema-auth.ts b/cli/template/extras/src/server/db/drizzle-schema-auth.ts new file mode 100644 index 0000000000..ee154f7e78 --- /dev/null +++ b/cli/template/extras/src/server/db/drizzle-schema-auth.ts @@ -0,0 +1,108 @@ +import { relations, sql } from "drizzle-orm"; +import { + bigint, + index, + int, + mysqlTableCreator, + primaryKey, + text, + timestamp, + uniqueIndex, + varchar, +} from "drizzle-orm/mysql-core"; +import { type AdapterAccount } from "next-auth/adapters"; + +/** + * This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same + * database instance for multiple projects. + * + * @see https://orm.drizzle.team/docs/goodies#multi-project-schema + */ +export const mysqlTable = mysqlTableCreator((name) => `project1_${name}`); + +export const example = mysqlTable( + "example", + { + id: bigint("id", { mode: "number" }).primaryKey().autoincrement(), + name: varchar("name", { length: 256 }), + createdAt: timestamp("created_at") + .default(sql`CURRENT_TIMESTAMP`) + .notNull(), + updatedAt: timestamp("updatedAt").onUpdateNow(), + }, + (example) => ({ + nameIndex: uniqueIndex("name_idx").on(example.name), + }) +); + +export const users = mysqlTable("user", { + id: varchar("id", { length: 255 }).notNull().primaryKey(), + name: varchar("name", { length: 255 }), + email: varchar("email", { length: 255 }).notNull(), + emailVerified: timestamp("emailVerified", { + mode: "date", + fsp: 3, + }).default(sql`CURRENT_TIMESTAMP(3)`), + image: varchar("image", { length: 255 }), +}); + +export const usersRelations = relations(users, ({ many }) => ({ + accounts: many(accounts), +})); + +export const accounts = mysqlTable( + "account", + { + userId: varchar("userId", { length: 255 }).notNull(), + type: varchar("type", { length: 255 }) + .$type() + .notNull(), + provider: varchar("provider", { length: 255 }).notNull(), + providerAccountId: varchar("providerAccountId", { length: 255 }).notNull(), + refresh_token: text("refresh_token"), + access_token: text("access_token"), + expires_at: int("expires_at"), + token_type: varchar("token_type", { length: 255 }), + scope: varchar("scope", { length: 255 }), + id_token: text("id_token"), + session_state: varchar("session_state", { length: 255 }), + }, + (account) => ({ + compoundKey: primaryKey(account.provider, account.providerAccountId), + userIdIdx: index("userId_idx").on(account.userId), + }) +); + +export const accountsRelations = relations(accounts, ({ one }) => ({ + user: one(users, { fields: [accounts.userId], references: [users.id] }), +})); + +export const sessions = mysqlTable( + "session", + { + sessionToken: varchar("sessionToken", { length: 255 }) + .notNull() + .primaryKey(), + userId: varchar("userId", { length: 255 }).notNull(), + expires: timestamp("expires", { mode: "date" }).notNull(), + }, + (session) => ({ + userIdIdx: index("userId_idx").on(session.userId), + }) +); + +export const sessionsRelations = relations(sessions, ({ one }) => ({ + user: one(users, { fields: [sessions.userId], references: [users.id] }), +})); + +export const verificationTokens = mysqlTable( + "verificationToken", + { + identifier: varchar("identifier", { length: 255 }).notNull(), + token: varchar("token", { length: 255 }).notNull(), + expires: timestamp("expires", { mode: "date" }).notNull(), + }, + (vt) => ({ + compoundKey: primaryKey(vt.identifier, vt.token), + }) +); diff --git a/cli/template/extras/src/server/db/drizzle-schema-base.ts b/cli/template/extras/src/server/db/drizzle-schema-base.ts new file mode 100644 index 0000000000..bf0360bc6a --- /dev/null +++ b/cli/template/extras/src/server/db/drizzle-schema-base.ts @@ -0,0 +1,34 @@ +// Example model schema from the Drizzle docs +// https://orm.drizzle.team/docs/sql-schema-declaration + +import { sql } from "drizzle-orm"; +import { + bigint, + mysqlTableCreator, + timestamp, + uniqueIndex, + varchar, +} from "drizzle-orm/mysql-core"; + +/** + * This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same + * database instance for multiple projects. + * + * @see https://orm.drizzle.team/docs/goodies#multi-project-schema + */ +export const mysqlTable = mysqlTableCreator((name) => `project1_${name}`); + +export const example = mysqlTable( + "example", + { + id: bigint("id", { mode: "number" }).primaryKey().autoincrement(), + name: varchar("name", { length: 256 }), + createdAt: timestamp("created_at") + .default(sql`CURRENT_TIMESTAMP`) + .notNull(), + updatedAt: timestamp("updatedAt").onUpdateNow(), + }, + (example) => ({ + nameIndex: uniqueIndex("name_idx").on(example.name), + }) +); diff --git a/cli/template/extras/src/server/db/index-drizzle.ts b/cli/template/extras/src/server/db/index-drizzle.ts new file mode 100644 index 0000000000..2a0c8e8f4d --- /dev/null +++ b/cli/template/extras/src/server/db/index-drizzle.ts @@ -0,0 +1,12 @@ +import { Client } from "@planetscale/database"; +import { drizzle } from "drizzle-orm/planetscale-serverless"; + +import { env } from "~/env.mjs"; +import * as schema from "./schema"; + +export const db = drizzle( + new Client({ + url: env.DATABASE_URL, + }).connection(), + { schema } +); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b34fa48fc3..04ba79d28d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -64,6 +64,12 @@ importers: cli: dependencies: + '@clack/core': + specifier: ^0.3.2 + version: 0.3.2 + '@clack/prompts': + specifier: ^0.6.3 + version: 0.6.3 '@ianvs/prettier-plugin-sort-imports': specifier: ^4.1.0 version: 4.1.0(prettier@3.0.0) @@ -82,9 +88,6 @@ importers: gradient-string: specifier: ^2.0.2 version: 2.0.2 - inquirer: - specifier: ^9.2.3 - version: 9.2.3 ora: specifier: 6.3.1 version: 6.3.1 @@ -92,27 +95,36 @@ importers: specifier: ^2.4.1 version: 2.4.1 devDependencies: + '@auth/drizzle-adapter': + specifier: ^0.3.2 + version: 0.3.2 + '@next-auth/prisma-adapter': + specifier: ^1.0.7 + version: 1.0.7(@prisma/client@5.1.1)(next-auth@4.23.1) + '@planetscale/database': + specifier: ^1.11.0 + version: 1.11.0 '@prisma/client': - specifier: ^4.14.0 - version: 4.14.0(prisma@4.14.0) + specifier: ^5.1.1 + version: 5.1.1(prisma@4.14.0) '@t3-oss/env-nextjs': specifier: ^0.6.0 version: 0.6.0(typescript@5.0.4)(zod@3.21.4) '@tanstack/react-query': - specifier: ^4.29.7 - version: 4.29.7(react-dom@18.2.0)(react@18.2.0) + specifier: ^4.32.6 + version: 4.32.6(react-dom@18.2.0)(react@18.2.0) '@trpc/client': - specifier: ^10.26.0 - version: 10.26.0(@trpc/server@10.26.0) + specifier: ^10.37.1 + version: 10.37.1(@trpc/server@10.37.1) '@trpc/next': - specifier: ^10.26.0 - version: 10.26.0(@tanstack/react-query@4.29.7)(@trpc/client@10.26.0)(@trpc/react-query@10.26.0)(@trpc/server@10.26.0)(next@13.4.1)(react-dom@18.2.0)(react@18.2.0) + specifier: ^10.37.1 + version: 10.37.1(@tanstack/react-query@4.32.6)(@trpc/client@10.37.1)(@trpc/react-query@10.37.1)(@trpc/server@10.37.1)(next@13.4.19)(react-dom@18.2.0)(react@18.2.0) '@trpc/react-query': - specifier: ^10.26.0 - version: 10.26.0(@tanstack/react-query@4.29.7)(@trpc/client@10.26.0)(@trpc/server@10.26.0)(react-dom@18.2.0)(react@18.2.0) + specifier: ^10.37.1 + version: 10.37.1(@tanstack/react-query@4.32.6)(@trpc/client@10.37.1)(@trpc/server@10.37.1)(react-dom@18.2.0)(react@18.2.0) '@trpc/server': - specifier: ^10.26.0 - version: 10.26.0 + specifier: ^10.37.1 + version: 10.37.1 '@types/fs-extra': specifier: ^11.0.1 version: 11.0.1 @@ -125,12 +137,18 @@ importers: '@types/node': specifier: ^18.16.0 version: 18.16.1 + drizzle-kit: + specifier: ^0.19.13 + version: 0.19.13 + drizzle-orm: + specifier: ^0.28.5 + version: 0.28.5(@planetscale/database@1.11.0) next: - specifier: ^13.4.1 - version: 13.4.1(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0) + specifier: ^13.4.19 + version: 13.4.19(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0) next-auth: - specifier: ^4.22.1 - version: 4.22.1(next@13.4.1)(react-dom@18.2.0)(react@18.2.0) + specifier: ^4.23.1 + version: 4.23.1(next@13.4.19)(react-dom@18.2.0)(react@18.2.0) prettier: specifier: ^3.0.0 version: 3.0.0 @@ -204,11 +222,11 @@ importers: specifier: ^0.3.1 version: 0.3.1 lucide-react: - specifier: ^0.216.0 - version: 0.216.0(react@18.2.0) + specifier: ^0.263.1 + version: 0.263.1(react@18.2.0) next: - specifier: ^13.4.1 - version: 13.4.1(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0) + specifier: ^13.4.19 + version: 13.4.19(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0) react: specifier: 18.2.0 version: 18.2.0 @@ -767,6 +785,30 @@ packages: dependencies: undici: 5.22.1 + /@auth/core@0.12.0: + resolution: {integrity: sha512-XYipdAc/nKu014VOgpcPyLlj1ghWlnwyloaB1UjQd9ElZRZQ9YpSizzXGLON23t/a0FyabOBBl0/awD2tW58Rg==} + peerDependencies: + nodemailer: ^6.8.0 + peerDependenciesMeta: + nodemailer: + optional: true + dependencies: + '@panva/hkdf': 1.0.4 + cookie: 0.5.0 + jose: 4.13.1 + oauth4webapi: 2.3.0 + preact: 10.11.3 + preact-render-to-string: 5.2.3(preact@10.11.3) + dev: true + + /@auth/drizzle-adapter@0.3.2: + resolution: {integrity: sha512-fHfzwaTomm/RKgFKBO5AJ8JTfR44rX1KX2ASaKRk+4jvVhDh9FCir5BV1Fv68b5ay7XBo9DtcNSQuZp4hbpLYw==} + dependencies: + '@auth/core': 0.12.0 + transitivePeerDependencies: + - nodemailer + dev: true + /@babel/code-frame@7.22.5: resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==} engines: {node: '>=6.9.0'} @@ -1180,6 +1222,23 @@ packages: prettier: 2.8.8 dev: false + /@clack/core@0.3.2: + resolution: {integrity: sha512-FZnsNynwGDIDktx6PEZK1EuCkFpY4ldEX6VYvfl0dqeoLPb9Jpw1xoUXaVcGR8ExmYNm1w2vdGdJkEUYD/2pqg==} + dependencies: + picocolors: 1.0.0 + sisteransi: 1.0.5 + dev: false + + /@clack/prompts@0.6.3: + resolution: {integrity: sha512-AM+kFmAHawpUQv2q9+mcB6jLKxXGjgu/r2EQjEwujgpCdzrST6BJqYw00GRn56/L/Izw5U7ImoLmy00X/r80Pw==} + dependencies: + '@clack/core': 0.3.2 + picocolors: 1.0.0 + sisteransi: 1.0.5 + dev: false + bundledDependencies: + - is-unicode-supported + /@docsearch/css@3.3.4: resolution: {integrity: sha512-vDwCDoVXDgopw/hvr0zEADew2wWaGP8Qq0Bxhgii1Ewz2t4fQeyJwIRN/mWADeLFYPVkpz8TpEbxya/i6Tm0WA==} dev: false @@ -1209,6 +1268,10 @@ packages: - '@algolia/client-search' dev: false + /@drizzle-team/studio@0.0.5: + resolution: {integrity: sha512-ps5qF0tMxWRVu+V5gvCRrQNqlY92aTnIKdq27gm9LZMSdaKYZt6AVvSK1dlUMzs6Rt0Jm80b+eWct6xShBKhIw==} + dev: true + /@emmetio/abbreviation@2.3.3: resolution: {integrity: sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==} dependencies: @@ -1222,6 +1285,20 @@ packages: /@emmetio/scanner@1.0.4: resolution: {integrity: sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==} + /@esbuild-kit/core-utils@3.1.0: + resolution: {integrity: sha512-Uuk8RpCg/7fdHSceR1M6XbSZFSuMrxcePFuGgyvsBn+u339dk5OeL4jv2EojwTN2st/unJGsVm4qHWjWNmJ/tw==} + dependencies: + esbuild: 0.17.19 + source-map-support: 0.5.21 + dev: true + + /@esbuild-kit/esm-loader@2.5.5: + resolution: {integrity: sha512-Qwfvj/qoPbClxCRNuac1Du01r9gvNOT+pMYtJDapfB1eoGN1YlJ1BixLyL9WVENRx5RXgNLdfYdx/CuswlGhMw==} + dependencies: + '@esbuild-kit/core-utils': 3.1.0 + get-tsconfig: 4.7.0 + dev: true + /@esbuild/android-arm64@0.17.12: resolution: {integrity: sha512-WQ9p5oiXXYJ33F2EkE3r0FRDFVpEdcDiwNX3u7Xaibxfx6vQE0Sb8ytrfQsA5WO6kDn6mDfKLh6KrPBjvkk7xA==} engines: {node: '>=12'} @@ -2067,8 +2144,18 @@ packages: - supports-color dev: false - /@next/env@13.4.1: - resolution: {integrity: sha512-eD6WCBMFjLFooLM19SIhSkWBHtaFrZFfg2Cxnyl3vS3DAdFRfnx5TY2RxlkuKXdIRCC0ySbtK9JXXt8qLCqzZg==} + /@next-auth/prisma-adapter@1.0.7(@prisma/client@5.1.1)(next-auth@4.23.1): + resolution: {integrity: sha512-Cdko4KfcmKjsyHFrWwZ//lfLUbcLqlyFqjd/nYE2m3aZ7tjMNUjpks47iw7NTCnXf+5UWz5Ypyt1dSs1EP5QJw==} + peerDependencies: + '@prisma/client': '>=2.26.0 || >=3' + next-auth: ^4 + dependencies: + '@prisma/client': 5.1.1(prisma@4.14.0) + next-auth: 4.23.1(next@13.4.19)(react-dom@18.2.0)(react@18.2.0) + dev: true + + /@next/env@13.4.19: + resolution: {integrity: sha512-FsAT5x0jF2kkhNkKkukhsyYOrRqtSxrEhfliniIq0bwWbuXLgyt3Gv0Ml+b91XwjwArmuP7NxCiGd++GGKdNMQ==} /@next/eslint-plugin-next@13.4.1: resolution: {integrity: sha512-tVPS/2FKlA3ANCRCYZVT5jdbUKasBU8LG6bYqcNhyORDFTlDYa4cAWQJjZ7msIgLwMQIbL8CAsxrOL8maa/4Lg==} @@ -2091,72 +2178,72 @@ packages: source-map: 0.7.4 dev: false - /@next/swc-darwin-arm64@13.4.1: - resolution: {integrity: sha512-eF8ARHtYfnoYtDa6xFHriUKA/Mfj/cCbmKb3NofeKhMccs65G6/loZ15a6wYCCx4rPAd6x4t1WmVYtri7EdeBg==} + /@next/swc-darwin-arm64@13.4.19: + resolution: {integrity: sha512-vv1qrjXeGbuF2mOkhkdxMDtv9np7W4mcBtaDnHU+yJG+bBwa6rYsYSCI/9Xm5+TuF5SbZbrWO6G1NfTh1TMjvQ==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] requiresBuild: true optional: true - /@next/swc-darwin-x64@13.4.1: - resolution: {integrity: sha512-7cmDgF9tGWTgn5Gw+vP17miJbH4wcraMHDCOHTYWkO/VeKT73dUWG23TNRLfgtCNSPgH4V5B4uLHoZTanx9bAw==} + /@next/swc-darwin-x64@13.4.19: + resolution: {integrity: sha512-jyzO6wwYhx6F+7gD8ddZfuqO4TtpJdw3wyOduR4fxTUCm3aLw7YmHGYNjS0xRSYGAkLpBkH1E0RcelyId6lNsw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] requiresBuild: true optional: true - /@next/swc-linux-arm64-gnu@13.4.1: - resolution: {integrity: sha512-qwJqmCri2ie8aTtE5gjTSr8S6O8B67KCYgVZhv9gKH44yvc/zXbAY8u23QGULsYOyh1islWE5sWfQNLOj9iryg==} + /@next/swc-linux-arm64-gnu@13.4.19: + resolution: {integrity: sha512-vdlnIlaAEh6H+G6HrKZB9c2zJKnpPVKnA6LBwjwT2BTjxI7e0Hx30+FoWCgi50e+YO49p6oPOtesP9mXDRiiUg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] requiresBuild: true optional: true - /@next/swc-linux-arm64-musl@13.4.1: - resolution: {integrity: sha512-qcC54tWNGDv/VVIFkazxhqH1Bnagjfs4enzELVRlUOoJPD2BGJTPI7z08pQPbbgxLtRiu8gl2mXvpB8WlOkMeA==} + /@next/swc-linux-arm64-musl@13.4.19: + resolution: {integrity: sha512-aU0HkH2XPgxqrbNRBFb3si9Ahu/CpaR5RPmN2s9GiM9qJCiBBlZtRTiEca+DC+xRPyCThTtWYgxjWHgU7ZkyvA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] requiresBuild: true optional: true - /@next/swc-linux-x64-gnu@13.4.1: - resolution: {integrity: sha512-9TeWFlpLsBosZ+tsm/rWBaMwt5It9tPH8m3nawZqFUUrZyGRfGcI67js774vtx0k3rL9qbyY6+3pw9BCVpaYUA==} + /@next/swc-linux-x64-gnu@13.4.19: + resolution: {integrity: sha512-htwOEagMa/CXNykFFeAHHvMJeqZfNQEoQvHfsA4wgg5QqGNqD5soeCer4oGlCol6NGUxknrQO6VEustcv+Md+g==} engines: {node: '>= 10'} cpu: [x64] os: [linux] requiresBuild: true optional: true - /@next/swc-linux-x64-musl@13.4.1: - resolution: {integrity: sha512-sNDGaWmSqTS4QRUzw61wl4mVPeSqNIr1OOjLlQTRuyInxMxtqImRqdvzDvFTlDfdeUMU/DZhWGYoHrXLlZXe6A==} + /@next/swc-linux-x64-musl@13.4.19: + resolution: {integrity: sha512-4Gj4vvtbK1JH8ApWTT214b3GwUh9EKKQjY41hH/t+u55Knxi/0wesMzwQRhppK6Ddalhu0TEttbiJ+wRcoEj5Q==} engines: {node: '>= 10'} cpu: [x64] os: [linux] requiresBuild: true optional: true - /@next/swc-win32-arm64-msvc@13.4.1: - resolution: {integrity: sha512-+CXZC7u1iXdLRudecoUYbhbsXpglYv8KFYsFxKBPn7kg+bk7eJo738wAA4jXIl8grTF2mPdmO93JOQym+BlYGA==} + /@next/swc-win32-arm64-msvc@13.4.19: + resolution: {integrity: sha512-bUfDevQK4NsIAHXs3/JNgnvEY+LRyneDN788W2NYiRIIzmILjba7LaQTfihuFawZDhRtkYCv3JDC3B4TwnmRJw==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] requiresBuild: true optional: true - /@next/swc-win32-ia32-msvc@13.4.1: - resolution: {integrity: sha512-vIoXVVc7UYO68VwVMDKwJC2+HqAZQtCYiVlApyKEeIPIQpz2gpufzGxk1z3/gwrJt/kJ5CDZjlhYDCzd3hdz+g==} + /@next/swc-win32-ia32-msvc@13.4.19: + resolution: {integrity: sha512-Y5kikILFAr81LYIFaw6j/NrOtmiM4Sf3GtOc0pn50ez2GCkr+oejYuKGcwAwq3jiTKuzF6OF4iT2INPoxRycEA==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] requiresBuild: true optional: true - /@next/swc-win32-x64-msvc@13.4.1: - resolution: {integrity: sha512-n8V5ImLQZibKTu10UUdI3nIeTLkliEXe628qxqW9v8My3BAH2a7H0SaCqkV2OgqFnn8sG1wxKYw9/SNJ632kSA==} + /@next/swc-win32-x64-msvc@13.4.19: + resolution: {integrity: sha512-YzA78jBDXMYiINdPdJJwGgPNT3YqBNNGhsthsDoWHL9p24tEJn9ViQf/ZqTbwSpX/RrkPupLfuuTH2sf73JBAw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -2235,9 +2322,14 @@ packages: tiny-glob: 0.2.9 tslib: 2.5.0 - /@prisma/client@4.14.0(prisma@4.14.0): - resolution: {integrity: sha512-MK/XaA2sFdfaOa7I9MjNKz6dxeIEdeZlnpNRoF2w3JuRLlFJLkpp6cD3yaqw2nUUhbrn3Iqe3ZpVV+VuGGil7Q==} - engines: {node: '>=14.17'} + /@planetscale/database@1.11.0: + resolution: {integrity: sha512-aWbU+D/IRHoDE9975y+Q4c+EwwAWxCPwFId+N1AhQVFXzbeJMkj6KN2iQtoi03elcLMRdfT+V3i9Z4WRw+/oIA==} + engines: {node: '>=16'} + dev: true + + /@prisma/client@5.1.1(prisma@4.14.0): + resolution: {integrity: sha512-fxcCeK5pMQGcgCqCrWsi+I2rpIbk0rAhdrN+ke7f34tIrgPwA68ensrpin+9+fZvuV2OtzHmuipwduSY6HswdA==} + engines: {node: '>=16.13'} requiresBuild: true peerDependencies: prisma: '*' @@ -2245,12 +2337,12 @@ packages: prisma: optional: true dependencies: - '@prisma/engines-version': 4.14.0-67.d9a4c5988f480fa576d43970d5a23641aa77bc9c + '@prisma/engines-version': 5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e prisma: 4.14.0 dev: true - /@prisma/engines-version@4.14.0-67.d9a4c5988f480fa576d43970d5a23641aa77bc9c: - resolution: {integrity: sha512-3jum8/YSudeSN0zGW5qkpz+wAN2V/NYCQ+BPjvHYDfWatLWlQkqy99toX0GysDeaUoBIJg1vaz2yKqiA3CFcQw==} + /@prisma/engines-version@5.1.1-1.6a3747c37ff169c90047725a05a6ef02e32ac97e: + resolution: {integrity: sha512-owZqbY/wucbr65bXJ/ljrHPgQU5xXTSkmcE/JcbqE1kusuAXV/TLN3/exmz21SZ5rJ7WDkyk70J2G/n68iogbQ==} dev: true /@prisma/engines@4.14.0: @@ -2825,12 +2917,12 @@ packages: typescript: 5.0.4 zod: 3.21.4 - /@tanstack/query-core@4.29.7: - resolution: {integrity: sha512-GXG4b5hV2Loir+h2G+RXhJdoZhJLnrBWsuLB2r0qBRyhWuXq9w/dWxzvpP89H0UARlH6Mr9DiVj4SMtpkF/aUA==} + /@tanstack/query-core@4.32.6: + resolution: {integrity: sha512-YVB+mVWENQwPyv+40qO7flMgKZ0uI41Ph7qXC2Zf1ft5AIGfnXnMZyifB2ghhZ27u+5wm5mlzO4Y6lwwadzxCA==} dev: true - /@tanstack/react-query@4.29.7(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-ijBWEzAIo09fB1yd22slRZzprrZ5zMdWYzBnCg5qiXuFbH78uGN1qtGz8+Ed4MuhaPaYSD+hykn+QEKtQviEtg==} + /@tanstack/react-query@4.32.6(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-AITu/IKJJJXsHHeXNBy5bclu12t08usMCY0vFC2dh9SP/w6JAk5U9GwfjOIPj3p+ATADZvxQPe8UiCtMLNeQbg==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 @@ -2841,7 +2933,7 @@ packages: react-native: optional: true dependencies: - '@tanstack/query-core': 4.29.7 + '@tanstack/query-core': 4.32.6 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) use-sync-external-store: 1.2.0(react@18.2.0) @@ -2851,53 +2943,53 @@ packages: resolution: {integrity: sha512-yXt2BRRVCJVvzWaxac5n0nCXzIrQEBE/MeYlNQ8/Iq7UeelNmm/AdnUAu18ilSS893mbEQ4u6whPt/HvOPc4rw==} dev: false - /@trpc/client@10.26.0(@trpc/server@10.26.0): - resolution: {integrity: sha512-ojHxQFIE97rBEGPK8p1ijbzo0T1IdEBoJ9fFSgWWL9FMuEEA/DNQ9s0uuiOrDKhCCdTFT1unfRharoJhB2/O2w==} + /@trpc/client@10.37.1(@trpc/server@10.37.1): + resolution: {integrity: sha512-OSblNfeI0Z9ERn3usgLV2x63CwwPoNOHf1FQK85cOT7F8MNaWyEHoEv7tHUwNGJwyzKXmpU+ockZ0movzX3D0g==} peerDependencies: - '@trpc/server': 10.26.0 + '@trpc/server': 10.37.1 dependencies: - '@trpc/server': 10.26.0 + '@trpc/server': 10.37.1 dev: true - /@trpc/next@10.26.0(@tanstack/react-query@4.29.7)(@trpc/client@10.26.0)(@trpc/react-query@10.26.0)(@trpc/server@10.26.0)(next@13.4.1)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-p328crXBH6C228LKxjqbpDEXdLmy4+LdgsZuYK3oFMqaJEmCT22b+zcQ9IvQrcPfDxhKOpJym0QpuDNaWpG2qg==} + /@trpc/next@10.37.1(@tanstack/react-query@4.32.6)(@trpc/client@10.37.1)(@trpc/react-query@10.37.1)(@trpc/server@10.37.1)(next@13.4.19)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-0KEgr09mBfao56lkj7ZBfVOY86d3+bDH1o0zJkDHSH60Dp/hIJ7wLCnZJIhePlZxEwknCQjVeLsTy4Pqlu8NyQ==} peerDependencies: '@tanstack/react-query': ^4.18.0 - '@trpc/client': 10.26.0 - '@trpc/react-query': 10.26.0 - '@trpc/server': 10.26.0 + '@trpc/client': 10.37.1 + '@trpc/react-query': 10.37.1 + '@trpc/server': 10.37.1 next: '*' react: '>=16.8.0' react-dom: '>=16.8.0' dependencies: - '@tanstack/react-query': 4.29.7(react-dom@18.2.0)(react@18.2.0) - '@trpc/client': 10.26.0(@trpc/server@10.26.0) - '@trpc/react-query': 10.26.0(@tanstack/react-query@4.29.7)(@trpc/client@10.26.0)(@trpc/server@10.26.0)(react-dom@18.2.0)(react@18.2.0) - '@trpc/server': 10.26.0 - next: 13.4.1(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0) + '@tanstack/react-query': 4.32.6(react-dom@18.2.0)(react@18.2.0) + '@trpc/client': 10.37.1(@trpc/server@10.37.1) + '@trpc/react-query': 10.37.1(@tanstack/react-query@4.32.6)(@trpc/client@10.37.1)(@trpc/server@10.37.1)(react-dom@18.2.0)(react@18.2.0) + '@trpc/server': 10.37.1 + next: 13.4.19(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) react-ssr-prepass: 1.5.0(react@18.2.0) dev: true - /@trpc/react-query@10.26.0(@tanstack/react-query@4.29.7)(@trpc/client@10.26.0)(@trpc/server@10.26.0)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-n+enpalaCZhd3A/mbZmXeydRZHsAJo7mzc2ncgHn5S+C3SrfOM897uQdbHdj02Li25ULxzP1O92w+vZzmFbgkA==} + /@trpc/react-query@10.37.1(@tanstack/react-query@4.32.6)(@trpc/client@10.37.1)(@trpc/server@10.37.1)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-TbOOPp0fZVaKfaeEyDoV8QeTHW1vgPTbfOs0uSQ4AzBXqXPu+9v1B44z8GGRJSdUxuOX9pG/6Ap5Kx8PQ3eF+Q==} peerDependencies: '@tanstack/react-query': ^4.18.0 - '@trpc/client': 10.26.0 - '@trpc/server': 10.26.0 + '@trpc/client': 10.37.1 + '@trpc/server': 10.37.1 react: '>=16.8.0' react-dom: '>=16.8.0' dependencies: - '@tanstack/react-query': 4.29.7(react-dom@18.2.0)(react@18.2.0) - '@trpc/client': 10.26.0(@trpc/server@10.26.0) - '@trpc/server': 10.26.0 + '@tanstack/react-query': 4.32.6(react-dom@18.2.0)(react@18.2.0) + '@trpc/client': 10.37.1(@trpc/server@10.37.1) + '@trpc/server': 10.37.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: true - /@trpc/server@10.26.0: - resolution: {integrity: sha512-+Wt0NFAeflVSNiUnHIDNN3C8jP7XIRmYrcgJ6IsAnm0lK4p/FkpCpeu1aig5qxrgZx30PHNDLZ/3FttVSEW2aQ==} + /@trpc/server@10.37.1: + resolution: {integrity: sha512-r3VeA319/braYMBIzj+XLgLKQ9lJSVglvPvP9HUv4kr5w6Y5grQMxMcExhTiZWltE9bnSJHKtBBzHafOo7KC8A==} dev: true /@types/acorn@4.0.6: @@ -3543,13 +3635,6 @@ packages: engines: {node: '>=6'} dev: false - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - dev: false - /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -3905,6 +3990,12 @@ packages: balanced-match: 1.0.2 concat-map: 0.0.1 + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + /braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} @@ -3929,7 +4020,6 @@ packages: /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: false /buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} @@ -4013,13 +4103,15 @@ packages: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} + /camelcase@7.0.1: + resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} + engines: {node: '>=14.16'} + dev: true + /camelize@1.0.1: resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} dev: false - /caniuse-lite@1.0.30001469: - resolution: {integrity: sha512-Rcp7221ScNqQPP3W+lVOYDyjdR6dC+neEQCttoNr5bAyz54AboB4iwpnWgyi8P4YUsPybVzT4LgWiBbI3drL4g==} - /caniuse-lite@1.0.30001515: resolution: {integrity: sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA==} @@ -4113,12 +4205,16 @@ packages: resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} engines: {node: '>=10'} - /cli-cursor@3.1.0: - resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} - engines: {node: '>=8'} + /cli-color@2.0.3: + resolution: {integrity: sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==} + engines: {node: '>=0.10'} dependencies: - restore-cursor: 3.1.0 - dev: false + d: 1.0.1 + es5-ext: 0.10.62 + es6-iterator: 2.0.3 + memoizee: 0.4.15 + timers-ext: 0.1.7 + dev: true /cli-cursor@4.0.0: resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} @@ -4130,11 +4226,6 @@ packages: resolution: {integrity: sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==} engines: {node: '>=6'} - /cli-width@4.0.0: - resolution: {integrity: sha512-ZksGS2xpa/bYkNzN3BAw1wEjsLV/ZKOf/CCrJ/QOBsxx6fOARIkwTutxp1XIOIohi6HKmOFjMoK/XaqDVUpEEw==} - engines: {node: '>= 12'} - dev: false - /client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} @@ -4221,6 +4312,11 @@ packages: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} + /commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + dev: true + /common-ancestor-path@1.0.1: resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} @@ -4312,6 +4408,13 @@ packages: stream-transform: 2.1.3 dev: false + /d@1.0.1: + resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} + dependencies: + es5-ext: 0.10.62 + type: 1.2.0 + dev: true + /damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} dev: true @@ -4479,6 +4582,12 @@ packages: resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} engines: {node: '>=0.3.1'} + /difflib@0.2.4: + resolution: {integrity: sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==} + dependencies: + heap: 0.2.7 + dev: true + /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -4505,6 +4614,98 @@ packages: engines: {node: '>=10'} dev: false + /dreamopt@0.8.0: + resolution: {integrity: sha512-vyJTp8+mC+G+5dfgsY+r3ckxlz+QMX40VjPQsZc5gxVAxLmi64TBoVkP54A/pRAXMXsbu2GMMBrZPxNv23waMg==} + engines: {node: '>=0.4.0'} + dependencies: + wordwrap: 1.0.0 + dev: true + + /drizzle-kit@0.19.13: + resolution: {integrity: sha512-Rba5VW1O2JfJlwVBeZ8Zwt2E2us5oZ08PQBDiVSGlug53TOc8hzXjblZFuF+dnll9/RQEHrkzBmJFgqTvn5Rxg==} + hasBin: true + dependencies: + '@drizzle-team/studio': 0.0.5 + '@esbuild-kit/esm-loader': 2.5.5 + camelcase: 7.0.1 + chalk: 5.2.0 + commander: 9.5.0 + esbuild: 0.18.15 + esbuild-register: 3.4.2(esbuild@0.18.15) + glob: 8.1.0 + hanji: 0.0.5 + json-diff: 0.9.0 + minimatch: 7.4.6 + zod: 3.21.4 + transitivePeerDependencies: + - supports-color + dev: true + + /drizzle-orm@0.28.5(@planetscale/database@1.11.0): + resolution: {integrity: sha512-6r6Iw4c38NAmW6TiKH3TUpGUQ1YdlEoLJOQptn8XPx3Z63+vFNKfAiANqrIiYZiMjKR9+NYAL219nFrmo1duXA==} + peerDependencies: + '@aws-sdk/client-rds-data': '>=3' + '@cloudflare/workers-types': '>=3' + '@libsql/client': '*' + '@neondatabase/serverless': '>=0.1' + '@opentelemetry/api': ^1.4.1 + '@planetscale/database': '>=1' + '@types/better-sqlite3': '*' + '@types/pg': '*' + '@types/sql.js': '*' + '@vercel/postgres': '*' + better-sqlite3: '>=7' + bun-types: '*' + knex: '*' + kysely: '*' + mysql2: '>=2' + pg: '>=8' + postgres: '>=3' + sql.js: '>=1' + sqlite3: '>=5' + peerDependenciesMeta: + '@aws-sdk/client-rds-data': + optional: true + '@cloudflare/workers-types': + optional: true + '@libsql/client': + optional: true + '@neondatabase/serverless': + optional: true + '@opentelemetry/api': + optional: true + '@planetscale/database': + optional: true + '@types/better-sqlite3': + optional: true + '@types/pg': + optional: true + '@types/sql.js': + optional: true + '@vercel/postgres': + optional: true + better-sqlite3: + optional: true + bun-types: + optional: true + knex: + optional: true + kysely: + optional: true + mysql2: + optional: true + pg: + optional: true + postgres: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + dependencies: + '@planetscale/database': 1.11.0 + dev: true + /dset@3.1.2: resolution: {integrity: sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==} engines: {node: '>=4'} @@ -4649,6 +4850,51 @@ packages: is-date-object: 1.0.5 is-symbol: 1.0.4 + /es5-ext@0.10.62: + resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} + engines: {node: '>=0.10'} + requiresBuild: true + dependencies: + es6-iterator: 2.0.3 + es6-symbol: 3.1.3 + next-tick: 1.1.0 + dev: true + + /es6-iterator@2.0.3: + resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-symbol: 3.1.3 + dev: true + + /es6-symbol@3.1.3: + resolution: {integrity: sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==} + dependencies: + d: 1.0.1 + ext: 1.7.0 + dev: true + + /es6-weak-map@2.0.3: + resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-iterator: 2.0.3 + es6-symbol: 3.1.3 + dev: true + + /esbuild-register@3.4.2(esbuild@0.18.15): + resolution: {integrity: sha512-kG/XyTDyz6+YDuyfB9ZoSIOOmgyFCH+xPRtsCa8W85HLRV5Csp+o3jWVbOSHgSLfyLc5DmP+KFDNwty4mEjC+Q==} + peerDependencies: + esbuild: '>=0.12 <1' + dependencies: + debug: 4.3.4 + esbuild: 0.18.15 + transitivePeerDependencies: + - supports-color + dev: true + /esbuild@0.17.12: resolution: {integrity: sha512-bX/zHl7Gn2CpQwcMtRogTTBf9l1nl+H6R8nUbjk+RuKqAE3+8FDulLA+pHvX7aA7Xe07Iwa+CWvy9I8Y2qqPKQ==} engines: {node: '>=12'} @@ -5152,6 +5398,13 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + /event-emitter@0.3.5: + resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + dev: true + /events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -5204,6 +5457,12 @@ packages: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} + /ext@1.7.0: + resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} + dependencies: + type: 2.7.2 + dev: true + /extend-shallow@2.0.1: resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} engines: {node: '>=0.10.0'} @@ -5274,14 +5533,6 @@ packages: resolution: {integrity: sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==} dev: false - /figures@5.0.0: - resolution: {integrity: sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==} - engines: {node: '>=14'} - dependencies: - escape-string-regexp: 5.0.0 - is-unicode-supported: 1.3.0 - dev: false - /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -5501,7 +5752,6 @@ packages: /glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - dev: false /glob@7.1.6: resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} @@ -5534,6 +5784,17 @@ packages: once: 1.4.0 path-is-absolute: 1.0.1 + /glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + dev: true + /globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -5628,6 +5889,13 @@ packages: section-matter: 1.0.0 strip-bom-string: 1.0.0 + /hanji@0.0.5: + resolution: {integrity: sha512-Abxw1Lq+TnYiL4BueXqMau222fPSPMFtya8HdpWsz/xVAhifXou71mPh/kY2+08RgFcVccjG3uZHs6K5HAe3zw==} + dependencies: + lodash.throttle: 4.1.1 + sisteransi: 1.0.5 + dev: true + /hard-rejection@2.1.0: resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} engines: {node: '>=6'} @@ -5800,6 +6068,10 @@ packages: property-information: 6.2.0 space-separated-tokens: 2.0.2 + /heap@0.2.7: + resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} + dev: true + /hex-rgb@4.3.0: resolution: {integrity: sha512-Ox1pJVrDCyGHMG9CFg1tmrRUMRPRsAWYc/PinY0XzJU4K7y7vjNoLKIQ7BR5UJMCxNN8EM1MNDmHWA/B3aZUuw==} engines: {node: '>=6'} @@ -5904,27 +6176,6 @@ packages: resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} dev: false - /inquirer@9.2.3: - resolution: {integrity: sha512-/Et0+d28D7hnTYaqeCQkp3FYuD/X5cc2qbM6BzFdC5zs30oByoU5W/pmLc493FVVMwYmAILKjPBEmwRKTtknSQ==} - engines: {node: '>=14.18.0'} - dependencies: - ansi-escapes: 4.3.2 - chalk: 5.2.0 - cli-cursor: 3.1.0 - cli-width: 4.0.0 - external-editor: 3.1.0 - figures: 5.0.0 - lodash: 4.17.21 - mute-stream: 1.0.0 - ora: 5.4.1 - run-async: 3.0.0 - rxjs: 7.8.1 - string-width: 4.2.3 - strip-ansi: 6.0.1 - through: 2.3.8 - wrap-ansi: 6.2.0 - dev: false - /internal-slot@1.0.5: resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} engines: {node: '>= 0.4'} @@ -6057,11 +6308,6 @@ packages: resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} dev: false - /is-interactive@1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - dev: false - /is-interactive@2.0.0: resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} engines: {node: '>=12'} @@ -6107,6 +6353,10 @@ packages: engines: {node: '>=0.10.0'} dev: false + /is-promise@2.2.2: + resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} + dev: true + /is-reference@3.0.1: resolution: {integrity: sha512-baJJdQLiYaJdvFbJqXrcGv3WU3QCzBlUcI5QhbesIm6/xPsvmO+2CDoi/GMOFBQEQm+PXkwOPrp9KK5ozZsp2w==} dependencies: @@ -6167,11 +6417,6 @@ packages: gopd: 1.0.1 has-tostringtag: 1.0.0 - /is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - dev: false - /is-unicode-supported@1.3.0: resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} engines: {node: '>=12'} @@ -6269,6 +6514,15 @@ packages: resolution: {integrity: sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==} dev: false + /json-diff@0.9.0: + resolution: {integrity: sha512-cVnggDrVkAAA3OvFfHpFEhOnmcsUpleEKq4d4O8sQWWSH40MBrWstKigVB1kGrgLWzuom+7rRdaCsnBD6VyObQ==} + hasBin: true + dependencies: + cli-color: 2.0.3 + difflib: 0.2.4 + dreamopt: 0.8.0 + dev: true + /json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} dev: false @@ -6408,17 +6662,9 @@ packages: resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} dev: false - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: false - - /log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - dev: false + /lodash.throttle@4.1.1: + resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} + dev: true /log-symbols@5.1.0: resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} @@ -6464,8 +6710,14 @@ packages: dependencies: yallist: 4.0.0 - /lucide-react@0.216.0(react@18.2.0): - resolution: {integrity: sha512-PGWXs6JXI/08rhfkmj/joji0MAKDCcms44j0LYILO4J36AWqKhgjjaZ6WECRSyZ9TQe5gOrAR0g38O8cKrQngw==} + /lru-queue@0.1.0: + resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} + dependencies: + es5-ext: 0.10.62 + dev: true + + /lucide-react@0.263.1(react@18.2.0): + resolution: {integrity: sha512-keqxAx97PlaEN89PXZ6ki1N8nRjGWtDa4021GFYLNj0RgruM5odbpl8GHTExj0hhPq3sF6Up0gnxt6TSHu+ovw==} peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 dependencies: @@ -6684,6 +6936,19 @@ packages: dependencies: '@types/mdast': 3.0.11 + /memoizee@0.4.15: + resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==} + dependencies: + d: 1.0.1 + es5-ext: 0.10.62 + es6-weak-map: 2.0.3 + event-emitter: 0.3.5 + is-promise: 2.2.2 + lru-queue: 0.1.0 + next-tick: 1.1.0 + timers-ext: 0.1.7 + dev: true + /meow@6.1.1: resolution: {integrity: sha512-3YffViIt2QWgTy6Pale5QpopX/IvU3LPL03jOTqp6pGj3VjesdO/U8CuHMKpnQr4shCNCM5fd5XFFvIIl6JBHg==} engines: {node: '>=8'} @@ -7071,6 +7336,20 @@ packages: dependencies: brace-expansion: 1.1.11 + /minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@7.4.6: + resolution: {integrity: sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==} + engines: {node: '>=10'} + dependencies: + brace-expansion: 2.0.1 + dev: true + /minimist-options@4.1.0: resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} engines: {node: '>= 6'} @@ -7127,11 +7406,6 @@ packages: /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - /mute-stream@1.0.0: - resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: false - /mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} dependencies: @@ -7157,8 +7431,8 @@ packages: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} dev: false - /next-auth@4.22.1(next@13.4.1)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-NTR3f6W7/AWXKw8GSsgSyQcDW6jkslZLH8AiZa5PQ09w1kR8uHtR9rez/E9gAq/o17+p0JYHE8QjF3RoniiObA==} + /next-auth@4.23.1(next@13.4.19)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-mL083z8KgRtlrIV6CDca2H1kduWJuK/3pTS0Fe2og15KOm4v2kkLGdSDfc2g+019aEBrJUT0pPW2Xx42ImN1WA==} peerDependencies: next: ^12.2.5 || ^13 nodemailer: ^6.6.5 @@ -7172,7 +7446,7 @@ packages: '@panva/hkdf': 1.0.4 cookie: 0.5.0 jose: 4.13.1 - next: 13.4.1(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0) + next: 13.4.19(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0) oauth: 0.9.15 openid-client: 5.4.0 preact: 10.13.1 @@ -7182,46 +7456,45 @@ packages: uuid: 8.3.2 dev: true - /next@13.4.1(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-JBw2kAIyhKDpjhEWvNVoFeIzNp9xNxg8wrthDOtMctfn3EpqGCmW0FSviNyGgOSOSn6zDaX48pmvbdf6X2W9xA==} + /next-tick@1.1.0: + resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} + dev: true + + /next@13.4.19(@babel/core@7.22.9)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-HuPSzzAbJ1T4BD8e0bs6B9C1kWQ6gv8ykZoRWs5AQoiIuqbGHHdQO7Ljuvg05Q0Z24E2ABozHe6FxDvI6HfyAw==} engines: {node: '>=16.8.0'} hasBin: true peerDependencies: '@opentelemetry/api': ^1.1.0 - fibers: '>= 3.1.0' - node-sass: ^6.0.0 || ^7.0.0 react: ^18.2.0 react-dom: ^18.2.0 sass: ^1.3.0 peerDependenciesMeta: '@opentelemetry/api': optional: true - fibers: - optional: true - node-sass: - optional: true sass: optional: true dependencies: - '@next/env': 13.4.1 + '@next/env': 13.4.19 '@swc/helpers': 0.5.1 busboy: 1.6.0 - caniuse-lite: 1.0.30001469 + caniuse-lite: 1.0.30001515 postcss: 8.4.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) styled-jsx: 5.1.1(@babel/core@7.22.9)(react@18.2.0) + watchpack: 2.4.0 zod: 3.21.4 optionalDependencies: - '@next/swc-darwin-arm64': 13.4.1 - '@next/swc-darwin-x64': 13.4.1 - '@next/swc-linux-arm64-gnu': 13.4.1 - '@next/swc-linux-arm64-musl': 13.4.1 - '@next/swc-linux-x64-gnu': 13.4.1 - '@next/swc-linux-x64-musl': 13.4.1 - '@next/swc-win32-arm64-msvc': 13.4.1 - '@next/swc-win32-ia32-msvc': 13.4.1 - '@next/swc-win32-x64-msvc': 13.4.1 + '@next/swc-darwin-arm64': 13.4.19 + '@next/swc-darwin-x64': 13.4.19 + '@next/swc-linux-arm64-gnu': 13.4.19 + '@next/swc-linux-arm64-musl': 13.4.19 + '@next/swc-linux-x64-gnu': 13.4.19 + '@next/swc-linux-x64-musl': 13.4.19 + '@next/swc-win32-arm64-msvc': 13.4.19 + '@next/swc-win32-ia32-msvc': 13.4.19 + '@next/swc-win32-x64-msvc': 13.4.19 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros @@ -7313,6 +7586,10 @@ packages: set-blocking: 2.0.0 dev: false + /oauth4webapi@2.3.0: + resolution: {integrity: sha512-JGkb5doGrwzVDuHwgrR4nHJayzN4h59VCed6EW8Tql6iHDfZIabCJvg6wtbn5q6pyB2hZruI3b77Nudvq7NmvA==} + dev: true + /oauth@0.9.15: resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==} dev: true @@ -7434,21 +7711,6 @@ packages: type-check: 0.4.0 word-wrap: 1.2.3 - /ora@5.4.1: - resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} - engines: {node: '>=10'} - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.7.0 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - dev: false - /ora@6.3.1: resolution: {integrity: sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -7748,6 +8010,15 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /preact-render-to-string@5.2.3(preact@10.11.3): + resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==} + peerDependencies: + preact: '>=10' + dependencies: + preact: 10.11.3 + pretty-format: 3.8.0 + dev: true + /preact-render-to-string@5.2.6(preact@10.13.1): resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==} peerDependencies: @@ -7757,6 +8028,10 @@ packages: pretty-format: 3.8.0 dev: true + /preact@10.11.3: + resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} + dev: true + /preact@10.13.1: resolution: {integrity: sha512-KyoXVDU5OqTpG9LXlB3+y639JAGzl8JSBXLn1J9HTSB3gbKcuInga7bZnXLlxmK94ntTs1EFeZp0lrja2AuBYQ==} dev: true @@ -8336,14 +8611,6 @@ packages: lowercase-keys: 1.0.1 dev: false - /restore-cursor@3.1.0: - resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} - engines: {node: '>=8'} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: false - /restore-cursor@4.0.0: resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -8407,11 +8674,6 @@ packages: optionalDependencies: fsevents: 2.3.2 - /run-async@3.0.0: - resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} - engines: {node: '>=0.12.0'} - dev: false - /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: @@ -8421,6 +8683,7 @@ packages: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} dependencies: tslib: 2.5.0 + dev: true /s.color@0.0.15: resolution: {integrity: sha512-AUNrbEUHeKY8XsYr/DYpl+qk5+aM+DChopnWOPEzn8YKzOhv4l2zH6LzZms3tOZP3wwdOyc0RmTciyi46HLIuA==} @@ -8674,12 +8937,10 @@ packages: dependencies: buffer-from: 1.1.2 source-map: 0.6.1 - dev: false /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} - dev: false /source-map@0.7.4: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} @@ -9087,9 +9348,12 @@ packages: dependencies: any-promise: 1.3.0 - /through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - dev: false + /timers-ext@0.1.7: + resolution: {integrity: sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==} + dependencies: + es5-ext: 0.10.62 + next-tick: 1.1.0 + dev: true /tiny-glob@0.2.9: resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} @@ -9339,11 +9603,6 @@ packages: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: false - /type-fest@0.6.0: resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} engines: {node: '>=8'} @@ -9368,6 +9627,14 @@ packages: engines: {node: '>=14.16'} dev: true + /type@1.2.0: + resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} + dev: true + + /type@2.7.2: + resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} + dev: true + /typed-array-length@1.0.4: resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} dependencies: @@ -9732,7 +9999,6 @@ packages: dependencies: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 - dev: false /wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} @@ -9888,6 +10154,10 @@ packages: resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} engines: {node: '>=0.10.0'} + /wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + dev: true + /wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} diff --git a/upgrade/package.json b/upgrade/package.json index a0d490f719..7e3c9d5f42 100644 --- a/upgrade/package.json +++ b/upgrade/package.json @@ -27,8 +27,8 @@ "class-variance-authority": "^0.6.0", "clsx": "^1.2.1", "gitdiff-parser": "^0.3.1", - "lucide-react": "^0.216.0", - "next": "^13.4.1", + "lucide-react": "^0.263.1", + "next": "^13.4.19", "react": "18.2.0", "react-diff-view": "^3.0.3", "react-dom": "18.2.0", diff --git a/www/src/config.ts b/www/src/config.ts index f003da3d89..fea5bc399e 100644 --- a/www/src/config.ts +++ b/www/src/config.ts @@ -123,6 +123,7 @@ export const SIDEBAR: Sidebar = { { text: "Next.js", link: "en/usage/next-js" }, { text: "TypeScript", link: "en/usage/typescript" }, { text: "tRPC", link: "en/usage/trpc" }, + { text: "Drizzle", link: "en/usage/drizzle" }, { text: "Prisma", link: "en/usage/prisma" }, { text: "NextAuth.js", link: "en/usage/next-auth" }, { diff --git a/www/src/pages/en/faq.mdx b/www/src/pages/en/faq.mdx index d78823a77d..1271158411 100644 --- a/www/src/pages/en/faq.mdx +++ b/www/src/pages/en/faq.mdx @@ -21,6 +21,7 @@ If you are not familiar with the different technologies used in this project, pl - [Prisma](https://prisma.io) - [Tailwind CSS](https://tailwindcss.com) - [tRPC](https://trpc.io) +- [Drizzle](https://orm.drizzle.team/docs/overview) ## How do I keep my app up to date? diff --git a/www/src/pages/en/folder-structure.mdx b/www/src/pages/en/folder-structure.mdx index d10b0f3609..446e910953 100644 --- a/www/src/pages/en/folder-structure.mdx +++ b/www/src/pages/en/folder-structure.mdx @@ -203,3 +203,10 @@ The `prettier.config.mjs` file is used to configure Prettier to include the pret The `tsconfig.json` file is used to configure TypeScript. Some non-defaults, such as `strict mode`, have been enabled to ensure the best usage of TypeScript for Create T3 App and its libraries. See [TypeScript Docs](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) or [TypeScript Usage](usage/typescript) for more information. +
+ +### `drizzle.config.ts` + +The `drizzle.config.ts` file is used to configure drizzle kit. See [the documentation](https://orm.drizzle.team/kit-docs/config-reference) for more information. + +
\ No newline at end of file diff --git a/www/src/pages/en/usage/drizzle.mdx b/www/src/pages/en/usage/drizzle.mdx new file mode 100644 index 0000000000..aefe547554 --- /dev/null +++ b/www/src/pages/en/usage/drizzle.mdx @@ -0,0 +1,14 @@ +--- +title: Drizzle +description: Usage of Drizzle +layout: ../../../layouts/docs.astro +lang: en +isMdx: true +--- + +import Callout from "../../../components/docs/callout.tsx"; + + + The `drizzle` option is a new addition and no docs have yet been written. Contributions are welcome! + + diff --git a/www/src/pages/en/usage/first-steps.md b/www/src/pages/en/usage/first-steps.md index b88edf1fb7..c28fd5b8fa 100644 --- a/www/src/pages/en/usage/first-steps.md +++ b/www/src/pages/en/usage/first-steps.md @@ -9,8 +9,14 @@ You just scaffolded a new T3 App and are ready to go. Here is the bare minimum t ## Database +### Prisma + If your app includes Prisma, make sure to run `npx prisma db push` from the root directory of your app. This command will sync your Prisma schema with your database and will generate the TypeScript types for the Prisma Client based on your schema. Note that you need to [restart the TypeScript server](https://tinytip.co/tips/vscode-restart-ts/) after doing this so that it can detect the generated types. +### Drizzle + +If your app includes Drizzle, check the `.env` file for instructions on how to construct your `DATABASE_URL` env variable. Once your env file is ready, run `pnpm db:push` (or the equivalent for other package managers) to push your schema. + ## Authentication If your app includes NextAuth.js, we get you started with the `DiscordProvider`. This is one of the simplest providers that NextAuth.js offers, but it still requires a bit of initial setup on your part. diff --git a/www/src/pages/pl/faq.md b/www/src/pages/pl/faq.md index 4b286de7ec..735891ecd4 100644 --- a/www/src/pages/pl/faq.md +++ b/www/src/pages/pl/faq.md @@ -18,6 +18,7 @@ Jeżeli nie znasz poszczególnych technologi użytych w projekcie, skorzystaj z - [Prisma](https://prisma.io) - [Tailwind CSS](https://tailwindcss.com) - [tRPC](https://trpc.io) +- [Drizzle](https://orm.drizzle.team/docs/overview) ## Jak sprawić, by aplikacja była ciągle aktualna? diff --git a/www/src/pages/pl/folder-structure.mdx b/www/src/pages/pl/folder-structure.mdx index db132ae849..6567cfca17 100644 --- a/www/src/pages/pl/folder-structure.mdx +++ b/www/src/pages/pl/folder-structure.mdx @@ -203,3 +203,10 @@ Plik `prettier.config.mjs` jest używany do konfigurowania Prettiera. Dołącza Plik `tsconfig.json` jest używany do konfigurowania TypeScripta. Niektóre ustawienia zostały włączone (takie jak `strict mode`), aby zapewnić najlepsze użycie TypeScripta do Create T3 App i jej bibliotek. Po więcej informacji, zobacz [dokumentację TypeScripta](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) albo [korzystanie z TypeScripta](/pl/usage/typescript). +
+ +### `drizzle.config.ts` + +Plik `drizzle.config.ts` jest używany do konfigurowania Drizzle kit. Po więcej informacji przeczytaj [ich dokumentację](https://orm.drizzle.team/kit-docs/config-reference) + +
\ No newline at end of file