Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

dgeni

Package Overview
Dependencies
Maintainers
1
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dgeni - npm Package Compare versions

Comparing version 0.4.2 to 0.4.3

lib/Dgeni.d.ts

444

lib/Dgeni.js

@@ -0,8 +1,11 @@

"use strict";
/* tslint globals: require: true */
var _ = require('lodash');
var di = require('di');
var Package = require('./Package');
var sortByDependency = require('./util/dependency-sort');
var validate = require('validate.js');
var Q = require('q');
var Package_1 = require("./Package");
var processorValidation_1 = require("./legacyPackages/processorValidation");
var dependency_sort_1 = require("./util/dependency-sort");
var getInjectables_1 = require("./util/getInjectables");
var log_1 = require("./util/log");
/**

@@ -13,220 +16,227 @@ * Create an instance of the Dgeni documentation generator, loading any packages passed in as a

*/
function Dgeni(packages) {
this.packages = {};
packages = packages || [];
if ( !Array.isArray(packages) ) { throw new Error('packages must be an array'); }
_.map(packages, this.package, this);
}
/**
* @type {Package}
*/
Dgeni.Package = Package;
/**
* Load a package into dgeni
* @param {Package|string} package The package to load or the name of a new package to
* create.
* @param {Array.<Package|string>} dependencies A collection of dependencies for this package
* @return {Package} The package that was loaded, to allow chaining
*/
Dgeni.prototype.package = function(package, dependencies) {
if ( typeof package === 'string' ) { package = new Package(package, dependencies); }
if ( !(Package.isPackage(package)) ) { throw new Error('package must be an instance of Package'); }
if ( this.packages[package.name] ) {
throw new Error('The "' + package.name + '" package has already been loaded');
}
this.packages[package.name] = package;
// Extract all inline packages and load them into dgeni;
package.namedDependencies = package.dependencies.map(function(dependency) {
if ( Package.isPackage(dependency) ) {
// Only load dependent package if not already loaded
if ( !this.packages[dependency.name] ) { this.package(dependency); }
return dependency.name;
var Dgeni = (function () {
function Dgeni(packages) {
if (packages === void 0) { packages = []; }
var _this = this;
this.packages = {};
if (!Array.isArray(packages)) {
throw new Error('packages must be an array');
}
// Add in the legacy validation that was originally part of the core Dgeni tool.
this.package(processorValidation_1.processorValidationPackage);
packages.map(function (p) { return _this.package(p); });
}
return dependency;
}, this);
// Return the package to allow chaining
return package;
};
/**
* Configure the injector using the loaded packages.
*
* The injector is assigned to the `injector` property on `this`, which is used by the
* `generate()` method. Subsequent calls to this method will just return the same injector.
*
* This method is useful in unit testing services and processors as it gives an easy way to
* get hold of an instance of a ready instantiated component without having to load in all
* the potential dependencies manually:
*
* ```
* var Dgeni = require('dgeni');
*
* function getInjector() {
* var dgeni = new Dgeni();
* dgeni.package('testPackage', [require('dgeni-packages/base')])
* .factory('templateEngine', function dummyTemplateEngine() {});
* return dgeni.configureInjector();
* };
*
* describe('someService', function() {
* var someService;
* beforeEach(function() {
* var injector = getInjector();
* someService = injector.get('someService');
* });
*
* it("should do something", function() {
* someService.doSomething();
* ...
* });
* });
* ```
*/
Dgeni.prototype.configureInjector = function() {
if ( !this.injector ) {
// Sort the packages by their dependency - ensures that services and configs are loaded in the
// correct order
var packages = sortByDependency(this.packages, 'namedDependencies');
// Create a module containing basic shared services
var dgeniConfig = {
stopOnValidationError: true,
stopOnProcessingError: true
/**
* Load a package into dgeni
* @param package The package to load or the name of a new package to create.
* @param dependencies A collection of dependencies for this package
* @return The package that was loaded, to allow chaining
*/
Dgeni.prototype.package = function (pkg, dependencies) {
var _this = this;
if (dependencies === void 0) { dependencies = []; }
if (this.injector) {
throw new Error('injector already configured - you cannot add a new package');
}
if (typeof pkg === 'string') {
pkg = new Package_1.Package(pkg, dependencies);
}
if (!(Package_1.Package.isPackage(pkg))) {
throw new Error('package must be an instance of Package');
}
if (this.packages[pkg.name]) {
throw new Error('The "' + pkg.name + '" package has already been loaded');
}
this.packages[pkg.name] = pkg;
// Extract all inline packages and load them into dgeni;
pkg.namedDependencies = pkg.dependencies.map(function (dependency) {
if (Package_1.Package.isPackage(dependency)) {
// Only load dependent package if not already loaded
if (!_this.packages[dependency.name]) {
_this.package(dependency);
}
return dependency.name;
}
return dependency;
});
// Return the package to allow chaining
return pkg;
};
var dgeniModule = new di.Module()
.value('dgeni', dgeniConfig)
.factory('log', require('./util/log'))
.factory('getInjectables', require('./util/getInjectables'));
// Create the dependency injection container, from all the packages' modules
var modules = packages.map(function(package) { return package.module; });
modules.unshift(dgeniModule);
// Create the injector and
var injector = this.injector = new di.Injector(modules);
// Apply the config blocks
packages.forEach(function(package) {
package.configFns.forEach(function(configFn) {
injector.invoke(configFn);
});
});
// Get the collection of processors
// We use a Map here so that we only get one of each processor name
var processors = this.processors = {};
packages.forEach(function(package) {
package.processors.forEach(function(processorName) {
var processor = injector.get(processorName);
processor.name = processorName;
processor.$package = package.name;
// Ignore disabled processors
if ( processor.$enabled !== false ) {
processors[processorName] = processor;
/**
* Configure the injector using the loaded packages.
*
* The injector is assigned to the `injector` property on `this`, which is used by the
* `generate()` method. Subsequent calls to this method will just return the same injector.
*
* This method is useful in unit testing services and processors as it gives an easy way to
* get hold of an instance of a ready instantiated component without having to load in all
* the potential dependencies manually:
*
* ```
* const Dgeni = require('dgeni');
*
* function getInjector() {
* const dgeni = new Dgeni();
* dgeni.package('testPackage', [require('dgeni-packages/base')])
* .factory('templateEngine', function dummyTemplateEngine() {});
* return dgeni.configureInjector();
* };
*
* describe('someService', function() {
* const someService;
* beforeEach(function() {
* const injector = getInjector();
* someService = injector.get('someService');
* });
*
* it("should do something", function() {
* someService.doSomething();
* ...
* });
* });
* ```
*/
Dgeni.prototype.configureInjector = function () {
var _this = this;
if (!this.injector) {
// Sort the packages by their dependency - ensures that services and configs are loaded in the
// correct order
var packages = this.packages = dependency_sort_1.sortByDependency(this.packages, 'namedDependencies');
// Create a module containing basic shared services
this.stopOnProcessingError = true;
var dgeniModule = new di.Module()
.value('dgeni', this)
.factory('log', log_1.logFactory)
.factory('getInjectables', getInjectables_1.getInjectablesFactory);
// Create the dependency injection container, from all the packages' modules
var modules = packages.map(function (pkg) { return pkg.module; });
modules.unshift(dgeniModule);
// Create the injector and
var injector_1 = this.injector = new di.Injector(modules);
// Apply the config blocks
packages.forEach(function (pkg) { return pkg.configFns.forEach(function (configFn) { return injector_1.invoke(configFn); }); });
// Get the the processors and event handlers
var processorMap_1 = {};
this.handlerMap = {};
packages.forEach(function (pkg) {
pkg.processors.forEach(function (processorName) {
var processor = injector_1.get(processorName);
// Update the processor's name and package
processor.name = processorName;
processor.$package = pkg.name;
// Ignore disabled processors
if (processor.$enabled !== false) {
processorMap_1[processorName] = processor;
}
});
var _loop_1 = function (eventName) {
var handlers = _this.handlerMap[eventName] = (_this.handlerMap[eventName] || []);
pkg.handlers[eventName].forEach(function (handlerName) { return handlers.push(injector_1.get(handlerName)); });
};
for (var eventName in pkg.handlers) {
_loop_1(eventName);
}
});
// Once we have configured everything sort the processors.
// This allows the config blocks to modify the $runBefore and $runAfter properties of processors.
// (Crazy idea, I know, but useful for things like debugDumpProcessor)
this.processors = dependency_sort_1.sortByDependency(processorMap_1, '$runAfter', '$runBefore');
}
});
});
}
return this.injector;
};
/**
* Generate the documentation using the loaded packages
* @return {Promise} A promise to the generated documents
*/
Dgeni.prototype.generate = function() {
this.configureInjector();
var dgeniConfig = this.injector.get('dgeni');
// Once we have configured everything sort the processors.
// This allows the config blocks to modify the $runBefore and $runAfter
// properties of processors.
// (Crazy idea, I know, but useful for things like debugDumpProcessor)
processors = sortByDependency(this.processors, '$runAfter', '$runBefore');
var log = this.injector.get('log');
var processingPromise = Q();
var validationErrors = [];
// Apply the validations on each processor
_.forEach(processors, function(processor) {
processingPromise = processingPromise.then(function() {
return validate.async(processor, processor.$validate).catch(function(errors) {
validationErrors.push({
processor: processor.name,
package: processor.$package,
errors: errors
return this.injector;
};
/**
* Generate the documentation using the loaded packages
* @return {Promise} A promise to the generated documents
*/
Dgeni.prototype.generate = function () {
var _this = this;
var injector = this.configureInjector();
var log = injector.get('log');
var processingPromise = this.triggerEvent('generationStart');
// Process the docs
var currentDocs = [];
processingPromise = processingPromise.then(function () { return currentDocs; });
this.processors.forEach(function (processor) {
processingPromise = processingPromise.then(function (docs) { return _this.runProcessor(processor, docs); });
});
log.error('Invalid property in "' + processor.name + '" (in "' + processor.$package + '" package)');
log.error(errors);
});
});
});
processingPromise = processingPromise.then(function() {
if ( validationErrors.length > 0 && dgeniConfig.stopOnValidationError ) {
return Q.reject(validationErrors);
}
});
// Process the docs
var currentDocs = [];
processingPromise = processingPromise.then(function() {
return currentDocs;
});
_.forEach(processors, function(processor) {
if( processor.$process ) {
processingPromise = processingPromise.then(function(docs) {
currentDocs = docs;
log.info('running processor:', processor.name);
return Q(currentDocs).then(function() {
// We need to wrap this $process call in a new promise handler so that we can catch
// errors triggered by exceptions thrown in the $process method
// before they reach the processingPromise handlers
return processor.$process(docs) || docs;
}).catch(function(error) {
error.message = 'Error running processor "' + processor.name + '":\n' + error.message;
if ( error.stack ) {
log.error(error.stack);
}
if ( dgeniConfig.stopOnProcessingError ) { return Q.reject(error); }
return currentDocs;
processingPromise.catch(function (error) { return log.error('Error processing docs: ', error.stack || error.message || error); });
return processingPromise.then(function (docs) {
_this.triggerEvent('generationEnd');
return docs;
});
});
}
return currentDocs;
});
processingPromise.catch(function(error) {
log.error('Error processing docs: ', error );
});
return processingPromise;
};
/**
* @module Dgeni
*/
};
Dgeni.prototype.runProcessor = function (processor, docs) {
var _this = this;
var log = this.injector.get('log');
var promise = Q(docs);
if (!processor.$process) {
return promise;
}
return promise
.then(function () {
log.info('running processor:', processor.name);
return _this.triggerProcessorEvent('processorStart', processor, docs);
})
.then(function (docs) { return processor.$process(docs) || docs; })
.then(function (docs) { return _this.triggerProcessorEvent('processorEnd', processor, docs); })
.catch(function (error) {
error.message = 'Error running processor "' + processor.name + '":\n' + error.message;
log.error(error.stack || error.message);
if (_this.stopOnProcessingError) {
return Q.reject(error);
}
return docs;
});
};
/**
* Trigger a dgeni event and run all the registered handlers
* All the arguments to this call are passed through to each handler
* @param {string} eventName The event being triggered
* @return {Promise} A promise to an array of the results from each of the handlers
*/
Dgeni.prototype.triggerEvent = function (eventName) {
var extras = [];
for (var _i = 1; _i < arguments.length; _i++) {
extras[_i - 1] = arguments[_i];
}
var handlers = this.handlerMap[eventName];
var handlersPromise = Q();
var results = [];
if (handlers) {
handlers.forEach(function (handler) {
handlersPromise = handlersPromise.then(function () {
var handlerPromise = Q(handler.apply(void 0, [eventName].concat(extras)));
handlerPromise.then(function (result) { return results.push(result); });
return handlerPromise;
});
});
}
return handlersPromise.then(function () { return results; });
};
Dgeni.prototype.triggerProcessorEvent = function (eventName, processor, docs) {
return this.triggerEvent(eventName, processor, docs).then(function () { return docs; });
};
Dgeni.prototype.info = function () {
var injector = this.configureInjector();
var log = injector.get('log');
for (var pkgName in this.packages) {
log.info(pkgName, '[' + this.packages[pkgName].dependencies.map(function (dep) { return JSON.stringify(dep.name); }).join(', ') + ']');
}
log.info('== Processors (processing order) ==');
this.processors.forEach(function (processor, index) {
log.info((index + 1) + ': ' + processor.name, processor.$process ? '' : '(abstract)', ' from ', processor.$package);
if (processor.description) {
log.info(' ', processor.description);
}
});
};
;
return Dgeni;
}());
Dgeni.Package = Package_1.Package;
exports.Dgeni = Dgeni;
// This is a hack so that you can still require Dgeni
// in CommonJS as: `var Dgeni = require('dgeni');`
module.exports = Dgeni;
module.exports.Dgeni = Dgeni;
//# sourceMappingURL=Dgeni.js.map

@@ -1,4 +0,2 @@

var _ = require('lodash');
var Module = require('di').Module;
"use strict";
/**

@@ -10,151 +8,187 @@ * A Dgeni Package containing processors, services and config blocks.

*/
function Package(name, dependencies) {
if ( typeof name !== 'string' ) { throw new Error('You must provide a name for the package'); }
if ( dependencies && !Array.isArray(dependencies) ) { throw new Error('dependencies must be an array'); }
this.name = name;
this.dependencies = dependencies || [];
this.processors = [];
this.configFns = [];
// We can't use a real di.Module here as di uses instanceof to detect module instances
this.module = {};
var Package = (function () {
function Package(name, dependencies) {
if (dependencies === void 0) { dependencies = []; }
this.name = name;
this.dependencies = dependencies;
this.processors = [];
this.configFns = [];
this.handlers = {};
// We can't use a real di.Module here as di uses instanceof to detect module instances
this.module = {};
if (typeof name !== 'string') {
throw new Error('You must provide a name for the package');
}
if (dependencies && !Array.isArray(dependencies)) {
throw new Error('dependencies must be an array');
}
}
Package.isPackage = function (pkg) {
// Check the most important properties for dgeni to use a package
return isString(pkg.name) && Array.isArray(pkg.dependencies) && isObject(pkg.module);
};
/**
* Add a new processor to the package. The processor can be defined by a processor definition object
* or a factory function, which can be injected with services and will return the processor definition
* object. The following properties of a processor definition object have special meaning to Dgeni:
*
* * `name : {string}`: The name of the processor - if the processor is defined by a factory
* function or a name is explicitly provided as the first parameter, then this is ignored
* * `$process(docs : {string}) : {Array|Promise|undefined}`: The method that will be called to
* process the documents. If it is async then it should return a Promise.
* * `$runAfter : {string[]}`: Dgeni will ensure that this processor runs after those named here.
* * `$runBefore : {string[]}`: Dgeni will ensure that this processor runs before those named here.
* * `$validate: {Object}`: Dgeni will check that the properties of the processor, which match the
* keys of this object, pass the validation rules provided as the values of this object. See
* http://validatejs.org
*
* @param {function|object|string} processorDefOrName
* If this parameter is a string then it will be used as the processor's name, otherwise it is
* assumed that it used as the `processorDef`
*
* @param {function|object} processorDef
* The factory function or object that will be used by the injector to create the processor.
* * If a function then it is a factory and it must not be anonymous - it must have a name, e.g.
* `function myProcessor(dep1, dep2) { ... }` - since the name of the processor is taken from the
* name of the factory function.
* * If an object, then it is the actual processor and must have a `name` property. In this case,
* you cannot inject services into this processor.
*
* @return {Package}
* `this` package, to allow methods to be chained.
*/
Package.prototype.processor = function (processorDefOrName, processorDef) {
var name;
if (isString(processorDefOrName)) {
name = processorDefOrName;
}
else {
processorDef = processorDefOrName;
// Using `any` here because Functions do usually have names (if they are not anonymous)
if (!processorDef.name) {
throw new Error('processorDef must be an object or a function with a name');
}
name = processorDef.name;
}
if (typeof processorDef === 'function') {
this.module[name] = ['factory', processorDef];
}
else {
this.module[name] = ['value', processorDef];
}
this.processors.push(name);
return this;
};
/**
* Add a new service, defined by a factory function, to the package
*
* @param {function|string} serviceFactoryOrName
* If a string then this is the name of the service, otherwise it is assumed to be the
* `serviceFactory`.
*
* @param {function} serviceFactory
* The factory function that will be used by the injector to create the service. The function must
* not be anonymous - it must have a name, e.g. `function myService() { ... }` - since the name of
* the service is taken from the name of the factory function.
*
* @return {Package}
* "This" package, to allow methods to be chained.
*/
Package.prototype.factory = function (serviceFactoryOrName, serviceFactory) {
var name;
if (typeof serviceFactoryOrName === 'string') {
name = serviceFactoryOrName;
}
else {
serviceFactory = serviceFactoryOrName;
if (!serviceFactory.name) {
throw new Error('serviceFactory must have a name');
}
name = serviceFactory.name;
}
if (typeof serviceFactory !== 'function') {
throw new Error('serviceFactory must be a function.\nGot "' + typeof serviceFactory + '"');
}
this.module[name] = ['factory', serviceFactory];
return this;
};
/**
* Add a new service, defined as a Type to instantiated, to the package
*
* @param {function|string} ServiceTypeOrName
* If a string then this is the name of the service, otherwise it is assumed to be the
* `ServiceType`.
*
* @param {function} ServiceType
* The constructor function that will be used by the injector to create the processor. The function
* must not be anonymous - it must have a name, e.g. `function MyType() { ... }` - since the name of
* the service is taken from the name of the constructor function.
*
* @return {Package}
* "This" package, to allow methods to be chained.
*/
Package.prototype.type = function (ServiceTypeOrName, ServiceType) {
var name;
if (typeof ServiceTypeOrName === 'string') {
name = ServiceTypeOrName;
}
else {
ServiceType = ServiceTypeOrName;
if (!ServiceType.name) {
throw new Error('ServiceType must have a name');
}
name = ServiceType.name;
}
if (typeof ServiceType !== 'function') {
throw new Error('ServiceType must be a constructor function');
}
this.module[name] = ['type', ServiceType];
return this;
};
/**
* Add a new config block to the package. Config blocks are run at the beginning of the doc
* generation before the processors are run. They can be injected with services and processors
* to allow you access to their properties so that you can configure them.
*
* @param {function} configFn The config block function to run
*
* @return {Package}
* "This" package, to allow methods to be chained.
*/
Package.prototype.config = function (configFn) {
if (typeof configFn !== 'function') {
throw new Error('configFn must be a function');
}
this.configFns.push(configFn);
return this;
};
/**
* Add an event handler to this package
* @param {string} eventName The name of the event to handle
* @param {function} handlerFactory An injectable factory function that will return the handler
* @return {Package} This package for chaining
*/
Package.prototype.eventHandler = function (eventName, handlerFactory) {
if (typeof eventName !== 'string') {
throw new Error('You must provide a string identifying the type of event to handle');
}
if (typeof handlerFactory !== 'function') {
throw new Error('handlerFactory must be a function.\nGot "' + typeof handlerFactory + '"');
}
var handlers = this.handlers[eventName] = this.handlers[eventName] || [];
var handlerName = handlerFactory.name || (this.name + '_' + eventName + '_' + handlers.length);
this.factory(handlerName, handlerFactory);
handlers.push(handlerName);
return this;
};
return Package;
}());
exports.Package = Package;
function isObject(value) {
var type = typeof value;
return !!value && (type === 'object' || type === 'function');
}
/**
* Add a new processor to the package. The processor can be defined by a processor definition object
* or a factory function, which can be injected with services and will return the processor definition
* object. The following properties of a processor definition object have special meaning to Dgeni:
*
* * `name : {string}`: The name of the processor - if the processor is defined by a factory
* function or a name is explicitly provided as the first parameter, then this is ignored
* * `$process(docs : {string}) : {Array|Promise|undefined}`: The method that will be called to
* process the documents. If it is async then it should return a Promise.
* * `$runAfter : {string[]}`: Dgeni will ensure that this processor runs after those named here.
* * `$runBefore : {string[]}`: Dgeni will ensure that this processor runs before those named here.
* * `$validate: {Object}`: Dgeni will check that the properties of the processor, which match the
* keys of this object, pass the validation rules provided as the values of this object. See
* http://validatejs.org
*
* @param {function|object|string} processorDefOrName
* If this parameter is a string then it will be used as the processor's name, otherwise it is
* assumed that it used as the `processorDef`
*
* @param {function|object} processorDef
* The factory function or object that will be used by the injector to create the processor.
* * If a function then it is a factory and it must not be anonymous - it must have a name, e.g.
* `function myProcessor(dep1, dep2) { ... }` - since the name of the processor is taken from the
* name of the factory function.
* * If an object, then it is the actual processor and must have a `name` property. In this case,
* you cannot inject services into this processor.
*
* @return {Package}
* `this` package, to allow methods to be chained.
*/
Package.prototype.processor = function(processorDefOrName, processorDef) {
var name;
if( typeof processorDefOrName === 'string' ) {
name = processorDefOrName;
} else {
processorDef = processorDefOrName;
if (!processorDef.name) { throw new Error('processorDef must be an object or a function with a name'); }
name = processorDef.name;
}
if (typeof processorDef === 'function' ) {
this.module[name] = ['factory', processorDef];
} else {
this.module[name] = ['value', processorDef];
}
this.processors.push(name);
return this;
};
/**
* Add a new service, defined by a factory function, to the package
*
* @param {function|string} serviceFactoryOrName
* If a string then this is the name of the service, otherwise it is assumed to be the
* `serviceFactory`.
*
* @param {function} serviceFactory
* The factory function that will be used by the injector to create the service. The function must
* not be anonymous - it must have a name, e.g. `function myService() { ... }` - since the name of
* the service is taken from the name of the factory function.
*
* @return {Package}
* "This" package, to allow methods to be chained.
*/
Package.prototype.factory = function(serviceFactoryOrName, serviceFactory) {
var name;
if ( typeof serviceFactoryOrName === 'string' ) {
name = serviceFactoryOrName;
} else {
serviceFactory = serviceFactoryOrName;
if (!serviceFactory.name) { throw new Error('serviceFactory must have a name'); }
name = serviceFactory.name;
}
if (typeof serviceFactory !== 'function' ) {
throw new Error('serviceFactory must be a function.\nGot "' + typeof serviceFactory + '"');
}
this.module[name] = ['factory', serviceFactory];
return this;
};
/**
* Add a new service, defined as a Type to instantiated, to the package
*
* @param {function|string} ServiceTypeOrName
* If a string then this is the name of the service, otherwise it is assumed to be the
* `ServiceType`.
*
* @param {function} ServiceType
* The constructor function that will be used by the injector to create the processor. The function
* must not be anonymous - it must have a name, e.g. `function MyType() { ... }` - since the name of
* the service is taken from the name of the constructor function.
*
* @return {Package}
* "This" package, to allow methods to be chained.
*/
Package.prototype.type = function(ServiceTypeOrName, ServiceType) {
var name;
if ( typeof ServiceTypeOrName === 'string' ) {
name = ServiceTypeOrName;
} else {
ServiceType = ServiceTypeOrName;
if (!ServiceType.name) { throw new Error('ServiceType must have a name'); }
name = ServiceType.name;
}
if (typeof ServiceType !== 'function' ) { throw new Error('ServiceType must be a constructor function'); }
this.module[name] = ['type', ServiceType];
return this;
};
/**
* Add a new config block to the package. Config blocks are run at the beginning of the doc
* generation before the processors are run. They can be injected with services and processors
* to allow you access to their properties so that you can configure them.
*
* @param {function} configFn The config block function to run
*
* @return {Package}
* "This" package, to allow methods to be chained.
*/
Package.prototype.config = function(configFn) {
if (typeof configFn !== 'function' ) { throw new Error('configFn must be a function'); }
this.configFns.push(configFn);
return this;
};
Package.isPackage = function(package) {
// Check the most important properties for dgeni to use a package
return _.isString(package.name) && _.isArray(package.dependencies) && _.isObject(package.module);
};
/**
* @module Package
*/
module.exports = Package;
function isString(value) {
return typeof value === 'string';
}
//# sourceMappingURL=Package.js.map

@@ -0,4 +1,4 @@

"use strict";
var _ = require('lodash');
var DepGraph = require('dependency-graph').DepGraph;
/**

@@ -19,44 +19,42 @@ * @name sortByDependency

*/
module.exports = function sortByDependency(items, afterProp, beforeProp, nameProp) {
nameProp = nameProp || 'name';
var map = {};
var depGraph = new DepGraph();
var addDependencies = function(item, dependencyProp, addBefore) {
if ( dependencyProp && item[dependencyProp]) {
if ( !Array.isArray(item[dependencyProp]) ) {
throw new Error('Error in item "' + item[nameProp] + '" - ' + dependencyProp + ' must be an array');
}
item[dependencyProp].forEach(function(dependency) {
if ( !map[dependency] ) {
throw new Error('Missing dependency: "' + dependency + '" on "' + item[nameProp] + '"');
function sortByDependency(items, afterProp, beforeProp, nameProp) {
if (nameProp === void 0) { nameProp = 'name'; }
var map = {};
var depGraph = new DepGraph();
var addDependencies = function (item, dependencyProp, addBefore) {
if (addBefore === void 0) { addBefore = false; }
if (dependencyProp && item[dependencyProp]) {
if (!Array.isArray(item[dependencyProp])) {
throw new Error('Error in item "' + item[nameProp] + '" - ' + dependencyProp + ' must be an array');
}
item[dependencyProp].forEach(function (dependency) {
if (!map[dependency]) {
throw new Error('Missing dependency: "' + dependency + '" on "' + item[nameProp] + '"');
}
if (addBefore) {
depGraph.addDependency(dependency, item[nameProp]);
}
else {
depGraph.addDependency(item[nameProp], dependency);
}
});
}
if ( addBefore ) {
depGraph.addDependency(dependency, item[nameProp]);
} else {
depGraph.addDependency(item[nameProp], dependency);
};
_.forEach(items, function (item, index) {
if (!item[nameProp]) {
throw new Error('Missing ' + nameProp + ' property on item #' + (index + 1));
}
});
}
};
_.forEach(items, function(item, index) {
if ( !item[nameProp] ) {
throw new Error('Missing ' + nameProp + ' property on item #' + (index+1));
}
map[item[nameProp]] = item;
depGraph.addNode(item[nameProp]);
});
_.forEach(items, function(item) {
addDependencies(item, afterProp);
addDependencies(item, beforeProp, true);
});
return depGraph.overallOrder().map(function(itemName) {
return map[itemName];
});
};
map[item[nameProp]] = item;
depGraph.addNode(item[nameProp]);
});
_.forEach(items, function (item) {
addDependencies(item, afterProp);
addDependencies(item, beforeProp, true);
});
return depGraph.overallOrder().map(function (itemName) {
return map[itemName];
});
}
exports.sortByDependency = sortByDependency;
;
//# sourceMappingURL=dependency-sort.js.map

@@ -0,1 +1,2 @@

"use strict";
/**

@@ -7,10 +8,15 @@ * @dgService getInjectables

*/
module.exports = function getInjectables(injector) {
return function(factories) {
return factories.map(function(factory) {
var instance = injector.invoke(factory);
instance.name = instance.name || factory.name;
return instance;
});
};
};
function getInjectablesFactory(injector) {
return function (factories) {
return factories.map(function (factory) {
var instance = injector.invoke(factory);
if (!instance.name) {
instance.name = factory.name;
}
return instance;
});
};
}
exports.getInjectablesFactory = getInjectablesFactory;
;
//# sourceMappingURL=getInjectables.js.map

@@ -0,1 +1,2 @@

"use strict";
/**

@@ -7,7 +8,10 @@ * @dgService log

*/
module.exports = function logFactory() {
var winston = require('winston');
winston.cli();
winston.level = 'info';
return winston;
};
function logFactory() {
var winston = require('winston');
winston.cli();
winston.level = 'info';
return winston;
}
exports.logFactory = logFactory;
;
//# sourceMappingURL=log.js.map
{
"name": "dgeni",
"version": "0.4.2",
"description": "Flexible JavaScript documentation generator used by AngularJS",
"version": "0.4.3",
"description": "Flexible JavaScript documentation generator used by Angular",
"main": "lib/Dgeni.js",
"types": "lib/index.d.ts",
"bin": {
"dgeni": "lib/gen-docs.js"
},
"files": [
"lib"
],
"scripts": {
"test": "jasmine-node lib",
"cover": "istanbul cover jasmine-node -- lib",
"docs": "bin/gen-docs.js ./docs/dgeni-docs.js"
"prepublish": "npm build",
"prebuild": "rm -rf lib",
"build": "tsc",
"watch": "tsc -w",
"test": "mocha --compilers ts:ts-node/register -R spec src/**/*.spec.ts",
"docs": "node lib/gen-docs.js ./docs/dgeni-docs.js"
},
"bin": {
"dgeni": "bin/gen-docs.js"
},
"repository": {

@@ -19,4 +26,5 @@ "type": "git",

"author": "Pete Bacon Darwin",
"license": "Apache-2.0",
"license": "MIT",
"dependencies": {
"@types/mocha": "^2.2.39",
"canonical-path": "~0.0.2",

@@ -26,2 +34,3 @@ "dependency-graph": "~0.4.1",

"lodash": "^3.10.1",
"objectdiff": "^1.1.0",
"optimist": "~0.6.1",

@@ -33,6 +42,11 @@ "q": "~1.4.1",

"devDependencies": {
"dgeni-packages": "^0.11.1",
"istanbul": "^0.4.1",
"jasmine-node": "^2.0.0",
"rewire": "~2.5.1"
"@types/chai": "^3.4.34",
"@types/node": "^7.0.5",
"chai": "^3.5.0",
"chai-spies": "^0.7.1",
"dgeni-packages": "^0.16.0",
"mocha": "^3.2.0",
"ts-node": "^2.1.0",
"tslint": "^4.4.2",
"typescript": "^2.1.6"
},

@@ -39,0 +53,0 @@ "contributors": [

@@ -18,2 +18,13 @@ # Dgeni - Documentation Generator [![Build Status](https://travis-ci.org/angular/dgeni.svg?branch=master)](https://travis-ci.org/angular/dgeni)

## Documenting Angular 1 Apps
There are two projects out there that build upon dgeni to help create documentation for Angular 1 apps:
* dgeni-alive: https://github.com/wingedfox/dgeni-alive
* sia: https://github.com/boundstate/sia
Do check them out and thanks to [Ilya](https://github.com/wingedfox) and [Bound State Software](https://github.com/boundstate)
for putting these projects together.
## Installation

@@ -208,2 +219,6 @@

**Note that the validation feature has been moved to its own Dgeni Package `processorValidation`.
Currently dgeni automatically adds this new package to a new instance of dgeni so that is still available
for backward compatibility. In a future release this package will be moved to `dgeni-packages`.**
### Defining a Processor

@@ -279,2 +294,5 @@

* `typescript` - depends upon `base` and adds Processors and Services to support parsing and
extracting jsdoc style tags from comments in TypeScript (*.ts) code.
* `nunjucks` - provides a [nunjucks](http://mozilla.github.io/nunjucks/) based rendering

@@ -340,4 +358,58 @@ engine.

## Dgeni Events
In Dgeni you can trigger and handle **events** to allow packages to take part in the processing
lifecycle of the documentation generation.
### Triggering Events
You trigger an event simply by calling `triggerEvent(eventName, ...)` on a `Dgeni` instance.
The `eventName` is a string that identifies the event to be triggered, which is used to wire up
event handlers. Additional arguments are passed through to the handlers.
Each handler that is registered for the event is called in series. The return value
from the call is a promise to the event being handled. This allows event handlers to be async.
If any handler returns a rejected promise the event triggering is cancelled and the rejected
promise is returned.
For example:
```js
var eventPromise = dgeni.triggerEvent('someEventName', someArg, otherArg);
```
### Handling Events
You register an event handler in a `Package`, by calling `handleEvent(eventName, handlerFactory)` on
the package instance. The handlerFactory will be used by the DI system to get the handler, which allows
you to inject services to be available to the handler.
The handler factory should return the handler function. This function will receive all the arguments passed
to the `triggerHandler` method. As a minimum this will include the `eventName`.
For example:
```js
myPackage.eventHandler('generationStart', function validateProcessors(log, dgeni) {
return function validateProcessorsImpl(eventName) {
...
};
});
```
### Built-in Events
Dgeni itself triggers the following events during documentation generation:
* `generationStart`: triggered after the injector has been configured and before the processors begin
their work.
* `generationEnd`: triggered after the processors have all completed their work successfully.
* `processorStart`: triggered just before the call to `$process`, for each processor.
* `processorEnd`: triggered just after `$process` has completed successfully, for each processor.
## License
Apache 2

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc