UNPKG

@pattern-lab/core

Version:

Create atomic design systems with Pattern Lab. This is the core API and orchestrator of the ecosystem.

318 lines (290 loc) 11 kB
/** * Build thoughtful, pattern-driven user interfaces using atomic design principles. * Many of these functions are exposed to users within {@link https://github.com/pattern-lab/patternlab-node#editions|Editions}, but {@link https://github.com/pattern-lab/patternlab-node#direct-consumption|direct consumption} is also encouraged. * * @namespace patternlab * @see {@link patternlab.io} for more documentation. * @see {@link https://github.com/pattern-lab/patternlab-node} for code, issues, and releases * @license MIT */ 'use strict'; const updateNotifier = require('update-notifier'); const packageInfo = require('../package.json'); const events = require('./lib/events'); const pe = require('./lib/pattern_exporter'); const defaultConfig = require('../patternlab-config.json'); let buildPatterns = require('./lib/buildPatterns'); // eslint-disable-line let logger = require('./lib/log'); // eslint-disable-line let fs = require('fs-extra'); // eslint-disable-line let ui_builder = require('./lib/ui_builder'); // eslint-disable-line let copier = require('./lib/copier'); // eslint-disable-line let pattern_exporter = new pe(); // eslint-disable-line let serverModule = require('./lib/server'); // eslint-disable-line //bootstrap update notifier updateNotifier({ pkg: packageInfo, updateCheckInterval: 1000 * 60 * 60 * 24, // notify at most once a day }).notify(); /** * Static method that returns the standardized default config used to run Pattern Lab. This method can be called statically or after instantiation. * * @memberof patternlab * @name getDefaultConfig * @static * @return {object} Returns the object representation of the `patternlab-config.json` */ const getDefaultConfig = function () { return defaultConfig; }; /** * Static method that returns current version * * @memberof patternlab * @name getVersion * @static * @returns {string} current @pattern-lab/core version as defined in `package.json` */ const getVersion = function () { return packageInfo.version; }; const patternlab_module = function (config) { const PatternLabClass = require('./lib/patternlab'); const patternlab = new PatternLabClass(config); const server = serverModule(patternlab); const _api = { /** * Returns current version * * @memberof patternlab * @name version * @instance * @returns {string} current patternlab-node version as defined in `package.json`, as string */ version: function () { return patternlab.getVersion(); }, /** * Returns the current pattern lab configuration being used * * @memberof patternlab * @name getConfig * @instance * @returns {object} the current patternlab-node config (defaults + customizations) */ getConfig() { return config; }, /** * Returns if Pattern Lab is busy compiling or not * * @memberof patternlab * @name isBusy * @instance * @returns {boolean} if pattern lab is currently busy compiling */ isBusy: function () { return patternlab.isBusy; }, /** * Builds patterns, copies assets, and constructs user interface * * @memberof patternlab * @name build * @instance * @param {object} options an object used to control build behavior * @param {bool} [options.cleanPublic=true] whether or not to delete the configured output location (usually `public/`) before build * @param {object} [options.data={}] additional data to be merged with global data prior to build * @param {bool} [options.watch=true] whether or not Pattern Lab should watch configured `source/` directories for changes to rebuild * @emits PATTERNLAB_BUILD_START * @emits PATTERNLAB_BUILD_END * @see {@link ./events.md|all events} * @returns {Promise} a promise fulfilled when build is complete */ build: async function (options) { // process.on('unhandledRejection', (reason, p) => { // console.log('Unhandled Rejection at: Promise', p, 'reason:', reason); // // application specific logging, throwing an error, or other logic here // console.log(reason.stack); // debugger; // }); if (patternlab && patternlab.isBusy) { logger.info( 'Pattern Lab is busy building a previous run - returning early.' ); return Promise.resolve(); } patternlab.isBusy = true; return await buildPatterns( options.cleanPublic, patternlab, options.data ).then(() => { return new ui_builder().buildFrontend(patternlab).then(() => { copier() .copyAndWatch(patternlab.config.paths, patternlab, options) .then(() => { patternlab.isBusy = false; // only wire up this listener and the one inside serve.js // figure out how to detect if serve was called. we should not assume it was if ( patternlab.serverReady //check for server presence ? this.events.listenerCount( events.PATTERNLAB_PATTERN_CHANGE ) === 1 //if the server is started, it has already setup one listener : !this.events.listenerCount(events.PATTERNLAB_PATTERN_CHANGE) // else, check for the presnce of none ) { this.events.on(events.PATTERNLAB_PATTERN_CHANGE, () => { if (!patternlab.isBusy) { return this.build(options).then(() => { patternlab.isBusy = false; }); } return Promise.resolve(); }); } if (!this.events.listenerCount(events.PATTERNLAB_GLOBAL_CHANGE)) { this.events.on(events.PATTERNLAB_GLOBAL_CHANGE, () => { if (!patternlab.isBusy) { return this.build( Object.assign({}, options, { cleanPublic: true }) // rebuild everything ); } return Promise.resolve(); }); } }) .then(() => { this.events.emit(events.PATTERNLAB_BUILD_END, patternlab); }); }); }); }, /** * Returns the standardized default config used to run Pattern Lab. This method can be called statically or after instantiation. * * @memberof patternlab * @name getDefaultConfig * @instance * @return {object} Returns the object representation of the `patternlab-config.json` */ getDefaultConfig: function () { return getDefaultConfig(); }, /** * Returns all file extensions supported by installed PatternEngines * * @memberof patternlab * @name getSupportedTemplateExtensions * @instance * @returns {Array<string>} all supported file extensions */ getSupportedTemplateExtensions: function () { return patternlab.getSupportedTemplateExtensions(); }, /** * Fetches starterkit repositories from pattern-lab github org that contain 'starterkit' in their name * * @memberof patternlab * @name liststarterkits * @instance * @returns {Promise} Returns an Array<{name,url}> for the starterkit repos */ liststarterkits: function () { return patternlab.listStarterkits(); }, /** * Loads starterkit already available as a package dependency * * @memberof patternlab * @name loadstarterkit * @instance * @param {string} starterkitName name of starterkit * @param {boolean} clean whether or not to delete contents of source/ before load * @returns {void} */ loadstarterkit: function (starterkitName, clean) { patternlab.loadStarterKit(starterkitName, clean); }, /** * Builds patterns only, leaving existing user interface files intact * * @memberof patternlab * @name patternsonly * @instance * @param {bool} [options.cleanPublic=true] whether or not to delete the configured output location (usually `public/`) before build * @param {object} [options.data={}] additional data to be merged with global data prior to build * @param {bool} [options.watch=true] whether or not Pattern Lab should watch configured `source/` directories for changes to rebuild * @returns {Promise} a promise fulfilled when build is complete */ patternsonly: async function (options) { if (patternlab && patternlab.isBusy) { logger.info( 'Pattern Lab is busy building a previous run - returning early.' ); return Promise.resolve(); } patternlab.isBusy = true; return await buildPatterns( options.cleanPublic, patternlab, options.data ).then(() => { patternlab.isBusy = false; }); }, /** * Server module * * @memberof patternlab * @type {object} */ server: { /** * Build patterns, copies assets, and constructs user interface. Watches configured `source/` directories, and serves all output locally * * @method serve * @memberof patternlab.server * @param {object} options an object used to control build behavior * @param {bool} [options.cleanPublic=true] whether or not to delete the configured output location (usually `public/`) before build * @param {object} [options.data={}] additional data to be merged with global data prior to build * @param {bool} [options.watch=true] whether or not Pattern Lab should watch configured `source/` directories for changes to rebuild * @returns {Promise} a promise fulfilled when build is complete */ serve: (options) => { return _api .build(options) .then(() => server.serve()) .catch((e) => logger.error(`error inside core index.js server serve: ${e}`) ); }, /** * Reloads any active live-server instances * * @method reload * @memberof patternlab.server * @returns {Promise} a promise fulfilled when operation is complete */ reload: server.reload, /** * Reloads CSS on any active live-server instances * * @method refreshCSS * @memberof patternlab.server * @returns {Promise} a promise fulfilled when operation is complete */ refreshCSS: server.refreshCSS, }, /** * @memberof patternlab * @type {EventEmitter} * @see {@link https://nodejs.org/api/events.html#events_class_eventemitter|EventEmitter} * @see {@link ./events.md|All Pattern Lab events} */ events: patternlab.events, }; return _api; }; patternlab_module.getDefaultConfig = getDefaultConfig; patternlab_module.getVersion = getVersion; module.exports = patternlab_module;