@platformatic/db 3.4.1 → 3.5.1

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.
Files changed (61) hide show
  1. package/README.md +1 -1
  2. package/config.d.ts +442 -107
  3. package/eslint.config.js +9 -5
  4. package/index.d.ts +53 -31
  5. package/index.js +30 -139
  6. package/lib/application.js +102 -0
  7. package/lib/capability.js +35 -0
  8. package/lib/commands/index.js +59 -0
  9. package/lib/commands/migrations-apply.js +63 -0
  10. package/lib/commands/migrations-create.js +48 -0
  11. package/lib/commands/print-schema.js +31 -0
  12. package/lib/commands/seed.js +74 -0
  13. package/lib/commands/types.js +22 -0
  14. package/lib/config.js +52 -0
  15. package/lib/errors.js +16 -12
  16. package/lib/generator.js +229 -0
  17. package/lib/{migrator.mjs → migrator.js} +46 -38
  18. package/lib/{root-endpoint/index.js → root.js} +6 -7
  19. package/lib/schema.js +41 -20
  20. package/lib/{generator/code-templates.js → templates.js} +57 -16
  21. package/lib/types.js +161 -0
  22. package/lib/upgrade.js +8 -12
  23. package/lib/utils.js +12 -23
  24. package/lib/versions/0.18.0.js +3 -5
  25. package/lib/versions/{from-zero-twenty-height-to-will-see.js → 0.28.0.js} +3 -5
  26. package/lib/versions/2.0.0.js +3 -5
  27. package/lib/versions/3.0.0.js +14 -0
  28. package/package.json +32 -40
  29. package/schema.json +1385 -164
  30. package/tsconfig.json +16 -6
  31. package/db.mjs +0 -86
  32. package/help/compile.txt +0 -17
  33. package/help/create.txt +0 -13
  34. package/help/help.txt +0 -11
  35. package/help/migrations apply.txt +0 -45
  36. package/help/migrations create.txt +0 -27
  37. package/help/migrations.txt +0 -4
  38. package/help/schema.txt +0 -25
  39. package/help/seed.txt +0 -36
  40. package/help/start.txt +0 -47
  41. package/help/types.txt +0 -40
  42. package/index.test-d.ts +0 -43
  43. package/lib/adjust-config.js +0 -42
  44. package/lib/create.mjs +0 -89
  45. package/lib/gen-migration.mjs +0 -53
  46. package/lib/gen-schema.mjs +0 -68
  47. package/lib/gen-types.mjs +0 -202
  48. package/lib/generator/README.md +0 -38
  49. package/lib/generator/db-generator.js +0 -260
  50. package/lib/generator.d.ts +0 -7
  51. package/lib/migrate.mjs +0 -81
  52. package/lib/seed.mjs +0 -90
  53. package/lib/stackable.js +0 -49
  54. /package/{lib/root-endpoint/public → public}/images/dark_mode.svg +0 -0
  55. /package/{lib/root-endpoint/public → public}/images/favicon.ico +0 -0
  56. /package/{lib/root-endpoint/public → public}/images/light_mode.svg +0 -0
  57. /package/{lib/root-endpoint/public → public}/images/platformatic-logo-dark.svg +0 -0
  58. /package/{lib/root-endpoint/public → public}/images/platformatic-logo-light.svg +0 -0
  59. /package/{lib/root-endpoint/public → public}/images/triangle_dark.svg +0 -0
  60. /package/{lib/root-endpoint/public → public}/images/triangle_light.svg +0 -0
  61. /package/{lib/root-endpoint/public → public}/index.html +0 -0
