@vrbo/catalyst-server
Advanced tools
Comparing version 2.1.0 to 2.2.0
@@ -7,2 +7,6 @@ # Changelog | ||
## 2.2.0 - 2020-06-26 | ||
### Changed | ||
- Add support for merging multiple manifest files. | ||
## 2.1.0 - 2020-01-09 | ||
@@ -9,0 +13,0 @@ ### Changed |
{ | ||
"server": { | ||
"port": "exec:./utils#resolvePort", | ||
"host": "exec:./utils#resolveHost", | ||
// resolve port based on env var NODE_PORT, falls back to default 8080 | ||
"port": "execBase:./utils#resolvePort", | ||
// resolve host based on env var HOSTNAME, falls back to default '0.0.0.0' | ||
"host": "execBase:./utils#resolveHost", | ||
"state": { | ||
@@ -6,0 +8,0 @@ "strictHeader": false |
@@ -20,3 +20,2 @@ /* | ||
const Handlers = require('shortstop-handlers') | ||
const Determination = require('@vrbo/determination') | ||
const Steerage = require('@vrbo/steerage') | ||
@@ -29,3 +28,3 @@ const evalHandler = require('./shortstop/eval') | ||
* @param {object} options - init options | ||
* @param {object} options.userConfigPath - path of the manifest file | ||
* @param {object} options.userConfigPath - path or array of paths to a manifest file | ||
* @param {object} options.baseDir - directory of the manifest file | ||
@@ -39,3 +38,3 @@ * @param {object} options.onConfig - hook for config loaded | ||
userConfigPath, | ||
baseDir = userConfigPath ? Path.dirname(userConfigPath) : null, | ||
baseDir, | ||
onConfig, | ||
@@ -46,32 +45,22 @@ environment, | ||
// options may contain a link to a user manifest. if it does, merge it with default configs | ||
if (userConfigPath) { | ||
const protocols = Hoek.applyToDefaults({ | ||
file: Handlers.file(baseDir), | ||
path: Handlers.path(baseDir), | ||
base64: Handlers.base64(), | ||
env: Handlers.env(), | ||
require: Handlers.require(baseDir), | ||
exec: Handlers.exec(baseDir), | ||
glob: Handlers.glob(baseDir), | ||
eval: evalHandler | ||
}, shortstopHandlers) | ||
const baseConfig = Path.join(__dirname, 'config.json') | ||
const baseConfigBaseDir = Path.dirname(baseConfig) | ||
// resolver for user config | ||
const resolver = Determination.create({ | ||
config: userConfigPath, | ||
protocols, | ||
criteria: environment | ||
}) | ||
shortstopHandlers = Hoek.applyToDefaults({ | ||
eval: evalHandler, | ||
// Custom shortstop handler execBase: allows successful resolution | ||
// of catalyst-server base config.json plugin relative paths | ||
// by explicitly passing catalyst-server config | ||
// baseDir so that any user provided baseDir override does not cause | ||
// require resolution issues during initialization. | ||
execBase: Handlers.exec(baseConfigBaseDir) | ||
}, shortstopHandlers) | ||
if (userConfigPath.length) { | ||
// call the use supplied config hook within our own below | ||
const userOnConfigHook = onConfig | ||
// use the configuration hook in Steerage to merge the user config with default config | ||
onConfig = async function (config) { | ||
const appConfig = await resolver.resolve() | ||
const validated = await manifestSchema.validateAsync(appConfig.data) | ||
await manifestSchema.validateAsync(config.data) | ||
config.merge(validated) | ||
if (userOnConfigHook) { | ||
@@ -86,5 +75,10 @@ config = await userOnConfigHook(config) | ||
const server = await Steerage.init({ | ||
config: Path.join(__dirname, 'config.json'), | ||
basedir: baseDir, | ||
config: [ | ||
baseConfig, | ||
...userConfigPath | ||
], | ||
environment, | ||
onconfig: onConfig, | ||
environment | ||
protocols: shortstopHandlers | ||
}) | ||
@@ -91,0 +85,0 @@ |
@@ -20,4 +20,4 @@ /* | ||
const manifestSchema = Joi.object().keys({ | ||
server: Joi.object(), | ||
register: Joi.object() | ||
register: Joi.object(), | ||
server: Joi.object() | ||
}) | ||
@@ -31,9 +31,9 @@ | ||
const optionsSchema = Joi.object({ | ||
userConfigPath: Joi.string(), | ||
baseDir: Joi.string(), | ||
environment: Joi.object().default(defaults.environment), | ||
onConfig: Joi.func(), | ||
environment: Joi.object().default(defaults.environment), | ||
shortstopHandlers: Joi.object().default(defaults.shortstopHandlers) | ||
shortstopHandlers: Joi.object().default(defaults.shortstopHandlers), | ||
userConfigPath: Joi.array().items(Joi.string()).single().default([]) | ||
}).default(defaults) | ||
module.exports = { manifestSchema, optionsSchema } |
{ | ||
"name": "@vrbo/catalyst-server", | ||
"version": "2.1.0", | ||
"version": "2.2.0", | ||
"description": "Configuration and composition management for Hapi.js applications.", | ||
@@ -62,5 +62,5 @@ "main": "lib/index.js", | ||
"nyc": "^15.0.0", | ||
"sinon": "^8.0.0", | ||
"sinon": "^9.0.0", | ||
"standard": "^14.0.0", | ||
"mocha": "^6.1.4" | ||
"mocha": "^7.0.0" | ||
}, | ||
@@ -71,4 +71,3 @@ "dependencies": { | ||
"@hapi/joi": "^16.1.7", | ||
"@vrbo/determination": "^3.0.0", | ||
"@vrbo/steerage": "^8.0.0", | ||
"@vrbo/steerage": "^8.4.0", | ||
"hapi-pino": "^6.0.1", | ||
@@ -75,0 +74,0 @@ "shortstop-handlers": "^1.0.1" |
# @vrbo/catalyst-server | ||
[![NPM Version](https://img.shields.io/npm/v/@vrbo/catalyst-server.svg?style=flat-square)](https://www.npmjs.com/package/@vrbo/catalyst-server) | ||
[![Build Status](https://travis-ci.org/expediagroup/catalyst-server.svg?branch=master)](https://travis-ci.org/expediagroup/catalyst-server) | ||
![](https://github.com/ExpediaGroup/catalyst-server/workflows/Node_CI/badge.svg) | ||
[![Dependency Status](https://david-dm.org/expediagroup/catalyst-server.svg?theme=shields.io)](https://david-dm.org/expediagroup/catalyst-server) | ||
@@ -16,3 +16,3 @@ [![NPM Downloads](https://img.shields.io/npm/dm/@vrbo/catalyst-server.svg?style=flat-square)](https://npm-stat.com/charts.html?package=@vrbo/catalyst-server) | ||
## Introduction | ||
Catalyst-server is a configuration and composition management tool for Hapi.js applications. It allows for composition and configuration that is environment aware and extensible for a web application. This is managed from a single `manifest.json` file. The server also will include sensible defaults and implementations (like [hapi-pino](https://github.com/pinojs/hapi-pino) for logging and [crumb](https://github.com/hapijs/crumb) for CSRF). | ||
Catalyst-server is a configuration and composition management tool for Hapi.js applications. It allows for composition and configuration that is environment aware and extensible for a web application. This is managed from one or more `manifest.json` files. The `userConfigPath` accepts a string that is a path to a single `manifest.json` file, or an array of path strings to support merging multiple manifest files. Duplicate keys in configuration files will be overwritten upon merging. If an array is passed, values of the config file that is the last index of `userConfigPath` takes precedence when merging, otherwise values from the single config file passed to `userConfigPath` takes precedence. The server also will include sensible defaults and implementations (like [hapi-pino](https://github.com/pinojs/hapi-pino) for logging and [crumb](https://github.com/hapijs/crumb) for CSRF). | ||
@@ -31,2 +31,3 @@ ## Usage | ||
// Init a new Catalyst server, and pass the path to your manifest file to the userConfigPath option to compose your app plugins | ||
async function start(options = {}) { | ||
@@ -48,2 +49,12 @@ const server = await Catalyst.init({ | ||
```javascript | ||
// Alternatively, pass an array of paths to compose your app plugins from separate manifest files. | ||
const server = await Catalyst.init({ | ||
userConfigPath: [ | ||
path.resolve(__dirname, 'manifest.json'), | ||
path.resolve(__dirname, '/external/manifest.json') | ||
] | ||
}); | ||
``` | ||
#### manifest.json | ||
@@ -50,0 +61,0 @@ ```js |
{ | ||
"extends": [ | ||
"config:base", | ||
"github>ExpediaGroup/renovate-config-catalyst:semanticCommits" | ||
"github>ExpediaGroup/renovate-config-catalyst:semanticCommits", | ||
"github>ExpediaGroup/renovate-config-catalyst:temporarilyDisable" | ||
] | ||
} |
@@ -24,27 +24,70 @@ 'use strict' | ||
it('should load a plugin from a manifest', async () => { | ||
it('should override the default port', async () => { | ||
const server = await Catalyst.init({ | ||
userConfigPath: Path.join(__dirname, '..', 'fixtures/manifest.json') | ||
userConfigPath: Path.join(__dirname, '..', 'fixtures/manifest-port3000.json') | ||
}) | ||
const response = await server.inject('/test') | ||
expect(response.result).to.equal('test response') | ||
expect(server.info.port).to.equal(3000) | ||
}) | ||
it('should override the default port', async () => { | ||
const server = await Catalyst.init({ | ||
userConfigPath: Path.join(__dirname, '..', 'fixtures/manifest-port3000.json') | ||
describe('single manifest file passed to userConfigPath', () => { | ||
it('should load a plugin from a manifest', async () => { | ||
const server = await Catalyst.init({ | ||
userConfigPath: Path.join(__dirname, '..', 'fixtures/manifest.json') | ||
}) | ||
const response = await server.inject('/test') | ||
expect(response.result).to.equal('test response') | ||
await server.stop() | ||
}) | ||
expect(server.info.port).to.equal(3000) | ||
it('should allow baseDir to be altered', async () => { | ||
const server = await Catalyst.init({ | ||
userConfigPath: Path.join(__dirname, '..', 'fixtures/manifest-basedir.json'), | ||
baseDir: Path.join(__dirname, '..', 'fixtures', 'basedir') | ||
}) | ||
const response = await server.inject('/testbasedir') | ||
expect(response.result).to.equal('test response') | ||
await server.stop() | ||
}) | ||
}) | ||
it('should allow baseDir to be altered', async () => { | ||
const server = await Catalyst.init({ | ||
userConfigPath: Path.join(__dirname, '..', 'fixtures/manifest-basedir.json'), | ||
baseDir: Path.join(__dirname, '..', 'fixtures', 'basedir') | ||
describe('multiple manifest files passed as array to userConfigPath', () => { | ||
it('should load plugins from multiple manifest files', async () => { | ||
const server = await Catalyst.init({ | ||
userConfigPath: [ | ||
Path.join(__dirname, '..', 'fixtures/manifest.json'), | ||
Path.join(__dirname, '..', 'fixtures/external/manifest-external.json') | ||
] | ||
}) | ||
const response = await server.inject('/test') | ||
expect(response.result).to.equal('test response') | ||
const responseExternal = await server.inject('/test-external') | ||
expect(responseExternal.result).to.equal('test response external') | ||
await server.stop() | ||
}) | ||
const response = await server.inject('/testbasedir') | ||
expect(response.result).to.equal('test response') | ||
it('should allow baseDir to be altered', async () => { | ||
const server = await Catalyst.init({ | ||
userConfigPath: [ | ||
Path.join(__dirname, '..', 'fixtures/manifest-basedir.json'), | ||
Path.join(__dirname, '..', 'fixtures/external/manifest-external-basedir.json') | ||
], | ||
baseDir: Path.join(__dirname, '..', 'fixtures', 'basedir') | ||
}) | ||
const response = await server.inject('/testbasedir') | ||
expect(response.result).to.equal('test response') | ||
const responseExternal = await server.inject('/test-external-basedir') | ||
expect(responseExternal.result).to.equal('test response external basedir') | ||
await server.stop() | ||
}) | ||
}) | ||
@@ -175,8 +218,23 @@ | ||
it('should reject if manifest does not conform to schema', () => { | ||
const promise = Catalyst.init({ | ||
userConfigPath: Path.join(__dirname, '..', 'fixtures/manifest-schema.json') | ||
describe('single manifest file passed to userConfigPath', () => { | ||
it('should reject if manifest does not conform to schema', () => { | ||
const promise = Catalyst.init({ | ||
userConfigPath: Path.join(__dirname, '..', 'fixtures/manifest-schema.json') | ||
}) | ||
return expect(promise).to.be.rejectedWith(Error) | ||
}) | ||
}) | ||
return expect(promise).to.be.rejectedWith(Error) | ||
describe('multiple manifest files passed as array to userConfigPath', () => { | ||
it('should reject if one or more manifest files do not conform to schema', () => { | ||
const promise = Catalyst.init({ | ||
userConfigPath: [ | ||
Path.join(__dirname, '..', 'fixtures/manifest.json'), // valid | ||
Path.join(__dirname, '..', 'fixtures/external/manifest-schema.json') // invalid | ||
] | ||
}) | ||
return expect(promise).to.be.rejectedWith(Error) | ||
}) | ||
}) | ||
@@ -183,0 +241,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
47082
7
31
580
285
1
- Removed@vrbo/determination@^3.0.0
Updated@vrbo/steerage@^8.4.0