@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.
@@ -1,37 +1,36 @@
1
+ import type { Attribute, Attributes, Model } from '@stacksjs/types'
1
2
  import { italic, log } from '@stacksjs/cli'
2
3
  import { db } from '@stacksjs/database'
3
- import { ok } from '@stacksjs/error-handling'
4
- import { getModelName, getTableName } from '@stacksjs/orm'
4
+ import { type Ok, ok } from '@stacksjs/error-handling'
5
+ import { fetchOtherModelRelations, getModelName, getPivotTables, getTableName } from '@stacksjs/orm'
5
6
  import { path } from '@stacksjs/path'
6
- import { fs, glob } from '@stacksjs/storage'
7
+
8
+ import { fs, globSync } from '@stacksjs/storage'
7
9
  import { snakeCase } from '@stacksjs/strings'
8
- import type { Attribute, Attributes, Model } from '@stacksjs/types'
9
10
  import {
10
11
  arrangeColumns,
11
12
  checkPivotMigration,
12
- fetchOtherModelRelations,
13
- findCharacterLength,
13
+ fetchTables,
14
14
  findDifferingKeys,
15
15
  getLastMigrationFields,
16
- getPivotTables,
17
16
  hasTableBeenMigrated,
18
17
  isArrayEqual,
19
18
  mapFieldTypeToColumnType,
20
19
  pluckChanges,
21
20
  } from '.'
22
21
 
