This repository has been archived by the owner on Aug 13, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 24
/
after.js
259 lines (218 loc) · 12 KB
/
after.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/**
* Module dependencies
*/
var path = require('path');
var exec = require('child_process').exec;
var spawn = require('cross-spawn');
var _ = require('lodash');
var async = require('async');
var fsx = require('fs-extra');
/**
* after()
*
* Runs after this generator has successfully finished
* processing all of its targets.
*
* > Note: if any target fails, then the `error` LC runs instead.
*
*
* @param {Dictionary} scope
*
* @required {String} rootPath
* The absolute path of the destination for the copied file.
*
* @required {String} sailsRoot
* The absolute path of the Sails dependency to grab installed
* dependencies from.
*
* @required {String} appName
* The name of the Sails app.
* (at this point, this is used purely for logging purposes).
*
* @optional {Boolean} link[=false]
* This is only relevant if the userland process is on a
* laptop/server with NPM 3 installed.
* If set to `true`, then this generator will use the NPM v2-style
* strategy for dropping dependencies into the newly-generated
* Sails app (i.e. symlinks for everything.)
*
*
* @param {Function} cb
*/
module.exports = function afterGenerate(scope, cb) {
// Validate scope and provide defaults.
if (_.isUndefined(scope.rootPath) || !_.isString(scope.rootPath)) {
return cb(new Error('Consistency violation: `rootPath` is a required string.'));
}
if (_.isUndefined(scope.sailsRoot) || !_.isString(scope.sailsRoot)) {
return cb(new Error('Consistency violation: `sailsRoot` is a required string.'));
}
if (_.isUndefined(scope.appName) || !_.isString(scope.appName)) {
return cb(new Error('Consistency violation: `appName` is a required string.'));
}
_.defaults(scope, {
link: false
});
// Get the version of the installed NPM command-line tool, if possible.
exec('npm -v', function (err, stdout, stderr) {
var version;
// The strategy for NPM 3+ will always work, regardless of the
// actual NPM version (as long as NPM is installed). So we
// default to the '3.0.0' strategy if `npm -v` doesn't work
// for some reason.
if (err) {
version = '3.0.0';
}
else {
version = stdout;
}
// Keep track of any non-fatal errors that occur below
// when we try to create symlinks. This is used for
// logging a warning message at the very end.
var nonFatalErrorsWhenCreatingSymlinks = [];
// ███╗ ██╗██████╗ ███╗ ███╗ ██╗ ██╗██████╗
// ████╗ ██║██╔══██╗████╗ ████║ ██║ ██║╚════██╗
// ██╔██╗ ██║██████╔╝██╔████╔██║ ██║ ██║ █████╔╝
// ██║╚██╗██║██╔═══╝ ██║╚██╔╝██║ ╚██╗ ██╔╝██╔═══╝
// ██║ ╚████║██║ ██║ ╚═╝ ██║ ╚████╔╝ ███████╗
// ╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚══════╝
//
// ┌─ ┌─┐┬─┐ ┌┬┐┬ ┬┌─┐ ╦ ╦╔╗╔╦╔═ ┌─┐┬ ┌─┐┌─┐ ┬ ┬┌─┐┌─┐ ┌─┐┌┐┌┌─┐┌┐ ┬ ┌─┐┌┬┐ ─┐
// │─── │ │├┬┘ │ ├─┤├┤ ║ ║║║║╠╩╗ ├┤ │ ├─┤│ ┬ │││├─┤└─┐ ├┤ │││├─┤├┴┐│ ├┤ ││ ───│
// └─ └─┘┴└─ ┴ ┴ ┴└─┘ ╩═╝╩╝╚╝╩ ╩ └ ┴─┘┴ ┴└─┘ └┴┘┴ ┴└─┘ └─┘┘└┘┴ ┴└─┘┴─┘└─┘─┴┘ ─┘
// If this is NPM version 2 or the `link` flag was enabled...
if (version.split('.')[0] <= 2 || scope.link === true) {
// Automatically create symlinks for all of the necessary dependencies
// in the new app's node_modules/ subdirectory:
async.auto({
// Create the node_modules folder
create_node_modules: function (next) {
fsx.mkdir(path.resolve(scope.rootPath, './node_modules'), next);
},
// Create links to all necessary dependencies
dependencies: ['create_node_modules', function (results, next) {
// Read the contents of the newly created package.json file.
var pathToPackageJson = path.resolve(scope.rootPath, './package.json');
fsx.readJson(pathToPackageJson, function (err, pjData){
if (err) { return next(err); }
// Delete the sails dependency--we'll add it separately.
// (it always gets npm linked)
delete pjData.dependencies.sails;
async.parallel(_.map(_.keys(pjData.dependencies), function copyDependency(moduleName){
// Make a symlink between the dependency in the sails node_modules folder,
// and the new app's node_modules.
return function _copyDependency(next) {
var srcModulePath = path.resolve(scope.sailsRoot, './node_modules', moduleName);
var destModulePath = path.resolve(scope.rootPath, './node_modules', moduleName);
// Use the "junction" option for Windows
fsx.symlink(srcModulePath, destModulePath, 'junction', function (symLinkErr) {
// If a symbolic link fails, push it to the `nonFatalErrorsWhenCreatingSymlinks` stack,
if (symLinkErr) {
nonFatalErrorsWhenCreatingSymlinks.push(symLinkErr);
}
// >- but keep going either way.
return next();
});
};
}), next);//</async.parallel>
});//</fsx.readJson()>
}],//</dependencies>
// Create a link to the sails we used to create the app
create_sails_link: ['create_node_modules', function create_sails_link(results, next) {
fsx.symlink(scope.sailsRoot, path.resolve(scope.rootPath, './node_modules/sails'), 'junction', function (symLinkErr) {
// If a symbolic link fails, push it to the `nonFatalErrorsWhenCreatingSymlinks` stack,
if (symLinkErr) {
nonFatalErrorsWhenCreatingSymlinks.push(symLinkErr);
}
// but keep going either way.
return next();
});
}]
}, function (err){
if (err) { return cb(err); }
// SUCCESS!
cb.log.info('Created a new Sails app `' + scope.appName + '`!');
// Warn that user needs to run `npm install`:
if (nonFatalErrorsWhenCreatingSymlinks.length > 0) {
cb.log.warn('Could not create symbolic links in the newly generated `node_modules` folder');
cb.log.warn('(usually this is due to a permission issue on your filesystem)');
cb.log.warn('Before you run your new app, `cd` into the directory and run:');
cb.log.warn('$ rm -rf node_modules/ && npm install');
}
return cb();
});//</async.auto :: link deps (i.e. for npm <=v2 or if `link` flag is enabled)>
return;
}//</if this is npm <= v2>
// ███╗ ██╗██████╗ ███╗ ███╗ ██╗ ██╗██████╗
// ████╗ ██║██╔══██╗████╗ ████║ ██║ ██║╚════██╗
// ██╔██╗ ██║██████╔╝██╔████╔██║ ██║ ██║ █████╔╝
// ██║╚██╗██║██╔═══╝ ██║╚██╔╝██║ ╚██╗ ██╔╝ ╚═══██╗
// ██║ ╚████║██║ ██║ ╚═╝ ██║ ╚████╔╝ ██████╔╝
// ╚═╝ ╚═══╝╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚═════╝
// ┌─ ┌┐┌┌─┐┬─┐┌┬┐┌─┐┬ ┌─┐┌─┐┌┐┌ ┬ ┬┬┌┬┐┬ ┬┌─┐┬ ┬┌┬┐ ╦ ╦╔╗╔╦╔═ ┌─┐┬ ┌─┐┌─┐ ─┐
// │─── ││││ │├┬┘│││├─┤│ │ ┬├┤ │││ ││││ │ ├─┤│ ││ │ │ ║ ║║║║╠╩╗ ├┤ │ ├─┤│ ┬ ───│
// └─ ┘└┘└─┘┴└─┴ ┴┴ ┴┴─┘ └─┘└─┘┘└┘┘ └┴┘┴ ┴ ┴ ┴└─┘└─┘ ┴ ╩═╝╩╝╚╝╩ ╩ └ ┴─┘┴ ┴└─┘ ─┘
//
// --•
// Otherwise, this is a normal install on NPM v3... so, unfortunately, we'll
// have to actually `npm install` some of the dependencies again locally.
// Luckily, we can still at least symlink the `sails` dependency. But we can't
// safely symlink the others, at least not yet.
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// > If you work on NPM, or if you've dealt with this problem before and have
// > feedback on how to make `sails new` run faster on NPM v3, PLEASE let someone
// > from the core team know- we could use your help!
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
async.auto({
// Create the node_modules folder
create_node_modules: function create_node_modules(proceed) {
fsx.mkdir(path.resolve(scope.rootPath, './node_modules'), proceed);
},
// Create a link to the sails we used to create the app
create_sails_link: ['create_node_modules', function create_sails_link(results, proceed) {
fsx.symlink(scope.sailsRoot, path.resolve(scope.rootPath, './node_modules/sails'), 'junction', function (symLinkErr) {
// If a symbolic link fails, push it to the `nonFatalErrorsWhenCreatingSymlinks` stack,
if (symLinkErr) {
nonFatalErrorsWhenCreatingSymlinks.push(symLinkErr);
}
// but keep going either way.
return proceed();
});
}],
// Install other dependencies with NPM
install_other_deps: ['create_sails_link', function (results, proceed) {
console.log(
'=====================================================\n'+
'You seem to be using NPM >= v3.0.0, which no longer\n'+
'supports symbolic links in the `node_modules/` folder.\n'+
'\n'+
'Because of this, creating your new Sails app will\n'+
'take longer than you might be used to. Please bear\n'+
'with us; or if you have a need for speed, downgrade\n'+
'to NPM v2 in the mean time. Thanks!\n'+
'\n'+
'For more info about downgrading to NPM v2, see:\n'+
'https://github.com/npm/npm/issues/10214\n'+
'====================================================='+
'\n'+
'Installing dependencies... (this could take a little while)'
);
var npmInstall = spawn('npm', ['install'], {cwd: scope.rootPath, stdio: 'inherit'});
npmInstall.on('close', proceed);
}]
}, function (err) {
if (err) { return cb(err); }
// SUCCESS!
cb.log.info('Created a new Sails app `' + scope.appName + '`!');
// Warn that user needs to run `npm install`:
if (nonFatalErrorsWhenCreatingSymlinks.length > 0) {
cb.log.warn('Could not create symbolic links in the newly generated `node_modules` folder');
cb.log.warn('(usually this is due to a permission issue on your filesystem)');
cb.log.warn('Before you run your new app, `cd` into the directory and run:');
cb.log.warn('$ rm -rf node_modules/ && npm install');
}
return cb();
});//</async.auto :: install deps for npm 3>
});//</child_process.exec :: `npm -v`)>
};