@platformatic/db 2.71.1-alpha.0 → 3.0.0-alpha.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.
- package/config.d.ts +1 -19
- package/eslint.config.js +9 -5
- package/index.d.ts +56 -31
- package/index.js +67 -128
- package/lib/application.js +102 -0
- package/lib/commands/index.js +59 -0
- package/lib/commands/migrations-apply.js +62 -0
- package/lib/commands/migrations-create.js +48 -0
- package/lib/commands/print-schema.js +30 -0
- package/lib/commands/seed.js +88 -0
- package/lib/commands/types.js +21 -0
- package/lib/errors.js +15 -11
- package/lib/{generator/db-generator.js → generator.js} +57 -52
- package/lib/{migrator.mjs → migrator.js} +45 -37
- package/lib/{root-endpoint/index.js → root.js} +6 -7
- package/lib/schema.js +31 -21
- package/lib/stackable.js +14 -26
- package/lib/{generator/code-templates.js → templates.js} +47 -17
- package/lib/types.js +160 -0
- package/lib/upgrade.js +7 -10
- package/lib/utils.js +12 -23
- package/lib/versions/0.18.0.js +3 -5
- package/lib/versions/{from-zero-twenty-height-to-will-see.js → 0.28.0.js} +3 -5
- package/lib/versions/2.0.0.js +3 -5
- package/package.json +16 -23
- package/schema.json +2 -73
- package/tsconfig.json +16 -6
- package/.snapshots/810d795d512560f3863d8db472c81c27/0.json +0 -1
- package/.snapshots/810d795d512560f3863d8db472c81c27/1.json +0 -1
- package/db.mjs +0 -86
- package/help/compile.txt +0 -17
- package/help/create.txt +0 -13
- package/help/help.txt +0 -11
- package/help/migrations apply.txt +0 -45
- package/help/migrations create.txt +0 -27
- package/help/migrations.txt +0 -4
- package/help/schema.txt +0 -25
- package/help/seed.txt +0 -36
- package/help/start.txt +0 -47
- package/help/types.txt +0 -40
- package/index.test-d.ts +0 -43
- package/lib/adjust-config.js +0 -42
- package/lib/create.mjs +0 -89
- package/lib/gen-migration.mjs +0 -53
- package/lib/gen-schema.mjs +0 -68
- package/lib/gen-types.mjs +0 -202
- package/lib/generator/README.md +0 -38
- package/lib/generator.d.ts +0 -7
- package/lib/migrate.mjs +0 -87
- package/lib/seed.mjs +0 -90
- /package/{lib/root-endpoint/public → public}/images/dark_mode.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/favicon.ico +0 -0
- /package/{lib/root-endpoint/public → public}/images/light_mode.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/platformatic-logo-dark.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/platformatic-logo-light.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/triangle_dark.svg +0 -0
- /package/{lib/root-endpoint/public → public}/images/triangle_light.svg +0 -0
- /package/{lib/root-endpoint/public → public}/index.html +0 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import tsCompiler from '@platformatic/ts-compiler'
|
|
2
|
+
import { loadConfiguration, loadModule } from '@platformatic/utils'
|
|
3
|
+
import { access, readFile } from 'fs/promises'
|
|
4
|
+
import { createRequire } from 'node:module'
|
|
5
|
+
import { join, resolve } from 'node:path'
|
|
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)
|
|
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
|
+
let seedFile = resolve(process.cwd(), args[0])
|
|
33
|
+
|
|
34
|
+
// check if we are in Typescript and, in case, compile it
|
|
35
|
+
if (seedFile.endsWith('.ts')) {
|
|
36
|
+
await tsCompiler.compile({
|
|
37
|
+
cwd: process.cwd(),
|
|
38
|
+
logger,
|
|
39
|
+
tsConfig: config.plugins?.typescript?.tsConfig,
|
|
40
|
+
flags: config.plugins?.typescript?.flags
|
|
41
|
+
})
|
|
42
|
+
const tsConfigPath = config?.plugins?.typescript?.tsConfig || resolve(process.cwd(), 'tsconfig.json')
|
|
43
|
+
const tsConfig = JSON.parse(await readFile(tsConfigPath, 'utf8'))
|
|
44
|
+
const outDir = tsConfig.compilerOptions.outDir
|
|
45
|
+
seedFile = join(outDir, seedFile.replace('.ts', '.js'))
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
await access(seedFile)
|
|
49
|
+
|
|
50
|
+
logger.info(`Seeding from ${bold(seedFile)}`)
|
|
51
|
+
|
|
52
|
+
const importedModule = await loadModule(createRequire(resolve(process.cwd(), 'noop.js')), seedFile)
|
|
53
|
+
|
|
54
|
+
const seedFunction = typeof importedModule?.seed !== 'function' ? importedModule : importedModule
|
|
55
|
+
|
|
56
|
+
if (typeof seedFunction !== 'function') {
|
|
57
|
+
logFatalError(logger, 'Cannot find seed function.')
|
|
58
|
+
logFatalError(logger, "If you use an ESM module use the signature 'export async function seed (opts)'.")
|
|
59
|
+
logFatalError(logger, "If you use a CJS module use the signature 'module.exports = async function seed (opts)'.")
|
|
60
|
+
logFatalError(logger, "If you use Typescript use the signature 'export async function seed(opts)'")
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const { db, sql, entities } = await setupDB(logger, config.db)
|
|
65
|
+
await seedFunction({ db, sql, entities, logger })
|
|
66
|
+
logger.info('Seeding complete.')
|
|
67
|
+
|
|
68
|
+
// Once done seeding, close your connection.
|
|
69
|
+
await db.dispose()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const helpFooter = `
|
|
73
|
+
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.
|
|
74
|
+
|
|
75
|
+
Here is an example of a seed file:
|
|
76
|
+
|
|
77
|
+
\`\`\`
|
|
78
|
+
'use strict'
|
|
79
|
+
|
|
80
|
+
module.exports = async function ({ entities, db, sql }) {
|
|
81
|
+
await entities.graph.save({ input: { name: 'Hello' } })
|
|
82
|
+
await db.query(sql\`INSERT INTO graphs (name) VALUES ('Hello 2');\`)
|
|
83
|
+
}
|
|
84
|
+
\`\`\`
|
|
85
|
+
|
|
86
|
+
You can find more details about the configuration format here:
|
|
87
|
+
* [Platformatic DB Configuration](https://docs.platformatic.dev/docs/db/configuration)
|
|
88
|
+
`
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { loadConfiguration } from '@platformatic/utils'
|
|
2
|
+
import { schema } from '../schema.js'
|
|
3
|
+
import { execute } from '../types.js'
|
|
4
|
+
|
|
5
|
+
export async function generateTypes (logger, configFile, _args) {
|
|
6
|
+
const config = await loadConfiguration(configFile, schema)
|
|
7
|
+
|
|
8
|
+
const count = await execute({ logger, config })
|
|
9
|
+
|
|
10
|
+
if (count === 0) {
|
|
11
|
+
logger.warn('No entities found in your schema. Types were NOT generated.')
|
|
12
|
+
logger.warn('Make sure you have applied all the migrations and try again.')
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const helpFooter = `
|
|
17
|
+
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.
|
|
18
|
+
|
|
19
|
+
You can find more details about the configuration format here:
|
|
20
|
+
* [Platformatic DB Configuration](https://docs.platformatic.dev/docs/db/configuration)
|
|
21
|
+
`
|
package/lib/errors.js
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const createError = require('@fastify/error')
|
|
1
|
+
import createError from '@fastify/error'
|
|
4
2
|
|
|
5
3
|
const ERROR_PREFIX = 'PLT_DB'
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
+
)
|
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
import { BaseGenerator, generateTests } from '@platformatic/generators'
|
|
2
|
+
import { join } from 'node:path'
|
|
3
|
+
import { jsHelperMySQL, jsHelperPostgres, jsHelperSqlite, moviesTestJS, moviesTestTS, README } from './templates.js'
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
const { jsHelperSqlite, jsHelperMySQL, jsHelperPostgres, moviesTestTS, moviesTestJS } = require('./code-templates')
|
|
5
|
-
const { join } = require('node:path')
|
|
6
|
-
const { readFile } = require('node:fs/promises')
|
|
7
|
-
|
|
8
|
-
class DBGenerator extends BaseGenerator {
|
|
5
|
+
export class Generator extends BaseGenerator {
|
|
9
6
|
constructor (opts = {}) {
|
|
10
7
|
super({
|
|
11
8
|
...opts,
|
|
12
|
-
module: '@platformatic/db'
|
|
9
|
+
module: '@platformatic/db'
|
|
13
10
|
})
|
|
14
11
|
this.connectionStrings = {
|
|
15
12
|
postgres: 'postgres://postgres:postgres@127.0.0.1:5432/postgres',
|
|
16
13
|
sqlite: 'sqlite://./db.sqlite',
|
|
17
14
|
mysql: 'mysql://root@127.0.0.1:3306/platformatic',
|
|
18
|
-
mariadb: 'mysql://root@127.0.0.1:3306/platformatic'
|
|
15
|
+
mariadb: 'mysql://root@127.0.0.1:3306/platformatic'
|
|
19
16
|
}
|
|
20
17
|
}
|
|
21
18
|
|
|
@@ -29,7 +26,7 @@ class DBGenerator extends BaseGenerator {
|
|
|
29
26
|
tests: true,
|
|
30
27
|
types: true,
|
|
31
28
|
migrations: 'migrations',
|
|
32
|
-
createMigrations: true
|
|
29
|
+
createMigrations: true
|
|
33
30
|
}
|
|
34
31
|
}
|
|
35
32
|
|
|
@@ -43,11 +40,11 @@ class DBGenerator extends BaseGenerator {
|
|
|
43
40
|
connectionString: `{${this.getEnvVarName('DATABASE_URL')}}`,
|
|
44
41
|
graphql: true,
|
|
45
42
|
openapi: true,
|
|
46
|
-
schemalock: true
|
|
43
|
+
schemalock: true
|
|
47
44
|
},
|
|
48
45
|
watch: {
|
|
49
|
-
ignore: ['*.sqlite', '*.sqlite-journal']
|
|
50
|
-
}
|
|
46
|
+
ignore: ['*.sqlite', '*.sqlite-journal']
|
|
47
|
+
}
|
|
51
48
|
}
|
|
52
49
|
|
|
53
50
|
if (!isRuntimeContext) {
|
|
@@ -55,15 +52,15 @@ class DBGenerator extends BaseGenerator {
|
|
|
55
52
|
hostname: '{PLT_SERVER_HOSTNAME}',
|
|
56
53
|
port: '{PORT}',
|
|
57
54
|
logger: {
|
|
58
|
-
level: '{PLT_SERVER_LOGGER_LEVEL}'
|
|
59
|
-
}
|
|
55
|
+
level: '{PLT_SERVER_LOGGER_LEVEL}'
|
|
56
|
+
}
|
|
60
57
|
}
|
|
61
58
|
}
|
|
62
59
|
|
|
63
60
|
if (migrations) {
|
|
64
61
|
config.migrations = {
|
|
65
62
|
dir: migrations,
|
|
66
|
-
autoApply: `{${this.getEnvVarName('PLT_APPLY_MIGRATIONS')}}
|
|
63
|
+
autoApply: `{${this.getEnvVarName('PLT_APPLY_MIGRATIONS')}}`
|
|
67
64
|
}
|
|
68
65
|
|
|
69
66
|
this.addFile({ path: 'migrations', file: '.gitkeep', contents: '' })
|
|
@@ -71,19 +68,22 @@ class DBGenerator extends BaseGenerator {
|
|
|
71
68
|
|
|
72
69
|
if (plugin === true) {
|
|
73
70
|
config.plugins = {
|
|
74
|
-
paths: [
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
71
|
+
paths: [
|
|
72
|
+
{
|
|
73
|
+
path: './plugins',
|
|
74
|
+
encapsulate: false
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
path: './routes'
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
typescript: `{${this.getEnvVarName('PLT_TYPESCRIPT')}}`
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
if (types === true) {
|
|
85
85
|
config.types = {
|
|
86
|
-
autogenerate: true
|
|
86
|
+
autogenerate: true
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -94,22 +94,28 @@ class DBGenerator extends BaseGenerator {
|
|
|
94
94
|
if (!this.config.isUpdating) {
|
|
95
95
|
this.config.connectionString = this.config.connectionString || this.connectionStrings[this.config.database]
|
|
96
96
|
this.config.dependencies = {
|
|
97
|
-
'@platformatic/db': `^${this.platformaticVersion}
|
|
97
|
+
'@platformatic/db': `^${this.platformaticVersion}`
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
if (!this.config.isRuntimeContext) {
|
|
101
|
-
this.addEnvVars(
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
this.addEnvVars(
|
|
102
|
+
{
|
|
103
|
+
PLT_SERVER_HOSTNAME: this.config.hostname,
|
|
104
|
+
PLT_SERVER_LOGGER_LEVEL: 'info',
|
|
105
|
+
PORT: 3042
|
|
106
|
+
},
|
|
107
|
+
{ overwrite: false, default: true }
|
|
108
|
+
)
|
|
106
109
|
}
|
|
107
110
|
|
|
108
|
-
this.addEnvVars(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
this.addEnvVars(
|
|
112
|
+
{
|
|
113
|
+
PLT_TYPESCRIPT: this.config.typescript,
|
|
114
|
+
DATABASE_URL: this.connectionStrings[this.config.database],
|
|
115
|
+
PLT_APPLY_MIGRATIONS: 'true'
|
|
116
|
+
},
|
|
117
|
+
{ overwrite: false, default: true }
|
|
118
|
+
)
|
|
113
119
|
}
|
|
114
120
|
}
|
|
115
121
|
|
|
@@ -119,7 +125,7 @@ class DBGenerator extends BaseGenerator {
|
|
|
119
125
|
this.createMigrationFiles()
|
|
120
126
|
}
|
|
121
127
|
|
|
122
|
-
this.addFile({ path: '', file: 'README.md', contents:
|
|
128
|
+
this.addFile({ path: '', file: 'README.md', contents: README })
|
|
123
129
|
|
|
124
130
|
if (this.config.plugin) {
|
|
125
131
|
let jsHelper = { pre: '', config: '', post: '' }
|
|
@@ -148,7 +154,7 @@ class DBGenerator extends BaseGenerator {
|
|
|
148
154
|
|
|
149
155
|
// TODO(leorossi): this is unfortunate. We have already generated tests in BaseGenerator
|
|
150
156
|
// next line will override the test files
|
|
151
|
-
generateTests(this.config.typescript, '@platformatic/db', jsHelper).forEach(
|
|
157
|
+
generateTests(this.config.typescript, '@platformatic/db', jsHelper).forEach(fileObject => {
|
|
152
158
|
this.addFile(fileObject)
|
|
153
159
|
})
|
|
154
160
|
|
|
@@ -161,17 +167,17 @@ class DBGenerator extends BaseGenerator {
|
|
|
161
167
|
}
|
|
162
168
|
}
|
|
163
169
|
|
|
164
|
-
const
|
|
170
|
+
const ENVIRONMENT_TEMPLATE = `
|
|
165
171
|
import { FastifyInstance } from 'fastify'
|
|
166
|
-
import {
|
|
172
|
+
import { PlatformaticApplication, PlatformaticDatabaseConfig, PlatformaticDatabaseMixin, Entities } from '@platformatic/db'
|
|
167
173
|
|
|
168
174
|
declare module 'fastify' {
|
|
169
175
|
interface FastifyInstance {
|
|
170
|
-
platformatic:
|
|
176
|
+
platformatic: PlatformaticApplication<PlatformaticDatabaseConfig> & PlatformaticDatabaseMixin<Entities>
|
|
171
177
|
}
|
|
172
178
|
}
|
|
173
179
|
`
|
|
174
|
-
this.addFile({ path: '', file: '
|
|
180
|
+
this.addFile({ path: '', file: 'plt-env.d.ts', contents: ENVIRONMENT_TEMPLATE })
|
|
175
181
|
}
|
|
176
182
|
}
|
|
177
183
|
|
|
@@ -185,7 +191,7 @@ declare module 'fastify' {
|
|
|
185
191
|
postgres: 'SERIAL',
|
|
186
192
|
sqlite: 'INTEGER',
|
|
187
193
|
mysql: 'INTEGER UNSIGNED AUTO_INCREMENT',
|
|
188
|
-
mariadb: 'INTEGER UNSIGNED AUTO_INCREMENT'
|
|
194
|
+
mariadb: 'INTEGER UNSIGNED AUTO_INCREMENT'
|
|
189
195
|
}
|
|
190
196
|
|
|
191
197
|
return `
|
|
@@ -224,26 +230,26 @@ declare module 'fastify' {
|
|
|
224
230
|
label: 'What is the connection string?',
|
|
225
231
|
default: this.connectionStrings.sqlite,
|
|
226
232
|
type: 'string',
|
|
227
|
-
configValue: 'connectionString'
|
|
233
|
+
configValue: 'connectionString'
|
|
228
234
|
},
|
|
229
235
|
{
|
|
230
236
|
var: 'PLT_APPLY_MIGRATIONS',
|
|
231
237
|
label: 'Should migrations be applied automatically on startup?',
|
|
232
238
|
default: true,
|
|
233
|
-
type: 'boolean'
|
|
234
|
-
}
|
|
239
|
+
type: 'boolean'
|
|
240
|
+
}
|
|
235
241
|
]
|
|
236
242
|
}
|
|
237
243
|
|
|
238
244
|
async prepareQuestions () {
|
|
239
245
|
await super.prepareQuestions()
|
|
240
246
|
if (!this.config.connectionString) {
|
|
241
|
-
const def = this.getConfigFieldsDefinitions().find(
|
|
247
|
+
const def = this.getConfigFieldsDefinitions().find(q => q.var === 'DATABASE_URL')
|
|
242
248
|
this.questions.push({
|
|
243
249
|
type: 'input',
|
|
244
250
|
name: def.configValue,
|
|
245
251
|
message: def.label,
|
|
246
|
-
default: def.default
|
|
252
|
+
default: def.default
|
|
247
253
|
})
|
|
248
254
|
}
|
|
249
255
|
|
|
@@ -252,11 +258,10 @@ declare module 'fastify' {
|
|
|
252
258
|
name: 'createMigrations',
|
|
253
259
|
message: 'Do you want to create default migrations?',
|
|
254
260
|
default: true,
|
|
255
|
-
choices: [
|
|
261
|
+
choices: [
|
|
262
|
+
{ name: 'yes', value: true },
|
|
263
|
+
{ name: 'no', value: false }
|
|
264
|
+
]
|
|
256
265
|
})
|
|
257
266
|
}
|
|
258
267
|
}
|
|
259
|
-
|
|
260
|
-
module.exports = DBGenerator
|
|
261
|
-
module.exports.DBGenerator = DBGenerator
|
|
262
|
-
module.exports.Generator = DBGenerator
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { basename } from 'path'
|
|
2
|
-
import Postgrator from 'postgrator'
|
|
3
1
|
import { createConnectionPool } from '@platformatic/sql-mapper'
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
2
|
+
import { readdir, stat } from 'node:fs/promises'
|
|
3
|
+
import { basename } from 'node:path'
|
|
4
|
+
import { MigrateMissingMigrationsDirError, MigrateMissingMigrationsError } from './errors.js'
|
|
6
5
|
|
|
7
|
-
class Migrator {
|
|
6
|
+
export class Migrator {
|
|
8
7
|
constructor (migrationConfig, coreConfig, logger) {
|
|
9
8
|
this.coreConfig = coreConfig
|
|
10
9
|
this.migrationDir = migrationConfig.dir
|
|
@@ -21,6 +20,8 @@ class Migrator {
|
|
|
21
20
|
}
|
|
22
21
|
|
|
23
22
|
async setupPostgrator () {
|
|
23
|
+
const { default: Postgrator } = await import('postgrator')
|
|
24
|
+
|
|
24
25
|
this.appliedMigrationsCount = 0
|
|
25
26
|
if (this.postgrator instanceof Postgrator) return
|
|
26
27
|
|
|
@@ -28,7 +29,7 @@ class Migrator {
|
|
|
28
29
|
|
|
29
30
|
const { db, sql } = await createConnectionPool({
|
|
30
31
|
...this.coreConfig,
|
|
31
|
-
log: this.logger
|
|
32
|
+
log: this.logger
|
|
32
33
|
})
|
|
33
34
|
|
|
34
35
|
let driver
|
|
@@ -44,9 +45,7 @@ class Migrator {
|
|
|
44
45
|
driver = 'sqlite3'
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
const database = driver !== 'sqlite3'
|
|
48
|
-
? new URL(this.coreConfig.connectionString).pathname.replace(/^\//, '')
|
|
49
|
-
: ''
|
|
48
|
+
const database = driver !== 'sqlite3' ? new URL(this.coreConfig.connectionString).pathname.replace(/^\//, '') : ''
|
|
50
49
|
|
|
51
50
|
this.db = db
|
|
52
51
|
|
|
@@ -59,40 +58,31 @@ class Migrator {
|
|
|
59
58
|
driver,
|
|
60
59
|
database,
|
|
61
60
|
schemaTable: this.migrationsTable || 'versions',
|
|
62
|
-
execQuery: async
|
|
61
|
+
execQuery: async query => {
|
|
63
62
|
const res = await db.query(sql`${sql.__dangerous__rawValue(query)}`)
|
|
64
63
|
return { rows: res }
|
|
65
64
|
},
|
|
66
65
|
validateChecksums: this.validateChecksums,
|
|
67
66
|
newline: this.newline,
|
|
68
|
-
currentSchema: ['pg', 'mysql'].includes(driver) ? this.currentSchema : undefined
|
|
67
|
+
currentSchema: ['pg', 'mysql'].includes(driver) ? this.currentSchema : undefined
|
|
69
68
|
})
|
|
70
69
|
|
|
71
70
|
if (this.validateChecksums === true) {
|
|
72
|
-
this.postgrator.on(
|
|
73
|
-
|
|
74
|
-
(migration) => {
|
|
75
|
-
/* c8 ignore next 3 */
|
|
76
|
-
const migrationName = basename(migration.filename)
|
|
77
|
-
this.logger.info(`verifying checksum of migration ${migrationName}`)
|
|
78
|
-
}
|
|
79
|
-
)
|
|
80
|
-
}
|
|
81
|
-
this.postgrator.on(
|
|
82
|
-
'migration-started',
|
|
83
|
-
(migration) => {
|
|
84
|
-
const migrationName = basename(migration.filename)
|
|
85
|
-
this.logger.info(`running ${migrationName}`)
|
|
86
|
-
}
|
|
87
|
-
)
|
|
88
|
-
this.postgrator.on(
|
|
89
|
-
'migration-finished',
|
|
90
|
-
(migration) => {
|
|
91
|
-
this.appliedMigrationsCount++
|
|
71
|
+
this.postgrator.on('validation-started', migration => {
|
|
72
|
+
/* c8 ignore next 3 */
|
|
92
73
|
const migrationName = basename(migration.filename)
|
|
93
|
-
this.logger.
|
|
94
|
-
}
|
|
95
|
-
|
|
74
|
+
this.logger.info(`verifying checksum of migration ${migrationName}`)
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
this.postgrator.on('migration-started', migration => {
|
|
78
|
+
const migrationName = basename(migration.filename)
|
|
79
|
+
this.logger.info(`running ${migrationName}`)
|
|
80
|
+
})
|
|
81
|
+
this.postgrator.on('migration-finished', migration => {
|
|
82
|
+
this.appliedMigrationsCount++
|
|
83
|
+
const migrationName = basename(migration.filename)
|
|
84
|
+
this.logger.debug(`completed ${migrationName}`)
|
|
85
|
+
})
|
|
96
86
|
}
|
|
97
87
|
|
|
98
88
|
async checkMigrationsDirectoryExists () {
|
|
@@ -100,7 +90,7 @@ class Migrator {
|
|
|
100
90
|
await stat(this.migrationDir)
|
|
101
91
|
} catch (err) {
|
|
102
92
|
if (err.code === 'ENOENT') {
|
|
103
|
-
throw new
|
|
93
|
+
throw new MigrateMissingMigrationsDirError(this.migrationDir)
|
|
104
94
|
}
|
|
105
95
|
}
|
|
106
96
|
}
|
|
@@ -178,7 +168,7 @@ class Migrator {
|
|
|
178
168
|
}
|
|
179
169
|
} catch (err) {
|
|
180
170
|
if (err.code === 'ENOENT') {
|
|
181
|
-
throw new
|
|
171
|
+
throw new MigrateMissingMigrationsDirError(this.migrationDir)
|
|
182
172
|
}
|
|
183
173
|
}
|
|
184
174
|
}
|
|
@@ -192,4 +182,22 @@ class Migrator {
|
|
|
192
182
|
}
|
|
193
183
|
}
|
|
194
184
|
|
|
195
|
-
export
|
|
185
|
+
export async function execute (logger, config, to, rollback) {
|
|
186
|
+
const migrationsConfig = config.migrations
|
|
187
|
+
if (migrationsConfig === undefined) {
|
|
188
|
+
throw new MigrateMissingMigrationsError()
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const migrator = new Migrator(migrationsConfig, config.db, logger)
|
|
192
|
+
|
|
193
|
+
try {
|
|
194
|
+
if (rollback) {
|
|
195
|
+
await migrator.rollbackMigration()
|
|
196
|
+
} else {
|
|
197
|
+
await migrator.applyMigrations(to)
|
|
198
|
+
}
|
|
199
|
+
return migrator.appliedMigrationsCount > 0
|
|
200
|
+
} finally {
|
|
201
|
+
await migrator.close()
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
|
|
5
|
+
export async function root (app) {
|
|
7
6
|
app.register(fastifyStatic, {
|
|
8
|
-
root: path.join(
|
|
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
|
}
|
package/lib/schema.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
#! /usr/bin/env node
|
|
2
|
-
'use strict'
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
import { schemaComponents as serviceSchemaComponents } from '@platformatic/service'
|
|
4
|
+
import { fastifyServer as server, schemaComponents as utilsSchemaComponents, watch, wrappedRuntime } from '@platformatic/utils'
|
|
5
|
+
import { readFileSync } from 'node:fs'
|
|
6
|
+
import { resolve } from 'node:path'
|
|
8
7
|
|
|
9
|
-
const
|
|
8
|
+
export const packageJson = JSON.parse(readFileSync(resolve(import.meta.dirname, '../package.json'), 'utf8'))
|
|
9
|
+
export const version = packageJson.version
|
|
10
|
+
|
|
11
|
+
const { plugins, openApiBase, clients, $defs } = serviceSchemaComponents
|
|
12
|
+
|
|
13
|
+
export const db = {
|
|
10
14
|
type: 'object',
|
|
11
15
|
properties: {
|
|
12
16
|
connectionString: {
|
|
@@ -235,7 +239,7 @@ const db = {
|
|
|
235
239
|
required: ['connectionString']
|
|
236
240
|
}
|
|
237
241
|
|
|
238
|
-
const sharedAuthorizationRule = {
|
|
242
|
+
export const sharedAuthorizationRule = {
|
|
239
243
|
role: {
|
|
240
244
|
type: 'string',
|
|
241
245
|
description: 'the role name to match the rule'
|
|
@@ -261,7 +265,7 @@ const sharedAuthorizationRule = {
|
|
|
261
265
|
}
|
|
262
266
|
}
|
|
263
267
|
|
|
264
|
-
const authorization = {
|
|
268
|
+
export const authorization = {
|
|
265
269
|
type: 'object',
|
|
266
270
|
properties: {
|
|
267
271
|
adminSecret: {
|
|
@@ -367,7 +371,7 @@ const authorization = {
|
|
|
367
371
|
additionalProperties: false
|
|
368
372
|
}
|
|
369
373
|
|
|
370
|
-
const migrations = {
|
|
374
|
+
export const migrations = {
|
|
371
375
|
type: 'object',
|
|
372
376
|
properties: {
|
|
373
377
|
dir: {
|
|
@@ -410,7 +414,7 @@ const migrations = {
|
|
|
410
414
|
required: ['dir']
|
|
411
415
|
}
|
|
412
416
|
|
|
413
|
-
const types = {
|
|
417
|
+
export const types = {
|
|
414
418
|
type: 'object',
|
|
415
419
|
properties: {
|
|
416
420
|
autogenerate: {
|
|
@@ -433,10 +437,18 @@ const types = {
|
|
|
433
437
|
additionalProperties: false
|
|
434
438
|
}
|
|
435
439
|
|
|
436
|
-
const
|
|
437
|
-
|
|
440
|
+
export const schemaComponents = {
|
|
441
|
+
db,
|
|
442
|
+
sharedAuthorizationRule,
|
|
443
|
+
authorization,
|
|
444
|
+
migrations,
|
|
445
|
+
types
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
export const schema = {
|
|
449
|
+
$id: `https://schemas.platformatic.dev/@platformatic/db/${packageJson.version}.json`,
|
|
438
450
|
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
439
|
-
title: 'Platformatic
|
|
451
|
+
title: 'Platformatic Database Config',
|
|
440
452
|
type: 'object',
|
|
441
453
|
properties: {
|
|
442
454
|
basePath: {
|
|
@@ -455,12 +467,11 @@ const platformaticDBschema = {
|
|
|
455
467
|
db,
|
|
456
468
|
authorization,
|
|
457
469
|
migrations,
|
|
458
|
-
metrics,
|
|
459
470
|
types,
|
|
460
471
|
plugins,
|
|
461
|
-
telemetry,
|
|
472
|
+
telemetry: utilsSchemaComponents.telemetry,
|
|
462
473
|
clients,
|
|
463
|
-
runtime:
|
|
474
|
+
runtime: wrappedRuntime,
|
|
464
475
|
watch: {
|
|
465
476
|
anyOf: [
|
|
466
477
|
watch,
|
|
@@ -482,7 +493,7 @@ const platformaticDBschema = {
|
|
|
482
493
|
additionalProperties: false,
|
|
483
494
|
required: ['db'],
|
|
484
495
|
$defs: {
|
|
485
|
-
|
|
496
|
+
...$defs,
|
|
486
497
|
'crud-operation-auth': {
|
|
487
498
|
oneOf: [
|
|
488
499
|
{
|
|
@@ -534,8 +545,7 @@ const platformaticDBschema = {
|
|
|
534
545
|
}
|
|
535
546
|
}
|
|
536
547
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
console.log(JSON.stringify(platformaticDBschema, null, 2))
|
|
548
|
+
/* c8 ignore next 3 */
|
|
549
|
+
if (process.argv[1] === import.meta.filename) {
|
|
550
|
+
console.log(JSON.stringify(schema, null, 2))
|
|
541
551
|
}
|