create-absolutejs 0.18.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +9 -2
  3. package/changelog.json +24 -0
  4. package/dist/commands/migrateDatabase.d.ts +6 -0
  5. package/dist/commands/migrateDatabase.js +53 -0
  6. package/dist/data.d.ts +1 -1
  7. package/dist/data.js +1 -0
  8. package/dist/generators/configurations/generateDrizzleConfig.d.ts +5 -3
  9. package/dist/generators/configurations/generateDrizzleConfig.js +40 -14
  10. package/dist/generators/configurations/generateEnv.js +6 -0
  11. package/dist/generators/configurations/generateEslintConfig.js +1 -1
  12. package/dist/generators/configurations/generatePackageJson.d.ts +2 -1
  13. package/dist/generators/configurations/generatePackageJson.js +40 -4
  14. package/dist/generators/db/drizzleTargets.d.ts +5 -0
  15. package/dist/generators/db/drizzleTargets.js +27 -0
  16. package/dist/generators/db/generateDatabaseTypes.js +10 -6
  17. package/dist/generators/db/generateDockerContainer.d.ts +5 -0
  18. package/dist/generators/db/generateDockerContainer.js +22 -4
  19. package/dist/generators/db/generateDrizzleSchema.js +65 -81
  20. package/dist/generators/db/handlerTemplates.d.ts +4 -4
  21. package/dist/generators/db/handlerTemplates.js +7 -10
  22. package/dist/generators/db/scaffoldDatabase.js +31 -8
  23. package/dist/generators/db/scaffoldDocker.d.ts +2 -1
  24. package/dist/generators/db/scaffoldDocker.js +7 -3
  25. package/dist/generators/prisma/generatePrismaCode.d.ts +6 -0
  26. package/dist/generators/prisma/generatePrismaCode.js +148 -0
  27. package/dist/generators/prisma/generatePrismaConfig.d.ts +8 -0
  28. package/dist/generators/prisma/generatePrismaConfig.js +68 -0
  29. package/dist/generators/prisma/generatePrismaSchema.d.ts +9 -0
  30. package/dist/generators/prisma/generatePrismaSchema.js +80 -0
  31. package/dist/generators/prisma/prismaPackageJson.d.ts +8 -0
  32. package/dist/generators/prisma/prismaPackageJson.js +46 -0
  33. package/dist/generators/prisma/prismaTargets.d.ts +22 -0
  34. package/dist/generators/prisma/prismaTargets.js +91 -0
  35. package/dist/generators/prisma/scaffoldPrismaDatabase.d.ts +16 -0
  36. package/dist/generators/prisma/scaffoldPrismaDatabase.js +136 -0
  37. package/dist/generators/project/generateDBBlock.js +16 -2
  38. package/dist/generators/project/generateImportsBlock.js +17 -7
  39. package/dist/generators/project/generateServer.js +2 -1
  40. package/dist/index.js +2 -1
  41. package/dist/messages.d.ts +2 -1
  42. package/dist/messages.js +2 -1
  43. package/dist/questions/authOption.js +4 -1
  44. package/dist/questions/databaseEngine.d.ts +1 -1
  45. package/dist/questions/orm.js +5 -2
  46. package/dist/scaffold.d.ts +1 -0
  47. package/dist/scaffold.js +23 -5
  48. package/dist/templates/configurations/.prettierignore +2 -1
  49. package/dist/templates/configurations/eslint.config.example.mjs +81 -41
  50. package/dist/templates/db/migrations/cockroach-count-history/20260926210314_init/migration.sql +5 -0
  51. package/dist/templates/db/migrations/cockroach-count-history/20260926210314_init/snapshot.json +69 -0
  52. package/dist/templates/db/migrations/cockroach-users/20260926210315_init/migration.sql +5 -0
  53. package/dist/templates/db/migrations/cockroach-users/20260926210315_init/snapshot.json +62 -0
  54. package/dist/templates/db/migrations/mssql-count-history/20260926210316_init/migration.sql +6 -0
  55. package/dist/templates/db/migrations/mssql-count-history/20260926210316_init/snapshot.json +64 -0
  56. package/dist/templates/db/migrations/mssql-users/20260926210317_init/migration.sql +6 -0
  57. package/dist/templates/db/migrations/mssql-users/20260926210317_init/snapshot.json +70 -0
  58. package/dist/templates/db/migrations/mysql-count-history/20260926210318_init/migration.sql +5 -0
  59. package/dist/templates/db/migrations/mysql-count-history/20260926210318_init/snapshot.json +61 -0
  60. package/dist/templates/db/migrations/mysql-users/20260926210319_init/migration.sql +5 -0
  61. package/dist/templates/db/migrations/mysql-users/20260926210319_init/snapshot.json +61 -0
  62. package/dist/templates/db/migrations/postgresql-count-history/20260926210320_init/migration.sql +5 -0
  63. package/dist/templates/db/migrations/postgresql-count-history/20260926210320_init/snapshot.json +71 -0
  64. package/dist/templates/db/migrations/postgresql-users/20260926210320_init/migration.sql +5 -0
  65. package/dist/templates/db/migrations/postgresql-users/20260926210320_init/snapshot.json +62 -0
  66. package/dist/templates/db/migrations/prisma-cockroachdb-count-history/20260926000000_init/migration.sql +12 -0
  67. package/dist/templates/db/migrations/prisma-cockroachdb-count-history/migration_lock.toml +3 -0
  68. package/dist/templates/db/migrations/prisma-cockroachdb-users/20260926000000_init/migration.sql +12 -0
  69. package/dist/templates/db/migrations/prisma-cockroachdb-users/migration_lock.toml +3 -0
  70. package/dist/templates/db/migrations/prisma-mysql-count-history/20260926000000_init/migration.sql +9 -0
  71. package/dist/templates/db/migrations/prisma-mysql-count-history/migration_lock.toml +3 -0
  72. package/dist/templates/db/migrations/prisma-mysql-users/20260926000000_init/migration.sql +9 -0
  73. package/dist/templates/db/migrations/prisma-mysql-users/migration_lock.toml +3 -0
  74. package/dist/templates/db/migrations/prisma-postgresql-count-history/20260926000000_init/migration.sql +12 -0
  75. package/dist/templates/db/migrations/prisma-postgresql-count-history/migration_lock.toml +3 -0
  76. package/dist/templates/db/migrations/prisma-postgresql-users/20260926000000_init/migration.sql +12 -0
  77. package/dist/templates/db/migrations/prisma-postgresql-users/migration_lock.toml +3 -0
  78. package/dist/templates/db/migrations/prisma-sqlite-count-history/20260926000000_init/migration.sql +7 -0
  79. package/dist/templates/db/migrations/prisma-sqlite-count-history/migration_lock.toml +3 -0
  80. package/dist/templates/db/migrations/prisma-sqlite-users/20260926000000_init/migration.sql +7 -0
  81. package/dist/templates/db/migrations/prisma-sqlite-users/migration_lock.toml +3 -0
  82. package/dist/templates/db/migrations/prisma-sqlserver-count-history/20260926000000_init/migration.sql +28 -0
  83. package/dist/templates/db/migrations/prisma-sqlserver-count-history/migration_lock.toml +3 -0
  84. package/dist/templates/db/migrations/prisma-sqlserver-users/20260926000000_init/migration.sql +28 -0
  85. package/dist/templates/db/migrations/prisma-sqlserver-users/migration_lock.toml +3 -0
  86. package/dist/templates/db/migrations/singlestore-count-history/20260926210321_init/migration.sql +5 -0
  87. package/dist/templates/db/migrations/singlestore-count-history/20260926210321_init/snapshot.json +61 -0
  88. package/dist/templates/db/migrations/singlestore-users/20260926210322_init/migration.sql +5 -0
  89. package/dist/templates/db/migrations/singlestore-users/20260926210322_init/snapshot.json +61 -0
  90. package/dist/templates/db/migrations/sqlite-count-history/20260926210323_init/migration.sql +5 -0
  91. package/dist/templates/db/migrations/sqlite-count-history/20260926210323_init/snapshot.json +50 -0
  92. package/dist/templates/db/migrations/sqlite-users/20260926210324_init/migration.sql +5 -0
  93. package/dist/templates/db/migrations/sqlite-users/20260926210324_init/snapshot.json +50 -0
  94. package/dist/templates/db/migrations/turso-count-history/20260926210324_init/migration.sql +5 -0
  95. package/dist/templates/db/migrations/turso-count-history/20260926210324_init/snapshot.json +50 -0
  96. package/dist/templates/db/migrations/turso-users/20260926210325_init/migration.sql +5 -0
  97. package/dist/templates/db/migrations/turso-users/20260926210325_init/snapshot.json +50 -0
  98. package/dist/templates/git/gitignore +5 -3
  99. package/dist/typeGuards.d.ts +2 -2
  100. package/dist/typeGuards.js +2 -2
  101. package/dist/utils/parseCommandLineOptions.js +16 -31
  102. package/dist/utils/validateDatabaseSelection.d.ts +11 -0
  103. package/dist/utils/validateDatabaseSelection.js +34 -0
  104. package/dist/versions.d.ts +9 -0
  105. package/dist/versions.js +13 -0
  106. package/package.json +4 -1
  107. package/dist/templates/configurations/drizzle.config.ts +0 -13
