Skip to content

Commit c4e5f62

Browse files
committed
ensured dynamic imports are asynchronous
this is required in preparation of switching to ESM, where synchronous `require` will have to be replaced with dynamic `import` note that this constitutes a breaking change for developers
1 parent 035948c commit c4e5f62

File tree

8 files changed

+79
-74
lines changed

8 files changed

+79
-74
lines changed

bin/faucet

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,7 @@
44
let { faucetDispatch } = require("../lib");
55
let { parseCLI } = require("../lib/cli");
66

7-
let { referenceDir, config, options } = parseCLI();
8-
faucetDispatch(referenceDir, config, options);
7+
parseCLI().
8+
then(({ referenceDir, config, options }) => {
9+
faucetDispatch(referenceDir, config, options);
10+
});

lib/cli.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ Options:
2727
serve generated files via HTTP with live reloading
2828
`.trim();
2929

30-
exports.parseCLI = function parseCLI(argv = process.argv.slice(2), help = HELP) {
30+
exports.parseCLI = async function parseCLI(argv = process.argv.slice(2), help = HELP) {
3131
argv = parseArgs(argv, {
3232
boolean: ["watch", "fingerprint", "sourcemaps", "compact"],
3333
alias: {
@@ -56,6 +56,6 @@ exports.parseCLI = function parseCLI(argv = process.argv.slice(2), help = HELP)
5656
}
5757

5858
let rootDir = process.cwd();
59-
let { referenceDir, config } = readConfig(rootDir, argv.config);
59+
let { referenceDir, config } = await readConfig(rootDir, argv.config);
6060
return { referenceDir, config, options };
6161
};

lib/config.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
let path = require("path");
44

5-
exports.readConfig = function readConfig(rootDir, filepath = "faucet.config.js") {
5+
exports.readConfig = async function readConfig(rootDir, filepath = "faucet.config.js") {
66
let configPath = path.resolve(rootDir, filepath);
77
return {
88
referenceDir: path.dirname(configPath),
9-
config: require(configPath)
9+
config: await require(configPath)
1010
};
1111
};

lib/index.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ exports.faucetDispatch = async function faucetDispatch(referenceDir, config,
2222
browsers = [browsers];
2323
}
2424

25-
let plugins = pluginsByBucket(config);
25+
let plugins = await pluginsByBucket(config);
2626
// initialize plugins with corresponding configuration
2727
let buckets = Object.keys(plugins).reduce((memo, bucket) => {
2828
memo[bucket] = plugins[bucket].map(({ plugin, config }) => {
@@ -40,8 +40,10 @@ exports.faucetDispatch = async function faucetDispatch(referenceDir, config,
4040

4141
if(watch) {
4242
makeWatcher(config.watchDirs, referenceDir).
43-
on("edit", filepaths => {
44-
runner.rerun(filepaths);
43+
then(watcher => {
44+
watcher.on("edit", filepaths => {
45+
runner.rerun(filepaths);
46+
});
4547
});
4648
}
4749

@@ -60,8 +62,8 @@ function buildStep(plugins) {
6062
then(() => files);
6163
}
6264

63-
function makeWatcher(watchDirs, referenceDir) {
64-
let niteOwl = require("nite-owl");
65+
async function makeWatcher(watchDirs, referenceDir) {
66+
let niteOwl = await require("nite-owl");
6567

6668
if(watchDirs) {
6769
watchDirs = watchDirs.map(dir => resolvePath(dir, referenceDir,

lib/plugins.js

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,47 +33,50 @@ module.exports = {
3333

3434
// returns plugin functions grouped by bucket and filtered by relevance (based
3535
// on configuration)
36-
function pluginsByBucket(config, defaults) {
37-
let plugins = determinePlugins(config.plugins, defaults);
36+
async function pluginsByBucket(config, defaults) {
37+
let plugins = await determinePlugins(config.plugins, defaults);
3838
let buckets = [...BUCKETS].reduce((memo, bucket) => {
3939
memo[bucket] = [];
4040
return memo;
4141
}, {});
42-
Object.entries(plugins).forEach(([key, _plugin]) => {
42+
for(let [key, _plugin] of Object.entries(plugins)) {
4343
let pluginConfig = config[key];
4444
if(!pluginConfig) {
45-
return;
45+
continue;
4646
}
4747

4848
let { bucket, plugin } = _plugin;
49+
if(!plugin.call) {
50+
({ plugin } = await loadPlugin(plugin));
51+
}
4952
buckets[bucket].push({
50-
plugin: plugin.call ? plugin : loadPlugin(plugin).plugin,
53+
plugin,
5154
config: pluginConfig
5255
});
53-
});
56+
}
5457
return buckets;
5558
}
5659

5760
// `plugins` is an array of plugins, each either a package identifier or a
5861
// `{ key, bucket, plugin }` object`, with `key` being the configuration key and
5962
// `plugin` being either a function or a package identifier
60-
function determinePlugins(plugins = [], defaults = DEFAULTS) {
63+
async function determinePlugins(plugins = [], defaults = DEFAULTS) {
6164
let registry = {};
6265
// NB: default plugins are resolved lazily because eager loading would
6366
// result in them becoming a hard dependency rather than a convenience
6467
// preset - however, that requires us to duplicate the respective
6568
// configuration keys and buckets here
66-
defaults.forEach(plugin => {
67-
registerPlugin(registry, plugin, false);
68-
});
69-
plugins.forEach(plugin => {
70-
registerPlugin(registry, plugin, true);
71-
});
69+
for(let plugin of defaults) {
70+
await registerPlugin(registry, plugin, false);
71+
}
72+
for(let plugin of plugins) {
73+
await registerPlugin(registry, plugin, true);
74+
}
7275
return registry;
7376
}
7477

75-
function registerPlugin(registry, _plugin, eager) {
76-
let { key, bucket, plugin } = resolvePlugin(_plugin, eager);
78+
async function registerPlugin(registry, _plugin, eager) {
79+
let { key, bucket, plugin } = await resolvePlugin(_plugin, eager);
7780
// NB: default plugins may be overridden
7881
if(registry[key] && !DEFAULT_KEYS.has(key)) {
7982
abort(`ERROR: duplicate plugin key ${repr(key, false)}`);
@@ -84,14 +87,14 @@ function registerPlugin(registry, _plugin, eager) {
8487
}
8588
}
8689

87-
function resolvePlugin(_plugin, eager) {
90+
async function resolvePlugin(_plugin, eager) {
8891
if(_plugin.substr) { // package identifier
89-
_plugin = loadPlugin(_plugin);
92+
_plugin = await loadPlugin(_plugin);
9093
}
9194

9295
let { key, bucket, plugin } = _plugin;
9396
if(eager && plugin.substr && (!key || !bucket)) { // auto-configuration
94-
let _plugin = loadPlugin(plugin);
97+
let _plugin = await loadPlugin(plugin);
9598
plugin = _plugin.plugin;
9699
// local configuration takes precedence
97100
key = key || _plugin.key;
@@ -104,13 +107,13 @@ function resolvePlugin(_plugin, eager) {
104107
return { key, bucket, plugin };
105108
}
106109

107-
function loadPlugin(pkg) {
110+
async function loadPlugin(pkg) {
108111
let fail = prop => abort(`ERROR: invalid plugin ${repr(pkg)}; ` +
109112
`missing ${repr(prop, false)}`);
110113
let {
111114
key = fail("key"),
112115
bucket = fail("bucket"),
113116
plugin = fail("plugin")
114-
} = loadExtension(pkg, "ERROR: missing plugin");
117+
} = await loadExtension(pkg, "ERROR: missing plugin");
115118
return { key, bucket, plugin };
116119
}

lib/server.js

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,16 @@ let DEFAULTS = {
55
port: 3000
66
};
77

8-
exports.static = (config, webroot) => {
9-
let donny = loadExtension("donny", "failed to activate server");
8+
exports.static = async (config, webroot) => {
9+
let donny = await loadExtension("donny", "failed to activate server");
1010
let [host, port] = parseHost(config);
1111

12-
donny({ port, bind: host, webroot }).
13-
then(() => {
14-
console.error(`serving ${repr(webroot)} at http://${host}:${port}`);
15-
});
12+
await donny({ port, bind: host, webroot });
13+
console.error(`serving ${repr(webroot)} at http://${host}:${port}`);
1614
};
1715

18-
exports.live = (config, root) => {
19-
let liveServer = loadExtension("live-server", "failed to activate live-server");
16+
exports.live = async (config, root) => {
17+
let liveServer = await loadExtension("live-server", "failed to activate live-server");
2018
let [host, port] = parseHost(config);
2119

2220
liveServer.start({ port, host, root, open: false });

lib/util/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ exports.reportFileStatus = (filepath, referenceDir, error) => {
1313
console.error(error ? `✗ ${ref}: ${error.message || error}` : `✓ ${ref}`);
1414
};
1515

16-
// attempts to `require` a module, prompting the user to install the
17-
// corresponding package if it is unavailable
18-
exports.loadExtension = (pkg, errorMessage, supplier = pkg) => {
16+
// attempts to load a module, prompting the user to install the corresponding
17+
// package if it is unavailable
18+
exports.loadExtension = async (pkg, errorMessage, supplier = pkg) => {
1919
try {
20-
return require(pkg);
20+
return await require(pkg);
2121
} catch(err) {
2222
if(err.code !== "MODULE_NOT_FOUND") {
2323
throw err;

test/test_plugins.js

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ describe("plugin registration", () => {
3939
updateNodePath(NODE_PATH);
4040
});
4141

42-
it("only loads default plugins referenced within configuration", () => {
43-
let res = pluginsByBucket({
42+
it("only loads default plugins referenced within configuration", async () => {
43+
let res = await pluginsByBucket({
4444
js: [{ foo: "lorem" }]
4545
});
4646
assertDeep(normalizeAll(res), {
@@ -53,7 +53,7 @@ describe("plugin registration", () => {
5353
markup: []
5454
});
5555

56-
res = pluginsByBucket({
56+
res = await pluginsByBucket({
5757
sass: [{ bar: "ipsum" }]
5858
});
5959
assertDeep(normalizeAll(res), {
@@ -66,7 +66,7 @@ describe("plugin registration", () => {
6666
markup: []
6767
});
6868

69-
res = pluginsByBucket({
69+
res = await pluginsByBucket({
7070
js: [{ foo: "lorem" }],
7171
sass: [{ bar: "ipsum" }]
7272
});
@@ -84,8 +84,8 @@ describe("plugin registration", () => {
8484
});
8585
});
8686

87-
it("allows overriding default plugins", () => {
88-
let res = pluginsByBucket({
87+
it("allows overriding default plugins", async () => {
88+
let res = await pluginsByBucket({
8989
js: [{ foo: "bar" }],
9090
plugins: [{
9191
key: "js",
@@ -120,20 +120,20 @@ describe("plugin resolution", () => {
120120
updateNodePath(NODE_PATH);
121121
});
122122

123-
it("provides a default set of plugins", () => {
124-
let res = _determinePlugins();
123+
it("provides a default set of plugins", async () => {
124+
let res = await _determinePlugins();
125125
assertDeep(normalizePlugins(res), DEFAULTS);
126126
});
127127

128-
it("supports custom plugins", () => {
128+
it("supports custom plugins", async () => {
129129
// plugin function within configuration
130130
let anon = () => {};
131131
let config = [{
132132
key: "dummy",
133133
bucket: "static",
134134
plugin: anon
135135
}];
136-
let res = _determinePlugins(config);
136+
let res = await _determinePlugins(config);
137137
assertDeep(normalizePlugins(res), Object.assign({}, DEFAULTS, {
138138
dummy: {
139139
bucket: "static",
@@ -144,7 +144,7 @@ describe("plugin resolution", () => {
144144
// nested package identifier
145145
let pkg = "faucet-pipeline-dummy";
146146
config[0].plugin = pkg;
147-
res = _determinePlugins(config);
147+
res = await _determinePlugins(config);
148148
assertDeep(normalizePlugins(res), Object.assign({}, DEFAULTS, {
149149
dummy: {
150150
bucket: "static",
@@ -154,7 +154,7 @@ describe("plugin resolution", () => {
154154
}));
155155

156156
// simple package identifier
157-
res = _determinePlugins([pkg]);
157+
res = await _determinePlugins([pkg]);
158158
assertDeep(normalizePlugins(res), Object.assign({}, DEFAULTS, {
159159
dummy: {
160160
bucket: "static",
@@ -163,12 +163,12 @@ describe("plugin resolution", () => {
163163
}));
164164
});
165165

166-
it("allows overriding plugins' default configuration", () => {
166+
it("allows overriding plugins' default configuration", async () => {
167167
let config = [{
168168
key: "yummy",
169169
plugin: "faucet-pipeline-dummy"
170170
}];
171-
let res = _determinePlugins(config);
171+
let res = await _determinePlugins(config);
172172
assertDeep(normalizePlugins(res), Object.assign({}, DEFAULTS, {
173173
yummy: {
174174
bucket: "static",
@@ -177,7 +177,7 @@ describe("plugin resolution", () => {
177177
}));
178178

179179
config[0].bucket = "styles";
180-
res = _determinePlugins(config);
180+
res = await _determinePlugins(config);
181181
assertDeep(normalizePlugins(res), Object.assign({}, DEFAULTS, {
182182
yummy: {
183183
bucket: "styles",
@@ -188,12 +188,12 @@ describe("plugin resolution", () => {
188188
});
189189

190190
it("balks at invalid package identifiers", () => {
191-
assert.throws(() => {
192-
_determinePlugins(["faucet-pipeline-yummy"]);
191+
assert.rejects(async () => {
192+
return _determinePlugins(["faucet-pipeline-yummy"]);
193193
}, /exit 1/);
194194

195-
assert.throws(() => {
196-
_determinePlugins([{
195+
assert.rejects(() => {
196+
return _determinePlugins([{
197197
// NB: local configuration must not be comprehensive to ensure
198198
// plugin is loaded
199199
key: "yummy",
@@ -203,8 +203,8 @@ describe("plugin resolution", () => {
203203
});
204204

205205
it("balks at duplicate configuration keys", () => {
206-
assert.throws(() => {
207-
_determinePlugins([{
206+
assert.rejects(() => {
207+
return _determinePlugins([{
208208
key: "dummy",
209209
bucket: "static",
210210
plugin: () => {}
@@ -217,16 +217,16 @@ describe("plugin resolution", () => {
217217
});
218218

219219
it("balks at invalid plugins", () => {
220-
assert.throws(() => {
221-
_determinePlugins(["faucet-pipeline-invalid-a"]);
220+
assert.rejects(() => {
221+
return _determinePlugins(["faucet-pipeline-invalid-a"]);
222222
}, /exit 1/);
223223

224-
assert.throws(() => {
225-
_determinePlugins(["faucet-pipeline-invalid-b"]);
224+
assert.rejects(() => {
225+
return _determinePlugins(["faucet-pipeline-invalid-b"]);
226226
}, /exit 1/);
227227

228-
assert.throws(() => {
229-
_determinePlugins(["faucet-pipeline-invalid-c"]);
228+
assert.rejects(() => {
229+
return _determinePlugins(["faucet-pipeline-invalid-c"]);
230230
}, /exit 1/);
231231
});
232232

@@ -237,14 +237,14 @@ describe("plugin resolution", () => {
237237
};
238238
["static", "scripts", "styles", "markup"].forEach(bucket => {
239239
plugin.bucket = bucket;
240-
assert.doesNotThrow(() => {
241-
_determinePlugins([plugin]);
240+
assert.doesNotReject(() => {
241+
return _determinePlugins([plugin]);
242242
}, /exit 1/);
243243
});
244244

245245
plugin.bucket = "dummy";
246-
assert.throws(() => {
247-
_determinePlugins([plugin]);
246+
assert.rejects(() => {
247+
return _determinePlugins([plugin]);
248248
}, /exit 1/);
249249
});
250250
});

0 commit comments

Comments
 (0)