1 | ;
|
2 |
|
3 | const ask = require('ask-nicely');
|
4 | const path = require('path');
|
5 |
|
6 | const APP = Symbol('app');
|
7 | const CONTEXTINFORMERS = Symbol('context informers');
|
8 | const LOCATION = Symbol('location');
|
9 | const 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 | */
|
15 | class 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 |
|
161 | module.exports = ModuleRegistrationApi;
|