@stacksjs/database 0.64.5 → 0.65.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/index.js +55 -55
- package/dist/index.js.map +136 -142
- package/package.json +16 -22
- package/src/drivers/index.ts +65 -171
- package/src/drivers/mysql.ts +95 -54
- package/src/drivers/postgres.ts +34 -32
- package/src/drivers/sqlite.ts +165 -62
- package/src/index.ts +2 -1
- package/src/migrations.ts +38 -61
- package/src/seeder.ts +17 -97
- package/src/table.ts +1 -1
- package/src/types.ts +2 -0
- package/src/utils.ts +19 -11
package/src/seeder.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
+
import type { Model, RelationConfig } from '@stacksjs/types'
|
|
1
2
|
import { italic, log } from '@stacksjs/cli'
|
|
2
3
|
import { db } from '@stacksjs/database'
|
|
3
|
-
import { modelTableName } from '@stacksjs/orm'
|
|
4
|
-
import { getModelName, getTableName } from '@stacksjs/orm'
|
|
4
|
+
import { fetchOtherModelRelations, modelTableName } from '@stacksjs/orm'
|
|
5
5
|
import { path } from '@stacksjs/path'
|
|
6
|
-
import { makeHash } from '@stacksjs/security'
|
|
7
|
-
import { fs, glob } from '@stacksjs/storage'
|
|
8
|
-
import { plural, singular, snakeCase } from '@stacksjs/strings'
|
|
9
|
-
import type { Model, RelationConfig } from '@stacksjs/types'
|
|
10
|
-
import { isString } from '@stacksjs/validation'
|
|
11
6
|
|
|
12
|
-
import {
|
|
7
|
+
import { makeHash } from '@stacksjs/security'
|
|
8
|
+
import { fs } from '@stacksjs/storage'
|
|
9
|
+
import { singular, snakeCase } from '@stacksjs/strings'
|
|
13
10
|
|
|
14
11
|
async function seedModel(name: string, model?: Model) {
|
|
15
12
|
if (model?.traits?.useSeeder === false || model?.traits?.seedable === false) {
|
|
@@ -17,11 +14,12 @@ async function seedModel(name: string, model?: Model) {
|
|
|
17
14
|
return
|
|
18
15
|
}
|
|
19
16
|
|
|
20
|
-
if (!model)
|
|
17
|
+
if (!model)
|
|
18
|
+
model = (await import(path.userModelsPath(name))) as Model
|
|
21
19
|
|
|
22
20
|
const tableName = await modelTableName(model)
|
|
23
|
-
const seedCount
|
|
24
|
-
typeof model.traits?.useSeeder === 'object' && model.traits?.useSeeder?.count ? model.traits.useSeeder.count : 10
|
|
21
|
+
const seedCount
|
|
22
|
+
= typeof model.traits?.useSeeder === 'object' && model.traits?.useSeeder?.count ? model.traits.useSeeder.count : 10
|
|
25
23
|
|
|
26
24
|
log.info(`Seeding ${seedCount} records into ${italic(tableName)}`)
|
|
27
25
|
|
|
@@ -68,7 +66,8 @@ async function seedPivotRelation(relation: RelationConfig): Promise<any> {
|
|
|
68
66
|
const modelInstance = (await import(path.userModelsPath(relation?.model))).default
|
|
69
67
|
const relationModelInstance = (await import(path.userModelsPath(relation?.relationModel))).default
|
|
70
68
|
|
|
71
|
-
if (!relationModelInstance)
|
|
69
|
+
if (!relationModelInstance)
|
|
70
|
+
return 1
|
|
72
71
|
|
|
73
72
|
const relationModelTable = relationModelInstance.table
|
|
74
73
|
const relationTable = relation.table
|
|
@@ -102,13 +101,15 @@ async function seedPivotRelation(relation: RelationConfig): Promise<any> {
|
|
|
102
101
|
pivotRecord[foreignKey] = relationData
|
|
103
102
|
pivotRecord[modelKey] = modelData
|
|
104
103
|
|
|
105
|
-
if (pivotTable)
|
|
104
|
+
if (pivotTable)
|
|
105
|
+
await db.insertInto(pivotTable).values(pivotRecord).executeTakeFirstOrThrow()
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
async function seedModelRelation(modelName: string): Promise<
|
|
108
|
+
async function seedModelRelation(modelName: string): Promise<bigint | number> {
|
|
109
109
|
const modelInstance = (await import(path.userModelsPath(modelName))).default
|
|
110
110
|
|
|
111
|
-
if (!modelInstance)
|
|
111
|
+
if (!modelInstance)
|
|
112
|
+
return 1
|
|
112
113
|
|
|
113
114
|
const record: any = {}
|
|
114
115
|
const table = modelInstance.table
|
|
@@ -128,87 +129,6 @@ async function seedModelRelation(modelName: string): Promise<BigInt | number> {
|
|
|
128
129
|
return data.insertId || 1
|
|
129
130
|
}
|
|
130
131
|
|
|
131
|
-
export async function getRelations(model: Model, modelPath: string): Promise<RelationConfig[]> {
|
|
132
|
-
const relationsArray = ['hasOne', 'hasMany', 'belongsToMany', 'hasOneThrough']
|
|
133
|
-
const relationships = []
|
|
134
|
-
|
|
135
|
-
const modelName = getModelName(model, modelPath)
|
|
136
|
-
const tableName = getTableName(model, modelPath)
|
|
137
|
-
|
|
138
|
-
for (const relation of relationsArray) {
|
|
139
|
-
if (hasRelations(model, relation)) {
|
|
140
|
-
for (const relationInstance of model[relation]) {
|
|
141
|
-
let relationModel = relationInstance.model
|
|
142
|
-
|
|
143
|
-
if (isString(relationInstance)) {
|
|
144
|
-
relationModel = relationInstance
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const modelRelationPath = path.userModelsPath(`${relationModel}.ts`)
|
|
148
|
-
const modelRelation = (await import(modelRelationPath)).default
|
|
149
|
-
const formattedModelName = modelName?.toLowerCase()
|
|
150
|
-
|
|
151
|
-
relationships.push({
|
|
152
|
-
relationship: relation,
|
|
153
|
-
model: relationModel,
|
|
154
|
-
table: modelRelation.table,
|
|
155
|
-
relationModel: modelName,
|
|
156
|
-
relationTable: tableName,
|
|
157
|
-
foreignKey: relationInstance.foreignKey || `${formattedModelName}_id`,
|
|
158
|
-
relationName: relationInstance.relationName,
|
|
159
|
-
throughModel: relationInstance.through,
|
|
160
|
-
throughForeignKey: relationInstance.throughForeignKey,
|
|
161
|
-
pivotTable: relationInstance?.pivotTable || getPivotTableName(formattedModelName || '', modelRelation.table),
|
|
162
|
-
})
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return relationships
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function getPivotTableName(formattedModelName: string, modelRelationTable: string): string {
|
|
171
|
-
// Create an array of the model names
|
|
172
|
-
const models = [formattedModelName, modelRelationTable]
|
|
173
|
-
|
|
174
|
-
// Sort the array alphabetically
|
|
175
|
-
models.sort()
|
|
176
|
-
|
|
177
|
-
models[0] = singular(models[0] || '')
|
|
178
|
-
models[1] = plural(models[1] || '')
|
|
179
|
-
|
|
180
|
-
// Join the sorted array with an underscore
|
|
181
|
-
const pivotTableName = models.join('_')
|
|
182
|
-
|
|
183
|
-
return pivotTableName
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
export async function fetchOtherModelRelations(model: Model): Promise<RelationConfig[]> {
|
|
187
|
-
const modelFiles = glob.sync(path.userModelsPath('*.ts'))
|
|
188
|
-
const modelRelations = []
|
|
189
|
-
|
|
190
|
-
for (let i = 0; i < modelFiles.length; i++) {
|
|
191
|
-
const modelFileElement = modelFiles[i] as string
|
|
192
|
-
const modelFile = await import(modelFileElement)
|
|
193
|
-
|
|
194
|
-
if (model.name === modelFile.default.name) continue
|
|
195
|
-
|
|
196
|
-
const relations = await getRelations(modelFile.default, modelFileElement)
|
|
197
|
-
|
|
198
|
-
if (!relations.length) continue
|
|
199
|
-
|
|
200
|
-
const relation = relations.find((relation) => relation.model === model.name)
|
|
201
|
-
|
|
202
|
-
if (relation) modelRelations.push(relation)
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return modelRelations
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
function hasRelations(obj: any, key: string): boolean {
|
|
209
|
-
return key in obj
|
|
210
|
-
}
|
|
211
|
-
|
|
212
132
|
export async function seed() {
|
|
213
133
|
// TODO: need to check other databases too
|
|
214
134
|
// const dbPath = path.userDatabasePath('stacks.sqlite')
|
|
@@ -236,7 +156,7 @@ export async function seed() {
|
|
|
236
156
|
|
|
237
157
|
// otherwise, seed all models
|
|
238
158
|
const modelsDir = path.userModelsPath()
|
|
239
|
-
const modelFiles = fs.readdirSync(modelsDir).filter(
|
|
159
|
+
const modelFiles = fs.readdirSync(modelsDir).filter(file => file.endsWith('.ts'))
|
|
240
160
|
|
|
241
161
|
for (const file of modelFiles) {
|
|
242
162
|
const modelPath = path.join(modelsDir, file)
|
package/src/table.ts
CHANGED
|
@@ -26,7 +26,7 @@ export class Table {
|
|
|
26
26
|
|
|
27
27
|
// Method to simulate the execution of the schema definition
|
|
28
28
|
execute(): void {
|
|
29
|
-
log.info(`Creating table with columns: ${this.columns.map(
|
|
29
|
+
log.info(`Creating table with columns: ${this.columns.map(col => col.name).join(', ')}`)
|
|
30
30
|
// run kysely mirgration
|
|
31
31
|
}
|
|
32
32
|
}
|
package/src/types.ts
CHANGED
package/src/utils.ts
CHANGED
|
@@ -1,29 +1,34 @@
|
|
|
1
|
-
import { database } from '@stacksjs/config'
|
|
2
|
-
import { log } from '@stacksjs/logging'
|
|
3
1
|
import type { Database } from '@stacksjs/orm'
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
2
|
+
import type { RawBuilder } from 'kysely'
|
|
3
|
+
import { app, database } from '@stacksjs/config'
|
|
4
|
+
import { log } from '@stacksjs/logging'
|
|
5
|
+
import { path } from '@stacksjs/path'
|
|
6
6
|
import { Kysely, MysqlDialect, PostgresDialect, sql } from 'kysely'
|
|
7
7
|
import { BunWorkerDialect } from 'kysely-bun-worker'
|
|
8
8
|
import { createPool } from 'mysql2'
|
|
9
9
|
import { Pool } from 'pg'
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
const appEnv = app.env || 'local'
|
|
12
|
+
|
|
13
|
+
export function getDialect(): MysqlDialect | PostgresDialect | BunWorkerDialect {
|
|
12
14
|
const driver = database.default ?? 'sqlite'
|
|
13
15
|
|
|
14
16
|
log.debug(`Using database driver: ${driver}`)
|
|
15
17
|
|
|
16
18
|
if (driver === 'sqlite') {
|
|
17
|
-
const
|
|
19
|
+
const defaultName = appEnv !== 'testing' ? 'database/stacks.sqlite' : 'database/stacks_testing.sqlite'
|
|
20
|
+
const sqliteDbName = database.connections?.sqlite.database ?? defaultName
|
|
21
|
+
const dbPath = path.projectPath(sqliteDbName)
|
|
22
|
+
|
|
18
23
|
return new BunWorkerDialect({
|
|
19
|
-
url:
|
|
24
|
+
url: dbPath,
|
|
20
25
|
})
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
if (driver === 'mysql') {
|
|
24
29
|
return new MysqlDialect({
|
|
25
30
|
pool: createPool({
|
|
26
|
-
database: database.connections?.mysql?.name
|
|
31
|
+
database: database.connections?.mysql?.name || 'stacks', // Use modified dbName
|
|
27
32
|
host: database.connections?.mysql?.host ?? '127.0.0.1',
|
|
28
33
|
user: database.connections?.mysql?.username ?? 'root',
|
|
29
34
|
password: database.connections?.mysql?.password ?? '',
|
|
@@ -33,9 +38,12 @@ export function getDialect() {
|
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
if (driver === 'postgres') {
|
|
41
|
+
const pgDbName = database.connections?.postgres?.name ?? 'stacks' // Default Postgres database name
|
|
42
|
+
const finalPgDbName = appEnv === 'testing' ? `${pgDbName}_testing` : pgDbName // Modify if testing
|
|
43
|
+
|
|
36
44
|
return new PostgresDialect({
|
|
37
45
|
pool: new Pool({
|
|
38
|
-
database:
|
|
46
|
+
database: finalPgDbName, // Use modified pgDbName
|
|
39
47
|
host: database.connections?.postgres?.host ?? '127.0.0.1',
|
|
40
48
|
user: database.connections?.postgres?.username ?? '',
|
|
41
49
|
password: database.connections?.postgres?.password ?? '',
|
|
@@ -47,8 +55,8 @@ export function getDialect() {
|
|
|
47
55
|
throw new Error(`Unsupported driver: ${driver}`)
|
|
48
56
|
}
|
|
49
57
|
|
|
50
|
-
export const now = sql`now()`
|
|
58
|
+
export const now: RawBuilder<any> = sql`now()`
|
|
51
59
|
|
|
52
|
-
export const db = new Kysely<Database>({
|
|
60
|
+
export const db: Kysely<Database> = new Kysely<Database>({
|
|
53
61
|
dialect: getDialect(),
|
|
54
62
|
})
|