@platformatic/db 3.4.1 → 3.5.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/README.md +1 -1
- package/config.d.ts +442 -107
- package/eslint.config.js +9 -5
- package/index.d.ts +53 -31
- package/index.js +30 -139
- package/lib/application.js +102 -0
- package/lib/capability.js +35 -0
- package/lib/commands/index.js +59 -0
- package/lib/commands/migrations-apply.js +63 -0
- package/lib/commands/migrations-create.js +48 -0
- package/lib/commands/print-schema.js +31 -0
- package/lib/commands/seed.js +74 -0
- package/lib/commands/types.js +22 -0
- package/lib/config.js +52 -0
- package/lib/errors.js +16 -12
- package/lib/generator.js +229 -0
- package/lib/{migrator.mjs → migrator.js} +46 -38
- package/lib/{root-endpoint/index.js → root.js} +6 -7
- package/lib/schema.js +41 -20
- package/lib/{generator/code-templates.js → templates.js} +57 -16
- package/lib/types.js +161 -0
- package/lib/upgrade.js +8 -12
- 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/lib/versions/3.0.0.js +14 -0
- package/package.json +32 -40
- package/schema.json +1385 -164
- package/tsconfig.json +16 -6
- 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/db-generator.js +0 -260
- package/lib/generator.d.ts +0 -7
- package/lib/migrate.mjs +0 -81
- package/lib/seed.mjs +0 -90
- package/lib/stackable.js +0 -49
- /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
package/index.d.ts
CHANGED
|
@@ -1,42 +1,64 @@
|
|
|
1
|
-
/// <reference types="@platformatic/sql-graphql" />
|
|
2
|
-
/// <reference types="@platformatic/sql-openapi" />
|
|
3
|
-
import { FastifyInstance } from 'fastify'
|
|
4
|
-
import { PlatformaticDB } from './config'
|
|
5
|
-
import ConfigManager from '@platformatic/config'
|
|
6
|
-
import type { ConfigManagerConfig, StackableInterface } from '@platformatic/config'
|
|
7
|
-
import { SQLMapperPluginInterface, Entities } from '@platformatic/sql-mapper'
|
|
8
|
-
import { SQLEventsPluginInterface } from '@platformatic/sql-events'
|
|
9
1
|
import { DBAuthorizationPluginInterface } from '@platformatic/db-authorization'
|
|
10
|
-
import {
|
|
2
|
+
import { Configuration, ConfigurationOptions } from '@platformatic/foundation'
|
|
3
|
+
import { PlatformaticApplication, ServiceCapability, Generator as ServiceGenerator } from '@platformatic/service'
|
|
4
|
+
import { SQLEventsPluginInterface } from '@platformatic/sql-events'
|
|
5
|
+
import { Entities, SQLMapperPluginInterface } from '@platformatic/sql-mapper'
|
|
6
|
+
import { JSONSchemaType } from 'ajv'
|
|
7
|
+
import { FastifyError, FastifyInstance } from 'fastify'
|
|
8
|
+
import type { PlatformaticDatabaseConfig } from './config.d.ts'
|
|
11
9
|
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
10
|
+
export { PlatformaticApplication } from '@platformatic/service'
|
|
11
|
+
export { createConnectionPool, Entities, Entity, EntityHooks } from '@platformatic/sql-mapper'
|
|
12
|
+
export type { PlatformaticDatabaseConfig } from './config.d.ts'
|
|
14
13
|
|
|
15
|
-
export type
|
|
16
|
-
SQLMapperPluginInterface<T> &
|
|
14
|
+
export type PlatformaticDatabaseMixin<T extends Entities> = SQLMapperPluginInterface<T> &
|
|
17
15
|
SQLEventsPluginInterface &
|
|
18
16
|
DBAuthorizationPluginInterface
|
|
19
17
|
|
|
20
|
-
export type
|
|
18
|
+
export type DatabaseCapability = ServiceCapability<PlatformaticDatabaseConfig>
|
|
19
|
+
|
|
20
|
+
export type ServerInstance<T = {}> = FastifyInstance & {
|
|
21
|
+
platformatic: PlatformaticApplication<PlatformaticDatabaseConfig> & PlatformaticDatabaseMixin<Entities> & T
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type DatabaseConfiguration = Configuration<PlatformaticDatabaseConfig>
|
|
25
|
+
|
|
26
|
+
export declare function transform (config: DatabaseConfiguration): Promise<DatabaseConfiguration>
|
|
21
27
|
|
|
22
|
-
export function
|
|
28
|
+
export declare function loadConfiguration (
|
|
29
|
+
root: string | PlatformaticDatabaseConfig,
|
|
30
|
+
source?: string | PlatformaticDatabaseConfig,
|
|
31
|
+
context?: ConfigurationOptions
|
|
32
|
+
): Promise<DatabaseConfiguration>
|
|
23
33
|
|
|
24
|
-
export function
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
stackable?: StackableInterface
|
|
30
|
-
}>
|
|
34
|
+
export declare function create (
|
|
35
|
+
root: string,
|
|
36
|
+
source?: string | PlatformaticDatabaseConfig,
|
|
37
|
+
context?: ConfigurationOptions
|
|
38
|
+
): Promise<ServiceCapability>
|
|
31
39
|
|
|
32
|
-
|
|
33
|
-
* All the errors thrown by the plugin.
|
|
34
|
-
*/
|
|
35
|
-
export module errors {
|
|
40
|
+
export declare const skipTelemetryHooks: boolean
|
|
36
41
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
+
export declare function platformaticDatabase (app: FastifyInstance, capability: DatabaseCapability): Promise<void>
|
|
43
|
+
|
|
44
|
+
export declare class Generator extends ServiceGenerator {}
|
|
45
|
+
|
|
46
|
+
export declare const packageJson: Record<string, unknown>
|
|
47
|
+
|
|
48
|
+
export declare const schema: JSONSchemaType<PlatformaticDatabaseConfig>
|
|
49
|
+
|
|
50
|
+
export declare const schemaComponents: {
|
|
51
|
+
db: JSONSchemaType<object>
|
|
52
|
+
sharedAuthorizationRule: JSONSchemaType<object>
|
|
53
|
+
authorization: JSONSchemaType<object>
|
|
54
|
+
migrations: JSONSchemaType<object>
|
|
55
|
+
types: JSONSchemaType<object>
|
|
42
56
|
}
|
|
57
|
+
|
|
58
|
+
export declare const version: string
|
|
59
|
+
|
|
60
|
+
export declare function MigrateMissingMigrationsError (): FastifyError
|
|
61
|
+
export declare function UnknownDatabaseError (): FastifyError
|
|
62
|
+
export declare function MigrateMissingMigrationsDirError (dir: string): FastifyError
|
|
63
|
+
export declare function MissingSeedFileError (): FastifyError
|
|
64
|
+
export declare function MigrationsToApplyError (): FastifyError
|
package/index.js
CHANGED
|
@@ -1,145 +1,36 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const configManager = app.platformatic.configManager
|
|
20
|
-
const config = configManager.current
|
|
21
|
-
|
|
22
|
-
let createSchemaLock = false
|
|
23
|
-
await loadSchemaLock()
|
|
24
|
-
|
|
25
|
-
async function loadSchemaLock () {
|
|
26
|
-
if (config.db.schemalock) {
|
|
27
|
-
// ignore errors, this is an optimization
|
|
28
|
-
try {
|
|
29
|
-
const path = locateSchemaLock(configManager)
|
|
30
|
-
const dbschema = JSON.parse(await fs.readFile(path, 'utf8'))
|
|
31
|
-
config.db.dbschema = dbschema
|
|
32
|
-
app.log.trace({ dbschema }, 'loaded schema lock')
|
|
33
|
-
createSchemaLock = false
|
|
34
|
-
} catch (err) {
|
|
35
|
-
app.log.trace({ err }, 'failed to load schema lock')
|
|
36
|
-
app.log.info('no schema lock found, will create one')
|
|
37
|
-
createSchemaLock = true
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (config.migrations && config.migrations.autoApply === true && !app.restarted) {
|
|
43
|
-
app.log.debug({ migrations: config.migrations }, 'running migrations')
|
|
44
|
-
const { execute } = await import('./lib/migrate.mjs')
|
|
45
|
-
const migrationsApplied = await execute({ logger: app.log, config })
|
|
46
|
-
if (migrationsApplied) {
|
|
47
|
-
// reload schema lock
|
|
48
|
-
await updateSchemaLock(app.log, configManager)
|
|
49
|
-
await loadSchemaLock()
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (config.types && config.types.autogenerate === true) {
|
|
53
|
-
app.log.debug({ types: config.types }, 'generating types')
|
|
54
|
-
const { execute } = await import('./lib/gen-types.mjs')
|
|
55
|
-
await execute({ logger: app.log, config, configManager })
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (isKeyEnabled('healthCheck', config.server)) {
|
|
60
|
-
if (typeof config.server.healthCheck !== 'object') {
|
|
61
|
-
config.server.healthCheck = {}
|
|
62
|
-
}
|
|
63
|
-
config.server.healthCheck.fn = healthCheck
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (createSchemaLock) {
|
|
67
|
-
try {
|
|
68
|
-
const path = locateSchemaLock(configManager)
|
|
69
|
-
await fs.writeFile(path, JSON.stringify(app.platformatic.dbschema, null, 2))
|
|
70
|
-
app.log.info({ path }, 'created schema lock')
|
|
71
|
-
} catch (err) {
|
|
72
|
-
app.log.trace({ err }, 'unable to save schema lock')
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async function toLoad (app) {
|
|
77
|
-
await app.register(core, config.db)
|
|
78
|
-
|
|
79
|
-
if (config.authorization) {
|
|
80
|
-
await app.register(auth, config.authorization)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (Object.keys(app.platformatic.entities).length === 0) {
|
|
84
|
-
app.log.warn(
|
|
85
|
-
'No tables found in the database. Are you connected to the right database? Did you forget to run your migrations? ' +
|
|
86
|
-
'This guide can help with debugging Platformatic DB: https://docs.platformatic.dev/docs/guides/debug-platformatic-db'
|
|
87
|
-
)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
toLoad[Symbol.for('skip-override')] = true
|
|
91
|
-
|
|
92
|
-
await app.register(platformaticService, {
|
|
93
|
-
...opts,
|
|
94
|
-
beforePlugins: [toLoad],
|
|
1
|
+
import { resolve, validationOptions } from '@platformatic/basic'
|
|
2
|
+
import { kMetadata, loadConfiguration as utilsLoadConfiguration } from '@platformatic/foundation'
|
|
3
|
+
import { DatabaseCapability } from './lib/capability.js'
|
|
4
|
+
import { transform } from './lib/config.js'
|
|
5
|
+
import { schema } from './lib/schema.js'
|
|
6
|
+
import { upgrade } from './lib/upgrade.js'
|
|
7
|
+
|
|
8
|
+
export async function loadConfiguration (configOrRoot, sourceOrConfig, context) {
|
|
9
|
+
const { root, source } = await resolve(configOrRoot, sourceOrConfig, 'db')
|
|
10
|
+
|
|
11
|
+
return utilsLoadConfiguration(source, context?.schema ?? schema, {
|
|
12
|
+
validationOptions,
|
|
13
|
+
transform,
|
|
14
|
+
upgrade,
|
|
15
|
+
replaceEnv: true,
|
|
16
|
+
replaceEnvIgnore: ['$.db.openapi.ignoreRoutes'],
|
|
17
|
+
root,
|
|
18
|
+
...context
|
|
95
19
|
})
|
|
96
|
-
|
|
97
|
-
if (!app.hasRoute({ url: '/', method: 'GET' })) {
|
|
98
|
-
app.register(require('./lib/root-endpoint'), config)
|
|
99
|
-
}
|
|
100
20
|
}
|
|
101
21
|
|
|
102
|
-
async function
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
await db.query(sql`SELECT 1`)
|
|
106
|
-
return true
|
|
107
|
-
} catch (err) {
|
|
108
|
-
app.log.warn({ err }, 'Healthcheck failed')
|
|
109
|
-
return false
|
|
110
|
-
}
|
|
22
|
+
export async function create (configOrRoot, sourceOrConfig, context) {
|
|
23
|
+
const config = await loadConfiguration(configOrRoot, sourceOrConfig, context)
|
|
24
|
+
return new DatabaseCapability(config[kMetadata].root, config, context)
|
|
111
25
|
}
|
|
112
26
|
|
|
113
|
-
|
|
114
|
-
platformaticDB.schema = schema
|
|
115
|
-
platformaticDB.configType = 'db'
|
|
116
|
-
platformaticDB.configManagerConfig = {
|
|
117
|
-
version,
|
|
118
|
-
schema,
|
|
119
|
-
allowToWatch: ['.env'],
|
|
120
|
-
schemaOptions: platformaticService.configManagerConfig.schemaOptions,
|
|
121
|
-
replaceEnvIgnore: ['$.db.openapi.ignoreRoutes'],
|
|
122
|
-
async transformConfig () {
|
|
123
|
-
await adjustConfig(this)
|
|
124
|
-
},
|
|
125
|
-
upgrade,
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function _buildServer (options) {
|
|
129
|
-
return buildServer(options, platformaticDB)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
async function buildDbStackable (options) {
|
|
133
|
-
return buildStackable(options, platformaticDB, DbStackable)
|
|
134
|
-
}
|
|
27
|
+
export const skipTelemetryHooks = true
|
|
135
28
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
module.exports.buildStackable = buildDbStackable
|
|
145
|
-
module.exports.DbStackable = DbStackable
|
|
29
|
+
export { platformaticDatabase } from './lib/application.js'
|
|
30
|
+
export { DatabaseCapability } from './lib/capability.js'
|
|
31
|
+
export * from './lib/commands/index.js'
|
|
32
|
+
export { transform } from './lib/config.js'
|
|
33
|
+
export * from './lib/errors.js'
|
|
34
|
+
export * as errors from './lib/errors.js'
|
|
35
|
+
export { Generator } from './lib/generator.js'
|
|
36
|
+
export { packageJson, schema, schemaComponents, version } from './lib/schema.js'
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import auth from '@platformatic/db-authorization'
|
|
2
|
+
import core from '@platformatic/db-core'
|
|
3
|
+
import { isKeyEnabled } from '@platformatic/foundation'
|
|
4
|
+
import { platformaticService } from '@platformatic/service'
|
|
5
|
+
import { readFile, writeFile } from 'node:fs/promises'
|
|
6
|
+
import { execute as applyMigrations } from './migrator.js'
|
|
7
|
+
import { root } from './root.js'
|
|
8
|
+
import { execute as generateTypes } from './types.js'
|
|
9
|
+
import { locateSchemaLock, updateSchemaLock } from './utils.js'
|
|
10
|
+
|
|
11
|
+
async function healthCheck (app) {
|
|
12
|
+
const { db, sql } = app.platformatic
|
|
13
|
+
try {
|
|
14
|
+
await db.query(sql`SELECT 1`)
|
|
15
|
+
return true
|
|
16
|
+
} catch (err) {
|
|
17
|
+
app.log.warn({ err }, 'Healthcheck failed')
|
|
18
|
+
return false
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function platformaticDatabase (app, capability) {
|
|
23
|
+
const config = await capability.getConfig(true)
|
|
24
|
+
|
|
25
|
+
let createSchemaLock = false
|
|
26
|
+
await loadSchemaLock()
|
|
27
|
+
|
|
28
|
+
async function loadSchemaLock () {
|
|
29
|
+
if (config.db.schemalock) {
|
|
30
|
+
// ignore errors, this is an optimization
|
|
31
|
+
try {
|
|
32
|
+
const path = locateSchemaLock(config)
|
|
33
|
+
const dbschema = JSON.parse(await readFile(path, 'utf8'))
|
|
34
|
+
config.db.dbschema = dbschema
|
|
35
|
+
app.log.trace({ dbschema }, 'loaded schema lock')
|
|
36
|
+
createSchemaLock = false
|
|
37
|
+
} catch (err) {
|
|
38
|
+
app.log.trace({ err }, 'failed to load schema lock')
|
|
39
|
+
app.log.info('no schema lock found, will create one')
|
|
40
|
+
createSchemaLock = true
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (config.migrations && config.migrations.autoApply === true && !app.restarted) {
|
|
46
|
+
app.log.debug({ migrations: config.migrations }, 'running migrations')
|
|
47
|
+
|
|
48
|
+
const migrationsApplied = await applyMigrations(app.log, config)
|
|
49
|
+
if (migrationsApplied) {
|
|
50
|
+
// reload schema lock
|
|
51
|
+
await updateSchemaLock(app.log, config)
|
|
52
|
+
await loadSchemaLock()
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (config.types && config.types.autogenerate === true) {
|
|
56
|
+
app.log.debug({ types: config.types }, 'generating types')
|
|
57
|
+
await generateTypes({ logger: app.log, config })
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (isKeyEnabled('healthCheck', config.server)) {
|
|
62
|
+
const serverConfig = config.server
|
|
63
|
+
|
|
64
|
+
if (typeof serverConfig.healthCheck !== 'object') {
|
|
65
|
+
serverConfig.healthCheck = {}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
serverConfig.healthCheck.fn = healthCheck
|
|
69
|
+
await capability.updateContext({ serverConfig })
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (createSchemaLock) {
|
|
73
|
+
try {
|
|
74
|
+
const path = locateSchemaLock(config)
|
|
75
|
+
await writeFile(path, JSON.stringify(app.platformatic.dbschema, null, 2))
|
|
76
|
+
app.log.info({ path }, 'created schema lock')
|
|
77
|
+
} catch (err) {
|
|
78
|
+
app.log.trace({ err }, 'unable to save schema lock')
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
await app.register(core, config.db)
|
|
83
|
+
|
|
84
|
+
if (config.authorization) {
|
|
85
|
+
await app.register(auth, config.authorization)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
await platformaticService(app, capability)
|
|
89
|
+
|
|
90
|
+
if (Object.keys(app.platformatic.entities).length === 0) {
|
|
91
|
+
app.log.warn(
|
|
92
|
+
'No tables found in the database. Are you connected to the right database? Did you forget to run your migrations? ' +
|
|
93
|
+
'This guide can help with debugging Platformatic DB: https://docs.platformatic.dev/docs/guides/debug-platformatic-db'
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (!app.hasRoute({ url: '/', method: 'GET' }) && !app.hasRoute({ url: '/*', method: 'GET' })) {
|
|
98
|
+
await app.register(root, config)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
platformaticDatabase[Symbol.for('skip-override')] = true
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ServiceCapability } from '@platformatic/service'
|
|
2
|
+
import { platformaticDatabase } from './application.js'
|
|
3
|
+
import { packageJson } from './schema.js'
|
|
4
|
+
|
|
5
|
+
export class DatabaseCapability extends ServiceCapability {
|
|
6
|
+
constructor (root, config, context) {
|
|
7
|
+
super(root, config, context)
|
|
8
|
+
this.type = 'db'
|
|
9
|
+
this.version = packageJson.version
|
|
10
|
+
|
|
11
|
+
this.applicationFactory = this.context.applicationFactory ?? platformaticDatabase
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
updateContext (context) {
|
|
15
|
+
super.updateContext(context)
|
|
16
|
+
|
|
17
|
+
if (this.context.isProduction && this.config.autogenerate) {
|
|
18
|
+
this.config.autogenerate = false
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async getMeta () {
|
|
23
|
+
const applicationMeta = await super.getMeta()
|
|
24
|
+
const connectionString = this.config.db?.connectionString
|
|
25
|
+
|
|
26
|
+
if (connectionString) {
|
|
27
|
+
return {
|
|
28
|
+
...applicationMeta,
|
|
29
|
+
connectionStrings: [connectionString]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return applicationMeta
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { applyMigrations, helpFooter as applyMigrationsFooter } from './migrations-apply.js'
|
|
2
|
+
import { createMigrations, helpFooter as createMigrationsFooter } from './migrations-create.js'
|
|
3
|
+
import { printSchema } from './print-schema.js'
|
|
4
|
+
import { seed, helpFooter as seedFooter } from './seed.js'
|
|
5
|
+
import { generateTypes, helpFooter as typesFooter } from './types.js'
|
|
6
|
+
|
|
7
|
+
export function createCommands (id) {
|
|
8
|
+
return {
|
|
9
|
+
commands: {
|
|
10
|
+
[`${id}:migrations:create`]: createMigrations,
|
|
11
|
+
[`${id}:migrations:apply`]: applyMigrations,
|
|
12
|
+
[`${id}:seed`]: seed,
|
|
13
|
+
[`${id}:types`]: generateTypes,
|
|
14
|
+
[`${id}:schema`]: printSchema
|
|
15
|
+
},
|
|
16
|
+
help: {
|
|
17
|
+
[`${id}:migrations:create`]: {
|
|
18
|
+
usage: `${id}:migrations:create`,
|
|
19
|
+
description: 'Create a new migration file',
|
|
20
|
+
footer: createMigrationsFooter
|
|
21
|
+
},
|
|
22
|
+
[`${id}:migrations:apply`]: {
|
|
23
|
+
usage: `${id}:migrations:apply`,
|
|
24
|
+
description: 'Apply all configured migrations to the database',
|
|
25
|
+
footer: applyMigrationsFooter,
|
|
26
|
+
options: [
|
|
27
|
+
{
|
|
28
|
+
usage: '-r, --rollback',
|
|
29
|
+
description: 'Rollback migrations instead of applying them'
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
usage: '-t, --to <version>',
|
|
33
|
+
description: 'Migrate to a specific version'
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
[`${id}:seed`]: {
|
|
38
|
+
usage: `${id}:seed [file]`,
|
|
39
|
+
description: 'Load a seed into the database',
|
|
40
|
+
footer: seedFooter,
|
|
41
|
+
args: [
|
|
42
|
+
{
|
|
43
|
+
name: 'file',
|
|
44
|
+
description: 'The seed file to load.'
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
[`${id}:types`]: {
|
|
49
|
+
usage: `${id}:types`,
|
|
50
|
+
description: 'Generate TypeScript types for your entities from the database',
|
|
51
|
+
footer: typesFooter
|
|
52
|
+
},
|
|
53
|
+
[`${id}:schema`]: {
|
|
54
|
+
usage: `${id}:schema [openapi|graphql]`,
|
|
55
|
+
description: 'Prints the OpenAPI or GraphQL schema for the database'
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { loadConfiguration } from '@platformatic/foundation'
|
|
2
|
+
import { utimesSync } from 'node:fs'
|
|
3
|
+
import { transform } from '../config.js'
|
|
4
|
+
import { execute } from '../migrator.js'
|
|
5
|
+
import { schema } from '../schema.js'
|
|
6
|
+
import { updateSchemaLock } from '../utils.js'
|
|
7
|
+
import { generateTypes } from './types.js'
|
|
8
|
+
|
|
9
|
+
export async function applyMigrations (logger, configFile, args, context) {
|
|
10
|
+
const { parseArgs, logFatalError } = context
|
|
11
|
+
const config = await loadConfiguration(configFile, schema, { transform })
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
values: { to, rollback }
|
|
15
|
+
} = parseArgs(
|
|
16
|
+
args,
|
|
17
|
+
{
|
|
18
|
+
rollback: {
|
|
19
|
+
type: 'boolean',
|
|
20
|
+
short: 'r'
|
|
21
|
+
},
|
|
22
|
+
to: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
short: 't'
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
false
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
const appliedMigrations = await execute(logger, config, to, rollback)
|
|
32
|
+
|
|
33
|
+
if (config.types && config.types.autogenerate) {
|
|
34
|
+
await generateTypes(logger, configFile, args, context)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (appliedMigrations) {
|
|
38
|
+
await updateSchemaLock(logger, config)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// touch the @platformatic/db config to trigger a restart
|
|
42
|
+
const now = new Date()
|
|
43
|
+
|
|
44
|
+
utimesSync(configFile, now, now)
|
|
45
|
+
} catch (err) {
|
|
46
|
+
if (err.code === 'PTL_DB_MIGRATE_ERROR') {
|
|
47
|
+
logFatalError(logger, err.message)
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/* c8 ignore next 2 */
|
|
52
|
+
throw err
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const helpFooter = `
|
|
57
|
+
The migrations will be applied in the order they are specified in the
|
|
58
|
+
folder defined in the configuration file. If you want to apply a specific migration,
|
|
59
|
+
you can use the \`--to\` option (use \`000\` to reset to the initial state).
|
|
60
|
+
|
|
61
|
+
You can find more details about the configuration format here:
|
|
62
|
+
* [Platformatic DB Configuration](https://docs.platformatic.dev/docs/db/configuration)
|
|
63
|
+
`
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { kMetadata, loadConfiguration } from '@platformatic/foundation'
|
|
2
|
+
import { writeFile } from 'node:fs/promises'
|
|
3
|
+
import { join, relative } from 'node:path'
|
|
4
|
+
import { transform } from '../config.js'
|
|
5
|
+
import * as errors from '../errors.js'
|
|
6
|
+
import { Migrator } from '../migrator.js'
|
|
7
|
+
import { schema } from '../schema.js'
|
|
8
|
+
|
|
9
|
+
export async function createMigrations (logger, configFile, _, { colorette: { bold } }) {
|
|
10
|
+
const config = await loadConfiguration(configFile, schema, { transform })
|
|
11
|
+
const root = config[kMetadata].root
|
|
12
|
+
|
|
13
|
+
let migrator = null
|
|
14
|
+
try {
|
|
15
|
+
const migrationsConfig = config.migrations
|
|
16
|
+
if (migrationsConfig === undefined) {
|
|
17
|
+
throw new errors.MigrateMissingMigrationsError()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
migrator = new Migrator(migrationsConfig, config.db, logger)
|
|
21
|
+
|
|
22
|
+
const nextMigrationVersion = await migrator.getNextMigrationVersion()
|
|
23
|
+
const nextMigrationVersionStr = migrator.convertVersionToStr(nextMigrationVersion)
|
|
24
|
+
|
|
25
|
+
const nextDoMigrationName = `${nextMigrationVersionStr}.do.sql`
|
|
26
|
+
const nextUndoMigrationName = `${nextMigrationVersionStr}.undo.sql`
|
|
27
|
+
|
|
28
|
+
const doFile = join(migrator.migrationDir, nextDoMigrationName)
|
|
29
|
+
const undoFile = join(migrator.migrationDir, nextUndoMigrationName)
|
|
30
|
+
|
|
31
|
+
await Promise.all([writeFile(doFile, ''), writeFile(undoFile, '')])
|
|
32
|
+
|
|
33
|
+
logger.info(`Created migration files ${bold(relative(root, doFile))} and ${bold(relative(root, undoFile))}.`)
|
|
34
|
+
} catch (error) {
|
|
35
|
+
logger.error(error.message)
|
|
36
|
+
} finally {
|
|
37
|
+
await migrator?.close()
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const helpFooter = `
|
|
42
|
+
It will generate do and undo sql files in the migrations folder. The name of the files will be the next migration number.
|
|
43
|
+
|
|
44
|
+
The migration files are named \`001.<do|undo>.sql\`, \`002.<do|undo>.sql\` etc...
|
|
45
|
+
|
|
46
|
+
You can find more details about the configuration format here:
|
|
47
|
+
* [Platformatic DB Configuration](https://docs.platformatic.dev/docs/db/configuration)
|
|
48
|
+
`
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { abstractLogger, kMetadata, loadConfiguration } from '@platformatic/foundation'
|
|
2
|
+
import { printSchema as printGraphqlSchema } from 'graphql'
|
|
3
|
+
import { create } from '../../index.js'
|
|
4
|
+
import { transform } from '../config.js'
|
|
5
|
+
import { schema } from '../schema.js'
|
|
6
|
+
|
|
7
|
+
export async function printSchema (logger, configFile, args, { colorette: { bold }, logFatalError }) {
|
|
8
|
+
const config = await loadConfiguration(configFile, schema, { transform })
|
|
9
|
+
|
|
10
|
+
const type = args[0]
|
|
11
|
+
|
|
12
|
+
if (!type) {
|
|
13
|
+
logFatalError(logger, `Please specify a schema type between ${bold('openapi')} and ${bold('graphql')}.`)
|
|
14
|
+
} else if (type !== 'openapi' && type !== 'graphql') {
|
|
15
|
+
logFatalError(logger, `Invalid schema type ${bold(type)}. Use ${bold('openapi')} or ${bold('graphql')}.`)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const app = await create(config[kMetadata].root, configFile, { logger: abstractLogger })
|
|
19
|
+
await app.init()
|
|
20
|
+
|
|
21
|
+
let output
|
|
22
|
+
if (type === 'openapi') {
|
|
23
|
+
await app.start({ listen: true })
|
|
24
|
+
output = JSON.stringify(app.getApplication().swagger(), null, 2)
|
|
25
|
+
} else {
|
|
26
|
+
output = printGraphqlSchema(app.getApplication().graphql.schema)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
console.log(output)
|
|
30
|
+
await app.stop()
|
|
31
|
+
}
|