@@ -0,0 +1,74 @@
1
+ import { kMetadata, loadConfiguration, loadModule } from '@platformatic/foundation'
2
+ import { access } from 'fs/promises'
3
+ import { createRequire } from 'node:module'
4
+ import { resolve } from 'node:path'
5
+ import { transform } from '../config.js'
6
+ import { MissingSeedFileError } from '../errors.js'
7
+ import { Migrator } from '../migrator.js'
8
+ import { schema } from '../schema.js'
9
+ import { setupDB } from '../utils.js'
10
+
11
+ export async function seed (logger, configFile, args, { colorette: { bold }, logFatalError }) {
12
+ const config = await loadConfiguration(configFile, schema, { transform })
13
+
14
+ if (config.migrations !== undefined) {
15
+ const migrator = new Migrator(config.migrations, config.db, logger)
16
+
17
+ try {
18
+ const hasMigrationsToApply = await migrator.hasMigrationsToApply()
19
+ if (hasMigrationsToApply) {
20
+ logFatalError(logger, 'You must apply migrations before seeding the database.')
21
+ return
22
+ }
23
+ } finally {
24
+ await migrator.close()
25
+ }
26
+ }
27
+
28
+ if (!args.length) {
29
+ throw new MissingSeedFileError()
30
+ }
31
+
32
+ const root = config[kMetadata].root
33
+ const seedFile = resolve(root, args[0])
34
+ await access(seedFile)
35
+
36
+ logger.info(`Seeding from ${bold(seedFile)}`)
37
+
38
+ const importedModule = await loadModule(createRequire(resolve(root, 'noop.js')), seedFile)
39
+
40
+ const seedFunction = typeof importedModule?.seed !== 'function' ? importedModule : importedModule.seed
41
+
42
+ if (typeof seedFunction !== 'function') {
43
+ logFatalError(logger, 'Cannot find seed function.')
44
+ logFatalError(logger, "If you use an ESM module use the signature 'export async function seed (opts)'.")
45
+ logFatalError(logger, "If you use a CJS module use the signature 'module.exports = async function seed (opts)'.")
46
+ logFatalError(logger, "If you use Typescript use the signature 'export async function seed(opts)'")
47
+ return
48
+ }
49
+
50
+ const { db, sql, entities } = await setupDB(logger, config.db)
51
+ await seedFunction({ db, sql, entities, logger })
52
+ logger.info('Seeding complete.')
53
+
54
+ // Once done seeding, close your connection.
55
+ await db.dispose()
56
+ }
57
+
58
+ export const helpFooter = `
59
+ This is a convenience method that loads a JavaScript file and configure @platformatic/sql-mapper to connect to the database specified in the configuration file.
60
+
61
+ Here is an example of a seed file:
62
+
63
+ \`\`\`
64
+ 'use strict'
65
+
66
+ module.exports = async function ({ entities, db, sql }) {
67
+ await entities.graph.save({ input: { name: 'Hello' } })
68
+ await db.query(sql\`INSERT INTO graphs (name) VALUES ('Hello 2');\`)
69
+ }
70
+ \`\`\`
71
+
72
+ You can find more details about the configuration format here:
73
+ * [Platformatic DB Configuration](https://docs.platformatic.dev/docs/db/configuration)
74
+ `
@@ -0,0 +1,22 @@
1
+ import { loadConfiguration } from '@platformatic/foundation'
2
+ import { transform } from '../config.js'
3
+ import { schema } from '../schema.js'
4
+ import { execute } from '../types.js'
5
+
6
+ export async function generateTypes (logger, configFile, _args) {
7
+ const config = await loadConfiguration(configFile, schema, { transform })
8
+
9
+ const count = await execute({ logger, config })
10
+
11
+ if (count === 0) {
12
+ logger.warn('No entities found in your schema. Types were NOT generated.')
13
+ logger.warn('Make sure you have applied all the migrations and try again.')
14
+ }
15
+ }
16
+
17
+ export const helpFooter = `
18
+ As a result of executing this command, the Platformatic DB will generate a \`types\` folder with a typescript file for each database entity. It will also generate a \`plt-env.d.ts\` file that injects the types into the Application instance.
19
+
20
+ You can find more details about the configuration format here:
21
+ * [Platformatic DB Configuration](https://docs.platformatic.dev/docs/db/configuration)
22
+ `
package/lib/config.js ADDED
@@ -0,0 +1,52 @@
1
+ import { kMetadata } from '@platformatic/foundation'
2
+ import { transform as serviceTransform } from '@platformatic/service'
3
+ import { readFile } from 'node:fs/promises'
4
+ import { resolve as resolvePath } from 'node:path'
5
+
6
+ export async function transform (config) {
7
+ config = await serviceTransform(config)
8
+
9
+ if (
10
+ config.db &&
11
+ config.db.connectionString.indexOf('sqlite') === 0 &&
12
+ config.db.connectionString !== 'sqlite://:memory:'
13
+ ) {
14
+ const originalSqlitePath = config.db.connectionString.replace('sqlite://', '')
15
+ const sqliteFullPath = resolvePath(config[kMetadata].root, originalSqlitePath)
16
+ config.db.connectionString = 'sqlite://' + sqliteFullPath
17
+ }
18
+
19
+ /* c8 ignore next 3 */
20
+ if (config.db.graphql?.schemaPath) {
21
+ config.db.graphql.schema = await readFile(config.db.graphql.schemaPath, 'utf8')
22
+ }
23
+
24
+ /* c8 ignore next 2 */
25
+ const arePostgresqlSchemaDefined =
26
+ config.db?.connectionString.indexOf('postgres') === 0 && config.db?.schema?.length > 0
27
+ const migrationsTableName = arePostgresqlSchemaDefined ? 'public.versions' : 'versions'
28
+
29
+ // relative-to-absolute migrations path
30
+ if (config.migrations) {
31
+ config.migrations.table = config.migrations.table || migrationsTableName
32
+ }
33
+
34
+ if (config.migrations && config.db) {
35
+ // TODO remove the ignores
36
+ /* c8 ignore next 4 */
37
+ config.db.ignore = config.db.ignore || {}
38
+ config.db.ignore = Object.assign(
39
+ {},
40
+ {
41
+ [config.migrations.table || migrationsTableName]: true
42
+ },
43
+ config.db.ignore
44
+ )
45
+ }
46
+
47
+ if (config.types?.autogenerate === 'true') {
48
+ config.types.autogenerate = true
49
+ }
50
+
51
+ return config
52
+ }
package/lib/errors.js CHANGED
@@ -1,14 +1,18 @@
1
- 'use strict'
1
+ import createError from '@fastify/error'
2
2
 
