create-absolutejs 0.4.2 → 0.5.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/dist/data.d.ts +2 -1
- package/dist/data.js +48 -1
- package/dist/generators/configurations/generateEnv.js +6 -6
- package/dist/generators/configurations/generatePackageJson.js +68 -30
- package/dist/generators/configurations/initializeRoot.d.ts +1 -0
- package/dist/generators/configurations/initializeRoot.js +8 -2
- package/dist/generators/db/dockerInitTemplates.d.ts +13 -13
- package/dist/generators/db/dockerInitTemplates.js +39 -22
- package/dist/generators/db/generateDatabaseTypes.d.ts +8 -0
- package/dist/generators/db/generateDatabaseTypes.js +62 -0
- package/dist/generators/db/generateDockerContainer.js +13 -13
- package/dist/generators/db/generateDrizzleSchema.d.ts +2 -3
- package/dist/generators/db/generateDrizzleSchema.js +17 -27
- package/dist/generators/db/handlerTemplates.d.ts +28 -18
- package/dist/generators/db/handlerTemplates.js +157 -115
- package/dist/generators/db/scaffoldDatabase.d.ts +2 -1
- package/dist/generators/db/scaffoldDatabase.js +9 -3
- package/dist/generators/project/generateDBBlock.js +13 -21
- package/dist/generators/project/generateImportsBlock.js +101 -32
- package/dist/generators/project/generateUseBlock.js +5 -1
- package/dist/questions/databaseEngine.d.ts +1 -1
- package/dist/scaffold.js +3 -2
- package/package.json +1 -1
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
const DIALECTS = {
|
|
2
2
|
gel: {
|
|
3
|
-
builders: ['text', 'gelTable', 'timestamp', 'integer'],
|
|
4
|
-
json: '
|
|
3
|
+
builders: ['text', 'gelTable', 'timestamp', 'integer', 'json'],
|
|
4
|
+
json: 'json()',
|
|
5
5
|
pkg: 'gel-core',
|
|
6
6
|
string: 'text()',
|
|
7
7
|
table: 'gelTable',
|
|
8
8
|
time: 'timestamp()'
|
|
9
9
|
},
|
|
10
|
+
mariadb: {
|
|
11
|
+
builders: ['json', 'mysqlTable', 'timestamp', 'varchar', 'int'],
|
|
12
|
+
json: 'json()',
|
|
13
|
+
pkg: 'mysql-core',
|
|
14
|
+
string: 'varchar({ length: 255 })',
|
|
15
|
+
table: 'mysqlTable',
|
|
16
|
+
time: 'timestamp()'
|
|
17
|
+
},
|
|
10
18
|
mysql: {
|
|
11
19
|
builders: ['json', 'mysqlTable', 'timestamp', 'varchar', 'int'],
|
|
12
20
|
json: 'json()',
|
|
@@ -41,9 +49,11 @@ const DIALECTS = {
|
|
|
41
49
|
}
|
|
42
50
|
};
|
|
43
51
|
const builder = (expr) => expr.split('(')[0];
|
|
44
|
-
export const generateDrizzleSchema = ({ databaseEngine,
|
|
52
|
+
export const generateDrizzleSchema = ({ databaseEngine, authProvider }) => {
|
|
45
53
|
const cfg = DIALECTS[databaseEngine];
|
|
46
|
-
const intBuilder = databaseEngine === 'mysql' ||
|
|
54
|
+
const intBuilder = databaseEngine === 'mysql' ||
|
|
55
|
+
databaseEngine === 'singlestore' ||
|
|
56
|
+
databaseEngine === 'mariadb'
|
|
47
57
|
? 'int'
|
|
48
58
|
: 'integer';
|
|
49
59
|
const timeBuilder = builder(cfg.time);
|
|
@@ -57,23 +67,10 @@ export const generateDrizzleSchema = ({ databaseEngine, databaseHost, authProvid
|
|
|
57
67
|
const sqliteImports = databaseEngine === 'sqlite'
|
|
58
68
|
? `import { sql } from 'drizzle-orm';\n`
|
|
59
69
|
: '';
|
|
60
|
-
let dbImport = '';
|
|
61
|
-
let dbTypeLine = '';
|
|
62
|
-
if (databaseHost === 'neon') {
|
|
63
|
-
dbImport = `import { NeonHttpDatabase } from 'drizzle-orm/neon-http';`;
|
|
64
|
-
dbTypeLine = 'export type DatabaseType = NeonHttpDatabase<SchemaType>;';
|
|
65
|
-
}
|
|
66
|
-
else if (databaseHost === 'planetscale') {
|
|
67
|
-
dbImport = `import { PlanetScaleDatabase } from 'drizzle-orm/planetscale-serverless';`;
|
|
68
|
-
dbTypeLine =
|
|
69
|
-
'export type DatabaseType = PlanetScaleDatabase<SchemaType>;';
|
|
70
|
-
}
|
|
71
|
-
else if (databaseHost === 'turso') {
|
|
72
|
-
dbImport = `import { LibSQLDatabase } from 'drizzle-orm/libsql';`;
|
|
73
|
-
dbTypeLine = 'export type DatabaseType = LibSQLDatabase<SchemaType>;';
|
|
74
|
-
}
|
|
75
70
|
let uidColumn;
|
|
76
|
-
if (databaseEngine === 'mysql' ||
|
|
71
|
+
if (databaseEngine === 'mysql' ||
|
|
72
|
+
databaseEngine === 'singlestore' ||
|
|
73
|
+
databaseEngine === 'mariadb') {
|
|
77
74
|
uidColumn = `${intBuilder}('uid').primaryKey().autoincrement()`;
|
|
78
75
|
}
|
|
79
76
|
else if (databaseEngine === 'sqlite') {
|
|
@@ -101,14 +98,8 @@ const MILLIS_PER_DAY = 86400000;\n\n`
|
|
|
101
98
|
created_at: ${timestampColumn}
|
|
102
99
|
});`;
|
|
103
100
|
const schemaKey = authProvider === 'absoluteAuth' ? 'users' : 'countHistory';
|
|
104
|
-
const extraTypes = authProvider === 'absoluteAuth'
|
|
105
|
-
? `export type User = typeof users.$inferSelect;
|
|
106
|
-
export type NewUser = typeof users.$inferInsert;`
|
|
107
|
-
: `export type CountHistory = typeof countHistory.$inferSelect;
|
|
108
|
-
export type NewCountHistory = typeof countHistory.$inferInsert;`;
|
|
109
101
|
return `
|
|
110
102
|
${sqliteImports}${builderImport}
|
|
111
|
-
${dbImport}
|
|
112
103
|
|
|
113
104
|
${constsBlock}${tableBlock}
|
|
114
105
|
|
|
@@ -117,6 +108,5 @@ export const schema = {
|
|
|
117
108
|
};
|
|
118
109
|
|
|
119
110
|
export type SchemaType = typeof schema;
|
|
120
|
-
${dbTypeLine ? `${dbTypeLine}\n\n` : '\n'}${extraTypes}
|
|
121
111
|
`;
|
|
122
112
|
};
|
|
@@ -4,24 +4,30 @@ type QueryOperations = {
|
|
|
4
4
|
selectHistory: string;
|
|
5
5
|
insertHistory: string;
|
|
6
6
|
};
|
|
7
|
-
type HandlerType = {
|
|
8
|
-
CountHistoryRow: string;
|
|
9
|
-
UserRow: string;
|
|
10
|
-
};
|
|
11
7
|
declare const driverConfigurations: {
|
|
12
8
|
readonly 'cockroachdb:sql:local': {
|
|
13
|
-
readonly dbType: "
|
|
14
|
-
readonly importLines: "import {
|
|
9
|
+
readonly dbType: "SQL";
|
|
10
|
+
readonly importLines: "import { SQL } from 'bun'";
|
|
11
|
+
readonly queries: QueryOperations;
|
|
12
|
+
};
|
|
13
|
+
readonly 'gel:drizzle:local': {
|
|
14
|
+
readonly dbType: "GelJsDatabase<SchemaType>";
|
|
15
|
+
readonly importLines: "\nimport { eq } from 'drizzle-orm'\nimport { GelJsDatabase } from 'drizzle-orm/gel'\nimport { schema, type SchemaType } from '../../../db/schema'\n";
|
|
15
16
|
readonly queries: QueryOperations;
|
|
16
17
|
};
|
|
17
18
|
readonly 'gel:sql:local': {
|
|
18
|
-
readonly dbType: "
|
|
19
|
-
readonly importLines: "import {
|
|
19
|
+
readonly dbType: "Client";
|
|
20
|
+
readonly importLines: "import { Client } from 'gel'";
|
|
21
|
+
readonly queries: QueryOperations;
|
|
22
|
+
};
|
|
23
|
+
readonly 'mariadb:drizzle:local': {
|
|
24
|
+
readonly dbType: "MySql2Database<SchemaType>";
|
|
25
|
+
readonly importLines: "\nimport { eq } from 'drizzle-orm'\nimport { MySql2Database } from 'drizzle-orm/mysql2'\nimport { schema, type SchemaType } from '../../../db/schema'";
|
|
20
26
|
readonly queries: QueryOperations;
|
|
21
27
|
};
|
|
22
28
|
readonly 'mariadb:sql:local': {
|
|
23
|
-
readonly dbType: "
|
|
24
|
-
readonly importLines: "import {
|
|
29
|
+
readonly dbType: "SQL";
|
|
30
|
+
readonly importLines: "import { SQL } from 'bun'";
|
|
25
31
|
readonly queries: QueryOperations;
|
|
26
32
|
};
|
|
27
33
|
readonly 'mongodb:native:local': {
|
|
@@ -40,13 +46,12 @@ declare const driverConfigurations: {
|
|
|
40
46
|
readonly queries: QueryOperations;
|
|
41
47
|
};
|
|
42
48
|
readonly 'mysql:sql:local': {
|
|
43
|
-
readonly dbType: "
|
|
44
|
-
readonly
|
|
45
|
-
readonly importLines: "import { Pool, ResultSetHeader, RowDataPacket } from 'mysql2/promise'";
|
|
49
|
+
readonly dbType: "SQL";
|
|
50
|
+
readonly importLines: "import { SQL } from 'bun'";
|
|
46
51
|
readonly queries: QueryOperations;
|
|
47
52
|
};
|
|
48
53
|
readonly 'postgresql:drizzle:local': {
|
|
49
|
-
readonly dbType: "
|
|
54
|
+
readonly dbType: "BunSQLDatabase<SchemaType>";
|
|
50
55
|
readonly importLines: "\nimport { eq } from 'drizzle-orm'\nimport { BunSQLDatabase } from 'drizzle-orm/bun-sql'\nimport { schema, type SchemaType } from '../../../db/schema'";
|
|
51
56
|
readonly queries: QueryOperations;
|
|
52
57
|
};
|
|
@@ -61,13 +66,18 @@ declare const driverConfigurations: {
|
|
|
61
66
|
readonly queries: QueryOperations;
|
|
62
67
|
};
|
|
63
68
|
readonly 'postgresql:sql:neon': {
|
|
64
|
-
readonly dbType: "
|
|
65
|
-
readonly importLines: "import {
|
|
69
|
+
readonly dbType: "Pool";
|
|
70
|
+
readonly importLines: "import { Pool } from '@neondatabase/serverless'";
|
|
66
71
|
readonly queries: QueryOperations;
|
|
67
72
|
};
|
|
68
73
|
readonly 'singlestore:sql:local': {
|
|
69
|
-
readonly dbType: "
|
|
70
|
-
readonly importLines: "import {
|
|
74
|
+
readonly dbType: "Pool";
|
|
75
|
+
readonly importLines: "import { Pool, RowDataPacket } from 'mysql2/promise'";
|
|
76
|
+
readonly queries: QueryOperations;
|
|
77
|
+
};
|
|
78
|
+
readonly 'singlestore:drizzle:local': {
|
|
79
|
+
readonly dbType: "SingleStoreDriverDatabase<SchemaType>";
|
|
80
|
+
readonly importLines: "\nimport { eq } from 'drizzle-orm'\nimport { SingleStoreDriverDatabase } from 'drizzle-orm/singlestore'\nimport { schema, type SchemaType } from '../../../db/schema'";
|
|
71
81
|
readonly queries: QueryOperations;
|
|
72
82
|
};
|
|
73
83
|
readonly 'sqlite:drizzle:local': {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
const buildSqlAuthTemplate = ({ importLines,
|
|
2
|
-
import { isValidProviderOption, providers } from 'citra'
|
|
1
|
+
const buildSqlAuthTemplate = ({ importLines, dbType, queries }) => `
|
|
2
|
+
import { isValidProviderOption, providers, extractPropFromIdentity } from 'citra'
|
|
3
3
|
${importLines}
|
|
4
|
-
${handlerTypes?.UserRow ? `\ntype UserRow = ${handlerTypes.UserRow}` : ''}
|
|
5
4
|
type UserHandlerProps = {
|
|
6
5
|
authProvider: string
|
|
7
6
|
db: ${dbType}
|
|
@@ -9,22 +8,31 @@ type UserHandlerProps = {
|
|
|
9
8
|
}
|
|
10
9
|
|
|
11
10
|
export const getUser = async ({ authProvider, db, userIdentity }: UserHandlerProps) => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
const providerConfiguration = providers[authProvider]
|
|
12
|
+
|
|
13
|
+
const subject = extractPropFromIdentity(
|
|
14
|
+
userIdentity,
|
|
15
|
+
providerConfiguration.subject,
|
|
16
|
+
providerConfiguration.subjectType
|
|
17
|
+
)
|
|
18
|
+
const authSub = \`\${authProvider.toUpperCase()}|\${subject}\`;
|
|
15
19
|
${queries.selectUser}
|
|
16
20
|
}
|
|
17
21
|
|
|
18
22
|
export const createUser = async ({ authProvider, db, userIdentity }: UserHandlerProps) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
23
|
+
const providerConfiguration = providers[authProvider]
|
|
24
|
+
|
|
25
|
+
const subject = extractPropFromIdentity(
|
|
26
|
+
userIdentity,
|
|
27
|
+
providerConfiguration.subject,
|
|
28
|
+
providerConfiguration.subjectType
|
|
29
|
+
)
|
|
30
|
+
const authSub = \`\${authProvider.toUpperCase()}|\${subject}\`;
|
|
22
31
|
${queries.insertUser}
|
|
23
32
|
}
|
|
24
33
|
`;
|
|
25
|
-
const buildSqlCountTemplate = ({ importLines,
|
|
34
|
+
const buildSqlCountTemplate = ({ importLines, dbType, queries }) => `
|
|
26
35
|
${importLines}
|
|
27
|
-
${handlerTypes?.CountHistoryRow ? `\ntype CountHistoryRow = ${handlerTypes.CountHistoryRow}\n` : ''}
|
|
28
36
|
export const getCountHistory = async (db: ${dbType}, uid: number) => {
|
|
29
37
|
${queries.selectHistory}
|
|
30
38
|
}
|
|
@@ -73,6 +81,30 @@ const bunSqliteQueryOperations = {
|
|
|
73
81
|
const [user] = statement.all(authSub)
|
|
74
82
|
return user ?? null`
|
|
75
83
|
};
|
|
84
|
+
const postgresNeonQueryOperations = {
|
|
85
|
+
insertHistory: `const { rows } = await db.query(
|
|
86
|
+
'INSERT INTO count_history (count) VALUES ($1) RETURNING *',
|
|
87
|
+
[count]
|
|
88
|
+
)
|
|
89
|
+
return rows[0]`,
|
|
90
|
+
insertUser: `const { rows } = await db.query(
|
|
91
|
+
'INSERT INTO users (auth_sub, metadata) VALUES ($1, $2) RETURNING *',
|
|
92
|
+
[authSub, userIdentity]
|
|
93
|
+
)
|
|
94
|
+
const newUser = rows[0]
|
|
95
|
+
if (!newUser) throw new Error('Failed to create user')
|
|
96
|
+
return newUser`,
|
|
97
|
+
selectHistory: `const { rows } = await db.query(
|
|
98
|
+
'SELECT * FROM count_history WHERE uid = $1 LIMIT 1',
|
|
99
|
+
[uid]
|
|
100
|
+
)
|
|
101
|
+
return rows[0] ?? null`,
|
|
102
|
+
selectUser: `const { rows } = await db.query(
|
|
103
|
+
'SELECT * FROM users WHERE auth_sub = $1 LIMIT 1',
|
|
104
|
+
[authSub]
|
|
105
|
+
)
|
|
106
|
+
return rows[0] ?? null`
|
|
107
|
+
};
|
|
76
108
|
const postgresSqlQueryOperations = {
|
|
77
109
|
insertHistory: `const [newHistory] = await db\`
|
|
78
110
|
INSERT INTO count_history (count)
|
|
@@ -113,58 +145,40 @@ const mongodbQueryOperations = {
|
|
|
113
145
|
selectUser: `const user = await db.collection('users').findOne({ auth_sub: authSub })
|
|
114
146
|
return user ?? null`
|
|
115
147
|
};
|
|
116
|
-
const
|
|
117
|
-
insertHistory: `await db.
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return rows[0] ?? null`,
|
|
127
|
-
selectUser: `const [rows] = await db.query('SELECT * FROM users WHERE auth_sub = ? LIMIT 1', [authSub])
|
|
128
|
-
return rows[0] ?? null`
|
|
129
|
-
};
|
|
130
|
-
const gelSqlQueryOperations = {
|
|
131
|
-
insertHistory: `await db.query('INSERT INTO count_history (count) VALUES (?)', [count])
|
|
132
|
-
const [rows] = await db.query('SELECT * FROM count_history ORDER BY uid DESC LIMIT 1')
|
|
133
|
-
return rows[0]`,
|
|
134
|
-
insertUser: `await db.query('INSERT INTO users (auth_sub, metadata) VALUES (?, ?)', [authSub, JSON.stringify(userIdentity)])
|
|
135
|
-
const [rows] = await db.query('SELECT * FROM users WHERE auth_sub = ? LIMIT 1', [authSub])
|
|
136
|
-
const newUser = rows[0]
|
|
137
|
-
if (!newUser) throw new Error('Failed to create user')
|
|
148
|
+
const gelClientQueryOperations = {
|
|
149
|
+
insertHistory: `const newHistory = await db.queryRequiredSingle(
|
|
150
|
+
'select (insert count_history { count := <int16>$count }) { uid, count, created_at }',
|
|
151
|
+
{ count }
|
|
152
|
+
)
|
|
153
|
+
return newHistory`,
|
|
154
|
+
insertUser: `const newUser = await db.queryRequiredSingle(
|
|
155
|
+
'select (insert users { auth_sub := <str>$authSub, metadata := <json>$metadata }) { auth_sub, created_at, metadata }',
|
|
156
|
+
{ authSub, metadata: userIdentity }
|
|
157
|
+
)
|
|
138
158
|
return newUser`,
|
|
139
|
-
selectHistory: `const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
159
|
+
selectHistory: `const history = await db.querySingle(
|
|
160
|
+
'select count_history { uid, count, created_at } filter .uid = <int64>$uid',
|
|
161
|
+
{ uid }
|
|
162
|
+
)
|
|
163
|
+
return history ?? null`,
|
|
164
|
+
selectUser: `const user = await db.querySingle(
|
|
165
|
+
'select users { auth_sub, created_at, metadata } filter .auth_sub = <str>$authSub',
|
|
166
|
+
{ authSub }
|
|
167
|
+
)
|
|
168
|
+
return user ?? null`
|
|
143
169
|
};
|
|
144
170
|
const singlestoreSqlQueryOperations = {
|
|
145
171
|
insertHistory: `await db.query('INSERT INTO count_history (count) VALUES (?)', [count])
|
|
146
|
-
const [rows] = await db.query('SELECT * FROM count_history ORDER BY uid DESC LIMIT 1')
|
|
172
|
+
const [rows] = await db.query<RowDataPacket[]>('SELECT * FROM count_history ORDER BY uid DESC LIMIT 1')
|
|
147
173
|
return rows[0]`,
|
|
148
174
|
insertUser: `await db.query('INSERT INTO users (auth_sub, metadata) VALUES (?, ?)', [authSub, JSON.stringify(userIdentity)])
|
|
149
|
-
const [rows] = await db.query('SELECT * FROM users WHERE auth_sub = ? LIMIT 1', [authSub])
|
|
175
|
+
const [rows] = await db.query<RowDataPacket[]>('SELECT * FROM users WHERE auth_sub = ? LIMIT 1', [authSub])
|
|
150
176
|
const newUser = rows[0]
|
|
151
177
|
if (!newUser) throw new Error('Failed to create user')
|
|
152
178
|
return newUser`,
|
|
153
|
-
selectHistory: `const [rows] = await db.query('SELECT * FROM count_history WHERE uid = ? LIMIT 1', [uid])
|
|
179
|
+
selectHistory: `const [rows] = await db.query<RowDataPacket[]>('SELECT * FROM count_history WHERE uid = ? LIMIT 1', [uid])
|
|
154
180
|
return rows[0] ?? null`,
|
|
155
|
-
selectUser: `const [rows] = await db.query('SELECT * FROM users WHERE auth_sub = ? LIMIT 1', [authSub])
|
|
156
|
-
return rows[0] ?? null`
|
|
157
|
-
};
|
|
158
|
-
const cockroachdbPoolQueryOperations = {
|
|
159
|
-
insertHistory: `const { rows } = await db.query('INSERT INTO count_history (count) VALUES ($1) RETURNING *', [count])
|
|
160
|
-
return rows[0]`,
|
|
161
|
-
insertUser: `const { rows } = await db.query('INSERT INTO users (auth_sub, metadata) VALUES ($1, $2) RETURNING *', [authSub, userIdentity])
|
|
162
|
-
const newUser = rows[0]
|
|
163
|
-
if (!newUser) throw new Error('Failed to create user')
|
|
164
|
-
return newUser`,
|
|
165
|
-
selectHistory: `const { rows } = await db.query('SELECT * FROM count_history WHERE uid = $1 LIMIT 1', [uid])
|
|
166
|
-
return rows[0] ?? null`,
|
|
167
|
-
selectUser: `const { rows } = await db.query('SELECT * FROM users WHERE auth_sub = $1 LIMIT 1', [authSub])
|
|
181
|
+
selectUser: `const [rows] = await db.query<RowDataPacket[]>('SELECT * FROM users WHERE auth_sub = ? LIMIT 1', [authSub])
|
|
168
182
|
return rows[0] ?? null`
|
|
169
183
|
};
|
|
170
184
|
const mssqlSqlQueryOperations = {
|
|
@@ -183,58 +197,62 @@ const mssqlSqlQueryOperations = {
|
|
|
183
197
|
};
|
|
184
198
|
const mysqlSqlQueryOperations = {
|
|
185
199
|
insertHistory: `
|
|
186
|
-
const
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
200
|
+
const result = await db\`
|
|
201
|
+
INSERT INTO count_history (count)
|
|
202
|
+
VALUES (\${count})
|
|
203
|
+
\`;
|
|
204
|
+
|
|
205
|
+
const insertId = result.lastInsertRowid;
|
|
206
|
+
|
|
207
|
+
const [row] = await db\`
|
|
208
|
+
SELECT *
|
|
209
|
+
FROM count_history
|
|
210
|
+
WHERE uid = \${insertId}
|
|
211
|
+
LIMIT 1
|
|
212
|
+
\`;
|
|
213
|
+
|
|
214
|
+
if (!row) throw new Error("Could not retrieve the newly-inserted history");
|
|
215
|
+
return row;
|
|
197
216
|
`,
|
|
198
217
|
insertUser: `
|
|
199
|
-
const
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
218
|
+
const result = await db\`
|
|
219
|
+
INSERT INTO users (auth_sub, metadata)
|
|
220
|
+
VALUES (\${authSub}, \${JSON.stringify(userIdentity)})
|
|
221
|
+
\`;
|
|
222
|
+
|
|
223
|
+
const insertId = result.lastInsertRowid;
|
|
224
|
+
|
|
225
|
+
const [row] = await db\`
|
|
226
|
+
SELECT *
|
|
227
|
+
FROM users
|
|
228
|
+
WHERE uid = \${insertId}
|
|
229
|
+
LIMIT 1
|
|
230
|
+
\`;
|
|
231
|
+
|
|
232
|
+
if (!row) throw new Error("Failed to create user");
|
|
233
|
+
return row;
|
|
210
234
|
`,
|
|
211
235
|
selectHistory: `
|
|
212
|
-
const [
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
236
|
+
const [row] = await db\`
|
|
237
|
+
SELECT *
|
|
238
|
+
FROM count_history
|
|
239
|
+
WHERE uid = \${uid}
|
|
240
|
+
LIMIT 1
|
|
241
|
+
\`;
|
|
242
|
+
|
|
243
|
+
return row ?? null;
|
|
217
244
|
`,
|
|
218
245
|
selectUser: `
|
|
219
|
-
const [
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
246
|
+
const [row] = await db\`
|
|
247
|
+
SELECT *
|
|
248
|
+
FROM users
|
|
249
|
+
WHERE auth_sub = \${authSub}
|
|
250
|
+
LIMIT 1
|
|
251
|
+
\`;
|
|
252
|
+
|
|
253
|
+
return row ?? null;
|
|
224
254
|
`
|
|
225
255
|
};
|
|
226
|
-
const mysqlHandlerTypes = {
|
|
227
|
-
CountHistoryRow: `RowDataPacket & {
|
|
228
|
-
uid: number;
|
|
229
|
-
count: number;
|
|
230
|
-
created_at: number;
|
|
231
|
-
}`,
|
|
232
|
-
UserRow: `RowDataPacket & {
|
|
233
|
-
uid: number;
|
|
234
|
-
auth_sub: string;
|
|
235
|
-
metadata: string;
|
|
236
|
-
}`
|
|
237
|
-
};
|
|
238
256
|
const mysqlDrizzleQueryOperations = {
|
|
239
257
|
insertHistory: `const [row] = await db
|
|
240
258
|
.insert(schema.countHistory)
|
|
@@ -270,19 +288,36 @@ const mysqlDrizzleQueryOperations = {
|
|
|
270
288
|
};
|
|
271
289
|
const driverConfigurations = {
|
|
272
290
|
'cockroachdb:sql:local': {
|
|
273
|
-
dbType: '
|
|
274
|
-
importLines: `import {
|
|
275
|
-
queries:
|
|
291
|
+
dbType: 'SQL',
|
|
292
|
+
importLines: `import { SQL } from 'bun'`,
|
|
293
|
+
queries: postgresSqlQueryOperations
|
|
294
|
+
},
|
|
295
|
+
'gel:drizzle:local': {
|
|
296
|
+
dbType: 'GelJsDatabase<SchemaType>',
|
|
297
|
+
importLines: `
|
|
298
|
+
import { eq } from 'drizzle-orm'
|
|
299
|
+
import { GelJsDatabase } from 'drizzle-orm/gel'
|
|
300
|
+
import { schema, type SchemaType } from '../../../db/schema'
|
|
301
|
+
`,
|
|
302
|
+
queries: drizzleQueryOperations
|
|
276
303
|
},
|
|
277
304
|
'gel:sql:local': {
|
|
278
|
-
dbType: '
|
|
279
|
-
importLines: `import {
|
|
280
|
-
queries:
|
|
305
|
+
dbType: 'Client',
|
|
306
|
+
importLines: `import { Client } from 'gel'`,
|
|
307
|
+
queries: gelClientQueryOperations
|
|
308
|
+
},
|
|
309
|
+
'mariadb:drizzle:local': {
|
|
310
|
+
dbType: 'MySql2Database<SchemaType>',
|
|
311
|
+
importLines: `
|
|
312
|
+
import { eq } from 'drizzle-orm'
|
|
313
|
+
import { MySql2Database } from 'drizzle-orm/mysql2'
|
|
314
|
+
import { schema, type SchemaType } from '../../../db/schema'`,
|
|
315
|
+
queries: mysqlDrizzleQueryOperations
|
|
281
316
|
},
|
|
282
317
|
'mariadb:sql:local': {
|
|
283
|
-
dbType: '
|
|
284
|
-
importLines: `import {
|
|
285
|
-
queries:
|
|
318
|
+
dbType: 'SQL',
|
|
319
|
+
importLines: `import { SQL } from 'bun'`,
|
|
320
|
+
queries: mysqlSqlQueryOperations
|
|
286
321
|
},
|
|
287
322
|
'mongodb:native:local': {
|
|
288
323
|
dbType: 'Db',
|
|
@@ -303,13 +338,12 @@ import { schema, type SchemaType } from '../../../db/schema'`,
|
|
|
303
338
|
queries: mysqlDrizzleQueryOperations
|
|
304
339
|
},
|
|
305
340
|
'mysql:sql:local': {
|
|
306
|
-
dbType: '
|
|
307
|
-
|
|
308
|
-
importLines: `import { Pool, ResultSetHeader, RowDataPacket } from 'mysql2/promise'`,
|
|
341
|
+
dbType: 'SQL',
|
|
342
|
+
importLines: `import { SQL } from 'bun'`,
|
|
309
343
|
queries: mysqlSqlQueryOperations
|
|
310
344
|
},
|
|
311
345
|
'postgresql:drizzle:local': {
|
|
312
|
-
dbType: '
|
|
346
|
+
dbType: 'BunSQLDatabase<SchemaType>',
|
|
313
347
|
importLines: `
|
|
314
348
|
import { eq } from 'drizzle-orm'
|
|
315
349
|
import { BunSQLDatabase } from 'drizzle-orm/bun-sql'
|
|
@@ -330,15 +364,23 @@ import { schema, type SchemaType } from '../../../db/schema'`,
|
|
|
330
364
|
queries: postgresSqlQueryOperations
|
|
331
365
|
},
|
|
332
366
|
'postgresql:sql:neon': {
|
|
333
|
-
dbType: '
|
|
334
|
-
importLines: `import {
|
|
335
|
-
queries:
|
|
367
|
+
dbType: 'Pool',
|
|
368
|
+
importLines: `import { Pool } from '@neondatabase/serverless'`,
|
|
369
|
+
queries: postgresNeonQueryOperations
|
|
336
370
|
},
|
|
337
371
|
'singlestore:sql:local': {
|
|
338
|
-
dbType: '
|
|
339
|
-
importLines: `import {
|
|
372
|
+
dbType: 'Pool',
|
|
373
|
+
importLines: `import { Pool, RowDataPacket } from 'mysql2/promise'`,
|
|
340
374
|
queries: singlestoreSqlQueryOperations
|
|
341
375
|
},
|
|
376
|
+
'singlestore:drizzle:local': {
|
|
377
|
+
dbType: 'SingleStoreDriverDatabase<SchemaType>',
|
|
378
|
+
importLines: `
|
|
379
|
+
import { eq } from 'drizzle-orm'
|
|
380
|
+
import { SingleStoreDriverDatabase } from 'drizzle-orm/singlestore'
|
|
381
|
+
import { schema, type SchemaType } from '../../../db/schema'`,
|
|
382
|
+
queries: mysqlDrizzleQueryOperations
|
|
383
|
+
},
|
|
342
384
|
'sqlite:drizzle:local': {
|
|
343
385
|
dbType: 'BunSQLiteDatabase<SchemaType>',
|
|
344
386
|
importLines: `
|
|
@@ -2,6 +2,7 @@ import type { CreateConfiguration } from '../../types';
|
|
|
2
2
|
type ScaffoldDatabaseProps = Pick<CreateConfiguration, 'projectName' | 'databaseHost' | 'orm' | 'databaseDirectory' | 'authProvider' | 'databaseEngine'> & {
|
|
3
3
|
databaseDirectory: string;
|
|
4
4
|
backendDirectory: string;
|
|
5
|
+
typesDirectory: string;
|
|
5
6
|
};
|
|
6
|
-
export declare const scaffoldDatabase: ({ projectName, databaseEngine, databaseHost, databaseDirectory, backendDirectory, authProvider, orm }: ScaffoldDatabaseProps) => Promise<void>;
|
|
7
|
+
export declare const scaffoldDatabase: ({ projectName, databaseEngine, databaseHost, databaseDirectory, backendDirectory, authProvider, orm, typesDirectory }: ScaffoldDatabaseProps) => Promise<void>;
|
|
7
8
|
export {};
|
|
@@ -5,11 +5,12 @@ import { dim, yellow } from 'picocolors';
|
|
|
5
5
|
import { isDrizzleDialect } from '../../typeGuards';
|
|
6
6
|
import { checkSqliteInstalled } from '../../utils/checkSqliteInstalled';
|
|
7
7
|
import { createDrizzleConfig } from '../configurations/generateDrizzleConfig';
|
|
8
|
+
import { generateDatabaseTypes } from './generateDatabaseTypes';
|
|
8
9
|
import { generateDrizzleSchema } from './generateDrizzleSchema';
|
|
9
10
|
import { generateDBHandlers } from './generateHandlers';
|
|
10
11
|
import { generateSqliteSchema } from './generateSqliteSchema';
|
|
11
12
|
import { scaffoldDocker } from './scaffoldDocker';
|
|
12
|
-
export const scaffoldDatabase = async ({ projectName, databaseEngine, databaseHost, databaseDirectory, backendDirectory, authProvider, orm }) => {
|
|
13
|
+
export const scaffoldDatabase = async ({ projectName, databaseEngine, databaseHost, databaseDirectory, backendDirectory, authProvider, orm, typesDirectory }) => {
|
|
13
14
|
const projectDatabaseDirectory = join(projectName, databaseDirectory);
|
|
14
15
|
const handlerDirectory = join(backendDirectory, 'handlers');
|
|
15
16
|
mkdirSync(projectDatabaseDirectory, { recursive: true });
|
|
@@ -49,11 +50,16 @@ export const scaffoldDatabase = async ({ projectName, databaseEngine, databaseHo
|
|
|
49
50
|
}
|
|
50
51
|
const drizzleSchema = generateDrizzleSchema({
|
|
51
52
|
authProvider,
|
|
52
|
-
databaseEngine
|
|
53
|
-
databaseHost
|
|
53
|
+
databaseEngine
|
|
54
54
|
});
|
|
55
55
|
writeFileSync(join(projectDatabaseDirectory, 'schema.ts'), drizzleSchema);
|
|
56
56
|
createDrizzleConfig({ databaseDirectory, databaseEngine, projectName });
|
|
57
|
+
const drizzleTypes = generateDatabaseTypes({
|
|
58
|
+
authProvider,
|
|
59
|
+
databaseEngine,
|
|
60
|
+
databaseHost
|
|
61
|
+
});
|
|
62
|
+
writeFileSync(join(typesDirectory, 'databaseTypes.ts'), drizzleTypes);
|
|
57
63
|
return;
|
|
58
64
|
}
|
|
59
65
|
if (orm === 'prisma') {
|
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
import { availableDrizzleDialects } from '../../data';
|
|
2
2
|
const connectionMap = {
|
|
3
3
|
cockroachdb: {
|
|
4
|
-
none: { expr: 'new
|
|
4
|
+
none: { expr: 'new SQL(getEnv("DATABASE_URL"))' }
|
|
5
5
|
},
|
|
6
6
|
gel: {
|
|
7
|
-
none: { expr: '
|
|
7
|
+
none: { expr: 'createClient(getEnv("DATABASE_URL"))' }
|
|
8
8
|
},
|
|
9
9
|
mariadb: {
|
|
10
|
-
none: { expr: '
|
|
10
|
+
none: { expr: 'new SQL(getEnv("DATABASE_URL"))' }
|
|
11
11
|
},
|
|
12
12
|
mongodb: {
|
|
13
|
-
none: { expr: 'new MongoClient(getEnv("DATABASE_URL")
|
|
13
|
+
none: { expr: 'new MongoClient(getEnv("DATABASE_URL"))' }
|
|
14
14
|
},
|
|
15
15
|
mssql: {
|
|
16
16
|
none: { expr: 'await connect(getEnv("DATABASE_URL"))' }
|
|
17
17
|
},
|
|
18
18
|
mysql: {
|
|
19
|
-
none: { expr: '
|
|
19
|
+
none: { expr: 'new SQL(getEnv("DATABASE_URL"))' },
|
|
20
20
|
planetscale: { expr: 'connect({ url: getEnv("DATABASE_URL") })' }
|
|
21
21
|
},
|
|
22
22
|
postgresql: {
|
|
23
23
|
neon: {
|
|
24
24
|
expr: 'new Pool({ connectionString: getEnv("DATABASE_URL") })'
|
|
25
25
|
},
|
|
26
|
-
none: { expr: 'new
|
|
26
|
+
none: { expr: 'new SQL(getEnv("DATABASE_URL"))' }
|
|
27
27
|
},
|
|
28
28
|
singlestore: {
|
|
29
|
-
none: { expr: '
|
|
29
|
+
none: { expr: 'createPool(getEnv("DATABASE_URL"))' }
|
|
30
30
|
},
|
|
31
31
|
sqlite: {
|
|
32
32
|
none: { expr: 'new Database("db/database.sqlite")' },
|
|
@@ -49,28 +49,20 @@ export const generateDBBlock = ({ databaseEngine, orm, databaseHost }) => {
|
|
|
49
49
|
return '';
|
|
50
50
|
if (orm !== 'drizzle') {
|
|
51
51
|
const hostCfg = engineGroup[hostKey];
|
|
52
|
-
|
|
53
|
-
return '';
|
|
54
|
-
return `
|
|
55
|
-
const pool = ${hostCfg.expr}
|
|
56
|
-
`;
|
|
52
|
+
return hostCfg ? `const db = ${hostCfg.expr}` : '';
|
|
57
53
|
}
|
|
58
54
|
if (!drizzleDialectSet.has(databaseEngine))
|
|
59
55
|
return '';
|
|
60
56
|
const expr = engineGroup[hostKey]?.expr ?? remoteDrizzleInit[hostKey];
|
|
61
57
|
if (!expr)
|
|
62
58
|
return '';
|
|
63
|
-
if (databaseEngine === 'mysql') {
|
|
64
|
-
const mode = databaseHost === 'planetscale'
|
|
59
|
+
if (databaseEngine === 'mysql' || databaseEngine === 'mariadb') {
|
|
60
|
+
const mode = databaseHost === 'planetscale' && databaseEngine === 'mysql'
|
|
61
|
+
? 'planetscale'
|
|
62
|
+
: 'default';
|
|
65
63
|
return `
|
|
66
|
-
const pool =
|
|
64
|
+
const pool = createPool(getEnv("DATABASE_URL"))
|
|
67
65
|
const db = drizzle(pool, { schema, mode: '${mode}' })
|
|
68
|
-
`;
|
|
69
|
-
}
|
|
70
|
-
if (databaseEngine === 'sqlite') {
|
|
71
|
-
return `
|
|
72
|
-
const pool = ${expr}
|
|
73
|
-
const db = drizzle(pool, { schema })
|
|
74
66
|
`;
|
|
75
67
|
}
|
|
76
68
|
return `
|