Skip to main content

Registry configuration

Introduction​

The registry is a REST api that serves the components. You can have multiple registries connected to a library, but you can't have multiple libraries connected to a registry.

Setup​

First, create a dir and install oc:

mkdir oc-registry && cd oc-registry
npm init
npm install oc --save
touch index.js

For Google Storage registry configuration's documentation, look at this page.

This is the index.js content:

var oc = require("oc");

var configuration = {
verbosity: 0,
baseUrl: "https://my-components-registry.mydomain.com/",
port: 3000,
tempDir: "./temp/",
refreshInterval: 600,
pollingInterval: 5,
s3: {
key: "your-s3-key",
secret: "your-s3-secret",
bucket: "your-s3-bucket",
region: "your-s3-region",
path: "//s3.amazonaws.com/your-s3-bucket/",
componentsDir: "components",
},
env: { name: "production" },
};

var registry = new oc.Registry(configuration);

registry.start(function (err, app) {
if (err) {
console.log("Registry not started: ", err);
process.exit(1);
}
});

API​

var registry = new oc.Registry(configuration);​

Creates an instance of the registry. Configuration is an object that contains the registry configuration parameters.

registry.start(callback)​

Starts the registry.

registry.off(eventName, callback);​

For unsubscribing to an event.

registry.on(eventName, callback);​

For subscribing to an event.

registry.register(plugin [, callback]);​

Register a plugin. The plugin parameter has to be a valid plugin.

registry.register({
name: "doSomething",
register: require("my-oc-plugin"),
options: {
configuration: "value",
},
});

registry.reset(eventName);​

For unsuscribing to all events.

Registry configuration​

ParameterTypeMandatoryDescription
baseUrlstringyessets the URL which will be used to compose the components' URLs. This needs to be the registry's public url
customHeadersToSkipOnWeakVersionarraynothe custom headers to skip when serving a component requested by a weak version (eg. 1.x.x rather than 1.2.3). This is useful, for instance, in case of components that have quite static logic, setting cache headers - so that it makes sense in order to implement reactive consumers' caches
dependenciesarraynothe npm modules available for components logic
discoverybooleannoEnable registry UI. Default: true
envobjectnosets the registry environment
env.namestringnosets the environment name
executionTimeoutnumber (seconds)notimeout for component's server execution time
fallbackRegistryUrlstring (url)noUrl to another registry which will be used by current registry when component cannot be found in current registry
keepAliveTimeoutnumber (milliseconds)noKeep Alive Timeout for HTTP server. Default: 5000
pollingIntervalnumber (seconds)noWhen the components' list cache will be refreshed. This is required for distributing the components on each registry instance. Given the polling mechanism is quite efficient, this number should be very low. Suggested is around 5-10 seconds.
portnumbernodefault 3000, sets the port where to start the registry
postRequestPayloadSizestringnoSets the limit for the post body size. Example: 50mb. When unset, the limit is 100KB
prefixstringnosets the href prefix, for example: /v2/
publishAuthobjectnosets the authentication parameters for publishing a component to the registry. When undefined, no authorisation is required.
publishAuth.typestringnoThe authorisation type. Only basic is supported at the moment.
publishAuth.usernamestringnosets the user name
publishAuth.passwordstringnosets the user password
publishValidationfunctionnoUsed to validate package.json when components is published. Look at the example
refreshIntervalnumber (seconds)noWhen the components' data cache will be refreshed. Given the data is immutable, this should be high and just for robustness.
routesarray of objectsnosets additional actions via URL mapping to specific action handlers
routes[index].routestringnosets URL pattern. Routes should be outside of the components' namespace (which you can set by using the prefix parameter.)
routes[index].methodstringnosets verb
routes[index].handlerfunctionnosets function handler for routed action Look at the example
s3objectyessets the Amazon S3 credentials
s3.agentProxyinstance of http agentnoallows to interact with aws API via a custom agent and a proxy. Usage: agentProxy = require('proxy-agent')('https://yourproxy.com');
s3.bucketstringyessets S3 bucket
s3.componentsDirstringyesthe path where the data will be saved inside the bucket
s3.keystringnosets S3 access key. User should either specify both key/secret or skip both when leveraging IAM Role based S3 access from EC2
s3.pathstringyessets the path that will be used for composing static resources' urls. Can be the s3 url, or, when using cloudfront, it can be //cloudfront-id.cloudfront.net/. Signature should not include the protocol
s3.regionstringyessets S3 region
s3.secretstringnosets S3 secret. User should either specify both key/secret or skip both when leveraging IAM Role based S3 access from EC2
s3.timeoutnumber (milliseconds)nodefault 10000, optionally sets the timeout for s3 requests.
tempDirstringnodefault ./temp/, sets the directory where the components' packages are temporarily stored during the publishing phase inside the registry box
templatesarraynothe templates available allowed on the registry. Will extend the default base templates of [require('oc-template-jade'), require('oc-template-handlebars')]
timeoutnumber (milliseconds)noSocket timeout for HTTP server. Default: 0
verbositynumbernodefault 0, sets the console.log verbosity during the execution

Publish validation example​

options.publishValidation = function (package) {
var isValid =
!!package.author && !!package.repository && !!package.description;

if (isValid) {
// Can return boolean
return true;
} else {
// Can return object with error so that it will be propagated to the user
return {
isValid: false,
error:
"Package.json is missing mandatory params: author, repository, description",
};
}
};

Routes example​

options.routes = [
{
route: "/example-route",
method: "get",
handler: function (req, res) {
// Handling function content
},
},
];

Registry events​

Event nameCallback Data TypeDescription
cache-pollobjectFired when the components list is refreshed. The callback data contains the last edit unix utc timestamp.
component-retrievedobjectFired when the component is retrieved. This includes the component's validation, data gathering and execution, view retrieving, and (when requested) rendering. The callback data contains the duration, component details, and, in case, the error details.
errorobjectFired when an internal operation errors.
requestobjectFired every time the registry receives a request. The callback data contains some request and response details.
startundefinedFired when the registry starts

Plugins​

Plugins are a way to extend registry's context allowing components to inherit custom functionalities.

This is a plugin example:

// ./registry/oc-plugins/hobknob.js
var connection,
client = require("./hobknob-client");

module.exports.register = function (options, dependencies, next) {
client.connect(options.connectionString, function (err, conn) {
connection = conn;
next();
});
};

module.exports.execute = function (featureName) {
return connection.get(featureName);
};

This is how to register it in a registry:

// ./registry/init.js
...
var registry = new oc.Registry(configuration);

registry.register({
name: 'getFeatureSwitch',
register: require('./oc-plugins/hobknob'),
options: {
connectionString: connectionString
}
});
...

This is how to use a plugin from a component:

// ./my-component/server.js
module.exports.data = function (context, callback) {
callback(null, {
variable: context.plugins.getFeatureSwitch("AbTestHomePage"),
});
};

This is how to depend on (and use) other plugins:

// ./registry/oc-plugins/hobknob.js
var connection,
client = require("./hobknob-client");

module.exports.dependencies = ["log", "otherplugin"];

module.exports.register = function (options, dependencies, next) {
// this register function is only called after all dependencies are registered
client.connect(options.connectionString, function (err, conn) {
connection = conn;
dependencies.log("hobknob client initialised");
next();
});
};

module.exports.execute = function (featureName) {
return connection.get(featureName);
};