Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Config as param #484

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 70 additions & 139 deletions lib/config.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,38 @@
import convict from 'convict';
import yaml from 'js-yaml';
import pino from 'pino';
import path, { join } from 'path';
import fs from 'fs';
import os from 'os';
import Sink from '@eik/sink';

/**
* Configuration object
* @typedef {import('@eik/sink')} Sink
* @typedef Config
* @type {object}
* @property {string} name - Name of the application
* @property {('development' | 'production')} env - Applicaton environments
* @property {boolean} metrics - Enable metrics
* @property {object} log - Log configuration
* @property {('trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal')} log.level - Log level to log at
* @property {object} http - Http configuration
* @property {boolean} http.http2 - Enable http2 for the server
* @property {string} http.address - The address the http server should bind to
* @property {number} http.port - The port the http server should bind to
* @property {object} compression - Compression configuration
* @property {boolean} compression.global - Enable global compression for all http routes
* @property {object} jwt - JWT configuration
* @property {string} jwt.secret - Secret used for JWT signing
* @property {object} basicAuth - Basic auth configuration
* @property {('key' | 'disabled')} basicAuth.type - Type of basic auth to use
* @property {string} basicAuth.key - Key used for basic authorization
* @property {object} organization - Organization configuration
* @property {string} organization.name - Organization name - Used as a folder name in the storage of files
* @property {Array.<string>} organization.hostnames - Hostnames the organization maps to
* @property {object | Sink} sink - Sink configuration
* @property {('fs' | 'mem' | 'test')} sink.type - Type of sink to use
* @property {string} sink.path - Absolute path to store files in when using the "fs" sink
* @property {string} notFoundCacheControl - Cache control header value for 404 responses
* @property {string} aliasCacheControl - Cache control header value for alias responses
*/

const CWD = process.cwd();

Expand All @@ -14,156 +43,58 @@ try {
/* empty */
}

convict.addParser({ extension: ['yml', 'yaml'], parse: yaml.load });
/**
* @param {Config} config
* @returns {Config}
*/
const withDefaults = (config) => ({
name: pack.name,
env: 'development',
metrics: true,
notFoundCacheControl: 'public, max-age=5',
aliasCacheControl: '',

convict.addFormat({
name: 'secret-string',
validate: (value) => {
if (typeof value !== 'string') {
throw new Error('Value must be a String');
}
},
coerce: (value) => {
if (path.isAbsolute(value)) {
try {
const file = fs.readFileSync(value);
return file.toString();
} catch (error) {
throw new Error(`Config could not load secret from path: ${value}`);
}
}
return value;
}
});
...config,

const conf = convict({
name: {
doc: 'Name of the apllication',
default: pack.name,
format: String,
},
env: {
doc: 'Applicaton environments',
format: ['development', 'production'],
default: 'development',
env: 'NODE_ENV',
arg: 'node-env',
},
metrics: {
format: Boolean,
default: true,
env: 'METRICS',
},
log: {
level: {
doc: 'Log level to log at',
format: ['trace', 'debug', 'info', 'warn', 'error', 'fatal'],
default: 'info',
env: 'LOG_LEVEL',
arg: 'log-level',
},
level: 'info',
...config.log,
},
http: {
http2: {
doc: 'Enable http2 for the server',
format: Boolean,
default: false,
env: 'HTTP_HTTP2',
},
address: {
doc: 'The address the http server should bind to',
format: String,
default: 'localhost',
env: 'HTTP_ADDRESS',
},
port: {
doc: 'The port the http server should bind to',
format: 'port',
default: 4001,
env: 'HTTP_PORT',
},
http2: false,
address: 'localhost',
port: 4001,
...config.http,
},
compression: {
global: {
doc: 'Enable global compression for all http routes',
format: Boolean,
default: true,
env: 'COMPRESSION_GLOBAL',
},
global: true,
...config.compression,
},
jwt: {
secret: {
doc: 'Secret used for JWT signing',
format: 'secret-string',
default: 'change_me',
env: 'AUTH_JWT_SECRET',
sensitive: true,
},
expire: {
doc: 'Expire time for JWT',
format: String,
default: '60d',
env: 'AUTH_JWT_EXPIRE',
},
secret: 'change_me',
expire: '60d',
...config.jwt,
},
basicAuth: {
type: {
doc: 'Type of basic auth to use',
format: ['key', 'disabled'],
default: 'key',
env: 'BASIC_AUTH_TYPE',
},
key: {
doc: 'Key used for basic authorization',
format: 'secret-string',
default: 'change_me',
env: 'BASIC_AUTH_KEY',
sensitive: true,
},
type: 'key',
key: 'change_me',
...config.basicAuth,
},
organization: {
name: {
doc: 'Organization name - Used as a folder name in the storage of files',
format: String,
default: 'local',
env: 'ORG_NAME',
},
hostnames: {
doc: 'Hostnames the organization maps to',
format: Array,
default: ['localhost', '127.0.0.1'],
env: 'ORG_HOSTNAMES',
},
name: 'local',
hostnames: ['localhost', '127.0.0.1'],
...config.organization,
},
sink: {
type: {
doc: 'Type of sink to use',
format: ['fs', 'mem', 'test'],
default: 'fs',
env: 'SINK_TYPE',
},
path: {
doc: 'Absolute path to store files in when using the "fs" sink',
format: String,
default: path.join(os.tmpdir(), '/eik'),
env: 'SINK_PATH',
},
}
sink:
config.sink instanceof Sink
? config.sink
: {
type: 'fs',
path: path.join(os.tmpdir(), '/eik'),
...config.sink,
},
});

const env = conf.get('env');

const logger = pino({
level: conf.get('log.level'),
name: conf.get('name'),
});

try {
conf.loadFile(path.join(CWD, `/config/${env}.yaml`));
} catch (error) {
logger.error(error);
}

conf.validate();
const DefaultConfig = withDefaults({});

export default conf;
export { DefaultConfig, withDefaults };
Loading