mirror of
https://github.com/directus/directus.git
synced 2026-04-03 03:00:39 -04:00
Merge pull request #607 from WoLfulus/feat/route-hooks
Add init/destroy hooks
This commit is contained in:
@@ -51,9 +51,9 @@
|
||||
"directus": "cli.js"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "cross-env NODE_ENV=production node dist/server.js",
|
||||
"start": "npx directus start",
|
||||
"build": "rm -rf dist && tsc --build && copyfiles \"src/**/*.*\" -e \"src/**/*.ts\" -u 1 dist",
|
||||
"dev": "cross-env NODE_ENV=development LOG_LEVEL=trace ts-node-dev --files src/server.ts --respawn --watch \"src/**/*.ts\" --transpile-only",
|
||||
"dev": "cross-env NODE_ENV=development LOG_LEVEL=trace ts-node-dev --files src/start.ts --respawn --watch \"src/**/*.ts\" --transpile-only",
|
||||
"cli": "cross-env NODE_ENV=development ts-node --script-mode --transpile-only src/cli/index.ts",
|
||||
"prepublishOnly": "npm run build"
|
||||
},
|
||||
@@ -67,6 +67,7 @@
|
||||
"@directus/app": "file:../app",
|
||||
"@directus/format-title": "file:../packages/format-title",
|
||||
"@directus/specs": "file:../packages/spec",
|
||||
"@godaddy/terminus": "^4.4.1",
|
||||
"@slynova/flydrive": "^1.0.2",
|
||||
"@slynova/flydrive-gcs": "^1.0.2",
|
||||
"@slynova/flydrive-s3": "^1.0.2",
|
||||
|
||||
@@ -137,6 +137,7 @@ registerExtensions(customRouter);
|
||||
|
||||
track('serverStarted');
|
||||
|
||||
emitter.emitAsync('server.started').catch((err) => logger.warn(err));
|
||||
emitter.emit('init.before', { app });
|
||||
emitter.emitAsync('init').catch((err) => logger.warn(err));
|
||||
|
||||
export default app;
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
import knex from 'knex';
|
||||
import logger from '../../logger';
|
||||
import { Express } from 'express';
|
||||
|
||||
export default async function start() {
|
||||
const { default: env } = require('../../env');
|
||||
const database = require('../../database');
|
||||
const connection = database.default as knex;
|
||||
|
||||
await database.validateDBConnection();
|
||||
|
||||
const app: Express = require('../../app').default;
|
||||
|
||||
const port = env.PORT;
|
||||
|
||||
const server = app.listen(port, () => {
|
||||
logger.info(`Server started at port ${port}`);
|
||||
});
|
||||
|
||||
const signals: NodeJS.Signals[] = ['SIGHUP', 'SIGINT', 'SIGTERM'];
|
||||
signals.forEach((signal) => {
|
||||
process.on(signal, () =>
|
||||
server.close((err) => {
|
||||
if (err) {
|
||||
logger.error(`Failed to close server: ${err.message}`, {
|
||||
err,
|
||||
});
|
||||
process.exit(1);
|
||||
}
|
||||
logger.info('Server stopped.');
|
||||
|
||||
connection
|
||||
.destroy()
|
||||
.then(() => {
|
||||
logger.info('Database connection stopped.');
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((err) => {
|
||||
logger.info(`Failed to destroy database connections: ${err.message}`, {
|
||||
err,
|
||||
});
|
||||
process.exit(1);
|
||||
});
|
||||
})
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import program from 'commander';
|
||||
|
||||
const pkg = require('../../package.json');
|
||||
|
||||
import start from './commands/start';
|
||||
import start from '../start';
|
||||
import init from './commands/init';
|
||||
import dbInstall from './commands/database/install';
|
||||
import dbMigrate from './commands/database/migrate';
|
||||
|
||||
@@ -1,16 +1,43 @@
|
||||
import app from './app';
|
||||
import logger from './logger';
|
||||
import env from './env';
|
||||
import { validateDBConnection } from './database';
|
||||
import { createTerminus, TerminusOptions } from '@godaddy/terminus';
|
||||
import http from 'http';
|
||||
import emitter from './emitter';
|
||||
import database from './database';
|
||||
import app from './app';
|
||||
|
||||
export default async function start() {
|
||||
await validateDBConnection();
|
||||
const server = http.createServer(app);
|
||||
|
||||
const port = env.NODE_ENV === 'development' ? 8055 : env.PORT;
|
||||
const terminusOptions: TerminusOptions = {
|
||||
timeout: 1000,
|
||||
signals: ['SIGINT', 'SIGTERM', 'SIGHUP'],
|
||||
beforeShutdown,
|
||||
onSignal,
|
||||
onShutdown,
|
||||
};
|
||||
|
||||
app.listen(port, () => {
|
||||
logger.info(`Server started at port ${port}`);
|
||||
});
|
||||
createTerminus(server, terminusOptions);
|
||||
|
||||
export default server;
|
||||
|
||||
async function beforeShutdown() {
|
||||
await emitter.emitAsync('server.stop.before', { server });
|
||||
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
logger.info('Restarting...');
|
||||
} else {
|
||||
logger.info('Shutting down...');
|
||||
}
|
||||
}
|
||||
|
||||
start();
|
||||
async function onSignal() {
|
||||
await database.destroy();
|
||||
logger.info('Database connections destroyed');
|
||||
}
|
||||
|
||||
async function onShutdown() {
|
||||
emitter.emitAsync('server.stop').catch((err) => logger.warn(err));
|
||||
|
||||
if (process.env.NODE_ENV !== 'development') {
|
||||
logger.info('Directus shut down OK. Bye bye!');
|
||||
}
|
||||
}
|
||||
|
||||
33
api/src/start.ts
Normal file
33
api/src/start.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import emitter from './emitter';
|
||||
import env from './env';
|
||||
import logger from './logger';
|
||||
|
||||
// If this file is called directly using node, start the server
|
||||
if (require.main === module) {
|
||||
start();
|
||||
}
|
||||
|
||||
export default async function start() {
|
||||
const server = require('./server').default;
|
||||
const { validateDBConnection } = require('./database');
|
||||
|
||||
await validateDBConnection();
|
||||
|
||||
await emitter.emitAsync('server.start.before', { server });
|
||||
|
||||
const port = env.PORT;
|
||||
|
||||
server
|
||||
.listen(port, () => {
|
||||
logger.info(`Server started at port ${port}`);
|
||||
emitter.emitAsync('server.start').catch((err) => logger.warn(err));
|
||||
})
|
||||
.once('error', (err: any) => {
|
||||
if (err?.code === 'EADDRINUSE') {
|
||||
logger.fatal(`Port ${port} is already in use`);
|
||||
process.exit(1);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -24,7 +24,6 @@ Next, you will want to define your event. You can trigger your custom hook with
|
||||
<scope>.<action>(.<before>)
|
||||
// eg: items.create
|
||||
// eg: files.create
|
||||
// eg: server.start
|
||||
// eg: collections.*
|
||||
// eg: users.update.before
|
||||
```
|
||||
@@ -84,9 +83,10 @@ module.exports = function registerHook({ exceptions }) {
|
||||
| `settings` | `create`, `update` and `delete` | Optional |
|
||||
| `users` | `create`, `update` and `delete` | Optional |
|
||||
| `webhooks` | `create`, `update` and `delete` | Optional |
|
||||
| `server` | `start` and `error`† | No |
|
||||
| `response` | | No† |
|
||||
| `auth` | `success`†, `fail`† and `refresh`† | No |
|
||||
| `init` | | Optional |
|
||||
| `server` | `start` and `stop` | Optional |
|
||||
|
||||
† TBD
|
||||
|
||||
|
||||
176
package-lock.json
generated
176
package-lock.json
generated
@@ -8200,6 +8200,13 @@
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"commander": {
|
||||
"version": "2.20.3",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
|
||||
@@ -8237,6 +8244,83 @@
|
||||
"worker-rpc": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"fork-ts-checker-webpack-plugin-v5": {
|
||||
"version": "npm:fork-ts-checker-webpack-plugin@5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.2.0.tgz",
|
||||
"integrity": "sha512-NEKcI0+osT5bBFZ1SFGzJMQETjQWZrSvMO1g0nAR/w0t328Z41eN8BJEIZyFCl2HsuiJpa9AN474Nh2qLVwGLQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.8.3",
|
||||
"@types/json-schema": "^7.0.5",
|
||||
"chalk": "^4.1.0",
|
||||
"cosmiconfig": "^6.0.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"fs-extra": "^9.0.0",
|
||||
"memfs": "^3.1.2",
|
||||
"minimatch": "^3.0.4",
|
||||
"schema-utils": "2.7.0",
|
||||
"semver": "^7.3.2",
|
||||
"tapable": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"semver": {
|
||||
"version": "7.3.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz",
|
||||
"integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"globby": {
|
||||
"version": "9.2.0",
|
||||
"resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz",
|
||||
@@ -8282,6 +8366,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
|
||||
"integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.4",
|
||||
"ajv": "^6.12.2",
|
||||
"ajv-keywords": "^3.4.1"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
@@ -15912,6 +16008,7 @@
|
||||
"resolve-cwd": "^3.0.0",
|
||||
"sharp": "^0.25.4",
|
||||
"sqlite3": "^5.0.0",
|
||||
"terminus": "^1.1.0",
|
||||
"uuid": "^8.3.0",
|
||||
"uuid-validate": "0.0.3"
|
||||
},
|
||||
@@ -18454,51 +18551,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"fork-ts-checker-webpack-plugin-v5": {
|
||||
"version": "npm:fork-ts-checker-webpack-plugin@5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-5.2.0.tgz",
|
||||
"integrity": "sha512-NEKcI0+osT5bBFZ1SFGzJMQETjQWZrSvMO1g0nAR/w0t328Z41eN8BJEIZyFCl2HsuiJpa9AN474Nh2qLVwGLQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.8.3",
|
||||
"@types/json-schema": "^7.0.5",
|
||||
"chalk": "^4.1.0",
|
||||
"cosmiconfig": "^6.0.0",
|
||||
"deepmerge": "^4.2.2",
|
||||
"fs-extra": "^9.0.0",
|
||||
"memfs": "^3.1.2",
|
||||
"minimatch": "^3.0.4",
|
||||
"schema-utils": "2.7.0",
|
||||
"semver": "^7.3.2",
|
||||
"tapable": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
|
||||
"integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"@types/json-schema": "^7.0.4",
|
||||
"ajv": "^6.12.2",
|
||||
"ajv-keywords": "^3.4.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"form-data": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||
@@ -37046,6 +37098,40 @@
|
||||
"supports-hyperlinks": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"terminus": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/terminus/-/terminus-1.1.0.tgz",
|
||||
"integrity": "sha1-ZH44xEYE+vYQtiOXT+8nRQIBrIQ=",
|
||||
"requires": {
|
||||
"readable-stream": "~2.0.4",
|
||||
"xtend": "~4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
|
||||
"integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M="
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
|
||||
"integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
|
||||
"requires": {
|
||||
"core-util-is": "~1.0.0",
|
||||
"inherits": "~2.0.1",
|
||||
"isarray": "~1.0.0",
|
||||
"process-nextick-args": "~1.0.6",
|
||||
"string_decoder": "~0.10.x",
|
||||
"util-deprecate": "~1.0.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"terser": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz",
|
||||
|
||||
Reference in New Issue
Block a user