@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.
Files changed (58) hide show
  1. package/config.d.ts +1 -19
  2. package/eslint.config.js +9 -5
  3. package/index.d.ts +56 -31
  4. package/index.js +67 -128
  5. package/lib/application.js +102 -0
  6. package/lib/commands/index.js +59 -0
  7. package/lib/commands/migrations-apply.js +62 -0
  8. package/lib/commands/migrations-create.js +48 -0
  9. package/lib/commands/print-schema.js +30 -0
  10. package/lib/commands/seed.js +88 -0
  11. package/lib/commands/types.js +21 -0
  12. package/lib/errors.js +15 -11
  13. package/lib/{generator/db-generator.js → generator.js} +57 -52
  14. package/lib/{migrator.mjs → migrator.js} +45 -37
  15. package/lib/{root-endpoint/index.js → root.js} +6 -7
  16. package/lib/schema.js +31 -21
  17. package/lib/stackable.js +14 -26
  18. package/lib/{generator/code-templates.js → templates.js} +47 -17
  19. package/lib/types.js +160 -0
  20. package/lib/upgrade.js +7 -10
  21. package/lib/utils.js +12 -23
  22. package/lib/versions/0.18.0.js +3 -5
  23. package/lib/versions/{from-zero-twenty-height-to-will-see.js → 0.28.0.js} +3 -5
  24. package/lib/versions/2.0.0.js +3 -5
  25. package/package.json +16 -23
  26. package/schema.json +2 -73
  27. package/tsconfig.json +16 -6
  28. package/.snapshots/810d795d512560f3863d8db472c81c27/0.json +0 -1
  29. package/.snapshots/810d795d512560f3863d8db472c81c27/1.json +0 -1
  30. package/db.mjs +0 -86
  31. package/help/compile.txt +0 -17
  32. package/help/create.txt +0 -13
  33. package/help/help.txt +0 -11
  34. package/help/migrations apply.txt +0 -45
  35. package/help/migrations create.txt +0 -27
  36. package/help/migrations.txt +0 -4
  37. package/help/schema.txt +0 -25
  38. package/help/seed.txt +0 -36
  39. package/help/start.txt +0 -47
  40. package/help/types.txt +0 -40
  41. package/index.test-d.ts +0 -43
  42. package/lib/adjust-config.js +0 -42
  43. package/lib/create.mjs +0 -89
  44. package/lib/gen-migration.mjs +0 -53
  45. package/lib/gen-schema.mjs +0 -68
  46. package/lib/gen-types.mjs +0 -202
  47. package/lib/generator/README.md +0 -38
  48. package/lib/generator.d.ts +0 -7
  49. package/lib/migrate.mjs +0 -87
  50. package/lib/seed.mjs +0 -90
  51. /package/{lib/root-endpoint/public → public}/images/dark_mode.svg +0 -0
  52. /package/{lib/root-endpoint/public → public}/images/favicon.ico +0 -0
  53. /package/{lib/root-endpoint/public → public}/images/light_mode.svg +0 -0
  54. /package/{lib/root-endpoint/public → public}/images/platformatic-logo-dark.svg +0 -0
  55. /package/{lib/root-endpoint/public → public}/images/platformatic-logo-light.svg +0 -0
  56. /package/{lib/root-endpoint/public → public}/images/triangle_dark.svg +0 -0
  57. /package/{lib/root-endpoint/public → public}/images/triangle_light.svg +0 -0
  58. /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 PlatformaticDB {
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
- 'use strict'
1
+ import neostandard from 'neostandard'
2
2
 
3
- const neostandard = require('neostandard')
4
-
5
- module.exports = neostandard({
3
+ export default neostandard({
6
4
  ts: true,
7
- ignores: [...neostandard.resolveIgnoresFromGitignore(), 'test/tmp/**/*'],
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 { FastifyError } from '@fastify/error'
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 { Entities, EntityHooks, Entity, createConnectionPool } from '@platformatic/sql-mapper'
13
- export { PlatformaticApp } from '@platformatic/service'
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 PlatformaticDBMixin<T extends Entities> =
16
- SQLMapperPluginInterface<T> &
15
+ export type PlatformaticDatabaseMixin<T extends Entities> = SQLMapperPluginInterface<T> &
17
16
  SQLEventsPluginInterface &
18
17
  DBAuthorizationPluginInterface
19
18
 
20
- export type PlatformaticDBConfig = PlatformaticDB
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 buildServer (opts: object, app?: object, ConfigManagerContructor?: object): Promise<FastifyInstance>
31
+ export declare function loadConfiguration (
32
+ root: string | PlatformaticDatabaseConfig,
33
+ source?: string | PlatformaticDatabaseConfig,
34
+ context?: ConfigurationOptions
35
+ ): Promise<DatabaseConfiguration>
23
36
 
24
- export function buildStackable (opts: object, app?: object): Promise<{
25
- configType: string,
26
- configManager?: ConfigManager<PlatformaticDBConfig>,
27
- configManagerConfig?: ConfigManagerConfig<PlatformaticDBConfig>,
28
- schema?: object,
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
- export const MigrateMissingMigrationsError: () => FastifyError
38
- export const UnknownDatabaseError: () => FastifyError
39
- export const MigrateMissingMigrationsDirError: (dir: string) => FastifyError
40
- export const MissingSeedFileError: () => FastifyError
41
- export const MigrationsToApplyError: () => FastifyError
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
- 'use strict'
2
-
3
- const core = require('@platformatic/db-core')
4
- const auth = require('@platformatic/db-authorization')
5
- const { createConnectionPool } = require('@platformatic/sql-mapper')
6
- const { platformaticService, buildServer, buildStackable } = require('@platformatic/service')
7
- const { isKeyEnabled } = require('@platformatic/utils')
8
- const { schema } = require('./lib/schema')
9
- const ConfigManager = require('@platformatic/config')
10
- const adjustConfig = require('./lib/adjust-config')
11
- const { locateSchemaLock, updateSchemaLock } = require('./lib/utils')
12
- const errors = require('./lib/errors')
13
- const upgrade = require('./lib/upgrade')
14
- const fs = require('fs/promises')
15
- const { DbStackable } = require('./lib/stackable')
16
- const version = require('./package.json').version
17
-
18
- async function platformaticDB (app, opts) {
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
- }
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
- 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
- }
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
- if (isKeyEnabled('healthCheck', config.server)) {
60
- if (typeof config.server.healthCheck !== 'object') {
61
- config.server.healthCheck = {}
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
- 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
- }
33
+ // relative-to-absolute migrations path
34
+ if (config.migrations) {
35
+ config.migrations.table = config.migrations.table || migrationsTableName
74
36
  }
75
37
 
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
- }
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 (!app.hasRoute({ url: '/', method: 'GET' }) && !app.hasRoute({ url: '/*', method: 'GET' })) {
98
- app.register(require('./lib/root-endpoint'), config)
51
+ if (config.types?.autogenerate === 'true') {
52
+ config.types.autogenerate = true
99
53
  }
100
- }
101
54
 
102
- async function healthCheck (app) {
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
- platformaticDB[Symbol.for('skip-override')] = true
114
- platformaticDB.schema = schema
115
- platformaticDB.configType = 'db'
116
- platformaticDB.isPLTService = true
117
- platformaticDB.configManagerConfig = {
118
- version,
119
- schema,
120
- allowToWatch: ['.env'],
121
- schemaOptions: platformaticService.configManagerConfig.schemaOptions,
122
- replaceEnvIgnore: ['$.db.openapi.ignoreRoutes'],
123
- async transformConfig () {
124
- await adjustConfig(this)
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 _buildServer (options) {
130
- return buildServer(options, platformaticDB)
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
- async function buildDbStackable (options) {
134
- return buildStackable(options, platformaticDB, DbStackable)
135
- }
77
+ export const skipTelemetryHooks = true
136
78
 
137
- module.exports = platformaticDB
138
- module.exports.buildServer = _buildServer
139
- module.exports.schema = schema
140
- module.exports.platformaticDB = platformaticDB
141
- module.exports.ConfigManager = ConfigManager
142
- module.exports.errors = errors
143
- module.exports.createConnectionPool = createConnectionPool
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
+ }