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
|
const pkgDir = args.packages
|
||||||
|
|
||||||
getFolders(pkgDir)
|
getFolders(pkgDir)
|
||||||
.map(file => path.join(pkgDir, file, TSCONFIG_FILENAME))
|
.map(folder => path.join(folder, TSCONFIG_FILENAME))
|
||||||
.filter(file => fs.existsSync(file))
|
.filter(file => fs.existsSync(file))
|
||||||
.forEach(file => {
|
.forEach(file => {
|
||||||
const tsconfig = JSON.parse(fs.readFileSync(file, 'utf8'))
|
const tsconfig = JSON.parse(fs.readFileSync(file, 'utf8'))
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { Config } from './Config'
|
|||||||
import { ServerConfigurator } from './configureServer'
|
import { ServerConfigurator } from './configureServer'
|
||||||
import { createServer } from './createServer'
|
import { createServer } from './createServer'
|
||||||
|
|
||||||
export interface CLIBootstrapParams {
|
export interface ServerBootstrapParams {
|
||||||
readonly config: Config
|
readonly config: Config
|
||||||
readonly configureServer: ServerConfigurator
|
readonly configureServer: ServerConfigurator
|
||||||
readonly namespace?: Namespace
|
readonly namespace?: Namespace
|
||||||
@ -26,7 +26,7 @@ function getFunctions(obj: object): Function[] {
|
|||||||
.filter(f => typeof f === 'function')
|
.filter(f => typeof f === 'function')
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CLIBootstrap implements Bootstrap {
|
export class ServerBootstrap implements Bootstrap {
|
||||||
protected config: Config
|
protected config: Config
|
||||||
protected configureServer: ServerConfigurator
|
protected configureServer: ServerConfigurator
|
||||||
protected namespace: Namespace
|
protected namespace: Namespace
|
||||||
@ -37,7 +37,7 @@ export class CLIBootstrap implements Bootstrap {
|
|||||||
readonly application: Application
|
readonly application: Application
|
||||||
readonly database: Database
|
readonly database: Database
|
||||||
|
|
||||||
constructor(params: CLIBootstrapParams) {
|
constructor(params: ServerBootstrapParams) {
|
||||||
this.config = {
|
this.config = {
|
||||||
...params.config,
|
...params.config,
|
||||||
app: {
|
app: {
|
||||||
@ -76,22 +76,6 @@ export class CLIBootstrap implements Bootstrap {
|
|||||||
return createServer(configureServer(this.getConfig(), database))
|
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(
|
async listen(
|
||||||
port: number | string | undefined = process.env.PORT || 3000,
|
port: number | string | undefined = process.env.PORT || 3000,
|
||||||
hostname: string | undefined= process.env.BIND_HOST,
|
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(
|
protected async start(
|
||||||
port: number | string | undefined = process.env.PORT,
|
port: number | string | undefined = process.env.PORT,
|
||||||
hostname?: string,
|
hostname?: string,
|
||||||
@ -140,11 +112,12 @@ export class CLIBootstrap implements Bootstrap {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const apiLogger = loggerFactory.getLogger('api')
|
const apiLogger = loggerFactory.getLogger('api')
|
||||||
|
const address = this.getAddress()
|
||||||
|
|
||||||
if (hostname) {
|
if (typeof address === 'string') {
|
||||||
apiLogger.info('Listening on %s %s', port, hostname)
|
apiLogger.info('Listening on %s', address)
|
||||||
} else {
|
} 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> {
|
async close(): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
this.server!.close(err => {
|
this.server!.close(err => {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
return resolve()
|
return resolve()
|
||||||
@ -1,4 +1,4 @@
|
|||||||
export * from './CLIBootstrap'
|
export * from './ServerBootstrap'
|
||||||
export * from './Bootstrap'
|
export * from './Bootstrap'
|
||||||
export * from './Application'
|
export * from './Application'
|
||||||
export * from './Config'
|
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 { configureServer } from './application/configureServer'
|
||||||
import { config } from './config'
|
import { config } from './config'
|
||||||
|
import * as entities from './entities'
|
||||||
|
import * as migrations from './migrations'
|
||||||
|
|
||||||
export default new CLIBootstrap({
|
export default new ServerBootstrap({
|
||||||
config,
|
config,
|
||||||
|
entities,
|
||||||
|
migrations,
|
||||||
configureServer,
|
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 './application'
|
||||||
|
export * from './cli'
|
||||||
export * from './database'
|
export * from './database'
|
||||||
export * from './entities'
|
export * from './entities'
|
||||||
export * from './error'
|
export * from './error'
|
||||||
@ -18,7 +19,8 @@ import * as rpc from './rpc'
|
|||||||
export {rpc}
|
export {rpc}
|
||||||
|
|
||||||
import bootstrap from './bootstrap'
|
import bootstrap from './bootstrap'
|
||||||
|
import { CLI } from './cli'
|
||||||
|
|
||||||
if (require.main === module) {
|
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 { APIDef } from '@rondo.dev/common'
|
||||||
import { createNamespace } from 'cls-hooked'
|
import { createNamespace } from 'cls-hooked'
|
||||||
import { CLIBootstrap } from './application'
|
import { ServerBootstrap } from './application'
|
||||||
import { configureServer } from './application/configureServer'
|
import { configureServer } from './application/configureServer'
|
||||||
import { config } from './config'
|
import { config } from './config'
|
||||||
import { TestUtils } from './test-utils'
|
import { TestUtils } from './test-utils'
|
||||||
|
|
||||||
export const exit = jest.fn()
|
export const exit = jest.fn()
|
||||||
|
|
||||||
export const bootstrap = new CLIBootstrap({
|
export const bootstrap = new ServerBootstrap({
|
||||||
config,
|
config,
|
||||||
configureServer,
|
configureServer,
|
||||||
namespace: createNamespace('test'),
|
namespace: createNamespace('test'),
|
||||||
|
|||||||
@ -7,6 +7,9 @@
|
|||||||
{
|
{
|
||||||
"path": "../common/tsconfig.esm.json"
|
"path": "../common/tsconfig.esm.json"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"path": "../argparse/tsconfig.esm.json"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"path": "../client/tsconfig.esm.json"
|
"path": "../client/tsconfig.esm.json"
|
||||||
},
|
},
|
||||||
@ -32,4 +35,4 @@
|
|||||||
"path": "../validator/tsconfig.esm.json"
|
"path": "../validator/tsconfig.esm.json"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -6,6 +6,7 @@
|
|||||||
},
|
},
|
||||||
"references": [
|
"references": [
|
||||||
{"path": "../common"},
|
{"path": "../common"},
|
||||||
|
{"path": "../argparse"},
|
||||||
{"path": "../client"},
|
{"path": "../client"},
|
||||||
{"path": "../jsonrpc"},
|
{"path": "../jsonrpc"},
|
||||||
{"path": "../logger"},
|
{"path": "../logger"},
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user