UNPKG

2.78 kBJavaScriptView Raw
1/**
2 * Provides a means to install missing dependencies at runtime.
3 *
4 * Written By:
5 * Matthew Knox
6 *
7 * License:
8 * MIT License. All code unless otherwise specified is
9 * Copyright (c) Matthew Knox and Contributors 2015.
10 */
11
12let exec = require('child_process').execSync,
13 path = require('path'),
14 fs = require('fs'),
15 csHasLoaded = false,
16 nativeReloadHacksCache = {},
17 nativeReloadHacks = ['deasync'],
18
19 command = function(args) {
20 args.unshift('--silent');
21 args.unshift('npm');
22 let cmd = args.join(' ');
23 exec(cmd, {cwd:global.__rootPath});
24 },
25
26 // inject require modifications into all coffeescript code because babel wont
27 coffeescriptRequireInjector = function () {
28 if (!csHasLoaded && global.coffeescriptLoaded) {
29 let cs = require('coffee-script'),
30 orig = cs._compileFile,
31 requirejs = require('./require.js');
32 cs._compileFile = function () {
33 let res = orig.apply(this, arguments);
34 return requirejs.injectionString + res;
35 };
36 csHasLoaded = true;
37 }
38 },
39
40 install = function(name) {
41 let t = global.$$, // translations might not have loaded
42 startStr = t ? t`Installing "${name}" from npm.` : `Installing "${name}" from npm.`,
43 endStr = t ? t`Installation complete.` : `Installation complete.`;
44
45 console.info(startStr);
46 command(['install', name]);
47 console.info(endStr);
48 };
49
50exports.requireOrInstall = function (req, name) {
51 coffeescriptRequireInjector();
52 let parsed = path.parse(name);
53 if (((parsed.ext === '.js' || parsed.ext === '.coffee') &&
54 (parsed.dir.startsWith('.') || parsed.dir.startsWith('/') || parsed.dir.startsWith('\\'))) || parsed.root.length > 0) {
55 return req(name); // try to prevent needless npm install
56 }
57
58 if (nativeReloadHacksCache.hasOwnProperty(name)) {
59 return nativeReloadHacksCache[name];
60 }
61
62 var r;
63 try {
64 r = req(name);
65 }
66 catch (e) {
67 if (!e || !e.code || e.code !== 'MODULE_NOT_FOUND') {
68 throw e;
69 }
70 try {
71 fs.statSync(name);
72 }
73 catch (p) {
74 install(name);
75 }
76 r = require(name);
77 }
78
79 // Native bindings fail to reload in node. Leave if you want restarting or hotswapping to work...
80 if (nativeReloadHacks.includes(name) || name.endsWith('.node')) {
81 nativeReloadHacksCache[name] = r;
82 }
83 return r;
84};
85
86exports.update = function() {
87 command(['update']);
88};