Add packages/server/cli
This commit is contained in:
parent
ae6b00c24c
commit
f51b41c576
@ -21,7 +21,7 @@ export async function syncEsmConfig(...argv: string[]) {
|
||||
const pkgDir = args.packages
|
||||
|
||||
getFolders(pkgDir)
|
||||
.map(file => path.join(pkgDir, file, TSCONFIG_FILENAME))
|
||||
.map(folder => path.join(folder, TSCONFIG_FILENAME))
|
||||
.filter(file => fs.existsSync(file))
|
||||
.forEach(file => {
|
||||
const tsconfig = JSON.parse(fs.readFileSync(file, 'utf8'))
|
||||
|
||||
@ -10,7 +10,7 @@ import { Config } from './Config'
|
||||
import { ServerConfigurator } from './configureServer'
|
||||
import { createServer } from './createServer'
|
||||
|
||||
export interface CLIBootstrapParams {
|
||||
export interface ServerBootstrapParams {
|
||||
readonly config: Config
|
||||
readonly configureServer: ServerConfigurator
|
||||
readonly namespace?: Namespace
|
||||
@ -26,7 +26,7 @@ function getFunctions(obj: object): Function[] {
|
||||
.filter(f => typeof f === 'function')
|
||||
}
|
||||
|
||||
export class CLIBootstrap implements Bootstrap {
|
||||
export class ServerBootstrap implements Bootstrap {
|
||||
protected config: Config
|
||||
protected configureServer: ServerConfigurator
|
||||
protected namespace: Namespace
|
||||
@ -37,7 +37,7 @@ export class CLIBootstrap implements Bootstrap {
|
||||
readonly application: Application
|
||||
readonly database: Database
|
||||
|
||||
constructor(params: CLIBootstrapParams) {
|
||||
constructor(params: ServerBootstrapParams) {
|
||||
this.config = {
|
||||
...params.config,
|
||||
app: {
|
||||
@ -76,22 +76,6 @@ export class CLIBootstrap implements Bootstrap {
|
||||
return createServer(configureServer(this.getConfig(), database))
|
||||
}
|
||||
|
||||
async exec(command = 'listen') {
|
||||
switch (command) {
|
||||
case 'listen':
|
||||
await this.listen()
|
||||
return
|
||||
case 'migrate':
|
||||
await this.migrate()
|
||||
return
|
||||
case 'migrate-undo':
|
||||
await this.migrateUndo()
|
||||
return
|
||||
default:
|
||||
throw new Error('Unknown command: ' + command)
|
||||
}
|
||||
}
|
||||
|
||||
async listen(
|
||||
port: number | string | undefined = process.env.PORT || 3000,
|
||||
hostname: string | undefined= process.env.BIND_HOST,
|
||||
@ -106,18 +90,6 @@ export class CLIBootstrap implements Bootstrap {
|
||||
}
|
||||
}
|
||||
|
||||
async migrate() {
|
||||
const connection = await this.database.connect()
|
||||
await connection.runMigrations()
|
||||
await connection.close()
|
||||
}
|
||||
|
||||
async migrateUndo() {
|
||||
const connection = await this.database.connect()
|
||||
await connection.undoLastMigration()
|
||||
await connection.close()
|
||||
}
|
||||
|
||||
protected async start(
|
||||
port: number | string | undefined = process.env.PORT,
|
||||
hostname?: string,
|
||||
@ -140,11 +112,12 @@ export class CLIBootstrap implements Bootstrap {
|
||||
})
|
||||
|
||||
const apiLogger = loggerFactory.getLogger('api')
|
||||
const address = this.getAddress()
|
||||
|
||||
if (hostname) {
|
||||
apiLogger.info('Listening on %s %s', port, hostname)
|
||||
if (typeof address === 'string') {
|
||||
apiLogger.info('Listening on %s', address)
|
||||
} else {
|
||||
apiLogger.info('Listening on %s', port)
|
||||
apiLogger.info('Listening on %s %s', address.address, address.port)
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,7 +130,7 @@ export class CLIBootstrap implements Bootstrap {
|
||||
}
|
||||
|
||||
async close(): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
this.server!.close(err => {
|
||||
if (!err) {
|
||||
return resolve()
|
||||
@ -1,4 +1,4 @@
|
||||
export * from './CLIBootstrap'
|
||||
export * from './ServerBootstrap'
|
||||
export * from './Bootstrap'
|
||||
export * from './Application'
|
||||
export * from './Config'
|
||||
|
||||
0
packages/server/src/application/processArgs.ts
Normal file
0
packages/server/src/application/processArgs.ts
Normal file
@ -1,8 +1,12 @@
|
||||
import { CLIBootstrap } from './application'
|
||||
import { ServerBootstrap } from './application'
|
||||
import { configureServer } from './application/configureServer'
|
||||
import { config } from './config'
|
||||
import * as entities from './entities'
|
||||
import * as migrations from './migrations'
|
||||
|
||||
export default new CLIBootstrap({
|
||||
export default new ServerBootstrap({
|
||||
config,
|
||||
entities,
|
||||
migrations,
|
||||
configureServer,
|
||||
})
|
||||
|
||||
72
packages/server/src/cli/CLI.ts
Normal file
72
packages/server/src/cli/CLI.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import { Bootstrap } from "../application";
|
||||
import { argparse, arg } from "@rondo.dev/argparse";
|
||||
|
||||
export class CLI {
|
||||
constructor(readonly bootstrap: Bootstrap) {
|
||||
}
|
||||
|
||||
execute(argv: string[]) {
|
||||
const choices: Array<keyof typeof commands> = ['start', 'migrate']
|
||||
const {parse} = argparse({
|
||||
command: arg('string', {
|
||||
default: 'start',
|
||||
choices,
|
||||
positional: true,
|
||||
description: 'Command to run',
|
||||
}),
|
||||
args: arg('string[]', {
|
||||
n: '*',
|
||||
positional: true,
|
||||
description: 'Command arguments',
|
||||
}),
|
||||
help: arg('boolean', {alias: 'h'}),
|
||||
})
|
||||
const args = parse(argv)
|
||||
const command = args.command as keyof typeof commands
|
||||
commands[command](this.bootstrap, [args.command, ...args.args])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const commands = {
|
||||
async start(bootstrap: Bootstrap, argv: string[]) {
|
||||
const {parse} = argparse({
|
||||
host: arg('string', {
|
||||
description: '',
|
||||
}),
|
||||
socket: arg('number', {
|
||||
alias: 's',
|
||||
description: 'Socket to listen on',
|
||||
}),
|
||||
port: arg('number', {
|
||||
alias: 'p',
|
||||
description: 'Port to listen on',
|
||||
}),
|
||||
help: arg('boolean', {alias: 'h'}),
|
||||
})
|
||||
const args = parse(argv)
|
||||
await bootstrap.listen(args.port || args.socket, args.host)
|
||||
},
|
||||
async migrate(bootstrap: Bootstrap, argv: string[]) {
|
||||
const {parse} = argparse({
|
||||
undo: arg('boolean', {
|
||||
alias: 'u',
|
||||
description: 'Undo last migration',
|
||||
}),
|
||||
help: arg('boolean', {alias: 'h'}),
|
||||
})
|
||||
|
||||
const args = parse(argv)
|
||||
|
||||
const {database} = bootstrap
|
||||
const connection = await database.connect()
|
||||
try {
|
||||
await (args.undo
|
||||
? connection.undoLastMigration()
|
||||
: connection.runMigrations())
|
||||
} finally {
|
||||
await connection.close()
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
1
packages/server/src/cli/index.ts
Normal file
1
packages/server/src/cli/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './CLI'
|
||||
@ -4,6 +4,7 @@ if (require.main === module) {
|
||||
}
|
||||
}
|
||||
export * from './application'
|
||||
export * from './cli'
|
||||
export * from './database'
|
||||
export * from './entities'
|
||||
export * from './error'
|
||||
@ -18,7 +19,8 @@ import * as rpc from './rpc'
|
||||
export {rpc}
|
||||
|
||||
import bootstrap from './bootstrap'
|
||||
import { CLI } from './cli'
|
||||
|
||||
if (require.main === module) {
|
||||
bootstrap.exec(process.argv[2])
|
||||
new CLI(bootstrap).execute(process.argv.slice(1))
|
||||
}
|
||||
|
||||
11
packages/server/src/migrations/index.ts
Normal file
11
packages/server/src/migrations/index.ts
Normal file
@ -0,0 +1,11 @@
|
||||
// This file has been autogenerated by exportDir script
|
||||
export * from './1547031984999-user'
|
||||
export * from './1547474320589-session'
|
||||
export * from './1547480973242-sessionUserId'
|
||||
export * from './1548148128477-comments'
|
||||
export * from './1548155222136-unique-votes'
|
||||
export * from './1548347305012-indices'
|
||||
export * from './1548412884820-role-unique'
|
||||
export * from './1552227347990-comment-parentid-nullable'
|
||||
export * from './1552227652042-nullable'
|
||||
export * from './1552899385211-user-first-last-name'
|
||||
@ -1,13 +1,13 @@
|
||||
import { APIDef } from '@rondo.dev/common'
|
||||
import { createNamespace } from 'cls-hooked'
|
||||
import { CLIBootstrap } from './application'
|
||||
import { ServerBootstrap } from './application'
|
||||
import { configureServer } from './application/configureServer'
|
||||
import { config } from './config'
|
||||
import { TestUtils } from './test-utils'
|
||||
|
||||
export const exit = jest.fn()
|
||||
|
||||
export const bootstrap = new CLIBootstrap({
|
||||
export const bootstrap = new ServerBootstrap({
|
||||
config,
|
||||
configureServer,
|
||||
namespace: createNamespace('test'),
|
||||
|
||||
@ -7,6 +7,9 @@
|
||||
{
|
||||
"path": "../common/tsconfig.esm.json"
|
||||
},
|
||||
{
|
||||
"path": "../argparse/tsconfig.esm.json"
|
||||
},
|
||||
{
|
||||
"path": "../client/tsconfig.esm.json"
|
||||
},
|
||||
@ -32,4 +35,4 @@
|
||||
"path": "../validator/tsconfig.esm.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -6,6 +6,7 @@
|
||||
},
|
||||
"references": [
|
||||
{"path": "../common"},
|
||||
{"path": "../argparse"},
|
||||
{"path": "../client"},
|
||||
{"path": "../jsonrpc"},
|
||||
{"path": "../logger"},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user