Skip to content

Commit

Permalink
feat: Add more db options (t3-oss#1622)
Browse files Browse the repository at this point in the history
Co-authored-by: juliusmarminge <[email protected]>
  • Loading branch information
ronanru and juliusmarminge committed Jan 20, 2024
1 parent 9a34ba8 commit 06b1bca
Show file tree
Hide file tree
Showing 38 changed files with 995 additions and 63 deletions.
5 changes: 5 additions & 0 deletions .changeset/lemon-deers-grin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-t3-app": minor
---

add more db options
9 changes: 5 additions & 4 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ jobs:
prisma: ["true", "false"]
appRouter: ["true", "false"]
drizzle: ["true", "false"]
dbType: ["planetscale", "sqlite", "mysql", "postgres"]

name: "Build and Start T3 App ${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.prisma }}-${{ matrix.drizzle}}-${{ matrix.appRouter }}"
name: "Build and Start T3 App ${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.prisma }}-${{ matrix.drizzle}}-${{ matrix.appRouter }}-${{ matrix.dbType }}"
steps:
- uses: actions/checkout@v3
with:
Expand All @@ -39,7 +40,7 @@ jobs:
- name: Check valid matrix
id: matrix-valid
run: |
echo "continue=${{ matrix.prisma == 'false' || matrix.drizzle == 'false' }}" >> $GITHUB_OUTPUT
echo "continue=${{ (matrix.prisma == 'false' || matrix.drizzle == 'false') && (matrix.drizzle == 'true' || matrix.prisma == 'true' || matrix.dbType == 'sqlite') }}" >> $GITHUB_OUTPUT
- name: Install Node.js
if: ${{ steps.matrix-valid.outputs.continue == 'true' }}
Expand Down Expand Up @@ -79,9 +80,9 @@ jobs:
# 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 }}-${{ matrix.drizzle}}-${{ matrix.appRouter }} --noGit --CI --trpc=${{ matrix.trpc }} --tailwind=${{ matrix.tailwind }} --nextAuth=${{ matrix.nextAuth }} --prisma=${{ matrix.prisma }} --drizzle=${{ matrix.drizzle }} --appRouter=${{ matrix.appRouter }}
- run: cd cli && pnpm start ../../ci-${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.prisma }}-${{ matrix.drizzle}}-${{ matrix.appRouter }}-${{ matrix.dbType }} --noGit --CI --trpc=${{ matrix.trpc }} --tailwind=${{ matrix.tailwind }} --nextAuth=${{ matrix.nextAuth }} --prisma=${{ matrix.prisma }} --drizzle=${{ matrix.drizzle }} --appRouter=${{ matrix.appRouter }} --dbProvider=${{ matrix.dbType }}
if: ${{ steps.matrix-valid.outputs.continue == 'true' }}
- run: cd ../ci-${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.prisma }}-${{ matrix.drizzle}}-${{ matrix.appRouter }} && pnpm build
- run: cd ../ci-${{ matrix.trpc }}-${{ matrix.tailwind }}-${{ matrix.nextAuth }}-${{ matrix.prisma }}-${{ matrix.drizzle}}-${{ matrix.appRouter }}-${{ matrix.dbType }} && pnpm build
if: ${{ steps.matrix-valid.outputs.continue == 'true' }}
env:
NEXTAUTH_SECRET: foo
Expand Down
1 change: 1 addition & 0 deletions cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"@auth/drizzle-adapter": "^0.3.6",
"@next-auth/prisma-adapter": "^1.0.7",
"@planetscale/database": "^1.11.0",
"@prisma/adapter-planetscale": "^5.6.0",
"@prisma/client": "^5.6.0",
"@t3-oss/env-nextjs": "^0.7.1",
"@tanstack/react-query": "^4.36.1",
Expand Down
34 changes: 33 additions & 1 deletion cli/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@ import chalk from "chalk";
import { Command } from "commander";

import { CREATE_T3_APP, DEFAULT_APP_NAME } from "~/consts.js";
import { type AvailablePackages } from "~/installers/index.js";
import {
databaseProviders,
type AvailablePackages,
type DatabaseProvider,
} from "~/installers/index.js";
import { getVersion } from "~/utils/getT3Version.js";
import { getUserPkgManager } from "~/utils/getUserPkgManager.js";
import { IsTTYError } from "~/utils/isTTYError.js";
Expand Down Expand Up @@ -37,6 +41,7 @@ interface CliResults {
appName: string;
packages: AvailablePackages[];
flags: CliFlags;
databaseProvider: DatabaseProvider;
}

