@platformatic/db 2.72.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
package/config.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ export type CrudOperationAuth =
|
|
|
22
22
|
}
|
|
23
23
|
| boolean;
|
|
24
24
|
|
|
25
|
-
export interface
|
|
25
|
+
export interface PlatformaticDatabaseConfig {
|
|
26
26
|
basePath?: string;
|
|
27
27
|
server?: {
|
|
28
28
|
hostname?: string;
|
|
@@ -387,24 +387,6 @@ export interface PlatformaticDB {
|
|
|
387
387
|
*/
|
|
388
388
|
currentSchema?: string;
|
|
389
389
|
};
|
|
390
|
-
metrics?:
|
|
391
|
-
| boolean
|
|
392
|
-
| {
|
|
393
|
-
port?: number | string;
|
|
394
|
-
hostname?: string;
|
|
395
|
-
endpoint?: string;
|
|
396
|
-
server?: "own" | "parent" | "hide";
|
|
397
|
-
defaultMetrics?: {
|
|
398
|
-
enabled: boolean;
|
|
399
|
-
};
|
|
400
|
-
auth?: {
|
|
401
|
-
username: string;
|
|
402
|
-
password: string;
|
|
403
|
-
};
|
|
404
|
-
labels?: {
|
|
405
|
-
[k: string]: string;
|
|
406
|
-
};
|
|
407
|
-
};
|
|
408
390
|
types?: {
|
|
409
391
|
/**
|
|
410
392
|
* Should types be auto generated.
|
package/eslint.config.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import neostandard from 'neostandard'
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
module.exports = neostandard({
|
|
3
|
+
export default neostandard({
|
|
6
4
|
ts: true,
|
|
7
|
-
ignores: [
|
|
5
|
+
ignores: [
|
|
6
|
+
...neostandard.resolveIgnoresFromGitignore(),
|
|
7
|
+
'test/tmp/**/*',
|
|
8
|
+
'test/fixtures/*/dist/**/*',
|
|
9
|
+
'**/dist/*',
|
|
10
|
+
'tmp/**/*'
|
|
11
|
+
]
|
|
8
12
|
})
|
package/index.d.ts
CHANGED
|
@@ -1,42 +1,67 @@
|
|
|
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 { BaseGenerator } from '@platformatic/generators'
|
|
3
|
+
import { PlatformaticApplication, ServiceStackable } from '@platformatic/service'
|
|
4
|
+
import { SQLEventsPluginInterface } from '@platformatic/sql-events'
|
|
5
|
+
import { Entities, SQLMapperPluginInterface } from '@platformatic/sql-mapper'
|
|
6
|
+
import { Configuration, ConfigurationOptions } from '@platformatic/utils'
|
|
7
|
+
import { JSONSchemaType } from 'ajv'
|
|
8
|
+
import { FastifyError, FastifyInstance } from 'fastify'
|
|
9
|
+
import { PlatformaticDatabaseConfig } from './config'
|
|
11
10
|
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
11
|
+
export { PlatformaticApplication } from '@platformatic/service'
|
|
12
|
+
export { createConnectionPool, Entities, Entity, EntityHooks } from '@platformatic/sql-mapper'
|
|
13
|
+
export { PlatformaticDatabaseConfig } from './config'
|
|
14
14
|
|
|
15
|
-
export type
|
|
16
|
-
SQLMapperPluginInterface<T> &
|
|
15
|
+
export type PlatformaticDatabaseMixin<T extends Entities> = SQLMapperPluginInterface<T> &
|
|
17
16
|
SQLEventsPluginInterface &
|
|
18
17
|
DBAuthorizationPluginInterface
|
|
19
18
|
|
|
20
|
-
export type
|
|
19
|
+
export type DatabaseStackable = ServiceStackable<PlatformaticDatabaseConfig>
|
|
20
|
+
|
|
21
|
+
export type ServerInstance<T = {}> = FastifyInstance & {
|
|
22
|
+
platformatic: PlatformaticApplication<PlatformaticDatabaseConfig> & PlatformaticDatabaseMixin<Entities> & T
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type DatabaseConfiguration = Configuration<PlatformaticDatabaseConfig>
|
|
26
|
+
|
|
27
|
+
export declare function transform (
|
|
28
|
+
config: DatabaseConfiguration
|
|
29
|
+
): Promise<DatabaseConfiguration> | DatabaseConfiguration
|
|
21
30
|
|
|
22
|
-
export function
|
|
31
|
+
export declare function loadConfiguration (
|
|
32
|
+
root: string | PlatformaticDatabaseConfig,
|
|
33
|
+
source?: string | PlatformaticDatabaseConfig,
|
|
34
|
+
context?: ConfigurationOptions
|
|
35
|
+
): Promise<DatabaseConfiguration>
|
|
23
36
|
|
|
24
|
-
export function
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
stackable?: StackableInterface
|
|
30
|
-
}>
|
|
37
|
+
export declare function create (
|
|
38
|
+
root: string,
|
|
39
|
+
source?: string | PlatformaticDatabaseConfig,
|
|
40
|
+
context?: ConfigurationOptions
|
|
41
|
+
): Promise<ServiceStackable>
|
|
31
42
|
|
|
32
|
-
|
|
33
|
-
* All the errors thrown by the plugin.
|
|
34
|
-
*/
|
|
35
|
-
export module errors {
|
|
43
|
+
export declare const skipTelemetryHooks: boolean
|
|
36
44
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
export declare function platformaticDatabase (app: FastifyInstance, stackable: DatabaseStackable): Promise<void>
|
|
46
|
+
|
|
47
|
+
export declare class Generator extends BaseGenerator.BaseGenerator {}
|
|
48
|
+
|
|
49
|
+
export declare const packageJson: Record<string, unknown>
|
|
50
|
+
|
|
51
|
+
export declare const schema: JSONSchemaType<PlatformaticDatabaseConfig>
|
|
52
|
+
|
|
53
|
+
export declare const schemaComponents: {
|
|
54
|
+
db: JSONSchemaType<object>
|
|
55
|
+
sharedAuthorizationRule: JSONSchemaType<object>
|
|
56
|
+
authorization: JSONSchemaType<object>
|
|
57
|
+
migrations: JSONSchemaType<object>
|
|
58
|
+
types: JSONSchemaType<object>
|
|
42
59
|
}
|
|
60
|
+
|
|
61
|
+
export declare const version: string
|
|
62
|
+
|
|
63
|
+
export declare function MigrateMissingMigrationsError (): FastifyError
|
|
64
|
+
export declare function UnknownDatabaseError (): FastifyError
|
|
65
|
+
export declare function MigrateMissingMigrationsDirError (dir: string): FastifyError
|
|
66
|
+
export declare function MissingSeedFileError (): FastifyError
|
|
67
|
+
export declare function MigrationsToApplyError (): FastifyError
|
package/index.js
CHANGED
|
@@ -1,146 +1,85 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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
|
-
}
|
|
1
|
+
import { resolve, validationOptions } from '@platformatic/basic'
|
|
2
|
+
import { transform as serviceTransform } from '@platformatic/service'
|
|
3
|
+
import { kMetadata, loadConfiguration as utilsLoadConfiguration } from '@platformatic/utils'
|
|
4
|
+
import { readFile } from 'node:fs/promises'
|
|
5
|
+
import { resolve as resolvePath } from 'node:path'
|
|
6
|
+
import { schema } from './lib/schema.js'
|
|
7
|
+
import { DatabaseStackable } from './lib/stackable.js'
|
|
8
|
+
import { upgrade } from './lib/upgrade.js'
|
|
9
|
+
|
|
10
|
+
export async function transform (config) {
|
|
11
|
+
config = await serviceTransform(config)
|
|
12
|
+
|
|
13
|
+
if (
|
|
14
|
+
config.db &&
|
|
15
|
+
config.db.connectionString.indexOf('sqlite') === 0 &&
|
|
16
|
+
config.db.connectionString !== 'sqlite://:memory:'
|
|
17
|
+
) {
|
|
18
|
+
const originalSqlitePath = config.db.connectionString.replace('sqlite://', '')
|
|
19
|
+
const sqliteFullPath = resolvePath(config[kMetadata].root, originalSqlitePath)
|
|
20
|
+
config.db.connectionString = 'sqlite://' + sqliteFullPath
|
|
40
21
|
}
|
|
41
22
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
}
|
|
23
|
+
/* c8 ignore next 3 */
|
|
24
|
+
if (config.db.graphql?.schemaPath) {
|
|
25
|
+
config.db.graphql.schema = await readFile(config.db.graphql.schemaPath, 'utf8')
|
|
57
26
|
}
|
|
58
27
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
config.server.healthCheck.fn = healthCheck
|
|
64
|
-
}
|
|
28
|
+
/* c8 ignore next 2 */
|
|
29
|
+
const arePostgresqlSchemaDefined =
|
|
30
|
+
config.db?.connectionString.indexOf('postgres') === 0 && config.db?.schema?.length > 0
|
|
31
|
+
const migrationsTableName = arePostgresqlSchemaDefined ? 'public.versions' : 'versions'
|
|
65
32
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
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
|
-
}
|
|
33
|
+
// relative-to-absolute migrations path
|
|
34
|
+
if (config.migrations) {
|
|
35
|
+
config.migrations.table = config.migrations.table || migrationsTableName
|
|
74
36
|
}
|
|
75
37
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
)
|
|
88
|
-
}
|
|
38
|
+
if (config.migrations && config.db) {
|
|
39
|
+
// TODO remove the ignores
|
|
40
|
+
/* c8 ignore next 4 */
|
|
41
|
+
config.db.ignore = config.db.ignore || {}
|
|
42
|
+
config.db.ignore = Object.assign(
|
|
43
|
+
{},
|
|
44
|
+
{
|
|
45
|
+
[config.migrations.table || migrationsTableName]: true
|
|
46
|
+
},
|
|
47
|
+
config.db.ignore
|
|
48
|
+
)
|
|
89
49
|
}
|
|
90
|
-
toLoad[Symbol.for('skip-override')] = true
|
|
91
|
-
|
|
92
|
-
await app.register(platformaticService, {
|
|
93
|
-
...opts,
|
|
94
|
-
beforePlugins: [toLoad],
|
|
95
|
-
})
|
|
96
50
|
|
|
97
|
-
if (
|
|
98
|
-
|
|
51
|
+
if (config.types?.autogenerate === 'true') {
|
|
52
|
+
config.types.autogenerate = true
|
|
99
53
|
}
|
|
100
|
-
}
|
|
101
54
|
|
|
102
|
-
|
|
103
|
-
const { db, sql } = app.platformatic
|
|
104
|
-
try {
|
|
105
|
-
await db.query(sql`SELECT 1`)
|
|
106
|
-
return true
|
|
107
|
-
} catch (err) {
|
|
108
|
-
app.log.warn({ err }, 'Healthcheck failed')
|
|
109
|
-
return false
|
|
110
|
-
}
|
|
55
|
+
return config
|
|
111
56
|
}
|
|
112
57
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
},
|
|
126
|
-
upgrade,
|
|
58
|
+
export async function loadConfiguration (configOrRoot, sourceOrConfig, context) {
|
|
59
|
+
const { root, source } = await resolve(configOrRoot, sourceOrConfig, 'db')
|
|
60
|
+
|
|
61
|
+
return utilsLoadConfiguration(source, context?.schema ?? schema, {
|
|
62
|
+
validationOptions,
|
|
63
|
+
transform,
|
|
64
|
+
upgrade,
|
|
65
|
+
replaceEnv: true,
|
|
66
|
+
replaceEnvIgnore: ['$.db.openapi.ignoreRoutes'],
|
|
67
|
+
root,
|
|
68
|
+
...context
|
|
69
|
+
})
|
|
127
70
|
}
|
|
128
71
|
|
|
129
|
-
function
|
|
130
|
-
|
|
72
|
+
export async function create (configOrRoot, sourceOrConfig, context) {
|
|
73
|
+
const config = await loadConfiguration(configOrRoot, sourceOrConfig, context)
|
|
74
|
+
return new DatabaseStackable(config[kMetadata].root, config, context)
|
|
131
75
|
}
|
|
132
76
|
|
|
133
|
-
|
|
134
|
-
return buildStackable(options, platformaticDB, DbStackable)
|
|
135
|
-
}
|
|
77
|
+
export const skipTelemetryHooks = true
|
|
136
78
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
module.exports.Generator = require('./lib/generator/db-generator').Generator
|
|
145
|
-
module.exports.buildStackable = buildDbStackable
|
|
146
|
-
module.exports.DbStackable = DbStackable
|
|
79
|
+
export { platformaticDatabase } from './lib/application.js'
|
|
80
|
+
export * from './lib/commands/index.js'
|
|
81
|
+
export * from './lib/errors.js'
|
|
82
|
+
export * as errors from './lib/errors.js'
|
|
83
|
+
export { Generator } from './lib/generator.js'
|
|
84
|
+
export { packageJson, schema, schemaComponents, version } from './lib/schema.js'
|
|
85
|
+
export { DatabaseStackable } from './lib/stackable.js'
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import auth from '@platformatic/db-authorization'
|
|
2
|
+
import core from '@platformatic/db-core'
|
|
3
|
+
import { platformaticService } from '@platformatic/service'
|
|
4
|
+
import { isKeyEnabled } from '@platformatic/utils'
|
|
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, stackable) {
|
|
23
|
+
const config = await stackable.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 stackable.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, stackable)
|
|
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,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,62 @@
|
|
|
1
|
+
import { loadConfiguration } from '@platformatic/utils'
|
|
2
|
+
import { utimesSync } from 'node:fs'
|
|
3
|
+
import { execute } from '../migrator.js'
|
|
4
|
+
import { schema } from '../schema.js'
|
|
5
|
+
import { updateSchemaLock } from '../utils.js'
|
|
6
|
+
import { generateTypes } from './types.js'
|
|
7
|
+
|
|
8
|
+
export async function applyMigrations (logger, configFile, args, context) {
|
|
9
|
+
const { parseArgs, logFatalError } = context
|
|
10
|
+
const config = await loadConfiguration(configFile, schema)
|
|
11
|
+
|
|
12
|
+
const {
|
|
13
|
+
values: { to, rollback }
|
|
14
|
+
} = parseArgs(
|
|
15
|
+
args,
|
|
16
|
+
{
|
|
17
|
+
rollback: {
|
|
18
|
+
type: 'boolean',
|
|
19
|
+
short: 'r'
|
|
20
|
+
},
|
|
21
|
+
to: {
|
|
22
|
+
type: 'string',
|
|
23
|
+
short: 't'
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
false
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const appliedMigrations = await execute(logger, config, to, rollback)
|
|
31
|
+
|
|
32
|
+
if (config.types && config.types.autogenerate) {
|
|
33
|
+
await generateTypes(logger, configFile, args, context)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (appliedMigrations) {
|
|
37
|
+
await updateSchemaLock(logger, config)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// touch the @platformatic/db config to trigger a restart
|
|
41
|
+
const now = new Date()
|
|
42
|
+
|
|
43
|
+
utimesSync(configFile, now, now)
|
|
44
|
+
} catch (err) {
|
|
45
|
+
if (err.code === 'PTL_DB_MIGRATE_ERROR') {
|
|
46
|
+
logFatalError(logger, err.message)
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* c8 ignore next 2 */
|
|
51
|
+
throw err
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const helpFooter = `
|
|
56
|
+
The migrations will be applied in the order they are specified in the
|
|
57
|
+
folder defined in the configuration file. If you want to apply a specific migration,
|
|
58
|
+
you can use the \`--to\` option (use \`000\` to reset to the initial state).
|
|
59
|
+
|
|
60
|
+
You can find more details about the configuration format here:
|
|
61
|
+
* [Platformatic DB Configuration](https://docs.platformatic.dev/docs/db/configuration)
|
|
62
|
+
`
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { loadConfiguration } from '@platformatic/utils'
|
|
2
|
+
import { writeFile } from 'node:fs/promises'
|
|
3
|
+
import { join, relative } from 'node:path'
|
|
4
|
+
import * as errors from '../errors.js'
|
|
5
|
+
import { Migrator } from '../migrator.js'
|
|
6
|
+
import { schema } from '../schema.js'
|
|
7
|
+
|
|
8
|
+
export async function createMigrations (logger, configFile, _, { colorette: { bold } }) {
|
|
9
|
+
const config = await loadConfiguration(configFile, schema)
|
|
10
|
+
|
|
11
|
+
let migrator = null
|
|
12
|
+
try {
|
|
13
|
+
const migrationsConfig = config.migrations
|
|
14
|
+
if (migrationsConfig === undefined) {
|
|
15
|
+
throw new errors.MigrateMissingMigrationsError()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
migrator = new Migrator(migrationsConfig, config.db, logger)
|
|
19
|
+
|
|
20
|
+
const nextMigrationVersion = await migrator.getNextMigrationVersion()
|
|
21
|
+
const nextMigrationVersionStr = migrator.convertVersionToStr(nextMigrationVersion)
|
|
22
|
+
|
|
23
|
+
const nextDoMigrationName = `${nextMigrationVersionStr}.do.sql`
|
|
24
|
+
const nextUndoMigrationName = `${nextMigrationVersionStr}.undo.sql`
|
|
25
|
+
|
|
26
|
+
const doFile = join(migrator.migrationDir, nextDoMigrationName)
|
|
27
|
+
const undoFile = join(migrator.migrationDir, nextUndoMigrationName)
|
|
28
|
+
|
|
29
|
+
await Promise.all([writeFile(doFile, ''), writeFile(undoFile, '')])
|
|
30
|
+
|
|
31
|
+
logger.info(
|
|
32
|
+
`Created migration files ${bold(relative(process.cwd(), doFile))} and ${bold(relative(process.cwd(), undoFile))}.`
|
|
33
|
+
)
|
|
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,30 @@
|
|
|
1
|
+
import { abstractLogger, kMetadata, loadConfiguration } from '@platformatic/utils'
|
|
2
|
+
import { printSchema as printGraphqlSchema } from 'graphql'
|
|
3
|
+
import { create } from '../../index.js'
|
|
4
|
+
import { schema } from '../schema.js'
|
|
5
|
+
|
|
6
|
+
export async function printSchema (logger, configFile, args, { colorette: { bold }, logFatalError }) {
|
|
7
|
+
const config = await loadConfiguration(configFile, schema)
|
|
8
|
+
|
|
9
|
+
const type = args[0]
|
|
10
|
+
|
|
11
|
+
if (!type) {
|
|
12
|
+
logFatalError(logger, `Please specify a schema type between ${bold('openapi')} and ${bold('graphql')}.`)
|
|
13
|
+
} else if (type !== 'openapi' && type !== 'graphql') {
|
|
14
|
+
logFatalError(logger, `Invalid schema type ${bold(type)}. Use ${bold('openapi')} or ${bold('graphql')}.`)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const app = await create(config[kMetadata].root, configFile, { logger: abstractLogger })
|
|
18
|
+
await app.init()
|
|
19
|
+
|
|
20
|
+
let output
|
|
21
|
+
if (type === 'openapi') {
|
|
22
|
+
await app.start({ listen: true })
|
|
23
|
+
output = JSON.stringify(app.getApplication().swagger(), null, 2)
|
|
24
|
+
} else {
|
|
25
|
+
output = printGraphqlSchema(app.getApplication().graphql.schema)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
console.log(output)
|
|
29
|
+
await app.stop()
|
|
30
|
+
}
|