3
- const createError = require('@fastify/error')
3
+ export const ERROR_PREFIX = 'PLT_DB'
4
4
 
5
- const ERROR_PREFIX = 'PLT_DB'
6
-
7
- module.exports = {
8
- MigrateMissingMigrationsError: createError(`${ERROR_PREFIX}_MIGRATE_ERROR`, 'Missing "migrations" section in config file'),
9
- UnknownDatabaseError: createError(`${ERROR_PREFIX}_UNKNOWN_DATABASE_ERROR`, 'Unknown database'),
10
- MigrateMissingMigrationsDirError: createError(`${ERROR_PREFIX}_MIGRATE_ERROR`, 'Migrations directory %s does not exist'),
11
- MissingSeedFileError: createError(`${ERROR_PREFIX}_MISSING_SEED_FILE_ERROR`, 'Missing seed file'),
12
- MigrationsToApplyError: createError(`${ERROR_PREFIX}_MIGRATIONS_TO_APPLY_ERROR`, 'You have migrations to apply. Please run `platformatic db migrations apply` first.'),
13
-
14
- }
5
+ export const MigrateMissingMigrationsError = createError(
6
+ `${ERROR_PREFIX}_MIGRATE_ERROR`,
7
+ 'Missing "migrations" section in config file'
8
+ )
9
+ export const UnknownDatabaseError = createError(`${ERROR_PREFIX}_UNKNOWN_DATABASE_ERROR`, 'Unknown database')
10
+ export const MigrateMissingMigrationsDirError = createError(
11
+ `${ERROR_PREFIX}_MIGRATE_ERROR`,
12
+ 'Migrations directory %s does not exist'
13
+ )
14
+ export const MissingSeedFileError = createError(`${ERROR_PREFIX}_MISSING_SEED_FILE_ERROR`, 'Missing seed file')
15
+ export const MigrationsToApplyError = createError(
16
+ `${ERROR_PREFIX}_MIGRATIONS_TO_APPLY_ERROR`,
17
+ 'You have migrations to apply.'
18
+ )
@@ -0,0 +1,229 @@
1
+ import { Generator as ServiceGenerator } from '@platformatic/service'
2
+ import { join } from 'node:path'
3
+ import {
4
+ ENVIRONMENT_TEMPLATE,
5
+ jsHelperMySQL,
6
+ jsHelperPostgres,
7
+ jsHelperSqlite,
8
+ moviesTestJS,
9
+ moviesTestTS,
10
+ README
11
+ } from './templates.js'
12
+
13
+ export class Generator extends ServiceGenerator {
14
+ constructor (opts = {}) {
15
+ super({
16
+ ...opts,
17
+ module: '@platformatic/db'
18
+ })
19
+ this.connectionStrings = {
20
+ postgres: 'postgres://postgres:postgres@127.0.0.1:5432/postgres',
21
+ sqlite: 'sqlite://./db.sqlite',
22
+ mysql: 'mysql://root@127.0.0.1:3306/platformatic',
23
+ mariadb: 'mysql://root@127.0.0.1:3306/platformatic'
24
+ }
25
+ }
26
+
27
+ getConfigFieldsDefinitions () {
28
+ return [
29
+ {
30
+ var: 'DATABASE_URL',
31
+ label: 'What is the connection string?',
32
+ default: this.connectionStrings.sqlite,
33
+ type: 'string',
34
+ configValue: 'connectionString'
35
+ },
36
+ {
37
+ var: 'PLT_APPLY_MIGRATIONS',
38
+ label: 'Should migrations be applied automatically on startup?',
39
+ default: true,
40
+ type: 'boolean'
41
+ }
42
+ ]
43
+ }
44
+
45
+ getDefaultConfig () {
46
+ const defaultBaseConfig = super.getDefaultConfig()
47
+
48
+ return {
49
+ ...defaultBaseConfig,
50
+ database: 'sqlite',
51
+ connectionString: null,
52
+ plugin: true,
53
+ tests: true,
54
+ types: true,
55
+ migrations: 'migrations',
56
+ createMigrations: true
57
+ }
58
+ }
59
+
60
+ async prepareQuestions () {
61
+ if (!this.config.connectionString) {
62
+ const def = this.getConfigFieldsDefinitions().find(q => q.var === 'DATABASE_URL')
63
+ this.questions.push({
64
+ type: 'input',
65
+ name: def.configValue,
66
+ message: def.label,
67
+ default: def.default
68
+ })
69
+ }
70
+
71
+ this.questions.push({
72
+ type: 'list',
73
+ name: 'createMigrations',
74
+ message: 'Do you want to create default migrations?',
75
+ default: true,
76
+ choices: [
77
+ { name: 'yes', value: true },
78
+ { name: 'no', value: false }
79
+ ]
80
+ })
81
+
82
+ await super.prepareQuestions()
83
+ }
84
+
85
+ getMoviesMigrationDo () {
86
+ const key = {
87
+ postgres: 'SERIAL',
88
+ sqlite: 'INTEGER',
89
+ mysql: 'INTEGER UNSIGNED AUTO_INCREMENT',
90
+ mariadb: 'INTEGER UNSIGNED AUTO_INCREMENT'
91
+ }
92
+
93
+ return `
94
+ -- Add SQL in this file to create the database tables for your API
95
+ CREATE TABLE IF NOT EXISTS movies (
96
+ id ${key[this.config.database]} PRIMARY KEY,
97
+ title TEXT NOT NULL
98
+ );
99
+ `
100
+ }
101
+
102
+ getMoviesMigrationUndo () {
103
+ return '-- Add SQL in this file to drop the database tables\nDROP TABLE movies;'
104
+ }
105
+
106
+ setConfigFields (fields) {
107
+ super.setConfigFields(fields)
108
+ this.config.database = this.getDatabaseFromConnectionString()
109
+ }
110
+
111
+ getDatabaseFromConnectionString () {
112
+ if (this.config.connectionString) {
113
+ if (this.config.connectionString.indexOf('://') !== -1) {
114
+ const splitted = this.config.connectionString.split('://')
115
+ return splitted[0]
116
+ }
117
+ return null
118
+ }
119
+ return null
120
+ }
121
+
122
+ async _beforePrepare () {
123
+ if (this.config.isUpdating) {
124
+ return
125
+ }
126
+
127
+ await super._beforePrepare()
128
+
129
+ this.config.connectionString = this.config.connectionString || this.connectionStrings[this.config.database]
130
+ this.config.dependencies = {
131
+ '@platformatic/db': `^${this.platformaticVersion}`
132
+ }
133
+
134
+ if (!this.config.isRuntimeContext) {
135
+ this.addEnvVars(
136
+ {
137
+ PLT_SERVER_HOSTNAME: this.config.hostname,
138
+ PLT_SERVER_LOGGER_LEVEL: 'info',
139
+ PORT: 3042
140
+ },
141
+ { overwrite: false, default: true }
142
+ )
143
+ }
144
+
145
+ this.addEnvVars(
146
+ {
147
+ DATABASE_URL: this.connectionStrings[this.config.database],
148
+ PLT_APPLY_MIGRATIONS: 'true'
149
+ },
150
+ { overwrite: false, default: true }
151
+ )
152
+ }
153
+
154
+ async _afterPrepare () {
155
+ if (this.config.isUpdating) {
156
+ return
157
+ }
158
+
159
+ if (this.config.createMigrations) {
160
+ this.addFile({ path: 'migrations', file: '001.do.sql', contents: this.getMoviesMigrationDo() })
161
+ this.addFile({ path: 'migrations', file: '001.undo.sql', contents: this.getMoviesMigrationUndo() })
162
+ }
163
+
164
+ this.addFile({ path: '', file: 'README.md', contents: README })
165
+
166
+ if (this.config.plugin) {
167
+ switch (this.config.database) {
168
+ case 'sqlite':
169
+ this.testHelperCustomizations = jsHelperSqlite
170
+ break
171
+ case 'mysql':
172
+ this.testHelperCustomizations = jsHelperMySQL(this.config.connectionString)
173
+ break
174
+ case 'postgres':
175
+ this.testHelperCustomizations = jsHelperPostgres(this.config.connectionString)
176
+ break
177
+ case 'mariadb':
178
+ this.testHelperCustomizations = jsHelperMySQL(this.config.connectionString)
179
+ break
180
+ }
181
+
182
+ if (this.config.createMigrations) {
183
+ if (this.config.typescript) {
184
+ this.addFile({ path: join('test', 'routes'), file: 'movies.test.ts', contents: moviesTestTS })
185
+ } else {
186
+ this.addFile({ path: join('test', 'routes'), file: 'movies.test.js', contents: moviesTestJS })
187
+ }
188
+ }
189
+ }
190
+
191
+ super._afterPrepare()
192
+
193
+ this.addFile({ path: '', file: 'plt-env.d.ts', contents: ENVIRONMENT_TEMPLATE })
194
+ }
195
+
196
+ async _getConfigFileContents () {
197
+ const config = await super._getConfigFileContents()
198
+ delete config.service
199
+ config.$schema = `https://schemas.platformatic.dev/@platformatic/db/${this.platformaticVersion}.json`
200
+
201
+ config.db = {
202
+ connectionString: `{${this.getEnvVarName('DATABASE_URL')}}`,
203
+ graphql: true,
204
+ openapi: true,
205
+ schemalock: true
206
+ }
207
+
208
+ config.watch = {
209
+ ignore: ['*.sqlite', '*.sqlite-journal']
210
+ }
211
+
212
+ if (this.config.migrations) {
213
+ config.migrations = {
214
+ dir: this.config.migrations,
215
+ autoApply: `{${this.getEnvVarName('PLT_APPLY_MIGRATIONS')}}`
216
+ }
217
+
218
+ this.addFile({ path: 'migrations', file: '.gitkeep', contents: '' })
219
+ }
220
+
221
+ if (this.config.types === true) {
222
+ config.types = {
223
+ autogenerate: true
224
+ }
225
+ }
226
+
227
+ return config
228
+ }
229
+ }
@@ -1,10 +1,10 @@
1
- import { join, basename } from 'path'
2
- import Postgrator from 'postgrator'
3
1
  import { createConnectionPool } from '@platformatic/sql-mapper'