23
- export async function resetMysqlDatabase() {
24
- const tables = await fetchMysqlTables()
22
+ export async function resetMysqlDatabase(): Promise<Ok<string, never>> {
23
+ const tables = await fetchTables()
25
24
 
26
25
  for (const table of tables) await db.schema.dropTable(table).ifExists().execute()
27
26
 
28
27
  await db.schema.dropTable('migrations').ifExists().execute()
29
28
  await db.schema.dropTable('migration_locks').ifExists().execute()
29
+ await db.schema.dropTable('migrations').ifExists().execute()
30
30
 
31
31
  const files = await fs.readdir(path.userMigrationsPath())
32
32
  const modelFiles = await fs.readdir(path.frameworkPath('database/models'))
33
-
34
- const userModelFiles = glob.sync(path.userModelsPath('*.ts'))
33
+ const userModelFiles = globSync([path.userModelsPath('*.ts')], { absolute: true })
35
34
 
36
35
  for (const userModel of userModelFiles) {
37
36
  const model = (await import(userModel)).default as Model
@@ -45,7 +44,8 @@ export async function resetMysqlDatabase() {
45
44
  if (modelFile.endsWith('.ts')) {
46
45
  const modelPath = path.frameworkPath(`database/models/${modelFile}`)
47
46
 
48
- if (fs.existsSync(modelPath)) await Bun.$`rm ${modelPath}`
47
+ if (fs.existsSync(modelPath))
48
+ await Bun.$`rm ${modelPath}`
49
49
  }
50
50
  }
51
51
  }
@@ -55,7 +55,8 @@ export async function resetMysqlDatabase() {
55
55
  if (file.endsWith('.ts')) {
56
56
  const migrationPath = path.userMigrationsPath(`${file}`)
57
57
 
58
- if (fs.existsSync(migrationPath)) await Bun.$`rm ${migrationPath}`
58
+ if (fs.existsSync(migrationPath))
59
+ await Bun.$`rm ${migrationPath}`
59
60
  }
60
61
  }
61
62
  }
@@ -63,9 +64,9 @@ export async function resetMysqlDatabase() {
63
64
  return ok('All tables dropped successfully!')
64
65
  }
65
66
 
66
- export async function generateMysqlMigration(modelPath: string) {
67
+ export async function generateMysqlMigration(modelPath: string): Promise<void> {
67
68
  // check if any files are in the database folder
68
- const files = await fs.readdir(path.userMigrationsPath())
69
+ // const files = await fs.readdir(path.userMigrationsPath())
69
70
 
70
71
  // if (files.length === 0) {
71
72
  // log.debug('No migrations found in the database folder, deleting all framework/database/*.json files...')
@@ -84,7 +85,7 @@ export async function generateMysqlMigration(modelPath: string) {
84
85
 
85
86
  const model = (await import(modelPath)).default as Model
86
87
  const fileName = path.basename(modelPath)
87
- const tableName = await getTableName(model, modelPath)
88
+ const tableName = getTableName(model, modelPath)
88
89
 
89
90
  const fieldsString = JSON.stringify(model.attributes, null, 2) // Pretty print the JSON
90
91
  const copiedModelPath = path.frameworkPath(`database/models/${fileName}`)
@@ -105,7 +106,8 @@ export async function generateMysqlMigration(modelPath: string) {
105
106
 
106
107
  haveFieldsChanged = true
107
108
  log.debug(`Fields have changed for ${tableName}`)
108
- } else {
109
+ }
110
+ else {
109
111
  log.debug(`Fields have not been generated for ${tableName}`)
110
112
  }
111
113
 
@@ -120,17 +122,19 @@ export async function generateMysqlMigration(modelPath: string) {
120
122
 
121
123
  log.debug(`Has ${tableName} been migrated? ${hasBeenMigrated}`)
122
124
 
123
- if (haveFieldsChanged) await createAlterTableMigration(modelPath)
125
+ if (haveFieldsChanged)
126
+ await createAlterTableMigration(modelPath)
124
127
  else await createTableMigration(modelPath)
125
128
  }
126
129
 
127
- async function createTableMigration(modelPath: string) {
130
+ async function createTableMigration(modelPath: string): Promise<void> {
128
131
  log.debug('createTableMigration modelPath:', modelPath)
129
132
 
130
133
  const model = (await import(modelPath)).default as Model
131
- const tableName = await getTableName(model, modelPath)
134
+ const tableName = getTableName(model, modelPath)
132
135
 
133
- const twoFactorEnabled = model.traits?.useAuth?.useTwoFactor
136
+ const twoFactorEnabled
137
+ = model.traits?.useAuth && typeof model.traits.useAuth !== 'boolean' ? model.traits.useAuth.useTwoFactor : false
134
138
 
135
139
  await createPivotTableMigration(model, modelPath)
136
140
  const otherModelRelations = await fetchOtherModelRelations(model, modelPath)
@@ -138,6 +142,11 @@ async function createTableMigration(modelPath: string) {
138
142
  const useTimestamps = model?.traits?.useTimestamps ?? model?.traits?.timestampable ?? true
139
143
  const useSoftDeletes = model?.traits?.useSoftDeletes ?? model?.traits?.softDeletable ?? false
140
144
 
145
+ const usePasskey = (typeof model.traits?.useAuth === 'object' && model.traits.useAuth.usePasskey) ?? false
146
+
147
+ if (usePasskey)
148
+ await createPasskeyMigration()
149
+
141
150
  let migrationContent = `import type { Database } from '@stacksjs/database'\n`
142
151
  migrationContent += `import { sql } from '@stacksjs/database'\n\n`
143
152
  migrationContent += `export async function up(db: Database<any>) {\n`
@@ -154,15 +163,17 @@ async function createTableMigration(modelPath: string) {
154
163
  // Check if there are configurations that require the lambda function
155
164
  if (fieldOptions.unique || fieldOptions?.required) {
156
165
  migrationContent += `, col => col`
157
- if (fieldOptions.unique) migrationContent += `.unique()`
158
- if (fieldOptions?.required) migrationContent += `.notNull()`
166
+ if (fieldOptions.unique)
167
+ migrationContent += `.unique()`
168
+ if (fieldOptions?.required)
169
+ migrationContent += `.notNull()`
159
170
  migrationContent += ``
160
171
  }
161
172
 
162
173
  migrationContent += `)\n`
163
174
  }
164
175
 
165
- if (false !== twoFactorEnabled && twoFactorEnabled) {
176
+ if (twoFactorEnabled !== false && twoFactorEnabled) {
166
177
  migrationContent += ` .addColumn('two_factor_secret', 'varchar(255)')\n`
167
178
  }
168
179
 
@@ -174,14 +185,18 @@ async function createTableMigration(modelPath: string) {
174
185
  }
175
186
  }
176
187
 
188
+ if (usePasskey)
189
+ migrationContent += ` .addColumn('public_passkey', 'text')\n`
190
+
177
191
  // Append created_at and updated_at columns if useTimestamps is true
178
192
  if (useTimestamps) {
179
193
  migrationContent += ` .addColumn('created_at', 'timestamp', col => col.notNull().defaultTo(sql.raw('CURRENT_TIMESTAMP')))\n`
180
- migrationContent += ` .addColumn('updated_at', 'timestamp', col => col.notNull().defaultTo(sql.raw('CURRENT_TIMESTAMP')))\n`
194
+ migrationContent += ` .addColumn('updated_at', 'timestamp')\n`
181
195
  }
182
196
 
183
197
  // Append deleted_at column if useSoftDeletes is true
184
- if (useSoftDeletes) migrationContent += ` .addColumn('deleted_at', 'timestamp')\n`
198
+ if (useSoftDeletes)
199
+ migrationContent += ` .addColumn('deleted_at', 'timestamp')\n`
185
200
 
186
201
  migrationContent += ` .execute()\n`
187
202
  migrationContent += `}\n`
@@ -190,20 +205,59 @@ async function createTableMigration(modelPath: string) {
190
205
  const migrationFileName = `${timestamp}-create-${tableName}-table.ts`
191
206
  const migrationFilePath = path.userMigrationsPath(migrationFileName)
192
207
 
208
+ // eslint-disable-next-line no-console
209
+ console.log(migrationFilePath)
210
+
193
211
  Bun.write(migrationFilePath, migrationContent)
194
212
 
195
213
  log.success(`Created migration: ${italic(migrationFileName)}`)
196
214
  }
197
215
 
198
- async function createPivotTableMigration(model: Model, modelPath: string) {
216
+ async function createPasskeyMigration() {
217
+ const hasBeenMigrated = await hasTableBeenMigrated('users')
218
+
219
+ if (hasBeenMigrated)
220
+ return
221
+
222
+ let migrationContent = `import type { Database } from '@stacksjs/database'\n`
223
+ migrationContent += `export async function up(db: Database<any>) {\n`
224
+ migrationContent += ` await db.schema\n`
225
+ migrationContent += ` .createTable('passkeys')\n`
226
+ migrationContent += ` .addColumn('id', 'integer', col => col.primaryKey().autoIncrement())\n`
227
+ migrationContent += ` .addColumn('cred_public_key', 'text')\n`
228
+ migrationContent += ` .addColumn('user_id', 'integer')\n`
229
+ migrationContent += ` .addColumn('webauthn_user_id', 'varchar(255)')\n`
230
+ migrationContent += ` .addColumn('counter', 'integer')\n`
231
+ migrationContent += ` .addColumn('device_type', 'varchar(255)')\n`
232
+ migrationContent += ` .addColumn('backup_eligible', 'boolean')\n`
233
+ migrationContent += ` .addColumn('backup_status', 'boolean')\n`
234
+ migrationContent += ` .addColumn('transports', 'varchar(255)')\n`
235
+ migrationContent += ` .addColumn('last_used_at', 'text')\n`
236
+ migrationContent += ` .addColumn('created_at', 'timestamp', col => col.notNull().defaultTo(sql.raw('CURRENT_TIMESTAMP')))\n`
237
+ migrationContent += ` .execute()\n`
238
+ migrationContent += ` }\n`
239
+
240
+ const timestamp = new Date().getTime().toString()
241
+ const migrationFileName = `${timestamp}-create-passkeys-table.ts`
242
+
243
+ const migrationFilePath = path.userMigrationsPath(migrationFileName)
244
+
245
+ Bun.write(migrationFilePath, migrationContent)
246
+
247
+ log.success(`Created pivot migration: ${migrationFileName}`)
248
+ }
249
+
250
+ async function createPivotTableMigration(model: Model, modelPath: string): Promise<void> {
199
251
  const pivotTables = await getPivotTables(model, modelPath)
200
252
 
201
- if (!pivotTables.length) return
253
+ if (!pivotTables.length)
254
+ return
202
255
 
203
256
  for (const pivotTable of pivotTables) {
204
257
  const hasBeenMigrated = await checkPivotMigration(pivotTable.table)
205
258
 
206
- if (hasBeenMigrated) return
259
+ if (hasBeenMigrated)
260
+ return
207
261
 
208
262
  let migrationContent = `import type { Database } from '@stacksjs/database'\n`
209
263
  migrationContent += `export async function up(db: Database<any>) {\n`
@@ -217,6 +271,7 @@ async function createPivotTableMigration(model: Model, modelPath: string) {
217
271
 
218
272
  const timestamp = new Date().getTime().toString()
219
273
  const migrationFileName = `${timestamp}-create-${pivotTable.table}-table.ts`
274
+
220
275
  const migrationFilePath = path.userMigrationsPath(migrationFileName)
221
276
 
222
277
  Bun.write(migrationFilePath, migrationContent)
@@ -225,12 +280,10 @@ async function createPivotTableMigration(model: Model, modelPath: string) {
225
280
  }
226
281
  }
227
282
 
228
- export async function createAlterTableMigration(modelPath: string) {
229
- console.log('createAlterTableMigration')
230
-
283
+ export async function createAlterTableMigration(modelPath: string): Promise<void> {
231
284
  const model = (await import(modelPath)).default as Model
232
285
  const modelName = getModelName(model, modelPath)
233
- const tableName = await getTableName(model, modelPath)
286
+ const tableName = getTableName(model, modelPath)
234
287
  let hasChanged = false
235
288
 
236
289
  // Assuming you have a function to get the fields from the last migration
@@ -257,7 +310,6 @@ export async function createAlterTableMigration(modelPath: string) {
257
310
  }
258
311
 
259
312
  const fieldValidations = findDifferingKeys(lastFields, currentFields)
260
-
261
313
  for (const fieldValidation of fieldValidations) {
262
314
  hasChanged = true
263
315
  const fieldNameFormatted = snakeCase(fieldValidation.key)
@@ -278,8 +330,10 @@ export async function createAlterTableMigration(modelPath: string) {
278
330
  // Check if there are configurations that require the lambda function
279
331
  if (options.unique || options?.required) {
280
332
  migrationContent += `, col => col`
281
- if (options.unique) migrationContent += `.unique()`
282
- if (options?.required) migrationContent += `.notNull()`
333
+ if (options.unique)
334
+ migrationContent += `.unique()`
335
+ if (options?.required)
336
+ migrationContent += `.notNull()`
283
337
  migrationContent += ``
284
338
  }
285
339
 
@@ -289,10 +343,11 @@ export async function createAlterTableMigration(modelPath: string) {
289
343
  // Remove fields that no longer exist
290
344
  for (const fieldName of fieldsToRemove) migrationContent += ` .dropColumn('${fieldName}')\n`
291
345
 
292
- if (fieldsToAdd.length || fieldsToRemove.length) migrationContent += ` .execute();\n`
346
+ if (fieldsToAdd.length || fieldsToRemove.length)
347
+ migrationContent += ` .execute();\n`
293
348
 
294
- const lastFieldOrder = Object.values(lastFields).map((attr) => attr.order)
295
- const currentFieldOrder = Object.values(currentFields).map((attr) => attr.order)
349
+ const lastFieldOrder = Object.values(lastFields).map(attr => attr.order)
350
+ const currentFieldOrder = Object.values(currentFields).map(attr => attr.order)
296
351
 
297
352
  if (!isArrayEqual(lastFieldOrder, currentFieldOrder)) {
298
353
  hasChanged = true
@@ -317,7 +372,7 @@ function reArrangeColumns(attributes: Attributes | undefined, tableName: string)
317
372
  let migrationContent = ''
318
373
 
319
374
  let previousField = ''
320
- for (const [fieldName, options] of fields) {
375
+ for (const [fieldName] of fields) {
321
376
  const fieldNameFormatted = snakeCase(fieldName)
322
377
 
323
378
  if (previousField) {
@@ -332,17 +387,3 @@ function reArrangeColumns(attributes: Attributes | undefined, tableName: string)
332
387
 
333
388
  return migrationContent
334
389
  }
335
-
336
- export async function fetchMysqlTables(): Promise<string[]> {
337
- const modelFiles = glob.sync(path.userModelsPath('*.ts'))
338
- const tables: string[] = []
339
-
340
- for (const modelPath of modelFiles) {
341
- const model = (await import(modelPath)).default as Model
342
- const tableName = await getTableName(model, modelPath)
343
-
344
- tables.push(tableName)
345
- }
346
-
347
- return tables
348
- }
@@ -1,24 +1,22 @@
1
+ import type { Attribute, Attributes, Model } from '@stacksjs/types'
1
2
  import { italic, log } from '@stacksjs/cli'
2
3
  import { db } from '@stacksjs/database'
3
4
  import { ok } from '@stacksjs/error-handling'
4
- import { getTableName } from '@stacksjs/orm'
5
+ import { fetchOtherModelRelations, getPivotTables, getTableName } from '@stacksjs/orm'
5
6
  import { path } from '@stacksjs/path'
6
- import { fs, glob } from '@stacksjs/storage'
7
+ import { fs, globSync } from '@stacksjs/storage'
7
8
  import { snakeCase } from '@stacksjs/strings'
8
- import type { Attribute, Attributes, Model } from '@stacksjs/types'
9
9
  import {
10
10
  arrangeColumns,
11
11
  checkPivotMigration,
12
- fetchOtherModelRelations,
13
12
  getLastMigrationFields,
14
- getPivotTables,
15
13
  hasTableBeenMigrated,
16
14
  mapFieldTypeToColumnType,
17
15
  pluckChanges,
18
16
  } from '.'
19
17
 
20
18
  export async function resetPostgresDatabase() {
21
- const tables = await fetchMysqlTables()
19
+ const tables = await fetchPostgresTables()
22
20
 
23
21
  for (const table of tables) await db.schema.dropTable(table).ifExists().execute()
24
22
 
@@ -28,7 +26,7 @@ export async function resetPostgresDatabase() {
28
26
  const files = await fs.readdir(path.userMigrationsPath())
29
27
  const modelFiles = await fs.readdir(path.frameworkPath('database/models'))
30
28
 
31
- const userModelFiles = glob.sync(path.userModelsPath('*.ts'))
29
+ const userModelFiles = globSync([path.userModelsPath('*.ts')], { absolute: true })
32
30
 
33
31
  for (const userModel of userModelFiles) {
34
32
  const userModelPath = (await import(userModel)).default
@@ -43,7 +41,8 @@ export async function resetPostgresDatabase() {
43
41
  if (modelFile.endsWith('.ts')) {
44
42
  const modelPath = path.frameworkPath(`database/models/${modelFile}`)
45
43
 
46
- if (fs.existsSync(modelPath)) await Bun.$`rm ${modelPath}`
44
+ if (fs.existsSync(modelPath))
45
+ await Bun.$`rm ${modelPath}`
47
46
  }
48
47
  }
49
48
  }
@@ -53,7 +52,8 @@ export async function resetPostgresDatabase() {
53
52
  if (file.endsWith('.ts')) {
54
53
  const migrationPath = path.userMigrationsPath(`${file}`)
55
54
 
56
- if (fs.existsSync(migrationPath)) await Bun.$`rm ${migrationPath}`
55
+ if (fs.existsSync(migrationPath))
56
+ await Bun.$`rm ${migrationPath}`
57
57
  }
58
58
  }
59
59
  }
@@ -61,7 +61,7 @@ export async function resetPostgresDatabase() {
61
61
  return ok('All tables dropped successfully!')
62
62
  }
63
63
 
64
- export async function generatePostgresMigration(modelPath: string) {
64
+ export async function generatePostgresMigration(modelPath: string): Promise<void> {
65
65
  // check if any files are in the database folder
66
66
  const files = await fs.readdir(path.userMigrationsPath())
67
67
 
@@ -75,7 +75,8 @@ export async function generatePostgresMigration(modelPath: string) {
75
75
  log.debug('No existing model files in framework path...')
76
76
 
77
77
  for (const file of modelFiles) {
78
- if (file.endsWith('.ts')) await fs.unlink(path.frameworkPath(`database/models/${file}`))
78
+ if (file.endsWith('.ts'))
79
+ await fs.unlink(path.frameworkPath(`database/models/${file}`))
79
80
  }
80
81
  }
81
82
  }
@@ -103,7 +104,8 @@ export async function generatePostgresMigration(modelPath: string) {
103
104
 
104
105
  haveFieldsChanged = true
105
106
  log.debug(`Fields have changed for ${tableName}`)
106
- } else {
107
+ }
108
+ else {
107
109
  log.debug(`Fields have not been generated for ${tableName}`)
108
110
  }
109
111
 
@@ -118,7 +120,8 @@ export async function generatePostgresMigration(modelPath: string) {
118
120
 
119
121
  log.debug(`Has ${tableName} been migrated? ${hasBeenMigrated}`)
120
122
 
121
- if (haveFieldsChanged) await createAlterTableMigration(modelPath)
123
+ if (haveFieldsChanged)
124
+ await createAlterTableMigration(modelPath)
122
125
  else await createTableMigration(modelPath)
123
126
  }
124
127
 
@@ -144,14 +147,16 @@ async function createTableMigration(modelPath: string) {
144
147
  for (const [fieldName, options] of arrangeColumns(model.attributes)) {
145
148
  const fieldOptions = options as Attribute
146
149
  const fieldNameFormatted = snakeCase(fieldName)
147
- const columnType = mapFieldTypeToColumnType(fieldOptions.validations?.rule)
150
+ const columnType = mapFieldTypeToColumnType(fieldOptions.validation?.rule)
148
151
  migrationContent += ` .addColumn('${fieldNameFormatted}', '${columnType}'`
149
152
 
150
153
  // Check if there are configurations that require the lambda function
151
- if (fieldOptions.unique || fieldOptions.validations?.rule?.required) {
154
+ if (fieldOptions.unique || fieldOptions.validation?.rule?.required) {
152
155
  migrationContent += `, col => col`
153
- if (fieldOptions.unique) migrationContent += `.unique()`
154
- if (fieldOptions.validations?.rule?.required) migrationContent += `.notNull()`
156
+ if (fieldOptions.unique)
157
+ migrationContent += `.unique()`
158
+ if (fieldOptions.validation?.rule?.required)
159
+ migrationContent += `.notNull()`
155
160
  migrationContent += ``
156
161
  }
157
162
 
@@ -173,7 +178,8 @@ async function createTableMigration(modelPath: string) {
173
178
  }
174
179
 
175
180
  // Append deleted_at column if useSoftDeletes is true
176
- if (useSoftDeletes) migrationContent += ` .addColumn('deleted_at', 'timestamp')\n`
181
+ if (useSoftDeletes)
182
+ migrationContent += ` .addColumn('deleted_at', 'timestamp')\n`
177
183
 
178
184
  migrationContent += ` .execute()\n`
179
185
  migrationContent += `}\n`
@@ -191,11 +197,13 @@ async function createTableMigration(modelPath: string) {
191
197
  async function createPivotTableMigration(model: Model, modelPath: string) {
192
198
  const pivotTables = await getPivotTables(model, modelPath)
193
199
 
194
- if (!pivotTables.length) return
200
+ if (!pivotTables.length)
201
+ return
195
202
  for (const pivotTable of pivotTables) {
196
203
  const hasBeenMigrated = await checkPivotMigration(pivotTable.table)
197
204
 
198
- if (hasBeenMigrated) return
205
+ if (hasBeenMigrated)
206
+ return
199
207
 
200
208
  let migrationContent = `import type { Database } from '@stacksjs/database'\n`
201
209
  migrationContent += `import { sql } from '@stacksjs/database'\n\n`
@@ -219,23 +227,18 @@ async function createPivotTableMigration(model: Model, modelPath: string) {
219
227
  }
220
228
  }
221
229
 
222
- export async function createAlterTableMigration(modelPath: string) {
223
- console.log('createAlterTableMigration')
224
-
230
+ async function createAlterTableMigration(modelPath: string) {
225
231
  const model = (await import(modelPath)).default as Model
226
232
  const modelName = path.basename(modelPath)
227
- const tableName = await getTableName(model, modelPath)
233
+ const tableName = getTableName(model, modelPath)
228
234
 
229
235
  // Assuming you have a function to get the fields from the last migration
230
236
  // For simplicity, this is not implemented here
231
237
  const lastMigrationFields = await getLastMigrationFields(modelName)
232
238
  const lastFields = lastMigrationFields ?? {}
233
239
  const currentFields = model.attributes as Attributes
234
-
235
240
  const changes = pluckChanges(Object.keys(lastFields), Object.keys(currentFields))
236
-
237
241
  const fieldsToAdd = changes?.added || []
238
-
239
242
  const fieldsToRemove = changes?.removed || []
240
243
 
241
244
  let migrationContent = `import type { Database } from '@stacksjs/database'\n`
@@ -246,7 +249,7 @@ export async function createAlterTableMigration(modelPath: string) {
246
249
  // Add new fields
247
250
  for (const fieldName of fieldsToAdd) {
248
251
  const options = currentFields[fieldName] as Attribute
249
- const columnType = mapFieldTypeToColumnType(options.validations?.rule)
252
+ const columnType = mapFieldTypeToColumnType(options.validation?.rule)
250
253
  migrationContent += ` .addColumn('${fieldName}', '${columnType}')\n`
251
254
  }
252
255
 
@@ -266,14 +269,13 @@ export async function createAlterTableMigration(modelPath: string) {
266
269
  log.success(`Created migration: ${italic(migrationFileName)}`)
267
270
  }
268
271
 
269
- export async function fetchMysqlTables(): Promise<string[]> {
270
- const modelFiles = glob.sync(path.userModelsPath('*.ts'))
272
+ export async function fetchPostgresTables(): Promise<string[]> {
273
+ const modelFiles = globSync([path.userModelsPath('*.ts')])
271
274
  const tables: string[] = []
272
275
 
273
276
  for (const modelPath of modelFiles) {
274
277
  const model = (await import(modelPath)).default
275
-
276
- const tableName = await getTableName(model, modelPath)
278
+ const tableName = getTableName(model, modelPath)
277
279
 
278
280
  tables.push(tableName)
279
281
  }