diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 05c06c0f..e801b340 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,6 +20,9 @@ dependencies: execa: specifier: ^8.0.1 version: 8.0.1 + pluralize: + specifier: ^8.0.0 + version: 8.0.0 strip-json-comments: specifier: ^5.0.1 version: 5.0.1 @@ -1067,6 +1070,11 @@ packages: engines: {node: '>=8.6'} dev: true + /pluralize@8.0.0: + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} + dev: false + /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} diff --git a/src/commands/add/auth/next-auth/generators.ts b/src/commands/add/auth/next-auth/generators.ts index 5551b277..af2c57c1 100644 --- a/src/commands/add/auth/next-auth/generators.ts +++ b/src/commands/add/auth/next-auth/generators.ts @@ -149,6 +149,7 @@ export const libAuthUtilsTs = ( dbType: DBType | null, orm: ORMType, ) => { + const { multiProjectSchema } = readConfigFile(); const { shared } = getFilePaths(); const dbIndex = getDbIndexPath(); const providersToUse = providers.map((provider) => { @@ -161,7 +162,7 @@ export const libAuthUtilsTs = ( return `${ dbType !== null - ? `import { db } from "${formatFilePath(dbIndex, { + ? `import { db${multiProjectSchema ? ", mysqlTable" : ""} } from "${formatFilePath(dbIndex, { prefix: "alias", removeExtension: true, })}"; @@ -204,7 +205,7 @@ export type AuthSession = { export const authOptions: NextAuthOptions = { ${ dbType !== null - ? `adapter: ${AuthDriver[orm].adapter}(db),` + ? `adapter: ${AuthDriver[orm].adapter}(db${multiProjectSchema ? ", mysqlTable" : ""}),` : "// adapter: yourDBAdapterHere" } callbacks: { @@ -234,7 +235,8 @@ export const checkAuth = async () => { // 4. create lib/db/schema/auth.ts export const createDrizzleAuthSchema = (dbType: DBType) => { - const { provider } = readConfigFile(); + const { provider, multiProjectSchema } = readConfigFile(); + const { drizzle } = getFilePaths(); switch (dbType) { case "pg": return `import { @@ -272,7 +274,9 @@ export const accounts = pgTable( session_state: text("session_state"), }, (account) => ({ - compoundKey: primaryKey(account.provider, account.providerAccountId), + compoundKey: primaryKey({ + columns: [account.provider, account.providerAccountId], + }), }) ); @@ -292,19 +296,23 @@ export const verificationTokens = pgTable( expires: timestamp("expires", { mode: "date" }).notNull(), }, (vt) => ({ - compoundKey: primaryKey(vt.identifier, vt.token), + compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }), }) ); `; case "mysql": return `import { int, - timestamp, - mysqlTable, + timestamp,${multiProjectSchema === true ? "" : "\n mysqlTable,"} primaryKey, varchar,${provider === "planetscale" ? "\n text" : "\n references"}, } from "drizzle-orm/mysql-core"; import type { AdapterAccount } from "@auth/core/adapters"; +${multiProjectSchema === true ? 'import { mysqlTable } from "' + +formatFilePath(drizzle.dbIndex, { + prefix: "alias", + removeExtension: true, +}) + '";' : ""} export const users = mysqlTable("user", { id: varchar("id", { length: 255 }).notNull().primaryKey(), @@ -344,7 +352,9 @@ export const accounts = mysqlTable( session_state: varchar("session_state", { length: 255 }), }, (account) => ({ - compoundKey: primaryKey(account.provider, account.providerAccountId), + compoundKey: primaryKey({ + columns: [account.provider, account.providerAccountId], + }), }) ); @@ -367,7 +377,7 @@ export const verificationTokens = mysqlTable( expires: timestamp("expires", { mode: "date" }).notNull(), }, (vt) => ({ - compoundKey: primaryKey(vt.identifier, vt.token), + compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }), }) );`; case "sqlite": @@ -405,7 +415,9 @@ export const accounts = sqliteTable( session_state: text("session_state"), }, (account) => ({ - compoundKey: primaryKey(account.provider, account.providerAccountId), + compoundKey: primaryKey({ + columns: [account.provider, account.providerAccountId], + }), }) ); @@ -425,7 +437,7 @@ export const verificationTokens = sqliteTable( expires: integer("expires", { mode: "timestamp_ms" }).notNull(), }, (vt) => ({ - compoundKey: primaryKey(vt.identifier, vt.token), + compoundKey: primaryKey({ columns: [vt.identifier, vt.token] }), }) );`; default: diff --git a/src/commands/add/misc/stripe/generators.ts b/src/commands/add/misc/stripe/generators.ts index ec57f1bf..79eb6829 100644 --- a/src/commands/add/misc/stripe/generators.ts +++ b/src/commands/add/misc/stripe/generators.ts @@ -944,6 +944,8 @@ export const generateSubscriptionsDrizzleSchema = ( driver: DBType, auth: AuthType, ) => { + const { multiProjectSchema } = readConfigFile(); + const { drizzle } = getFilePaths(); const authSubtype = AuthSubTypeMapping[auth]; // add references for pg and sqlite switch (driver) { @@ -975,18 +977,22 @@ export const subscriptions = pgTable( }, (table) => { return { - pk: primaryKey(table.userId, table.stripeCustomerId), + pk: primaryKey({ columns: [table.userId, table.stripeCustomerId] }), }; } ); `; case "mysql": - return `import { - mysqlTable, + return `import {${multiProjectSchema === true ? "" : "\n mysqlTable,"} primaryKey, timestamp, varchar, } from "drizzle-orm/mysql-core"; +${multiProjectSchema === true ? 'import { mysqlTable } from "' + +formatFilePath(drizzle.dbIndex, { + prefix: "alias", + removeExtension: true, +}) + '";' : ""} export const subscriptions = mysqlTable( "subscriptions", @@ -1001,7 +1007,7 @@ export const subscriptions = mysqlTable( }, (table) => { return { - pk: primaryKey(table.userId, table.stripeCustomerId), + pk: primaryKey({ columns: [table.userId, table.stripeCustomerId] }), }; } ); @@ -1034,7 +1040,7 @@ export const subscriptions = sqliteTable( }, (table) => { return { - pk: primaryKey(table.userId, table.stripeCustomerId), + pk: primaryKey({ columns: [table.userId, table.stripeCustomerId] }), }; } ); diff --git a/src/commands/add/orm/drizzle/generators.ts b/src/commands/add/orm/drizzle/generators.ts index 8aed2b40..4dfd1ace 100644 --- a/src/commands/add/orm/drizzle/generators.ts +++ b/src/commands/add/orm/drizzle/generators.ts @@ -37,6 +37,7 @@ const configDriverMappings = { }; export const createDrizzleConfig = (libPath: string, provider: DBProvider) => { + const { multiProjectSchema } = readConfigFile(); const { shared: { init: { envMjs }, @@ -60,12 +61,13 @@ export default { ? "url: env.DATABASE_URL" : "connectionString: env.DATABASE_URL" }${provider === "vercel-pg" ? '.concat("?sslmode=require")' : ""}, - } + },${multiProjectSchema === true ? "\n tablesFilter: ['kirimase_*']," : ""} } satisfies Config;` ); }; export const createIndexTs = (dbProvider: DBProvider) => { + const { multiProjectSchema } = readConfigFile(); const { shared: { init: { envMjs }, @@ -163,11 +165,21 @@ import { env } from "${formatFilePath(envMjs, { removeExtension: false, prefix: "alias", })}"; - +${ + multiProjectSchema === true + ? "import { mysqlTableCreator } from 'drizzle-orm/mysql-core';" + : "" +} + // create the connection export const connection = connect({ url: env.DATABASE_URL }); +${ + multiProjectSchema === true + ? "export const mysqlTable = mysqlTableCreator((name) => `kirimase_${name}`);" + : "" +} export const db = drizzle(connection); `; @@ -394,11 +406,12 @@ runMigrate().catch((err) => { }; export const createInitSchema = (libPath?: string, dbType?: DBType) => { - const { packages, driver, rootPath } = readConfigFile(); + const { packages, driver, rootPath, multiProjectSchema } = readConfigFile(); const { shared: { auth: { authSchema }, }, + drizzle, } = getFilePaths(); const path = `${rootPath}lib/db/schema/computers.ts`; const dbDriver = dbType ?? driver; @@ -426,7 +439,9 @@ export const computers = pgTable("computers", { break; case "mysql": - initModel = `import { mysqlTable, serial, varchar, int } from "drizzle-orm/mysql-core";${ + initModel = `import { ${ + multiProjectSchema === true ? "" : "\n mysqlTable," + } serial, varchar, int } from "drizzle-orm/mysql-core";${ packages.includes("next-auth") ? `\nimport { users } from "${formatFilePath(authSchema, { removeExtension: true, @@ -434,6 +449,16 @@ export const computers = pgTable("computers", { })}";` : "" } +${ + multiProjectSchema === true + ? 'import { mysqlTable } from "' + + formatFilePath(drizzle.dbIndex, { + prefix: "alias", + removeExtension: true, + }) + + '";' + : "" +} export const computers = mysqlTable("computers", { id: serial("id").primaryKey(), diff --git a/src/commands/add/orm/drizzle/index.ts b/src/commands/add/orm/drizzle/index.ts index 8a22b501..14699f05 100644 --- a/src/commands/add/orm/drizzle/index.ts +++ b/src/commands/add/orm/drizzle/index.ts @@ -52,6 +52,14 @@ export const addDrizzle = async (initOptions?: InitOptions) => { ], })) as DBType); + const multiProjectSchema = (await select({ + message: "Are you using a multi-project schema?", + choices: [ + { name: "No", value: false }, + { name: "Yes", value: true }, + ], + })) as boolean; + // const dbProviders = DBProviders[dbType].filter((p) => { // if (preferredPackageManager === "bun") return p.value !== "better-sqlite3"; // else return p.value !== "bun-sqlite"; @@ -97,6 +105,13 @@ export const addDrizzle = async (initOptions?: InitOptions) => { createFolder(`${hasSrc ? "src/" : ""}lib/api`); } + updateConfigFile({ + driver: dbType, + provider: dbProvider, + orm: "drizzle", + multiProjectSchema, + }); + // dependent on dbtype and driver, create createIndexTs(dbProvider); createMigrateTs(libPath, dbType, dbProvider); @@ -124,8 +139,6 @@ export const addDrizzle = async (initOptions?: InitOptions) => { rootPath ); await updateTsConfigTarget(); - - updateConfigFile({ driver: dbType, provider: dbProvider, orm: "drizzle" }); await installDependencies(dbProvider, preferredPackageManager); addPackageToConfig("drizzle"); }; diff --git a/src/commands/init/index.ts b/src/commands/init/index.ts index 538e59ed..bf4eaabc 100644 --- a/src/commands/init/index.ts +++ b/src/commands/init/index.ts @@ -72,6 +72,7 @@ export async function initProject(options?: InitOptions) { packages: [], preferredPackageManager, orm: undefined, + multiProjectSchema: undefined, auth: undefined, componentLib: undefined, t3: false, diff --git a/src/types.d.ts b/src/types.d.ts index b1c69f2f..8573c835 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -89,6 +89,7 @@ export type Config = { provider: DBProvider | null; packages: AvailablePackage[]; orm: ORMType | null; + multiProjectSchema: boolean | null; auth: AuthType | null; componentLib: ComponentLibType | null; t3: boolean;