package/CHANGELOG.md CHANGED
@@ -6,6 +6,22 @@ This file is generated by `absolute-changelog` from the entries in
6
6
  `changelog/`. Edit an entry, not this file — and add new ones under
7
7
  `changelog/unreleased/`.
8
8
 
9
+ ## 0.20.0 — 2026-09-27
10
+
11
+ ### Added
12
+
13
+ - **Scaffold Prisma for every Prisma database (PostgreSQL, Neon, PlanetScale, CockroachDB, MySQL, MariaDB, SQLite, Turso, SQL Server on Prisma 7.10 driver adapters; MongoDB on Prisma 6.19.3) with a committed initial migration, typed handlers and prisma generate / db:migrate scripts**
14
+
15
+ ## 0.19.0 — 2026-09-26
16
+
17
+ ### Added
18
+
19
+ - **Scaffold Drizzle for every Drizzle 1.0 dialect (PostgreSQL, MySQL, MariaDB, SQLite, Turso/libSQL, SingleStore, SQL Server, CockroachDB) with a committed initial migration and db:generate / db:migrate scripts**
20
+
21
+ ### Fixed
22
+
23
+ - **Accept --orm none as the help text documents, and refuse unsupported database, host and ORM combinations before writing any files**
24
+
9
25
  ## 0.18.0 — 2026-09-23
