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.
- package/CHANGELOG.md +16 -0
- package/README.md +9 -2
- package/changelog.json +24 -0
- package/dist/commands/migrateDatabase.d.ts +6 -0
- package/dist/commands/migrateDatabase.js +53 -0
- package/dist/data.d.ts +1 -1
- package/dist/data.js +1 -0
- package/dist/generators/configurations/generateDrizzleConfig.d.ts +5 -3
- package/dist/generators/configurations/generateDrizzleConfig.js +40 -14
- package/dist/generators/configurations/generateEnv.js +6 -0
- package/dist/generators/configurations/generateEslintConfig.js +1 -1
- package/dist/generators/configurations/generatePackageJson.d.ts +2 -1
- package/dist/generators/configurations/generatePackageJson.js +40 -4
- package/dist/generators/db/drizzleTargets.d.ts +5 -0
- package/dist/generators/db/drizzleTargets.js +27 -0
- package/dist/generators/db/generateDatabaseTypes.js +10 -6
- package/dist/generators/db/generateDockerContainer.d.ts +5 -0
- package/dist/generators/db/generateDockerContainer.js +22 -4
- package/dist/generators/db/generateDrizzleSchema.js +65 -81
- package/dist/generators/db/handlerTemplates.d.ts +4 -4
- package/dist/generators/db/handlerTemplates.js +7 -10
- package/dist/generators/db/scaffoldDatabase.js +31 -8
- package/dist/generators/db/scaffoldDocker.d.ts +2 -1
- package/dist/generators/db/scaffoldDocker.js +7 -3
- package/dist/generators/prisma/generatePrismaCode.d.ts +6 -0
- package/dist/generators/prisma/generatePrismaCode.js +148 -0
- package/dist/generators/prisma/generatePrismaConfig.d.ts +8 -0
- package/dist/generators/prisma/generatePrismaConfig.js +68 -0
- package/dist/generators/prisma/generatePrismaSchema.d.ts +9 -0
- package/dist/generators/prisma/generatePrismaSchema.js +80 -0
- package/dist/generators/prisma/prismaPackageJson.d.ts +8 -0
- package/dist/generators/prisma/prismaPackageJson.js +46 -0
- package/dist/generators/prisma/prismaTargets.d.ts +22 -0
- package/dist/generators/prisma/prismaTargets.js +91 -0
- package/dist/generators/prisma/scaffoldPrismaDatabase.d.ts +16 -0
- package/dist/generators/prisma/scaffoldPrismaDatabase.js +136 -0
- package/dist/generators/project/generateDBBlock.js +16 -2
- package/dist/generators/project/generateImportsBlock.js +17 -7
- package/dist/generators/project/generateServer.js +2 -1
- package/dist/index.js +2 -1
- package/dist/messages.d.ts +2 -1
- package/dist/messages.js +2 -1
- package/dist/questions/authOption.js +4 -1
- package/dist/questions/databaseEngine.d.ts +1 -1
- package/dist/questions/orm.js +5 -2
- package/dist/scaffold.d.ts +1 -0
- package/dist/scaffold.js +23 -5
- package/dist/templates/configurations/.prettierignore +2 -1
- package/dist/templates/configurations/eslint.config.example.mjs +81 -41
- package/dist/templates/db/migrations/cockroach-count-history/20260926210314_init/migration.sql +5 -0
- package/dist/templates/db/migrations/cockroach-count-history/20260926210314_init/snapshot.json +69 -0
- package/dist/templates/db/migrations/cockroach-users/20260926210315_init/migration.sql +5 -0
- package/dist/templates/db/migrations/cockroach-users/20260926210315_init/snapshot.json +62 -0
- package/dist/templates/db/migrations/mssql-count-history/20260926210316_init/migration.sql +6 -0
- package/dist/templates/db/migrations/mssql-count-history/20260926210316_init/snapshot.json +64 -0
- package/dist/templates/db/migrations/mssql-users/20260926210317_init/migration.sql +6 -0
- package/dist/templates/db/migrations/mssql-users/20260926210317_init/snapshot.json +70 -0
- package/dist/templates/db/migrations/mysql-count-history/20260926210318_init/migration.sql +5 -0
- package/dist/templates/db/migrations/mysql-count-history/20260926210318_init/snapshot.json +61 -0
- package/dist/templates/db/migrations/mysql-users/20260926210319_init/migration.sql +5 -0
- package/dist/templates/db/migrations/mysql-users/20260926210319_init/snapshot.json +61 -0
- package/dist/templates/db/migrations/postgresql-count-history/20260926210320_init/migration.sql +5 -0
- package/dist/templates/db/migrations/postgresql-count-history/20260926210320_init/snapshot.json +71 -0
- package/dist/templates/db/migrations/postgresql-users/20260926210320_init/migration.sql +5 -0
- package/dist/templates/db/migrations/postgresql-users/20260926210320_init/snapshot.json +62 -0
- package/dist/templates/db/migrations/prisma-cockroachdb-count-history/20260926000000_init/migration.sql +12 -0
- package/dist/templates/db/migrations/prisma-cockroachdb-count-history/migration_lock.toml +3 -0
- package/dist/templates/db/migrations/prisma-cockroachdb-users/20260926000000_init/migration.sql +12 -0
- package/dist/templates/db/migrations/prisma-cockroachdb-users/migration_lock.toml +3 -0
- package/dist/templates/db/migrations/prisma-mysql-count-history/20260926000000_init/migration.sql +9 -0
- package/dist/templates/db/migrations/prisma-mysql-count-history/migration_lock.toml +3 -0
- package/dist/templates/db/migrations/prisma-mysql-users/20260926000000_init/migration.sql +9 -0
- package/dist/templates/db/migrations/prisma-mysql-users/migration_lock.toml +3 -0
- package/dist/templates/db/migrations/prisma-postgresql-count-history/20260926000000_init/migration.sql +12 -0
- package/dist/templates/db/migrations/prisma-postgresql-count-history/migration_lock.toml +3 -0
- package/dist/templates/db/migrations/prisma-postgresql-users/20260926000000_init/migration.sql +12 -0
- package/dist/templates/db/migrations/prisma-postgresql-users/migration_lock.toml +3 -0
- package/dist/templates/db/migrations/prisma-sqlite-count-history/20260926000000_init/migration.sql +7 -0
- package/dist/templates/db/migrations/prisma-sqlite-count-history/migration_lock.toml +3 -0
- package/dist/templates/db/migrations/prisma-sqlite-users/20260926000000_init/migration.sql +7 -0
- package/dist/templates/db/migrations/prisma-sqlite-users/migration_lock.toml +3 -0
- package/dist/templates/db/migrations/prisma-sqlserver-count-history/20260926000000_init/migration.sql +28 -0
- package/dist/templates/db/migrations/prisma-sqlserver-count-history/migration_lock.toml +3 -0
- package/dist/templates/db/migrations/prisma-sqlserver-users/20260926000000_init/migration.sql +28 -0
- package/dist/templates/db/migrations/prisma-sqlserver-users/migration_lock.toml +3 -0
- package/dist/templates/db/migrations/singlestore-count-history/20260926210321_init/migration.sql +5 -0
- package/dist/templates/db/migrations/singlestore-count-history/20260926210321_init/snapshot.json +61 -0
- package/dist/templates/db/migrations/singlestore-users/20260926210322_init/migration.sql +5 -0
- package/dist/templates/db/migrations/singlestore-users/20260926210322_init/snapshot.json +61 -0
- package/dist/templates/db/migrations/sqlite-count-history/20260926210323_init/migration.sql +5 -0
- package/dist/templates/db/migrations/sqlite-count-history/20260926210323_init/snapshot.json +50 -0
- package/dist/templates/db/migrations/sqlite-users/20260926210324_init/migration.sql +5 -0
- package/dist/templates/db/migrations/sqlite-users/20260926210324_init/snapshot.json +50 -0
- package/dist/templates/db/migrations/turso-count-history/20260926210324_init/migration.sql +5 -0
- package/dist/templates/db/migrations/turso-count-history/20260926210324_init/snapshot.json +50 -0
- package/dist/templates/db/migrations/turso-users/20260926210325_init/migration.sql +5 -0
- package/dist/templates/db/migrations/turso-users/20260926210325_init/snapshot.json +50 -0
- package/dist/templates/git/gitignore +5 -3
- package/dist/typeGuards.d.ts +2 -2
- package/dist/typeGuards.js +2 -2
- package/dist/utils/parseCommandLineOptions.js +16 -31
- package/dist/utils/validateDatabaseSelection.d.ts +11 -0
- package/dist/utils/validateDatabaseSelection.js +34 -0
- package/dist/versions.d.ts +9 -0
- package/dist/versions.js +13 -0
- package/package.json +4 -1
- package/dist/templates/configurations/drizzle.config.ts +0 -13
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { posix } from 'path';
|
|
2
|
+
import { prismaClientDirectory } from './prismaTargets';
|
|
3
|
+
/* Mirrors the Drizzle example tables (count_history, or users with auth) so
|
|
4
|
+
both ORMs scaffold the same database. MongoDB documents are keyed by an
|
|
5
|
+
ObjectId, so the numeric `uid` the API exposes is a unique field there,
|
|
6
|
+
assigned from an atomic counter document. */
|
|
7
|
+
/* CockroachDB only autoincrements BigInt; an Int key takes a sequence, so
|
|
8
|
+
the uid stays a JavaScript number like every other engine's. Its maximum is
|
|
9
|
+
pinned to INT4's, which is what CockroachDB gives the identity column —
|
|
10
|
+
otherwise Prisma reports the migrated table as drifted from the schema. */
|
|
11
|
+
const countHistoryModel = ({ provider }) => provider === 'mongodb'
|
|
12
|
+
? `model CountHistory {
|
|
13
|
+
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
14
|
+
uid Int @unique
|
|
15
|
+
count Int
|
|
16
|
+
created_at DateTime @default(now())
|
|
17
|
+
|
|
18
|
+
@@map("count_history")
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// Hands out sequential count_history uids (MongoDB has no autoincrement).
|
|
22
|
+
model Counter {
|
|
23
|
+
id String @id @map("_id")
|
|
24
|
+
value Int
|
|
25
|
+
|
|
26
|
+
@@map("counters")
|
|
27
|
+
}`
|
|
28
|
+
: `model CountHistory {
|
|
29
|
+
uid Int @id @default(${provider === 'cockroachdb' ? 'sequence(maxValue: 2147483647)' : 'autoincrement()'})
|
|
30
|
+
count Int
|
|
31
|
+
created_at DateTime @default(now())
|
|
32
|
+
|
|
33
|
+
@@map("count_history")
|
|
34
|
+
}`;
|
|
35
|
+
/* The auth subject's column type: bounded like the Drizzle schema's
|
|
36
|
+
varchar(255) wherever the provider has a native type for it. */
|
|
37
|
+
const authSubType = {
|
|
38
|
+
cockroachdb: ' @db.String(255)',
|
|
39
|
+
mongodb: '',
|
|
40
|
+
mysql: ' @db.VarChar(255)',
|
|
41
|
+
postgresql: ' @db.VarChar(255)',
|
|
42
|
+
sqlite: '',
|
|
43
|
+
sqlserver: ' @db.NVarChar(255)'
|
|
44
|
+
};
|
|
45
|
+
/* `metadata` has no database default: Prisma renders a Json default as
|
|
46
|
+
invalid SQLite DDL, so the handlers always write it instead. */
|
|
47
|
+
const userModel = ({ provider, supportsJson }) => {
|
|
48
|
+
const metadataColumn = supportsJson
|
|
49
|
+
? 'metadata Json'
|
|
50
|
+
: 'metadata String @db.NVarChar(Max)';
|
|
51
|
+
const idColumns = provider === 'mongodb'
|
|
52
|
+
? `id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
53
|
+
auth_sub String @unique`
|
|
54
|
+
: `auth_sub String @id${authSubType[provider]}`;
|
|
55
|
+
return `model User {
|
|
56
|
+
${idColumns}
|
|
57
|
+
created_at DateTime @default(now())
|
|
58
|
+
${metadataColumn}
|
|
59
|
+
|
|
60
|
+
@@map("users")
|
|
61
|
+
}`;
|
|
62
|
+
};
|
|
63
|
+
export const generatePrismaSchema = ({ authOption, databaseDirectory, target }) => {
|
|
64
|
+
const output = posix.relative(posix.normalize(databaseDirectory), prismaClientDirectory);
|
|
65
|
+
/* Prisma 7 takes the connection URL from prisma.config.ts; Prisma 6 (the
|
|
66
|
+
MongoDB line) still reads it from the schema. */
|
|
67
|
+
const url = target.line === 'prisma6' ? '\n url = env("DATABASE_URL")' : '';
|
|
68
|
+
const model = authOption === 'abs' ? userModel(target) : countHistoryModel(target);
|
|
69
|
+
return `generator client {
|
|
70
|
+
provider = "prisma-client"
|
|
71
|
+
output = "${output}"
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
datasource db {
|
|
75
|
+
provider = "${target.provider}"${url}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
${model}
|
|
79
|
+
`;
|
|
80
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { PrismaTarget } from './prismaTargets';
|
|
2
|
+
type PrismaPackageJson = {
|
|
3
|
+
dependencies: Record<string, string>;
|
|
4
|
+
devDependencies: Record<string, string>;
|
|
5
|
+
scripts: Record<string, string>;
|
|
6
|
+
};
|
|
7
|
+
export declare const getPrismaPackageJson: (target: PrismaTarget, databaseDirectory: string) => PrismaPackageJson;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { prismaMongoDBVersion, versions } from '../../versions';
|
|
2
|
+
const migrationScripts = ({ migration }, databaseDirectory) => {
|
|
3
|
+
/* The Prisma MongoDB container is an unauthenticated single-node replica
|
|
4
|
+
set (see prismaMongoDBCompose), so its shell needs no credentials. */
|
|
5
|
+
if (migration === 'push')
|
|
6
|
+
return {
|
|
7
|
+
'db:migrate': 'prisma db push',
|
|
8
|
+
'db:mongodb': `docker compose -p mongodb -f ${databaseDirectory}/docker-compose.db.yml exec -it db mongosh database`
|
|
9
|
+
};
|
|
10
|
+
if (migration === 'libsql')
|
|
11
|
+
return {
|
|
12
|
+
'db:migrate': `bun ${databaseDirectory}/migrate.ts`,
|
|
13
|
+
'db:migrate:dev': 'prisma migrate dev'
|
|
14
|
+
};
|
|
15
|
+
return {
|
|
16
|
+
'db:migrate': 'prisma migrate deploy',
|
|
17
|
+
'db:migrate:dev': 'prisma migrate dev'
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
/* Dependencies and scripts a Prisma project adds. Versions are always the
|
|
21
|
+
pinned ones — never `--lts` resolved — because npm's `latest` dist-tag for
|
|
22
|
+
`prisma` currently points at a release candidate.
|
|
23
|
+
|
|
24
|
+
The client is generated by the project's own `postinstall` (a root package
|
|
25
|
+
script, which package managers always run) and by `db:generate`; it never
|
|
26
|
+
depends on a dependency's lifecycle script being trusted. */
|
|
27
|
+
export const getPrismaPackageJson = (target, databaseDirectory) => {
|
|
28
|
+
const version = target.line === 'prisma6' ? prismaMongoDBVersion : versions.prisma;
|
|
29
|
+
const dependencies = {
|
|
30
|
+
'@prisma/client': version
|
|
31
|
+
};
|
|
32
|
+
if (target.adapter)
|
|
33
|
+
dependencies[target.adapter.packageName] = version;
|
|
34
|
+
if (target.migration === 'libsql')
|
|
35
|
+
dependencies['@libsql/client'] = versions['@libsql/client'];
|
|
36
|
+
return {
|
|
37
|
+
dependencies,
|
|
38
|
+
devDependencies: { prisma: version },
|
|
39
|
+
scripts: {
|
|
40
|
+
'db:generate': 'prisma generate',
|
|
41
|
+
'db:studio': 'prisma studio',
|
|
42
|
+
postinstall: 'prisma generate',
|
|
43
|
+
...migrationScripts(target, databaseDirectory)
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AvailablePrismaDialect, DatabaseHost } from '../../types';
|
|
2
|
+
export declare const prismaProviders: readonly ["cockroachdb", "mongodb", "mysql", "postgresql", "sqlite", "sqlserver"];
|
|
3
|
+
export type PrismaProvider = (typeof prismaProviders)[number];
|
|
4
|
+
export type PrismaMigrationStrategy = 'libsql' | 'migrate' | 'push';
|
|
5
|
+
type PrismaAdapter = {
|
|
6
|
+
className: string;
|
|
7
|
+
expression: string;
|
|
8
|
+
packageName: string;
|
|
9
|
+
};
|
|
10
|
+
export type PrismaTarget = {
|
|
11
|
+
adapter: PrismaAdapter | undefined;
|
|
12
|
+
line: 'prisma6' | 'prisma7';
|
|
13
|
+
migration: PrismaMigrationStrategy;
|
|
14
|
+
provider: PrismaProvider;
|
|
15
|
+
supportsJson: boolean;
|
|
16
|
+
};
|
|
17
|
+
export declare const initialPrismaMigrationName = "20260926000000_init";
|
|
18
|
+
export declare const prismaClientDirectory = "src/generated/prisma";
|
|
19
|
+
export declare const getMigrationLockProvider: (provider: PrismaProvider) => "cockroachdb" | "mssql" | "mysql" | "postgresql" | "sqlite" | "mongodb";
|
|
20
|
+
export declare const getPrismaMigrationTemplateName: (provider: PrismaProvider, usesAuth: boolean) => string;
|
|
21
|
+
export declare const getPrismaTarget: (databaseEngine: AvailablePrismaDialect, databaseHost: DatabaseHost) => PrismaTarget;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/* The `provider` values a Prisma schema's datasource accepts. MariaDB has no
|
|
2
|
+
provider of its own: Prisma drives it as MySQL. */
|
|
3
|
+
export const prismaProviders = [
|
|
4
|
+
'cockroachdb',
|
|
5
|
+
'mongodb',
|
|
6
|
+
'mysql',
|
|
7
|
+
'postgresql',
|
|
8
|
+
'sqlite',
|
|
9
|
+
'sqlserver'
|
|
10
|
+
];
|
|
11
|
+
const databaseUrl = "getEnv('DATABASE_URL')";
|
|
12
|
+
const pgAdapter = {
|
|
13
|
+
className: 'PrismaPg',
|
|
14
|
+
expression: `new PrismaPg({ connectionString: ${databaseUrl} })`,
|
|
15
|
+
packageName: '@prisma/adapter-pg'
|
|
16
|
+
};
|
|
17
|
+
const mariadbAdapter = {
|
|
18
|
+
className: 'PrismaMariaDb',
|
|
19
|
+
expression: `new PrismaMariaDb(${databaseUrl})`,
|
|
20
|
+
packageName: '@prisma/adapter-mariadb'
|
|
21
|
+
};
|
|
22
|
+
/* A local libSQL `file:` URL needs no token; a Turso database does. */
|
|
23
|
+
const libsqlAdapter = {
|
|
24
|
+
className: 'PrismaLibSql',
|
|
25
|
+
expression: `new PrismaLibSql({ authToken: env.DATABASE_AUTH_TOKEN, url: ${databaseUrl} })`,
|
|
26
|
+
packageName: '@prisma/adapter-libsql'
|
|
27
|
+
};
|
|
28
|
+
const sqlTarget = (provider, adapter) => ({
|
|
29
|
+
adapter,
|
|
30
|
+
line: 'prisma7',
|
|
31
|
+
migration: 'migrate',
|
|
32
|
+
provider,
|
|
33
|
+
supportsJson: provider !== 'sqlserver'
|
|
34
|
+
});
|
|
35
|
+
const getPostgresqlTarget = (databaseHost) => {
|
|
36
|
+
if (databaseHost !== 'neon')
|
|
37
|
+
return sqlTarget('postgresql', pgAdapter);
|
|
38
|
+
return sqlTarget('postgresql', {
|
|
39
|
+
className: 'PrismaNeon',
|
|
40
|
+
expression: `new PrismaNeon({ connectionString: ${databaseUrl} })`,
|
|
41
|
+
packageName: '@prisma/adapter-neon'
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
const getMysqlTarget = (databaseHost) => {
|
|
45
|
+
if (databaseHost !== 'planetscale')
|
|
46
|
+
return sqlTarget('mysql', mariadbAdapter);
|
|
47
|
+
return sqlTarget('mysql', {
|
|
48
|
+
className: 'PrismaPlanetScale',
|
|
49
|
+
expression: `new PrismaPlanetScale({ url: ${databaseUrl} })`,
|
|
50
|
+
packageName: '@prisma/adapter-planetscale'
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
const engineTargets = {
|
|
54
|
+
mysql: getMysqlTarget,
|
|
55
|
+
postgresql: getPostgresqlTarget,
|
|
56
|
+
cockroachdb: () => sqlTarget('cockroachdb', pgAdapter),
|
|
57
|
+
mariadb: () => sqlTarget('mysql', mariadbAdapter),
|
|
58
|
+
mongodb: () => ({
|
|
59
|
+
adapter: undefined,
|
|
60
|
+
line: 'prisma6',
|
|
61
|
+
migration: 'push',
|
|
62
|
+
provider: 'mongodb',
|
|
63
|
+
supportsJson: true
|
|
64
|
+
}),
|
|
65
|
+
mssql: () => sqlTarget('sqlserver', {
|
|
66
|
+
className: 'PrismaMssql',
|
|
67
|
+
expression: `new PrismaMssql(${databaseUrl})`,
|
|
68
|
+
packageName: '@prisma/adapter-mssql'
|
|
69
|
+
}),
|
|
70
|
+
sqlite: (databaseHost) => ({
|
|
71
|
+
...sqlTarget('sqlite', libsqlAdapter),
|
|
72
|
+
migration: databaseHost === 'turso' ? 'libsql' : 'migrate'
|
|
73
|
+
})
|
|
74
|
+
};
|
|
75
|
+
/* The initial migration's directory name, in Prisma Migrate's
|
|
76
|
+
`<timestamp>_<name>` format. */
|
|
77
|
+
export const initialPrismaMigrationName = '20260926000000_init';
|
|
78
|
+
/* Where `prisma generate` writes the client, relative to the project root.
|
|
79
|
+
Fixed (independent of --db-dir) so server, handlers and types import it by
|
|
80
|
+
a stable path. It is build output: ignored by git, ESLint and Prettier. */
|
|
81
|
+
export const prismaClientDirectory = 'src/generated/prisma';
|
|
82
|
+
/* The value Prisma Migrate records in migrations/migration_lock.toml. Prisma 7
|
|
83
|
+
names SQL Server `mssql` there, not by its schema provider name. */
|
|
84
|
+
export const getMigrationLockProvider = (provider) => provider === 'sqlserver' ? 'mssql' : provider;
|
|
85
|
+
/* The directory holding the committed initial migration for a provider and
|
|
86
|
+
example table (users when auth is on, count_history otherwise). */
|
|
87
|
+
export const getPrismaMigrationTemplateName = (provider, usesAuth) => `prisma-${provider}-${usesAuth ? 'users' : 'count-history'}`;
|
|
88
|
+
/* Resolves the provider, driver adapter and migration strategy for an
|
|
89
|
+
engine/host pair. Hosts are validated beforehand (validateDatabaseSelection),
|
|
90
|
+
so PlanetScale Postgres is plain Postgres over `pg` here. */
|
|
91
|
+
export const getPrismaTarget = (databaseEngine, databaseHost) => engineTargets[databaseEngine](databaseHost);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { AuthOption, DatabaseEngine, DatabaseHost } from '../../types';
|
|
2
|
+
import { type PrismaTarget } from './prismaTargets';
|
|
3
|
+
type ScaffoldPrismaDatabaseProps = {
|
|
4
|
+
authOption: AuthOption;
|
|
5
|
+
backendDirectory: string;
|
|
6
|
+
databaseDirectory: string;
|
|
7
|
+
databaseEngine: DatabaseEngine;
|
|
8
|
+
databaseHost: DatabaseHost;
|
|
9
|
+
projectName: string;
|
|
10
|
+
typesDirectory: string;
|
|
11
|
+
verifyLocalDatabase: boolean;
|
|
12
|
+
};
|
|
13
|
+
export declare const prismaMongoDBCompose = "services:\n db:\n image: mongo:7.0\n restart: always\n command: [\"--replSet\", \"rs0\", \"--bind_ip_all\"]\n ports:\n - \"27017:27017\"\n healthcheck:\n test: [\"CMD-SHELL\", \"mongosh --quiet --eval \\\"try { if (rs.status().myState !== 1) quit(1) } catch (error) { rs.initiate({ _id: 'rs0', members: [{ _id: 0, host: 'localhost:27017' }] }); quit(1) }\\\"\"]\n interval: 2s\n timeout: 5s\n retries: 30\n start_period: 5s\n volumes:\n - db_data:/data/db\n\nvolumes:\n db_data:\n";
|
|
14
|
+
export declare const getPrismaLocalDatabaseUrl: (target: PrismaTarget, databaseDirectory: string, databaseHost: DatabaseHost) => string | undefined;
|
|
15
|
+
export declare const scaffoldPrismaDatabase: ({ authOption, backendDirectory, databaseDirectory, databaseEngine, databaseHost, projectName, typesDirectory, verifyLocalDatabase }: ScaffoldPrismaDatabaseProps) => Promise<boolean>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { cpSync, existsSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { dirname, join } from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { spinner } from '@clack/prompts';
|
|
5
|
+
import { $ } from 'bun';
|
|
6
|
+
import { green, red } from 'picocolors';
|
|
7
|
+
import { isPrismaDialect } from '../../typeGuards';
|
|
8
|
+
import { checkDockerInstalled, ensureDockerDaemonRunning, resolveDockerExe, shutdownDockerDaemon } from '../../utils/checkDockerInstalled';
|
|
9
|
+
import { scaffoldDocker } from '../db/scaffoldDocker';
|
|
10
|
+
import { generatePrismaDatabaseTypes, generatePrismaHandlers } from './generatePrismaCode';
|
|
11
|
+
import { generateLibsqlMigrateScript, generatePrismaConfig } from './generatePrismaConfig';
|
|
12
|
+
import { generatePrismaSchema } from './generatePrismaSchema';
|
|
13
|
+
import { getPrismaMigrationTemplateName, getPrismaTarget } from './prismaTargets';
|
|
14
|
+
/* Prisma requires MongoDB to run as a replica set (it writes through
|
|
15
|
+
transactions). A single-node set is initiated by the healthcheck itself,
|
|
16
|
+
which only passes once the node is PRIMARY — so `db:up --wait` is followed
|
|
17
|
+
safely by `db:migrate`. */
|
|
18
|
+
export const prismaMongoDBCompose = `services:
|
|
19
|
+
db:
|
|
20
|
+
image: mongo:7.0
|
|
21
|
+
restart: always
|
|
22
|
+
command: ["--replSet", "rs0", "--bind_ip_all"]
|
|
23
|
+
ports:
|
|
24
|
+
- "27017:27017"
|
|
25
|
+
healthcheck:
|
|
26
|
+
test: ["CMD-SHELL", "mongosh --quiet --eval \\"try { if (rs.status().myState !== 1) quit(1) } catch (error) { rs.initiate({ _id: 'rs0', members: [{ _id: 0, host: 'localhost:27017' }] }); quit(1) }\\""]
|
|
27
|
+
interval: 2s
|
|
28
|
+
timeout: 5s
|
|
29
|
+
retries: 30
|
|
30
|
+
start_period: 5s
|
|
31
|
+
volumes:
|
|
32
|
+
- db_data:/data/db
|
|
33
|
+
|
|
34
|
+
volumes:
|
|
35
|
+
db_data:
|
|
36
|
+
`;
|
|
37
|
+
/* The local DATABASE_URL a Prisma project starts with, where it differs from
|
|
38
|
+
the no-ORM default generateEnv writes: SQLite needs a URL at all (the libSQL
|
|
39
|
+
adapter and Prisma Migrate both take one), MongoDB is the unauthenticated
|
|
40
|
+
replica set above, SQL Server uses Prisma's `sqlserver://` format and
|
|
41
|
+
MariaDB the `mysql://` scheme. */
|
|
42
|
+
export const getPrismaLocalDatabaseUrl = (target, databaseDirectory, databaseHost) => {
|
|
43
|
+
const isLocal = databaseHost === undefined || databaseHost === 'none';
|
|
44
|
+
if (!isLocal)
|
|
45
|
+
return undefined;
|
|
46
|
+
switch (target.provider) {
|
|
47
|
+
case 'mongodb':
|
|
48
|
+
return 'mongodb://localhost:27017/database?replicaSet=rs0&directConnection=true';
|
|
49
|
+
/* MariaDB too: Prisma Migrate only accepts the mysql:// scheme, and the
|
|
50
|
+
mariadb driver adapter takes it as well. */
|
|
51
|
+
case 'mysql':
|
|
52
|
+
return 'mysql://user:userpassword@localhost:3306/database';
|
|
53
|
+
case 'sqlite':
|
|
54
|
+
return `file:./${databaseDirectory}/database.sqlite`;
|
|
55
|
+
case 'sqlserver':
|
|
56
|
+
return 'sqlserver://localhost:1433;database=master;user=sa;password=SApassword1;encrypt=true;trustServerCertificate=true';
|
|
57
|
+
default:
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
/* Sets DATABASE_URL in the project's own .env, keeping every other line. */
|
|
62
|
+
const setProjectDatabaseUrl = (projectName, url) => {
|
|
63
|
+
const envPath = join(projectName, '.env');
|
|
64
|
+
const lines = existsSync(envPath)
|
|
65
|
+
? readFileSync(envPath, 'utf8')
|
|
66
|
+
.split('\n')
|
|
67
|
+
.filter((line) => !line.startsWith('DATABASE_URL='))
|
|
68
|
+
: [];
|
|
69
|
+
writeFileSync(envPath, [...lines, `DATABASE_URL=${url}`].join('\n'));
|
|
70
|
+
};
|
|
71
|
+
const verifyMongoDBContainer = async (projectName, databaseDirectory) => {
|
|
72
|
+
const { freshInstall } = await checkDockerInstalled('mongodb');
|
|
73
|
+
const { daemonWasStarted } = await ensureDockerDaemonRunning();
|
|
74
|
+
const docker = resolveDockerExe();
|
|
75
|
+
const compose = [
|
|
76
|
+
'compose',
|
|
77
|
+
'-p',
|
|
78
|
+
'mongodb',
|
|
79
|
+
'-f',
|
|
80
|
+
`${databaseDirectory}/docker-compose.db.yml`
|
|
81
|
+
];
|
|
82
|
+
const spin = spinner();
|
|
83
|
+
spin.start('Starting mongodb replica set');
|
|
84
|
+
try {
|
|
85
|
+
await $ `${docker} ${compose} up -d --wait db`.cwd(projectName).quiet();
|
|
86
|
+
await $ `${docker} ${compose} down`.cwd(projectName).quiet();
|
|
87
|
+
spin.stop(green('Docker container verified'));
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
spin.cancel(red('Docker setup failed'));
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
if (daemonWasStarted)
|
|
94
|
+
await shutdownDockerDaemon();
|
|
95
|
+
return freshInstall;
|
|
96
|
+
};
|
|
97
|
+
const templatesDirectory = () => join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'templates');
|
|
98
|
+
/* Scaffolds a Prisma project's database layer: schema, prisma.config.ts, the
|
|
99
|
+
committed initial migration, typed handlers and types, local .env URL and
|
|
100
|
+
the Docker database. Everything is written under `projectName`. */
|
|
101
|
+
export const scaffoldPrismaDatabase = async ({ authOption, backendDirectory, databaseDirectory, databaseEngine, databaseHost, projectName, typesDirectory, verifyLocalDatabase }) => {
|
|
102
|
+
if (!isPrismaDialect(databaseEngine))
|
|
103
|
+
throw new Error(`Internal type error: "${databaseEngine}" is not a Prisma database`);
|
|
104
|
+
const target = getPrismaTarget(databaseEngine, databaseHost);
|
|
105
|
+
const projectDatabaseDirectory = join(projectName, databaseDirectory);
|
|
106
|
+
const usesAuth = authOption === 'abs';
|
|
107
|
+
writeFileSync(join(projectDatabaseDirectory, 'schema.prisma'), generatePrismaSchema({ authOption, databaseDirectory, target }));
|
|
108
|
+
writeFileSync(join(projectName, 'prisma.config.ts'), generatePrismaConfig({ databaseDirectory, target }));
|
|
109
|
+
if (target.provider !== 'mongodb')
|
|
110
|
+
cpSync(join(templatesDirectory(), 'db', 'migrations', getPrismaMigrationTemplateName(target.provider, usesAuth)), join(projectDatabaseDirectory, 'migrations'), { recursive: true });
|
|
111
|
+
if (target.migration === 'libsql')
|
|
112
|
+
writeFileSync(join(projectDatabaseDirectory, 'migrate.ts'), generateLibsqlMigrateScript());
|
|
113
|
+
writeFileSync(join(backendDirectory, 'handlers', usesAuth ? 'userHandlers.ts' : 'countHistoryHandlers.ts'), generatePrismaHandlers(authOption, target));
|
|
114
|
+
writeFileSync(join(typesDirectory, 'databaseTypes.ts'), generatePrismaDatabaseTypes(authOption, target));
|
|
115
|
+
const localUrl = getPrismaLocalDatabaseUrl(target, databaseDirectory, databaseHost);
|
|
116
|
+
if (localUrl)
|
|
117
|
+
setProjectDatabaseUrl(projectName, localUrl);
|
|
118
|
+
const isLocal = databaseHost === undefined || databaseHost === 'none';
|
|
119
|
+
if (!isLocal || target.provider === 'sqlite')
|
|
120
|
+
return false;
|
|
121
|
+
if (target.provider === 'mongodb') {
|
|
122
|
+
writeFileSync(join(projectDatabaseDirectory, 'docker-compose.db.yml'), prismaMongoDBCompose);
|
|
123
|
+
return (verifyLocalDatabase &&
|
|
124
|
+
verifyMongoDBContainer(projectName, databaseDirectory));
|
|
125
|
+
}
|
|
126
|
+
/* Migrations own the schema, so the container is only verified. */
|
|
127
|
+
const { dockerFreshInstall } = await scaffoldDocker({
|
|
128
|
+
authOption,
|
|
129
|
+
databaseEngine,
|
|
130
|
+
initializeSchema: false,
|
|
131
|
+
projectDatabaseDirectory,
|
|
132
|
+
projectName,
|
|
133
|
+
verifyLocalDatabase
|
|
134
|
+
});
|
|
135
|
+
return dockerFreshInstall;
|
|
136
|
+
};
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { availableDrizzleDialects } from '../../data';
|
|
2
|
+
import { isPrismaDialect } from '../../typeGuards';
|
|
3
|
+
import { generatePrismaDBBlock } from '../prisma/generatePrismaCode';
|
|
4
|
+
import { getPrismaTarget } from '../prisma/prismaTargets';
|
|
5
|
+
/* A Turso database needs its auth token; a local libSQL `file:` URL has none,
|
|
6
|
+
so the token stays optional. */
|
|
7
|
+
const tursoClient = 'createClient({ authToken: env.DATABASE_AUTH_TOKEN, url: getEnv("DATABASE_URL") })';
|
|
2
8
|
const connectionMap = {
|
|
3
9
|
cockroachdb: {
|
|
4
10
|
none: { expr: 'new SQL(getEnv("DATABASE_URL"))' }
|
|
@@ -36,19 +42,21 @@ const connectionMap = {
|
|
|
36
42
|
},
|
|
37
43
|
sqlite: {
|
|
38
44
|
none: { expr: 'new Database("db/database.sqlite")' },
|
|
39
|
-
turso: { expr:
|
|
45
|
+
turso: { expr: tursoClient }
|
|
40
46
|
}
|
|
41
47
|
};
|
|
42
48
|
const remoteDrizzleInit = {
|
|
43
49
|
neon: 'neon(getEnv("DATABASE_URL"));',
|
|
44
50
|
planetscale: 'new Client({ url: getEnv("DATABASE_URL") })',
|
|
45
|
-
turso:
|
|
51
|
+
turso: tursoClient
|
|
46
52
|
};
|
|
47
53
|
const drizzleDialectSet = new Set([...availableDrizzleDialects]);
|
|
48
54
|
export const generateDBBlock = ({ databaseEngine, orm, databaseHost }) => {
|
|
49
55
|
if (!databaseEngine || databaseEngine === 'none') {
|
|
50
56
|
throw new Error('Internal type error: Expected a valid database engine');
|
|
51
57
|
}
|
|
58
|
+
if (orm === 'prisma' && isPrismaDialect(databaseEngine))
|
|
59
|
+
return generatePrismaDBBlock(getPrismaTarget(databaseEngine, databaseHost));
|
|
52
60
|
const hostKey = databaseHost ?? 'none';
|
|
53
61
|
const engineGroup = connectionMap[databaseEngine];
|
|
54
62
|
if (!engineGroup)
|
|
@@ -67,6 +75,12 @@ export const generateDBBlock = ({ databaseEngine, orm, databaseHost }) => {
|
|
|
67
75
|
return `
|
|
68
76
|
const pool = createPool(getEnv("DATABASE_URL"))
|
|
69
77
|
const db = drizzle({ client: pool })
|
|
78
|
+
`;
|
|
79
|
+
}
|
|
80
|
+
if (databaseEngine === 'cockroachdb') {
|
|
81
|
+
return `
|
|
82
|
+
const pool = new Pool({ connectionString: getEnv("DATABASE_URL") })
|
|
83
|
+
const db = drizzle({ client: pool })
|
|
70
84
|
`;
|
|
71
85
|
}
|
|
72
86
|
if (databaseEngine === 'mssql' && hostKey === 'none') {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { isDrizzleDialect } from '../../typeGuards';
|
|
1
|
+
import { isDrizzleDialect, isPrismaDialect } from '../../typeGuards';
|
|
2
|
+
import { getPrismaServerImports } from '../prisma/generatePrismaCode';
|
|
3
|
+
import { getPrismaTarget } from '../prisma/prismaTargets';
|
|
2
4
|
export const generateImportsBlock = ({ deps, flags, orm, authOption, databaseEngine, databaseHost, frontendDirectories }) => {
|
|
3
5
|
const rawImports = [];
|
|
4
6
|
const pushHandler = (cond, name, pkg = '@absolutejs/absolute') => cond && rawImports.push(`import { ${name} } from '${pkg}'`);
|
|
@@ -42,7 +44,10 @@ export const generateImportsBlock = ({ deps, flags, orm, authOption, databaseEng
|
|
|
42
44
|
const connectorImports = {
|
|
43
45
|
neon: [`import { neon } from '@neondatabase/serverless'`],
|
|
44
46
|
planetscale: [`import { Client } from '@planetscale/database'`],
|
|
45
|
-
turso: [
|
|
47
|
+
turso: [
|
|
48
|
+
`import { createClient } from '@libsql/client'`,
|
|
49
|
+
`import { env } from 'bun'`
|
|
50
|
+
]
|
|
46
51
|
};
|
|
47
52
|
const dialectImports = {
|
|
48
53
|
neon: [`import { drizzle } from 'drizzle-orm/neon-http'`],
|
|
@@ -77,13 +82,15 @@ export const generateImportsBlock = ({ deps, flags, orm, authOption, databaseEng
|
|
|
77
82
|
};
|
|
78
83
|
const ormDatabaseImports = {
|
|
79
84
|
drizzle: {
|
|
80
|
-
|
|
81
|
-
`import {
|
|
82
|
-
`import {
|
|
85
|
+
cockroachdb: [
|
|
86
|
+
`import { drizzle } from 'drizzle-orm/cockroach'`,
|
|
87
|
+
`import { Pool } from 'pg'`
|
|
83
88
|
],
|
|
89
|
+
/* drizzle-orm/mysql2 1.0 sets options on the pool's `config`, which
|
|
90
|
+
only mysql2's callback pool has; it wraps it in .promise() itself. */
|
|
84
91
|
mariadb: [
|
|
85
92
|
`import { drizzle } from 'drizzle-orm/mysql2'`,
|
|
86
|
-
`import { createPool } from 'mysql2
|
|
93
|
+
`import { createPool } from 'mysql2'`
|
|
87
94
|
],
|
|
88
95
|
mssql: [
|
|
89
96
|
`import { connect } from 'mssql'`,
|
|
@@ -92,7 +99,7 @@ export const generateImportsBlock = ({ deps, flags, orm, authOption, databaseEng
|
|
|
92
99
|
mysql: !isRemoteHost
|
|
93
100
|
? [
|
|
94
101
|
`import { drizzle } from 'drizzle-orm/mysql2'`,
|
|
95
|
-
`import { createPool } from 'mysql2
|
|
102
|
+
`import { createPool } from 'mysql2'`
|
|
96
103
|
]
|
|
97
104
|
: [],
|
|
98
105
|
postgresql: getPostgresqlOrmDatabaseImports(),
|
|
@@ -180,6 +187,9 @@ export const generateImportsBlock = ({ deps, flags, orm, authOption, databaseEng
|
|
|
180
187
|
if (orm === 'drizzle' && isDrizzleDialect(databaseEngine)) {
|
|
181
188
|
rawImports.push(...ormDatabaseImports[orm][databaseEngine]);
|
|
182
189
|
}
|
|
190
|
+
if (orm === 'prisma' && isPrismaDialect(databaseEngine)) {
|
|
191
|
+
rawImports.push(...getPrismaServerImports(getPrismaTarget(databaseEngine, databaseHost)));
|
|
192
|
+
}
|
|
183
193
|
if (noOrm && hasDatabase && noOrmImports[databaseEngine]) {
|
|
184
194
|
rawImports.push(...noOrmImports[databaseEngine]);
|
|
185
195
|
}
|
|
@@ -34,7 +34,8 @@ export const generateServerFile = ({ tailwind, authOption, plugins, buildDirecto
|
|
|
34
34
|
const useBlock = deps
|
|
35
35
|
.flatMap((dependency) => dependency.imports ?? [])
|
|
36
36
|
.filter((pluginImport) => pluginImport.isPlugin &&
|
|
37
|
-
pluginImport.packageName !== 'networking' &&
|
|
37
|
+
pluginImport.packageName !== 'networking' &&
|
|
38
|
+
pluginImport.packageName !== 'openapi')
|
|
38
39
|
.map((pluginImport) => {
|
|
39
40
|
if (pluginImport.packageName === 'auth') {
|
|
40
41
|
return 'authPlugin';
|
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ if (help === true) {
|
|
|
14
14
|
exit(0);
|
|
15
15
|
}
|
|
16
16
|
const response = await prompt(argumentConfiguration);
|
|
17
|
-
const { dockerFreshInstall } = await scaffold({
|
|
17
|
+
const { databaseMigrationPending, dockerFreshInstall } = await scaffold({
|
|
18
18
|
envVariables,
|
|
19
19
|
latest,
|
|
20
20
|
packageManager,
|
|
@@ -27,6 +27,7 @@ const debugMessage = debug !== false
|
|
|
27
27
|
})
|
|
28
28
|
: '';
|
|
29
29
|
const outroMessage = getOutroMessage({
|
|
30
|
+
databaseMigrationPending,
|
|
30
31
|
installDependenciesNow: response.installDependenciesNow,
|
|
31
32
|
packageManager,
|
|
32
33
|
projectName: response.projectName
|
package/dist/messages.d.ts
CHANGED
|
@@ -4,8 +4,9 @@ type OutroMessageProps = {
|
|
|
4
4
|
projectName: string;
|
|
5
5
|
packageManager: string;
|
|
6
6
|
installDependenciesNow: boolean;
|
|
7
|
+
databaseMigrationPending: boolean;
|
|
7
8
|
};
|
|
8
|
-
export declare const getOutroMessage: ({ projectName, packageManager, installDependenciesNow }: OutroMessageProps) => string;
|
|
9
|
+
export declare const getOutroMessage: ({ databaseMigrationPending, projectName, packageManager, installDependenciesNow }: OutroMessageProps) => string;
|
|
9
10
|
type DebugMessageProps = {
|
|
10
11
|
response: CreateConfiguration;
|
|
11
12
|
packageManager: string;
|
package/dist/messages.js
CHANGED
|
@@ -46,9 +46,10 @@ Options:
|
|
|
46
46
|
${cyan('--vue')} Include a Vue frontend
|
|
47
47
|
${cyan('--vue-dir')} ${dim(cyan('<directory>'))} Specify the directory for and use the Vue frontend
|
|
48
48
|
`;
|
|
49
|
-
export const getOutroMessage = ({ projectName, packageManager, installDependenciesNow }) => `${green('Created successfully')}, you can now run:\n\n` +
|
|
49
|
+
export const getOutroMessage = ({ databaseMigrationPending, projectName, packageManager, installDependenciesNow }) => `${green('Created successfully')}, you can now run:\n\n` +
|
|
50
50
|
`${cyan('cd')} ${projectName}\n` +
|
|
51
51
|
`${installDependenciesNow ? '' : `${cyan(`${packageManager} install`)}\n`}` +
|
|
52
|
+
`${databaseMigrationPending ? `${cyan(`${packageManager} run db:migrate`)}\n` : ''}` +
|
|
52
53
|
`${cyan(`${packageManager} dev`)}`; // TODO: Some package managers need run
|
|
53
54
|
export const getDebugMessage = ({ response: { agentic, projectName, codeQualityTool, directoryConfig, useTailwind, tailwind, frontends, includeExamples, useHTMLScripts, frontendDirectories, buildDirectory, assetsDirectory, databaseEngine, databaseHost, databaseDirectory, orm, authOption, plugins, initializeGitNow, installDependenciesNow }, packageManager }) => {
|
|
54
55
|
const htmlScriptingValue = useHTMLScripts
|
|
@@ -6,7 +6,10 @@ export const getAuthOption = async () => {
|
|
|
6
6
|
message: 'Auth provider:',
|
|
7
7
|
options: [
|
|
8
8
|
{ label: 'None', value: 'none' },
|
|
9
|
-
{
|
|
9
|
+
{
|
|
10
|
+
label: cyan('Absolute Auth (Google; requires a database)'),
|
|
11
|
+
value: 'abs'
|
|
12
|
+
}
|
|
10
13
|
]
|
|
11
14
|
});
|
|
12
15
|
if (isCancel(authOption))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const getDatabaseEngine: () => Promise<"mariadb" | "mssql" | "mysql" | "postgresql" | "singlestore" | "sqlite" | "mongodb" | "
|
|
1
|
+
export declare const getDatabaseEngine: () => Promise<"cockroachdb" | "mariadb" | "mssql" | "mysql" | "postgresql" | "singlestore" | "sqlite" | "mongodb" | "gel" | undefined>;
|
package/dist/questions/orm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { select, isCancel } from '@clack/prompts';
|
|
2
|
-
import { cyan } from 'picocolors';
|
|
3
|
-
import { isDrizzleDialect } from '../typeGuards';
|
|
2
|
+
import { cyan, magenta } from 'picocolors';
|
|
3
|
+
import { isDrizzleDialect, isPrismaDialect } from '../typeGuards';
|
|
4
4
|
import { abort } from '../utils/abort';
|
|
5
5
|
export const getORM = async (databaseEngine) => {
|
|
6
6
|
const options = [
|
|
@@ -9,6 +9,9 @@ export const getORM = async (databaseEngine) => {
|
|
|
9
9
|
if (isDrizzleDialect(databaseEngine)) {
|
|
10
10
|
options.push({ label: cyan('Drizzle'), value: 'drizzle' });
|
|
11
11
|
}
|
|
12
|
+
if (isPrismaDialect(databaseEngine)) {
|
|
13
|
+
options.push({ label: magenta('Prisma'), value: 'prisma' });
|
|
14
|
+
}
|
|
12
15
|
const orm = await select({
|
|
13
16
|
message: 'Choose an ORM for your database:',
|
|
14
17
|
options
|
package/dist/scaffold.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ type ScaffoldProps = {
|
|
|
7
7
|
verifyLocalDatabase?: boolean;
|
|
8
8
|
};
|
|
9
9
|
export declare const scaffold: ({ response: { agentic, projectName, codeQualityTool, initializeGitNow, githubLink, githubRepoUrl, githubVisibility, databaseEngine, databaseHost, useHTMLScripts, useTailwind, databaseDirectory, absProviders, includeExamples, orm, frontends, plugins, authOption, buildDirectory, assetsDirectory, tailwind, installDependenciesNow, frontendDirectories }, latest, verifyLocalDatabase, envVariables, packageManager }: ScaffoldProps) => Promise<{
|
|
10
|
+
databaseMigrationPending: boolean;
|
|
10
11
|
dockerFreshInstall: boolean;
|
|
11
12
|
}>;
|
|
12
13
|
export {};
|