const defaultOptions: CliResults = {
Expand All @@ -55,6 +60,7 @@ const defaultOptions: CliResults = {
importAlias: "~/",
appRouter: false,
},
databaseProvider: "sqlite",
};

export const runCli = async (): Promise<CliResults> => {
Expand Down Expand Up @@ -124,6 +130,13 @@ export const runCli = async (): Promise<CliResults> => {
"Explicitly tell the CLI to use a custom import alias",
defaultOptions.flags.importAlias
)
.option(
"--dbProvider [provider]",
`Choose a database provider to use. Possible values: ${databaseProviders.join(
", "
)}`,
defaultOptions.flags.importAlias
)
.option(
"--appRouter [boolean]",
"Explicitly tell the CLI to use the new Next.js app router",
Expand Down Expand Up @@ -176,6 +189,10 @@ export const runCli = async (): Promise<CliResults> => {
process.exit(0);
}

cliResults.databaseProvider = cliResults.packages.includes("drizzle")
? "planetscale"
: "sqlite";

return cliResults;
}

Expand Down Expand Up @@ -262,6 +279,19 @@ export const runCli = async (): Promise<CliResults> => {
initialValue: false,
});
},
databaseProvider: ({ results }) => {
if (results.database === "none") return;
return p.select({
message: "What database provider would you like to use?",
options: [
{ value: "sqlite", label: "SQLite" },
{ value: "mysql", label: "MySQL" },
{ value: "postgres", label: "PostgreSQL" },
{ value: "planetscale", label: "Planetscale" },
],
initialValue: "sqlite",
});
},
...(!cliResults.flags.noGit && {
git: () => {
return p.confirm({
Expand Down Expand Up @@ -307,6 +337,8 @@ export const runCli = async (): Promise<CliResults> => {
return {
appName: project.name ?? cliResults.appName,
packages,
databaseProvider:
(project.databaseProvider as DatabaseProvider) || "sqlite",
flags: {
...cliResults.flags,
appRouter: project.appRouter ?? cliResults.flags.appRouter,
Expand Down
9 changes: 8 additions & 1 deletion cli/src/helpers/createProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import {
selectLayoutFile,
selectPageFile,
} from "~/helpers/selectBoilerplate.js";
import { type PkgInstallerMap } from "~/installers/index.js";
import {
type DatabaseProvider,
type PkgInstallerMap,
} from "~/installers/index.js";
import { getUserPkgManager } from "~/utils/getUserPkgManager.js";

interface CreateProjectOptions {
Expand All @@ -20,6 +23,7 @@ interface CreateProjectOptions {
noInstall: boolean;
importAlias: string;
appRouter: boolean;
databaseProvider: DatabaseProvider;
}

export const createProject = async ({
Expand All @@ -28,6 +32,7 @@ export const createProject = async ({
packages,
noInstall,
appRouter,
databaseProvider,
}: CreateProjectOptions) => {
const pkgManager = getUserPkgManager();
const projectDir = path.resolve(process.cwd(), projectName);
Expand All @@ -40,6 +45,7 @@ export const createProject = async ({
scopedAppName,
noInstall,
appRouter,
databaseProvider,
});

// Install the selected packages
Expand All @@ -51,6 +57,7 @@ export const createProject = async ({
packages,
noInstall,
appRouter,
databaseProvider,
});

// Select necessary _app,index / layout,page files
Expand Down
12 changes: 11 additions & 1 deletion cli/src/helpers/logNextSteps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@ export const logNextSteps = async ({
appRouter,
noInstall,
projectDir,
databaseProvider,
}: Pick<
InstallerOptions,
"projectName" | "packages" | "noInstall" | "projectDir" | "appRouter"
| "projectName"
| "packages"
| "noInstall"
| "projectDir"
| "appRouter"
| "databaseProvider"
>) => {
const pkgManager = getUserPkgManager();

Expand All @@ -28,6 +34,10 @@ export const logNextSteps = async ({
}
}

if (["postgres", "mysql"].includes(databaseProvider)) {
logger.info(" ./start-database.sh");
}

if (packages?.prisma.inUse || packages?.drizzle.inUse) {
if (["npm", "bun"].includes(pkgManager)) {
logger.info(` ${pkgManager} run db:push`);
Expand Down
5 changes: 4 additions & 1 deletion cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ const main = async () => {
appName,
packages,
flags: { noGit, noInstall, importAlias, appRouter },
databaseProvider,
} = await runCli();

const usePackages = buildPkgInstallerMap(packages);
const usePackages = buildPkgInstallerMap(packages, databaseProvider);

// e.g. dir/@mono/app returns ["@mono/app", "dir/app"]
const [scopedAppName, appDir] = parseNameAndPath(appName);
Expand All @@ -48,6 +49,7 @@ const main = async () => {
projectName: appDir,
scopedAppName,
packages: usePackages,
databaseProvider,
importAlias,
noInstall,
appRouter,
Expand Down Expand Up @@ -97,6 +99,7 @@ const main = async () => {
appRouter,
noInstall,
projectDir,
databaseProvider,
});

process.exit(0);
Expand Down
20 changes: 20 additions & 0 deletions cli/src/installers/dbContainer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import fs from "fs";
import path from "path";

import { PKG_ROOT } from "~/consts.js";
import { type Installer } from "~/installers/index.js";

export const dbContainerInstaller: Installer = ({
projectDir,
databaseProvider,
projectName,
}) => {
const scriptSrc = path.join(
PKG_ROOT,
`template/extras/start-database/${databaseProvider}.sh`
);
const scriptText = fs.readFileSync(scriptSrc, "utf-8");
const scriptDest = path.join(projectDir, "start-database.sh");
fs.writeFileSync(scriptDest, scriptText.replaceAll("project1", projectName));
fs.chmodSync(scriptDest, "755");
};
4 changes: 4 additions & 0 deletions cli/src/installers/dependencyVersionMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ export const dependencyVersionMap = {
// Prisma
prisma: "^5.6.0",
"@prisma/client": "^5.6.0",
"@prisma/adapter-planetscale": "^5.6.0",

// Drizzle
"drizzle-orm": "^0.29.3",
"drizzle-kit": "^0.20.9",
mysql2: "^3.6.1",
"@planetscale/database": "^1.11.0",
postgres: "^3.4.3",
"@types/better-sqlite3": "^7.6.6",
"better-sqlite3": "^9.0.0",

// TailwindCSS
tailwindcss: "^3.3.5",
Expand Down
49 changes: 41 additions & 8 deletions cli/src/installers/drizzle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,55 @@ 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";
import { type AvailableDependencies } from "./dependencyVersionMap.js";

export const drizzleInstaller: Installer = ({
projectDir,
packages,
scopedAppName,
databaseProvider,
}) => {
const devPackages: AvailableDependencies[] = ["drizzle-kit"];
if (databaseProvider === "planetscale") devPackages.push("mysql2");
if (databaseProvider === "sqlite") devPackages.push("@types/better-sqlite3");

addPackageDependency({
projectDir,
dependencies: ["drizzle-kit", "mysql2"],
dependencies: devPackages,
devMode: true,
});
addPackageDependency({
projectDir,
dependencies: ["drizzle-orm", "@planetscale/database"],
dependencies: [
"drizzle-orm",
(
{
planetscale: "@planetscale/database",
mysql: "mysql2",
postgres: "postgres",
sqlite: "better-sqlite3",
} as const
)[databaseProvider],
],
devMode: false,
});

const extrasDir = path.join(PKG_ROOT, "template/extras");

const configFile = path.join(extrasDir, "config/drizzle.config.ts");
const configFile = path.join(
extrasDir,
`config/drizzle-config-${
databaseProvider === "planetscale" ? "mysql" : databaseProvider
}.ts`
);
const configDest = path.join(projectDir, "drizzle.config.ts");

const schemaSrc = path.join(
extrasDir,
"src/server/db",
"src/server/db/schema-drizzle",
packages?.nextAuth.inUse
? "drizzle-schema-auth.ts"
: "drizzle-schema-base.ts"
? `with-auth-${databaseProvider}.ts`
: `base-${databaseProvider}.ts`
);
const schemaDest = path.join(projectDir, "src/server/db/schema.ts");

Expand All @@ -42,10 +63,15 @@ export const drizzleInstaller: Installer = ({
"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 clientSrc = path.join(
extrasDir,
`src/server/db/index-drizzle/with-${databaseProvider}.ts`
);
const clientDest = path.join(projectDir, "src/server/db/index.ts");

// add db:push script to package.json
Expand All @@ -54,7 +80,14 @@ export const drizzleInstaller: Installer = ({
const packageJsonContent = fs.readJSONSync(packageJsonPath) as PackageJson;
packageJsonContent.scripts = {
...packageJsonContent.scripts,
"db:push": "drizzle-kit push:mysql",
"db:push": `drizzle-kit push:${
{
postgres: "pg",
sqlite: "sqlite",
mysql: "mysql",
planetscale: "mysql",
}[databaseProvider]
}`,
"db:studio": "drizzle-kit studio",
};

Expand Down
Loading

0 comments on commit 06b1bca

Please sign in to comment.