10
26
 
11
27
  ### Fixed
package/README.md CHANGED
@@ -112,8 +112,9 @@ Usage: create-absolute [project-name] [options]
112
112
  - `--lts`
113
113
  Use LTS versions of required packages.
114
114
 
115
- - `--orm <drizzle|none>`
116
- ORM to configure: `drizzle` | `none`. Prisma scaffolding is not implemented and is rejected before files are written. Drizzle 1 no longer includes the Gel dialect; choose no ORM for Gel.
115
+ - `--orm <drizzle|prisma|none>`
116
+ ORM to configure: `drizzle` | `prisma` | `none`. Drizzle 1 no longer includes the Gel dialect; choose no ORM for Gel.
117
+ Prisma supports PostgreSQL (local, Neon, PlanetScale), CockroachDB, MySQL (local, PlanetScale), MariaDB, SQLite (local, Turso), SQL Server and MongoDB; Gel and SingleStore are rejected before files are written. A Prisma project ships `prisma.config.ts`, `db/schema.prisma` and a committed initial migration; `postinstall` / `db:generate` run `prisma generate` into `src/generated/prisma` (git-ignored), and `db:migrate` applies the migrations (`prisma migrate deploy`; Turso through `db/migrate.ts`, since Prisma Migrate cannot reach libSQL URLs; MongoDB through `prisma db push`). `db:migrate:dev` authors new migrations.
117
118
 
118
119
  - `--plugin <plugin>`
119
120
  Elysia plugin(s) to include (repeatable); `none` skips plugin setup. Select
@@ -206,6 +207,12 @@ switch a generated server back to Elysia 1.
206
207
  - TypeScript 5.9.3 and Angular's current 21 LTS patches match the framework's
207
208
  compiler peer dependencies. Newer incompatible compiler majors are not selected.
208
209
  - Drizzle ORM and Kit use the coordinated 1.0 release-candidate channel.
