@stacksjs/database 0.65.0 → 0.67.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/src/seeder.ts DELETED
@@ -1,166 +0,0 @@
1
- import type { Model, RelationConfig } from '@stacksjs/types'
2
- import { italic, log } from '@stacksjs/cli'
3
- import { db } from '@stacksjs/database'
4
- import { fetchOtherModelRelations, modelTableName } from '@stacksjs/orm'
5
- import { path } from '@stacksjs/path'
6
-
7
- import { makeHash } from '@stacksjs/security'
8
- import { fs } from '@stacksjs/storage'
9
- import { singular, snakeCase } from '@stacksjs/strings'
10
-
11
- async function seedModel(name: string, model?: Model) {
12
- if (model?.traits?.useSeeder === false || model?.traits?.seedable === false) {
13
- log.info(`Skipping seeding for ${italic(name)}`)
14
- return
15
- }
16
-
17
- if (!model)
18
- model = (await import(path.userModelsPath(name))) as Model
19
-
20
- const tableName = await modelTableName(model)
21
- const seedCount
22
- = typeof model.traits?.useSeeder === 'object' && model.traits?.useSeeder?.count ? model.traits.useSeeder.count : 10
23
-
24
- log.info(`Seeding ${seedCount} records into ${italic(tableName)}`)
25
-
26
- const records = []
27
- const otherRelations = await fetchOtherModelRelations(model)
28
-
29
- for (let i = 0; i < seedCount; i++) {
30
- const record: any = {}
31
-
32
- for (const fieldName in model.attributes) {
33
- const formattedFieldName = snakeCase(fieldName)
34
- const field = model.attributes[fieldName]
35
-
36
- // Use the factory function if available, otherwise leave the field undefined
37
- if (formattedFieldName === 'password')
38
- record[formattedFieldName] = field?.factory ? await makeHash('Test@123', { algorithm: 'bcrypt' }) : undefined
39
- else record[formattedFieldName] = field?.factory ? field.factory() : undefined
40
- }
41
-
42
- if (otherRelations?.length) {
43
- for (let j = 0; j < otherRelations.length; j++) {
44
- const relationElement = otherRelations[j] as RelationConfig
45
-
46
- if (relationElement.relationship === 'belongsToMany') {
47
- await seedPivotRelation(relationElement)
48
- }
49
-
50
- record[relationElement?.foreignKey] = await seedModelRelation(relationElement?.relationModel as string)
51
- }
52
- }
53
-
54
- records.push(record)
55
- }
56
-
57
- // @ts-expect-error todo: we can improve this in the future
58
- await db.insertInto(tableName).values(records).execute()
59
- }
60
-
61
- async function seedPivotRelation(relation: RelationConfig): Promise<any> {
62
- const record: any = {}
63
- const record2: any = {}
64
- const pivotRecord: any = {}
65
-
66
- const modelInstance = (await import(path.userModelsPath(relation?.model))).default
67
- const relationModelInstance = (await import(path.userModelsPath(relation?.relationModel))).default
68
-
69
- if (!relationModelInstance)
70
- return 1
71
-
72
- const relationModelTable = relationModelInstance.table
73
- const relationTable = relation.table
74
- const pivotTable = relation.pivotTable
75
- const modelKey = `${singular(relationTable)}_id`
76
- const foreignKey = relation.foreignKey
77
-
78
- for (const fieldName in relationModelInstance.attributes) {
79
- const formattedFieldName = snakeCase(fieldName)
80
- const field = relationModelInstance.attributes[fieldName]
81
- // Use the factory function if available, otherwise leave the field undefined
82
- if (formattedFieldName === 'password')
83
- record[formattedFieldName] = field?.factory ? await makeHash('Test@123', { algorithm: 'bcrypt' }) : undefined
84
- else record[formattedFieldName] = field?.factory ? field.factory() : undefined
85
- }
86
-
87
- for (const fieldName in modelInstance.attributes) {
88
- const formattedFieldName = snakeCase(fieldName)
89
- const field = modelInstance.attributes[fieldName]
90
- // Use the factory function if available, otherwise leave the field undefined
91
- if (formattedFieldName === 'password')
92
- record2[formattedFieldName] = field?.factory ? await makeHash('Test@123', { algorithm: 'bcrypt' }) : undefined
93
- else record2[formattedFieldName] = field?.factory ? field.factory() : undefined
94
- }
95
-
96
- const data = await db.insertInto(relationModelTable).values(record).executeTakeFirstOrThrow()
97
- const data2 = await db.insertInto(relationTable).values(record2).executeTakeFirstOrThrow()
98
- const relationData = data.insertId || 1
99
- const modelData = data2.insertId || 1
100
-
101
- pivotRecord[foreignKey] = relationData
102
- pivotRecord[modelKey] = modelData
103
-
104
- if (pivotTable)
105
- await db.insertInto(pivotTable).values(pivotRecord).executeTakeFirstOrThrow()
106
- }
107
-
108
- async function seedModelRelation(modelName: string): Promise<bigint | number> {
109
- const modelInstance = (await import(path.userModelsPath(modelName))).default
110
-
111
- if (!modelInstance)
112
- return 1
113
-
114
- const record: any = {}
115
- const table = modelInstance.table
116
-
117
- for (const fieldName in modelInstance.attributes) {
118
- const formattedFieldName = snakeCase(fieldName)
119
- const field = modelInstance.attributes[fieldName]
120
- // Use the factory function if available, otherwise leave the field undefined
121
-
122
- if (formattedFieldName === 'password')
123
- record[formattedFieldName] = field?.factory ? await makeHash(field.factory(), { algorithm: 'bcrypt' }) : undefined
124
- else record[formattedFieldName] = field?.factory ? field.factory() : undefined
125
- }
126
-
127
- const data = await db.insertInto(table).values(record).executeTakeFirstOrThrow()
128
-
129
- return data.insertId || 1
130
- }
131
-
132
- export async function seed() {
133
- // TODO: need to check other databases too
134
- // const dbPath = path.userDatabasePath('stacks.sqlite')
135
-
136
- // if (!fs.existsSync(dbPath)) {
137
- // log.warn('No database found, configuring it...')
138
- // // first, ensure the database is reset
139
- // await resetDatabase()
140
-
141
- // // then, generate the migrations
142
- // await generateMigrations()
143
-
144
- // // finally, migrate the database
145
- // await runDatabaseMigration()
146
- // } else {
147
- // log.debug('Database configured...')
148
- // }
149
-
150
- // if a custom seeder exists, use it instead
151
- const customSeederPath = path.userDatabasePath('seeder.ts')
152
- if (fs.existsSync(customSeederPath)) {
153
- log.info('Custom seeder found')
154
- await import(customSeederPath)
155
- }
156
-
157
- // otherwise, seed all models
158
- const modelsDir = path.userModelsPath()
159
- const modelFiles = fs.readdirSync(modelsDir).filter(file => file.endsWith('.ts'))
160
-
161
- for (const file of modelFiles) {
162
- const modelPath = path.join(modelsDir, file)
163
- const model = await import(modelPath)
164
- await seedModel(file, model.default)
165
- }
166
- }
package/src/table.ts DELETED
@@ -1,32 +0,0 @@
1
- import { log } from '@stacksjs/logging'
2
- import { Column } from './column'
3
-
4
- export class Table {
5
- private columns: Column[] = []
6
-
7
- increments(name: string): Column {
8
- const column = new Column(name, 'integer', {
9
- primaryKey: true,
10
- autoIncrement: true,
11
- })
12
- this.columns.push(column)
13
- return column
14
- }
15
-
16
- string(name: string, varchar = 255): Column {
17
- const column = new Column(name, `varchar(${varchar})`)
18
- this.columns.push(column)
19
- return column
20
- }
21
-
22
- timestamps(): void {
23
- this.columns.push(new Column('created_at', 'timestamp'))
24
- this.columns.push(new Column('updated_at', 'timestamp'))
25
- }
26
-
27
- // Method to simulate the execution of the schema definition
28
- execute(): void {
29
- log.info(`Creating table with columns: ${this.columns.map(col => col.name).join(', ')}`)
30
- // run kysely mirgration
31
- }
32
- }
package/src/types.ts DELETED
@@ -1,5 +0,0 @@
1
- export { Kysely as Database } from 'kysely'
2
-
3
- export { sql } from 'kysely'
4
-
5
- export type { Generated, Insertable, Selectable, Updateable } from 'kysely'
package/src/utils.ts DELETED
@@ -1,62 +0,0 @@
1
- import type { Database } from '@stacksjs/orm'
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
- import { Kysely, MysqlDialect, PostgresDialect, sql } from 'kysely'
7
- import { BunWorkerDialect } from 'kysely-bun-worker'
8
- import { createPool } from 'mysql2'
9
- import { Pool } from 'pg'
10
-
11
- const appEnv = app.env || 'local'
12
-
13
- export function getDialect(): MysqlDialect | PostgresDialect | BunWorkerDialect {
14
- const driver = database.default ?? 'sqlite'
15
-
16
- log.debug(`Using database driver: ${driver}`)
17
-
18
- if (driver === 'sqlite') {
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
-
23
- return new BunWorkerDialect({
24
- url: dbPath,
25
- })
26
- }
27
-
28
- if (driver === 'mysql') {
29
- return new MysqlDialect({
30
- pool: createPool({
31
- database: database.connections?.mysql?.name || 'stacks', // Use modified dbName
32
- host: database.connections?.mysql?.host ?? '127.0.0.1',
33
- user: database.connections?.mysql?.username ?? 'root',
34
- password: database.connections?.mysql?.password ?? '',
35
- port: database.connections?.mysql?.port ?? 3306,
36
- }),
37
- })
38
- }
39
-
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
-
44
- return new PostgresDialect({
45
- pool: new Pool({
46
- database: finalPgDbName, // Use modified pgDbName
47
- host: database.connections?.postgres?.host ?? '127.0.0.1',
48
- user: database.connections?.postgres?.username ?? '',
49
- password: database.connections?.postgres?.password ?? '',
50
- port: database.connections?.postgres?.port ?? 5432,
51
- }),
52
- })
53
- }
54
-
55
- throw new Error(`Unsupported driver: ${driver}`)
56
- }
57
-
58
- export const now: RawBuilder<any> = sql`now()`
59
-
60
- export const db: Kysely<Database> = new Kysely<Database>({
61
- dialect: getDialect(),
62
- })