Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add more db options #1622

Merged
merged 38 commits into from
Jan 20, 2024
Merged
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
bb89d66
it works but needs more testing
ronanru Oct 24, 2023
b89463b
fix drizzle config
ronanru Oct 24, 2023
80eed45
fix ci error
ronanru Oct 24, 2023
03634e6
use planetscale as default for drizzle
ronanru Oct 24, 2023
f5d5a2d
add ci tests
ronanru Oct 30, 2023
40405de
remove neon
ronanru Nov 2, 2023
071bfd9
move drizzle schemas to different files
ronanru Nov 3, 2023
19b0d66
add db container
ronanru Nov 3, 2023
7e36c88
fix drizzle config, switch to postgres.js
ronanru Nov 3, 2023
80643cb
chore: add changeset
ronanru Nov 3, 2023
1aae6fa
fixes for sqlite
ronanru Nov 3, 2023
d35ad8e
bugfixes
ronanru Nov 3, 2023
83a5639
fix ci
ronanru Nov 3, 2023
e2e4750
add @prisma/adapter-planetscale
ronanru Nov 19, 2023
962adeb
fix prisma + planetscale
ronanru Nov 19, 2023
52fb275
Merge remote-tracking branch 'upstream/main' into db-options
ronanru Nov 19, 2023
5a318d9
fix eslint error
ronanru Nov 19, 2023
5f92792
fix db script
ronanru Nov 19, 2023
423d9fe
Revert "fix prisma + planetscale"
ronanru Nov 20, 2023
6f668e5
remove unnecessary comment
ronanru Nov 20, 2023
84c4d4d
move password generation to the start script
ronanru Nov 22, 2023
166f3b7
add foreign keys to drizzle schemas
ronanru Nov 22, 2023
1e77b3a
docs: update first steps
ronanru Nov 22, 2023
cfd53be
Merge branch 'main' into db-options
ronanru Nov 22, 2023
fde1ed4
fix planetscale+prisma schema
ronanru Nov 23, 2023
59a65ce
add windows instructions to the db script
ronanru Nov 26, 2023
4887feb
Merge branch 'main' into db-options
ronanru Nov 26, 2023
f9a6b4b
Merge branch 'main' into db-options
ronanru Dec 6, 2023
7f8925d
Merge branch 'main' into db-options
ronanru Dec 7, 2023
e28a41c
merge
juliusmarminge Jan 4, 2024
1d89669
Merge branch 'main' into db-options
juliusmarminge Jan 4, 2024
a0c2050
fix schema
juliusmarminge Jan 4, 2024
255988d
add type cast for adapter to workaround version mismatch
juliusmarminge Jan 4, 2024
a72ea73
add mode
juliusmarminge Jan 4, 2024
ed73195
rm cast for prisma adapter
juliusmarminge Jan 4, 2024
60914c7
fix env var string
juliusmarminge Jan 4, 2024
1ef48ab
Merge branch 'main' into db-options
ronanru Jan 15, 2024
cfa68bf
Merge branch 'main' into db-options
juliusmarminge Jan 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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