210
+ - Prisma uses 7.10 (the `prisma-client` generator with driver adapters) for every
211
+ SQL database. MongoDB projects pin Prisma 6.19.3, because Prisma 7 does not
212
+ support MongoDB yet (Prisma's documentation directs MongoDB users to v6.19).
213
+ They need a replica set, which the generated Docker database provides. The npm
214
+ `latest` tag for `prisma` currently points at an 8.0 release candidate, so
215
+ Prisma is always pinned, including under `--lts`.
209
216
  - All other pins are checked against their latest published release channel.
210
217
 
211
218
  Automatic authentication setup currently supplies a complete Google configuration
package/changelog.json CHANGED
@@ -2,6 +2,30 @@
2
2
  "contract": 1,
3
3
  "name": "create-absolutejs",
4
4
  "releases": [
5
+ {
6
+ "changes": [
7
+ {
8
+ "kind": "added",
9
+ "summary": "Scaffold Prisma for every Prisma database (PostgreSQL, Neon, PlanetScale, CockroachDB, MySQL, MariaDB, SQLite, Turso, SQL Server on Prisma 7.10 driver adapters; MongoDB on Prisma 6.19.3) with a committed initial migration, typed handlers and prisma generate / db:migrate scripts"
10
+ }
11
+ ],
12
+ "date": "2026-09-27",
13
+ "version": "0.20.0"
14
+ },
15
+ {
16
+ "changes": [
17
+ {
18
+ "kind": "fixed",
19
+ "summary": "Accept --orm none as the help text documents, and refuse unsupported database, host and ORM combinations before writing any files"
20
+ },
21
+ {
22
+ "kind": "added",
23
+ "summary": "Scaffold Drizzle for every Drizzle 1.0 dialect (PostgreSQL, MySQL, MariaDB, SQLite, Turso/libSQL, SingleStore, SQL Server, CockroachDB) with a committed initial migration and db:generate / db:migrate scripts"
24
+ }
25
+ ],
26
+ "date": "2026-09-26",
27
+ "version": "0.19.0"
28
+ },
5
29
  {
6
30
  "changes": [
7
31
  {
@@ -0,0 +1,6 @@
1
+ import type { CreateConfiguration } from '../types';
2
+ type MigrateDatabaseProps = Pick<CreateConfiguration, 'databaseEngine' | 'databaseHost' | 'projectName'> & {
3
+ verifyLocalDatabase: boolean;
4
+ };
5
+ export declare const migrateDatabase: ({ databaseEngine, databaseHost, projectName, verifyLocalDatabase }: MigrateDatabaseProps) => Promise<boolean>;
6
+ export {};
@@ -0,0 +1,53 @@
1
+ import { spinner } from '@clack/prompts';
2
+ import { $ } from 'bun';
3
+ import { green, yellow } from 'picocolors';
4
+ import { isDockerDaemonRunning, resolveDockerExe } from '../utils/checkDockerInstalled';
5
+ const applyMigrations = async (projectName) => (await $ `bun run db:migrate`.cwd(projectName).quiet().nothrow())
6
+ .exitCode === 0;
7
+ const migrateDockerDatabase = async (projectName, databaseEngine) => {
8
+ if (!(await isDockerDaemonRunning()))
9
+ return false;
10
+ const docker = resolveDockerExe();
11
+ const compose = [
12
+ 'compose',
13
+ '-p',
14
+ databaseEngine,
15
+ '-f',
16
+ 'db/docker-compose.db.yml'
17
+ ];
18
+ const started = await $ `${docker} ${compose} up -d --wait db`
19
+ .cwd(projectName)
20
+ .quiet()
21
+ .nothrow();
22
+ if (started.exitCode !== 0)
23
+ return false;
24
+ const migrated = await applyMigrations(projectName);
25
+ await $ `${docker} ${compose} down`.cwd(projectName).quiet().nothrow();
26
+ return migrated;
27
+ };
28
+ /* Applies the project's committed initial migration once dependencies are
29
+ installed, so a fresh Drizzle project's example tables exist on first run.
30
+ Local SQLite and the default local libSQL file for Turso migrate directly;
31
+ a Docker database is migrated only when the daemon is already up and the
32
+ scaffold verified it. Hosted databases are left to `db:migrate`, which needs
33
+ the real DATABASE_URL. Returns whether the migration ran. */
34
+ export const migrateDatabase = async ({ databaseEngine, databaseHost, projectName, verifyLocalDatabase }) => {
35
+ const isLocal = databaseHost === undefined || databaseHost === 'none';
36
+ const isFileDatabase = databaseEngine === 'sqlite' && (isLocal || databaseHost === 'turso');
37
+ const isDockerDatabase = isLocal &&
38
+ verifyLocalDatabase &&
39
+ databaseEngine !== undefined &&
40
+ databaseEngine !== 'none' &&
41
+ databaseEngine !== 'sqlite';
42
+ if (!isFileDatabase && !isDockerDatabase)
43
+ return false;
44
+ const spin = spinner();
45
+ spin.start('Applying database migrations');
46
+ const migrated = isFileDatabase
47
+ ? await applyMigrations(projectName)
48
+ : await migrateDockerDatabase(projectName, databaseEngine ?? 'db');
49
+ spin.stop(migrated
50
+ ? green('Database migrated')
51
+ : yellow('Database not migrated — run db:migrate once it is up'));
52
+ return migrated;
53
+ };
package/dist/data.d.ts CHANGED
@@ -5,7 +5,7 @@ export declare const availableCodeQualityTools: readonly ["eslint+prettier", "bi
5
5
  export declare const availableDatabaseEngines: readonly ["postgresql", "mysql", "sqlite", "mongodb", "mariadb", "gel", "singlestore", "cockroachdb", "mssql", "none"];
6
6
  export declare const availableDatabaseHosts: readonly ["neon", "planetscale", "turso", "none"];
7
7
  export declare const availableDirectoryConfigurations: readonly ["default", "custom"];
8
- export declare const availableDrizzleDialects: readonly ["mariadb", "mssql", "mysql", "postgresql", "singlestore", "sqlite"];
8
+ export declare const availableDrizzleDialects: readonly ["cockroachdb", "mariadb", "mssql", "mysql", "postgresql", "singlestore", "sqlite"];
9
9
  export declare const availableFrontends: readonly ["react", "html", "svelte", "vue", "htmx", "angular"];
10
10
  export declare const availableORMs: readonly ["drizzle", "prisma", "none"];
11
11
  export declare const availablePlugins: AvailableDependency[];
package/dist/data.js CHANGED
@@ -35,6 +35,7 @@ export const availableDatabaseHosts = [
35
35
  ];
36
36
  export const availableDirectoryConfigurations = ['default', 'custom'];
37
37
  export const availableDrizzleDialects = [
38
+ 'cockroachdb',
38
39
  'mariadb',
39
40
  'mssql',
40
41
  'mysql',
@@ -1,8 +1,10 @@
1
- import type { DatabaseEngine } from '../../types';
1
+ import type { AvailableDrizzleDialect, DatabaseHost } from '../../types';
2
2
  type CreateDrizzleConfigProps = {
3
3
  projectName: string;
4
- databaseEngine: DatabaseEngine;
4
+ databaseEngine: AvailableDrizzleDialect;
5
+ databaseHost: DatabaseHost;
5
6
  databaseDirectory: string;
6
7
  };
7
- export declare const createDrizzleConfig: ({ projectName, databaseDirectory, databaseEngine }: CreateDrizzleConfigProps) => void;
8
+ export declare const createDrizzleConfig: ({ projectName, ...options }: CreateDrizzleConfigProps) => void;
9
+ export declare const generateDrizzleConfig: ({ databaseDirectory, databaseEngine, databaseHost }: Omit<CreateDrizzleConfigProps, "projectName">) => string;
8
10
  export {};
@@ -1,21 +1,47 @@
1
1
  import { writeFileSync } from 'fs';
2
2
  import { join } from 'path';
3
- export const createDrizzleConfig = ({ projectName, databaseDirectory, databaseEngine }) => {
4
- const drizzleConfig = `import { defineConfig } from "drizzle-kit";
5
- import { env } from 'process';
6
-
7
- if (!env.DATABASE_URL) {
3
+ import { getDrizzleKitDialect } from '../db/drizzleTargets';
4
+ const requireDatabaseUrl = `if (!env.DATABASE_URL) {
8
5
  throw new Error('DATABASE_URL must be set in the environment variables');
9
6
  }
7
+ `;
8
+ export const createDrizzleConfig = ({ projectName, ...options }) => {
9
+ writeFileSync(join(projectName, 'drizzle.config.ts'), generateDrizzleConfig(options));
10
+ };
11
+ export const generateDrizzleConfig = ({ databaseDirectory, databaseEngine, databaseHost }) => {
12
+ const dialect = getDrizzleKitDialect(databaseEngine, databaseHost);
13
+ const paths = `out: '${databaseDirectory}/migrations',
14
+ schema: '${databaseDirectory}/schema.ts'`;
15
+ /* Local SQLite lives in a file beside the schema — the same path the server
16
+ opens — so migrations need no environment at all. */
17
+ if (dialect === 'sqlite') {
18
+ return `import { defineConfig } from 'drizzle-kit';
19
+
20
+ export default defineConfig({
21
+ dbCredentials: {
22
+ url: '${databaseDirectory}/database.sqlite'
23
+ },
24
+ dialect: 'sqlite',
25
+ ${paths}
26
+ });
27
+ `;
28
+ }
29
+ /* Turso speaks libSQL: a \`libsql://\` URL plus an auth token in the cloud,
30
+ or a \`file:\` URL with no token for a local libSQL database. */
31
+ const credentials = dialect === 'turso'
32
+ ? `authToken: env.DATABASE_AUTH_TOKEN,
33
+ url: env.DATABASE_URL`
34
+ : 'url: env.DATABASE_URL';
35
+ return `import { env } from 'process';
36
+ import { defineConfig } from 'drizzle-kit';
10
37
 
11
- export default defineConfig({
12
- dbCredentials: {
13
- url: env.DATABASE_URL
14
- },
15
- dialect: '${databaseEngine === 'mariadb' ? 'mysql' : databaseEngine}',
16
- out: '${databaseDirectory}/migrations',
17
- schema: '${databaseDirectory}/schema.ts'
18
- });
38
+ ${requireDatabaseUrl}
39
+ export default defineConfig({
40
+ dbCredentials: {
41
+ ${credentials}
42
+ },
43
+ dialect: '${dialect}',
44
+ ${paths}
45
+ });
19
46
  `;
20
- writeFileSync(join(projectName, 'drizzle.config.ts'), drizzleConfig);
21
47
  };
@@ -18,6 +18,12 @@ export const generateEnv = ({ databaseEngine, databaseHost, envVariables = [], p
18
18
  (databaseHost === 'none' || databaseHost === undefined)) {
19
19
  vars.push(`DATABASE_URL=${databaseURLS[databaseEngine]}`);
20
20
  }
21
+ /* A Turso project starts on a local libSQL file so it runs (and migrates)
22
+ before a cloud database exists; pointing it at Turso is two variables. */
23
+ const setsDatabaseUrl = vars.some((entry) => entry.startsWith('DATABASE_URL='));
24
+ if (databaseHost === 'turso' && !setsDatabaseUrl) {
25
+ vars.push('# Local libSQL file. For Turso use DATABASE_URL=libsql://<database>.turso.io and set DATABASE_AUTH_TOKEN.', 'DATABASE_URL=file:db/database.db');
26
+ }
21
27
  if (vars.length === 0)
22
28
  return;
23
29
  const envPath = join(projectName, '.env');
@@ -7,7 +7,7 @@ ${frontends.includes('react') ? "import reactHooks from 'eslint-plugin-react-hoo
7
7
 
8
8
  export default defineConfig([
9
9
  // The copied HTMX distribution is third-party minified runtime code.
10
- { ignores: ['src/frontend/**/htmx.min.js', 'node_modules/**', 'build/**', 'dist/**', '.absolutejs/**', '.data/**', '**/.absolutejs-hmr-*', 'drizzle/**'] },
10
+ { ignores: ['src/frontend/**/htmx.min.js', 'node_modules/**', 'build/**', 'dist/**', '.absolutejs/**', '.data/**', '**/.absolutejs-hmr-*', 'drizzle/**', 'src/generated/**'] },
11
11
  { linterOptions: { noInlineConfig: true, reportUnusedDisableDirectives: 'error' } },
12
12
  ...tseslint.configs.recommended,
13
13
  {
@@ -1,8 +1,9 @@
1
1
  import type { CreateConfiguration } from '../../types';
2
2
  type CreatePackageJsonProps = Pick<CreateConfiguration, 'authOption' | 'agentic' | 'useTailwind' | 'databaseEngine' | 'databaseHost' | 'plugins' | 'orm' | 'frontendDirectories' | 'codeQualityTool'> & {
3
3
  projectName: string;
4
+ databaseDirectory?: string;
4
5
  latest: boolean;
5
6
  repositoryUrl: string | undefined;
6
7
  };
7
- export declare const createPackageJson: ({ agentic, projectName, authOption, plugins, databaseEngine, orm, databaseHost, useTailwind, latest, frontendDirectories, codeQualityTool, repositoryUrl }: CreatePackageJsonProps) => Promise<void>;
8
+ export declare const createPackageJson: ({ agentic, projectName, authOption, plugins, databaseEngine, orm, databaseHost, useTailwind, latest, frontendDirectories, codeQualityTool, databaseDirectory, repositoryUrl }: CreatePackageJsonProps) => Promise<void>;
8
9
  export {};
@@ -3,8 +3,11 @@ import { join } from 'path';
3
3
  import { spinner } from '@clack/prompts';
4
4
  import { green } from 'picocolors';
5
5
  import { absoluteAuthPlugin, availablePlugins, defaultDependencies, defaultPlugins, eslintAndPrettierDependencies, eslintReactDependencies } from '../../data';
6
+ import { isPrismaDialect } from '../../typeGuards';
6
7
  import { getPackageVersions } from '../../utils/getPackageVersion';
7
8
  import { versions } from '../../versions';
9
+ import { getPrismaPackageJson } from '../prisma/prismaPackageJson';
10
+ import { getPrismaTarget } from '../prisma/prismaTargets';
8
11
  import { computeFlags } from '../project/computeFlags';
9
12
  const dbClientCommands = {
10
13
  cockroachdb: 'cockroach sql --insecure --database=database',
@@ -16,7 +19,7 @@ const dbClientCommands = {
16
19
  postgresql: 'psql -h localhost -U user -d database',
17
20
  singlestore: 'singlestore -u root -ppassword -D database'
18
21
  };
19
- export const createPackageJson = async ({ agentic, projectName, authOption, plugins, databaseEngine, orm, databaseHost, useTailwind, latest, frontendDirectories, codeQualityTool, repositoryUrl }) => {
22
+ export const createPackageJson = async ({ agentic, projectName, authOption, plugins, databaseEngine, orm, databaseHost, useTailwind, latest, frontendDirectories, codeQualityTool, databaseDirectory = 'db', repositoryUrl }) => {
20
23
  const flags = computeFlags(frontendDirectories);
21
24
  const isLocal = !databaseHost || databaseHost === 'none';
22
25
  /* ── Collect all package names that need versions ─────────── */
@@ -118,6 +121,19 @@ export const createPackageJson = async ({ agentic, projectName, authOption, plug
118
121
  packageNames.add('mssql');
119
122
  packageNames.add('@types/mssql');
120
123
  }
124
+ /* drizzle-orm/cockroach (and drizzle-kit's cockroach dialect) drive
125
+ CockroachDB through node-postgres. */
126
+ const usesCockroachDrizzle = isLocal && databaseEngine === 'cockroachdb' && orm === 'drizzle';
127
+ if (usesCockroachDrizzle) {
128
+ packageNames.add('pg');
129
+ packageNames.add('@types/pg');
130
+ }
131
+ /* drizzle-kit migrates through the first Postgres driver it can import,
132
+ trying pg before Neon's serverless driver (which @absolutejs/auth brings
133
+ in transitively and which cannot reach a local database). */
134
+ const needsKitPostgresDriver = isLocal && databaseEngine === 'postgresql' && orm === 'drizzle';
135
+ if (needsKitPostgresDriver)
136
+ packageNames.add('pg');
121
137
  if (isLocal && databaseEngine === 'gel')
122
138
  packageNames.add('gel');
123
139
  if (databaseEngine === 'mongodb')
@@ -279,6 +295,13 @@ export const createPackageJson = async ({ agentic, projectName, authOption, plug
279
295
  dependencies['mssql'] = resolveVersion('mssql', versions['mssql']);
280
296
  devDependencies['@types/mssql'] = resolveVersion('@types/mssql', versions['@types/mssql']);
281
297
  }
298
+ if (needsKitPostgresDriver) {
299
+ devDependencies['pg'] = resolveVersion('pg', versions['pg']);
300
+ }
301
+ if (usesCockroachDrizzle) {
302
+ dependencies['pg'] = resolveVersion('pg', versions['pg']);
303
+ devDependencies['@types/pg'] = resolveVersion('@types/pg', versions['@types/pg']);
304
+ }
282
305
  if (isLocalDb && databaseEngine === 'gel') {
283
306
  dependencies['gel'] = resolveVersion('gel', versions['gel']);
284
307
  }
@@ -287,14 +310,27 @@ export const createPackageJson = async ({ agentic, projectName, authOption, plug
287
310
  }
288
311
  if (isLocalDb && databaseEngine === 'sqlite') {
289
312
  scripts['db:sqlite'] = 'sqlite3 db/database.sqlite';
290
- scripts['db:init'] = 'sqlite3 db/database.sqlite < db/init.sql';
313
+ }
314
+ if (isLocalDb && databaseEngine === 'sqlite' && orm !== 'drizzle') {
315
+ scripts['db:init'] = 'sqlite3 db/database.sqlite < db/schema.sql';
291
316
  }
292
317
  if (orm === 'drizzle') {
293
- scripts['db:studio'] = 'drizzle-kit studio';
294
- scripts['db:push'] = 'drizzle-kit push';
318
+ /* Migrations are the schema's source of truth: `db:generate` diffs
319
+ db/schema.ts into a new committed migration and `db:migrate` applies
320
+ pending ones. drizzle-kit runs on Bun so it can use Bun's own SQL and
321
+ SQLite drivers, exactly as the server does. */
322
+ scripts['db:generate'] = 'bun --bun drizzle-kit generate';
323
+ scripts['db:migrate'] = 'bun --bun drizzle-kit migrate';
324
+ scripts['db:studio'] = 'bun --bun drizzle-kit studio';
295
325
  /* `drizzle.config.ts` imports it and the scripts above shell out to it. */
296
326
  devDependencies['drizzle-kit'] = resolveVersion('drizzle-kit', versions['drizzle-kit']);
297
327
  }
328
+ if (orm === 'prisma' && isPrismaDialect(databaseEngine)) {
329
+ const prisma = getPrismaPackageJson(getPrismaTarget(databaseEngine, databaseHost), databaseDirectory);
330
+ Object.assign(dependencies, prisma.dependencies);
331
+ Object.assign(devDependencies, prisma.devDependencies);
332
+ Object.assign(scripts, prisma.scripts);
333
+ }
298
334
  const packageJson = {
299
335
  dependencies,
300
336
  devDependencies,
@@ -0,0 +1,5 @@
1
+ import type { AvailableDrizzleDialect, DatabaseHost } from '../../types';
2
+ export declare const drizzleKitDialects: readonly ["cockroach", "mssql", "mysql", "postgresql", "singlestore", "sqlite", "turso"];
3
+ export type DrizzleKitDialect = (typeof drizzleKitDialects)[number];
4
+ export declare const getDrizzleKitDialect: (databaseEngine: AvailableDrizzleDialect, databaseHost: DatabaseHost) => "mssql" | "mysql" | "postgresql" | "singlestore" | "sqlite" | "turso" | "cockroach";
5
+ export declare const getMigrationTemplateName: (kitDialect: DrizzleKitDialect, usesAuth: boolean) => string;
@@ -0,0 +1,27 @@
1
+ /* The `dialect` values drizzle-kit 1.0 accepts in drizzle.config.ts. Turso is
2
+ its own kit dialect (libSQL over HTTP/WebSocket with an auth token), even
3
+ though its tables are written with sqlite-core. */
4
+ export const drizzleKitDialects = [
5
+ 'cockroach',
6
+ 'mssql',
7
+ 'mysql',
8
+ 'postgresql',
9
+ 'singlestore',
10
+ 'sqlite',
11
+ 'turso'
12
+ ];
13
+ const engineKitDialects = {
14
+ cockroachdb: 'cockroach',
15
+ mariadb: 'mysql',
16
+ mssql: 'mssql',
17
+ mysql: 'mysql',
18
+ postgresql: 'postgresql',
19
+ singlestore: 'singlestore',
20
+ sqlite: 'sqlite'
21
+ };
22
+ export const getDrizzleKitDialect = (databaseEngine, databaseHost) => databaseEngine === 'sqlite' && databaseHost === 'turso'
23
+ ? 'turso'
24
+ : engineKitDialects[databaseEngine];
25
+ /* The directory holding the committed initial migration for a kit dialect and
26
+ example table (users when auth is on, count_history otherwise). */
27
+ export const getMigrationTemplateName = (kitDialect, usesAuth) => `${kitDialect}-${usesAuth ? 'users' : 'count-history'}`;
@@ -127,16 +127,19 @@ export const generateDatabaseTypes = ({ databaseEngine, databaseHost, authOption
127
127
  if ((!databaseHost || databaseHost === 'none') &&
128
128
  isDrizzleDialect(databaseEngine)) {
129
129
  switch (databaseEngine) {
130
- case 'mariadb':
131
- case 'mysql':
132
- dbImport = `import type { drizzle } from 'drizzle-orm/mysql2';`;
130
+ case 'cockroachdb':
131
+ dbImport = `import type { drizzle } from 'drizzle-orm/cockroach';`;
133
132
  dbTypeLine =
134
133
  'export type DatabaseType = ReturnType<typeof drizzle>;';
135
134
  break;
135
+ case 'mariadb':
136
+ case 'mysql':
137
+ dbImport = `import type { MySql2Database } from 'drizzle-orm/mysql2';`;
138
+ dbTypeLine = 'export type DatabaseType = MySql2Database;';
139
+ break;
136
140
  case 'mssql':
137
141
  dbImport = `import type { NodeMsSqlDatabase } from 'drizzle-orm/node-mssql';`;
138
- dbTypeLine =
139
- 'export type DatabaseType = NodeMsSqlDatabase;';
142
+ dbTypeLine = 'export type DatabaseType = NodeMsSqlDatabase;';
140
143
  break;
141
144
  case 'postgresql':
142
145
  dbImport = `import type { drizzle } from 'drizzle-orm/bun-sql';`;
@@ -145,7 +148,8 @@ export const generateDatabaseTypes = ({ databaseEngine, databaseHost, authOption
145
148
  break;
146
149
  case 'singlestore':
147
150
  dbImport = `import type { SingleStoreDriverDatabase } from 'drizzle-orm/singlestore';`;
148
- dbTypeLine = 'export type DatabaseType = SingleStoreDriverDatabase;';
151
+ dbTypeLine =
152
+ 'export type DatabaseType = SingleStoreDriverDatabase;';
149
153
  break;
150
154
  case 'sqlite':
151
155
  dbImport = `import type { drizzle } from 'drizzle-orm/bun-sqlite';`;
@@ -1,2 +1,7 @@
1
1
  import { DatabaseEngine } from '../../types';
2
2
  export declare const generateDockerContainer: (databaseEngine: DatabaseEngine) => string;
3
+ export declare const getDockerInitScript: (databaseEngine: DatabaseEngine) => {
4
+ fileName: string;
5
+ mountPath: string;
6
+ sql: string;
7
+ } | undefined;
@@ -6,7 +6,9 @@ const templates = {
6
6
  },
7
7
  healthcheck: {
8
8
  startPeriod: '5s',
9
- test: 'cockroach sql --insecure -e "select 1" >/dev/null 2>&1'
9
+ /* Healthy once COCKROACH_DATABASE exists, not merely once the node
10
+ answers, so `db:up --wait` is followed safely by `db:migrate`. */
11
+ test: 'cockroach sql --insecure -e "SHOW DATABASES" 2>/dev/null | grep -q "^database"'
10
12
  },
11
13
  image: 'cockroachdb/cockroach:latest-v25.3',
12
14
  port: '26257:26257',
@@ -101,9 +103,17 @@ const templates = {
101
103
  },
102
104
  healthcheck: {
103
105
  startPeriod: '30s',
104
- test: 'singlestore -u root -ppassword -e "SELECT 1" >/dev/null 2>&1'
106
+ /* Healthy once the init script has created the database. */
107
+ test: 'singlestore -u root -ppassword -D database -e "SELECT 1" >/dev/null 2>&1'
105
108
  },
106
109
  image: 'ghcr.io/singlestore-labs/singlestoredb-dev', // NOTE: No tag specified due to data persistence
110
+ /* The dev image has no "create this database" variable; without it the
111
+ DATABASE_URL's database would not exist until something created it. */
112
+ initScript: {
113
+ fileName: 'singlestore-init.sql',
114
+ mountPath: '/init.sql',
115
+ sql: 'CREATE DATABASE IF NOT EXISTS `database`;\n'
116
+ },
107
117
  platform: 'linux/amd64', // Required for ARM64 (Apple Silicon); no-op on amd64
108
118
  port: '3306:3306',
109
119
  volumePath: '/data'
@@ -115,7 +125,10 @@ export const generateDockerContainer = (databaseEngine) => {
115
125
  databaseEngine === 'sqlite') {
116
126
  throw new Error('Internal type error: Expected a valid local database engine');
117
127
  }
118
- const { command, env, healthcheck, image, platform, port, volumePath } = templates[databaseEngine];
128
+ const { command, env, healthcheck, image, initScript, platform, port, volumePath } = templates[databaseEngine];
129
+ const initScriptLine = initScript
130
+ ? `\n - ./${initScript.fileName}:${initScript.mountPath}:ro`
131
+ : '';
119
132
  const commandLine = command ? `\n command: ${command}` : '';
120
133
  const platformLine = platform ? `\n platform: ${platform}` : '';
121
134
  const envLines = Object.entries(env)
@@ -136,9 +149,14 @@ ${envLines}
136
149
  retries: 30
137
150
  start_period: ${healthcheck.startPeriod}
138
151
  volumes:
139
- - db_data:${volumePath}
152
+ - db_data:${volumePath}${initScriptLine}
140
153
 
141
154
  volumes:
142
155
  db_data:
143
156
  `;
144
157
  };
158
+ export const getDockerInitScript = (databaseEngine) => databaseEngine === undefined ||
159
+ databaseEngine === 'none' ||
160
+ databaseEngine === 'sqlite'
161
+ ? undefined
162
+ : templates[databaseEngine].initScript;