4
- import { stat, readdir } from 'fs/promises'
5
- import errors from './errors.js'
2
+ import { readdir, stat } from 'node:fs/promises'
3
+ import { basename } from 'node:path'
4
+ import Postgrator from 'postgrator'
5
+ import { MigrateMissingMigrationsDirError, MigrateMissingMigrationsError } from './errors.js'
6
6
 
7
- class Migrator {
7
+ export class Migrator {
8
8
  constructor (migrationConfig, coreConfig, logger) {
9
9
  this.coreConfig = coreConfig
10
10
  this.migrationDir = migrationConfig.dir
@@ -28,7 +28,7 @@ class Migrator {
28
28
 
29
29
  const { db, sql } = await createConnectionPool({
30
30
  ...this.coreConfig,
31
- log: this.logger,
31
+ log: this.logger
32
32
  })
33
33
 
34
34
  let driver
@@ -44,13 +44,12 @@ class Migrator {
44
44
  driver = 'sqlite3'
45
45
  }
46
46
 
47
- const database = driver !== 'sqlite3'
48
- ? new URL(this.coreConfig.connectionString).pathname.replace(/^\//, '')
49
- : ''
47
+ const database = driver !== 'sqlite3' ? new URL(this.coreConfig.connectionString).pathname.replace(/^\//, '') : ''
50
48
 
51
49
  this.db = db
52
50
 
53
- const migrationPattern = join(this.migrationDir, '*')
51
+ // Glob patterns should always use / as a path separator, even on Windows systems, as \ is used to escape glob characters.
52
+ const migrationPattern = this.migrationDir + '/*'
54
53
  this.logger.debug(`Migrating from ${migrationPattern}`)
55
54
 
56
55
  this.postgrator = new Postgrator({
@@ -58,40 +57,31 @@ class Migrator {
58
57
  driver,
59
58
  database,
60
59
  schemaTable: this.migrationsTable || 'versions',
61
- execQuery: async (query) => {
60
+ execQuery: async query => {
62
61
  const res = await db.query(sql`${sql.__dangerous__rawValue(query)}`)
63
62
  return { rows: res }
64
63
  },
65
64
  validateChecksums: this.validateChecksums,
66
65
  newline: this.newline,
67
- currentSchema: ['pg', 'mysql'].includes(driver) ? this.currentSchema : undefined,
66
+ currentSchema: ['pg', 'mysql'].includes(driver) ? this.currentSchema : undefined
68
67
  })
69
68
 
70
69
  if (this.validateChecksums === true) {
71
- this.postgrator.on(
72
- 'validation-started',
73
- (migration) => {
74
- /* c8 ignore next 3 */
75
- const migrationName = basename(migration.filename)
76
- this.logger.info(`verifying checksum of migration ${migrationName}`)
77
- }
78
- )
79
- }
80
- this.postgrator.on(
81
- 'migration-started',
82
- (migration) => {
83
- const migrationName = basename(migration.filename)
84
- this.logger.info(`running ${migrationName}`)
85
- }
86
- )
87
- this.postgrator.on(
88
- 'migration-finished',
89
- (migration) => {
90
- this.appliedMigrationsCount++
70
+ this.postgrator.on('validation-started', migration => {
71
+ /* c8 ignore next 3 */
91
72
  const migrationName = basename(migration.filename)
92
- this.logger.debug(`completed ${migrationName}`)
93
- }
94
- )
73
+ this.logger.info(`verifying checksum of migration ${migrationName}`)
74
+ })
75
+ }
76
+ this.postgrator.on('migration-started', migration => {
77
+ const migrationName = basename(migration.filename)
78
+ this.logger.info(`running ${migrationName}`)
79
+ })
80
+ this.postgrator.on('migration-finished', migration => {
81
+ this.appliedMigrationsCount++
82
+ const migrationName = basename(migration.filename)
83
+ this.logger.debug(`completed ${migrationName}`)
84
+ })
95
85
  }
96
86
 
97
87
  async checkMigrationsDirectoryExists () {
@@ -99,7 +89,7 @@ class Migrator {
99
89
  await stat(this.migrationDir)
100
90
  } catch (err) {
101
91
  if (err.code === 'ENOENT') {
102
- throw new errors.MigrateMissingMigrationsDirError(this.migrationDir)
92
+ throw new MigrateMissingMigrationsDirError(this.migrationDir)
103
93
  }
104
94
  }
105
95
  }
@@ -177,7 +167,7 @@ class Migrator {
177
167
  }
178
168
  } catch (err) {
179
169
  if (err.code === 'ENOENT') {
180
- throw new errors.MigrateMissingMigrationsDirError(this.migrationDir)
170
+ throw new MigrateMissingMigrationsDirError(this.migrationDir)
181
171
  }
182
172
  }
183
173
  }
@@ -191,4 +181,22 @@ class Migrator {
191
181
  }
192
182
  }
193
183
 
194
- export { Migrator }
184
+ export async function execute (logger, config, to, rollback) {
185
+ const migrationsConfig = config.migrations
186
+ if (migrationsConfig === undefined) {
187
+ throw new MigrateMissingMigrationsError()
188
+ }
189
+
190
+ const migrator = new Migrator(migrationsConfig, config.db, logger)
191
+
192
+ try {
193
+ if (rollback) {
194
+ await migrator.rollbackMigration()
195
+ } else {
196
+ await migrator.applyMigrations(to)
197
+ }
198
+ return migrator.appliedMigrationsCount > 0
199
+ } finally {
200
+ await migrator.close()
201
+ }
202
+ }
@@ -1,11 +1,10 @@
1
- 'use strict'
2
- const path = require('path')
3
- const fastifyStatic = require('@fastify/static')
4
- const userAgentParser = require('my-ua-parser')
1
+ import fastifyStatic from '@fastify/static'
2
+ import userAgentParser from 'my-ua-parser'
3
+ import path from 'node:path'
5
4
 
6
- module.exports = async (app, opts) => {
5
+ export async function root (app) {
7
6
  app.register(fastifyStatic, {
8
- root: path.join(__dirname, 'public'),
7
+ root: path.join(import.meta.dirname, '../public')
9
8
  })
10
9
  // root endpoint
11
10
  app.route({
@@ -21,6 +20,6 @@ module.exports = async (app, opts) => {
21
20
  }
22
21
  }
23
22
  return { message: 'Welcome to Platformatic! Please visit https://docs.platformatic.dev' }
24
- },
23
+ }
25
24
  })
26
25
  }