UNPKG

4.08 kBJavaScriptView Raw
1'use strict';
2
3const ask = require('ask-nicely');
4const path = require('path');
5
6const APP = Symbol('app');
7const CONTEXTINFORMERS = Symbol('context informers');
8const LOCATION = Symbol('location');
9const PACKAGEJSON = Symbol('package.json');
10
11/**
12 * The unified API for registering module functionality with the FDT instance. The callback exposed
13 * by a module will get an instance of ModuleRegistrationApi to register itself with.
14 */
15class ModuleRegistrationApi {
16 /**
17 * Should not be called by a module.
18 *
19 * @param {App} app The app.
20 * @param {string} moduleLocation The location of the module that is being registered.
21 *
22 * @constructor
23 */
24 constructor(app, moduleLocation) {
25 this[APP] = app;
26
27 this[LOCATION] = moduleLocation;
28
29 this[PACKAGEJSON] = require(path.join(this[LOCATION], 'package.json'));
30
31 this[CONTEXTINFORMERS] = [];
32
33 this.hidden = false;
34
35 Object.assign(this, ask);
36 }
37
38 /**
39 * Should not be called by a module. Loads and evaluates the Javascript code belonging to a module.
40 *
41 * @param {...*} extra
42 */
43 load(...extra) {
44 const mod = require(this[LOCATION]);
45
46 if (typeof mod !== 'function') {
47 throw new Error(this[PACKAGEJSON].name + ' is not a function.');
48 }
49
50 mod(this, ...extra);
51 }
52
53 /**
54 * Passes on the information returned by App#getInfo.
55 *
56 * @see App#getInfo
57 *
58 * @return {object} The app information.
59 */
60 getAppInfo() {
61 return this[APP].getInfo();
62 }
63
64 /**
65 * Returns metadata about the module that is being registered.
66 *
67 * @return {{name, version, builtIn, description, path}} The module information.
68 */
69 getInfo() {
70 return {
71 name: this[PACKAGEJSON].name,
72 version: this[PACKAGEJSON].version,
73 builtIn: this[APP].builtInModules.some(mod => mod === this),
74 description: this[PACKAGEJSON].description,
75 path: this[LOCATION]
76 };
77 }
78
79 /**
80 * Adds a command to the root of the FDT instance.
81 *
82 * @see FdtCommand#addCommand
83 *
84 * @param {string} commandName
85 * @param {string|function(AskNicelyRequest, SpeakSoftly)} [controller]
86 *
87 * @return {Command} The command object that was created.
88 */
89 registerCommand(commandName, controller) {
90 const command = this[APP].cli.addCommand(commandName, controller);
91 command._moduleRegistration = this;
92 return command;
93 }
94
95 /**
96 * Adds a hidden command to the root of the FDT instance.
97 *
98 * @see FdtCommand#addHiddenCommand
99 *
100 * @param {string} commandName
101 * @param {string|function(AskNicelyRequest, SpeakSoftly)} [controller]
102 *
103 * @return {Command} The command object that was created.
104 */
105 registerHiddenCommand(commandName, controller) {
106 const command = this[APP].cli.addHiddenCommand(commandName, controller);
107 command._moduleRegistration = this;
108 return command;
109 }
110
111 /**
112 * NOTE: Only use this from the module's index.js, not from within commands, or else your config might be overridden.
113 *
114 * @see ConfigManager#registerConfiguration
115 *
116 * @param {string} configName
117 * @param {*} defaultValue
118 * @param {*|function(config): ?*} [serialize]
119 *
120 * @return {*} The configuration value.
121 */
122 registerConfiguration(configName, defaultValue, serialize) {
123 return this[APP].config.registerConfig(configName, defaultValue, serialize);
124 }
125
126 /**
127 * Get the registered configuration.
128 *
129 * @param {string} configName
130 *
131 * @return {*} The configuration value.
132 */
133 getConfiguration(configName) {
134 return this[APP].config[configName];
135 }
136
137 /**
138 * Register a subcontroller to render additional info provided by a module in the "who" command
139 * provided by FDT.
140 *
141 * @param {function(AskNicelyRequest, SpeakSoftly)} contextInformer
142 *
143 * @return {Object} The context informer.
144 */
145 registerContextInformer(contextInformer) {
146 this[CONTEXTINFORMERS].push(contextInformer);
147
148 return contextInformer;
149 }
150
151 /**
152 * Should not be called by a module. Return the list of context informers registered by this module.
153 *
154 * @return {Array} The context informers.
155 */
156 getContextInformers() {
157 return this[CONTEXTINFORMERS].slice(0);
158 }
159}
160
161module.exports = ModuleRegistrationApi;