Files
freeCodeCamp/api-server/src/server/index.js

101 lines
2.4 KiB
JavaScript
Raw Normal View History

const path = require('path');
require('dotenv').config({ path: path.resolve(__dirname, '../../../.env') });
const _ = require('lodash');
const loopback = require('loopback');
const boot = require('loopback-boot');
const createDebugger = require('debug');
const morgan = require('morgan');
2020-03-23 18:31:25 +01:00
const Sentry = require('@sentry/node');
const { sentry } = require('../../../config/secrets');
const { setupPassport } = require('./component-passport');
const log = createDebugger('fcc:server');
const reqLogFormat = ':date[iso] :status :method :response-time ms - :url';
2020-03-23 18:31:25 +01:00
// force logger to always output
// this may be brittle
log.enabled = true;
2013-11-26 23:15:13 -05:00
2020-03-23 18:31:25 +01:00
if (sentry.dns === 'dsn_from_sentry_dashboard') {
log('Sentry reporting disabled unless DSN is provided.');
} else {
Sentry.init({
dsn: sentry.dns
});
log('Sentry initialized');
}
const app = loopback();
2015-07-13 18:47:19 -07:00
app.set('state namespace', '__fcc__');
feat: add Docker build (#41187) * feat(docker): build and use client and api images * feat: always use .env dotenv fails without throwing if the .env file is missing and never overwrites variables if they already exist. As such, we can use it in build pipelines. * fix: remove quotes from env vars dotenv normalises quoted and unquoted strings (X=x, X='x' and X="x") all become the same .env object {X: 'x'}. However, Docker's env_file does not (the three cases are distinct). As a result, we should use unquoted strings for consistency. * fix: provide custom warning when .env is missing * feat(docker): include client-config * fix(docker): remove build packages from api image * fix(docker): run script from correct dir * fix(docker): correct permissions and dests * fix(docker): consolidate run steps This is standard practice, but did not have a noticable affect on the image size * fix(docker): clean the npm cache Prior to this step the image was 1.11GB uncompressed and we got a modest saving, 1.09GB after. * refactor(docker): regexless COPY directives * feat(docker): use alpine This shrinks the image down to 259MB * fix(docker): update build scripts * fix: correct the server Dockerfile RUNs * DEBUG: expose mysql port for seeding * chore: update client Dockerfile's node versions * fix: remove executable permissions from index.js It's not a cli, so I don't think it needs to be executable. * chore: update node and remove stale comments * feat: use ENTRYPOINT + CMD to allow runtime config * fix: add CURRICULUM_LOCALE arg * feat: allow client port configuration * feat: allow api port to be configured * refactor: use unique variable names for ports * fix: add default CLIENT_PORT * refactor: clean up
2021-04-20 15:59:31 +02:00
app.set('port', process.env.API_PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
2015-08-16 09:54:34 -07:00
app.use(loopback.token());
app.use(
morgan(reqLogFormat, { stream: { write: msg => log(_.split(msg, '\n')[0]) } })
);
app.disable('x-powered-by');
const createLogOnce = () => {
let called = false;
return str => {
if (called) {
return null;
}
called = true;
return log(str);
};
};
const logOnce = createLogOnce();
boot(app, __dirname, err => {
if (err) {
// rethrowing the error here because any error thrown in the boot stage
// is silent
logOnce('The below error was thrown in the boot stage');
throw err;
}
2015-06-04 10:52:12 -07:00
});
setupPassport(app);
2015-06-04 10:52:12 -07:00
const { db } = app.datasources;
db.on(
'connected',
_.once(() => log('db connected'))
);
app.start = _.once(function () {
const server = app.listen(app.get('port'), function () {
2015-07-01 14:35:15 -07:00
app.emit('started');
log(
'freeCodeCamp server listening on port %d in %s',
app.get('port'),
app.get('env')
);
log(`connecting to db at ${db.settings.url}`);
});
process.on('SIGINT', () => {
log('Shutting down server');
server.close(() => {
log('Server is closed');
});
log('closing db connection');
db.disconnect().then(() => {
log('DB connection closed');
// exit process
// this may close kept alive sockets
// eslint-disable-next-line no-process-exit
process.exit(0);
});
});
});
module.exports = app;
if (require.main === module) {
app.start();
}