1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | const path = require("path");
|
19 | const rimraf = require("rimraf");
|
20 | const events = require("events");
|
21 | const mkdirp = require("mkdirp");
|
22 | const common_1 = require("./utils/common");
|
23 | const ui_1 = require("./utils/ui");
|
24 | const config_1 = require("./config");
|
25 | const registry_manager_1 = require("./install/registry-manager");
|
26 | const cache_1 = require("./utils/cache");
|
27 | const global_config_file_1 = require("./config/global-config-file");
|
28 | const fetch_1 = require("./install/fetch");
|
29 | const cjs_convert_1 = require("./compile/cjs-convert");
|
30 |
|
31 | const install_1 = require("./install");
|
32 | const run_cmd_1 = require("./utils/run-cmd");
|
33 | const api_1 = require("./api");
|
34 |
|
35 | let hasGit = true;
|
36 | try {
|
37 | require('which').sync('git');
|
38 | }
|
39 | catch (e) {
|
40 | hasGit = false;
|
41 | }
|
42 | function applyDefaultConfiguration(userConfig) {
|
43 | const config = Object.assign({}, userConfig);
|
44 | if (!config.registries) {
|
45 | const registriesGlobalConfig = global_config_file_1.default.get('registries') || {};
|
46 | const registries = {};
|
47 | Object.keys(registriesGlobalConfig).forEach((registryName) => {
|
48 | const registry = registriesGlobalConfig[registryName];
|
49 | if (registry.handler === 'jspm-npm' || registry.handler === 'jspm-github')
|
50 | registry.handler = undefined;
|
51 | registries[registryName] = {
|
52 | handler: registry.handler || `@jspm/${registryName}`,
|
53 | config: registry
|
54 | };
|
55 | });
|
56 | config.registries = registries;
|
57 | }
|
58 | if (!config.defaultRegistry) {
|
59 | let defaultRegistry = global_config_file_1.default.get('defaultRegistry');
|
60 | if (!defaultRegistry || defaultRegistry === 'jspm')
|
61 | defaultRegistry = 'npm';
|
62 | config.defaultRegistry = defaultRegistry;
|
63 | }
|
64 | if ('offline' in config === false)
|
65 | config.offline = false;
|
66 | if ('preferOffline' in config === false)
|
67 | config.preferOffline = global_config_file_1.default.get('preferOffline') || false;
|
68 | if ('cli' in config === false)
|
69 | config.cli = true;
|
70 | if ('timeouts' in config === false)
|
71 | config.timeouts = {
|
72 | resolve: global_config_file_1.default.get('timeouts.resolve') || 30000,
|
73 | download: global_config_file_1.default.get('timeouts.download') || 300000
|
74 | };
|
75 | if ('userInput' in config === false)
|
76 | config.userInput = true;
|
77 | if ('cacheDir' in config === false)
|
78 | config.cacheDir = common_1.JSPM_CACHE_DIR;
|
79 | if ('strictSSL' in config === false)
|
80 | config.strictSSL = global_config_file_1.default.get('strictSSL');
|
81 | return config;
|
82 | }
|
83 | class Project {
|
84 | constructor(projectPath, options) {
|
85 | this.projectPath = projectPath;
|
86 | if (!hasGit)
|
87 | throw new common_1.JspmUserError(`${common_1.bold('git')} is not installed in path. You can install git from http://git-scm.com/downloads.`);
|
88 | const config = applyDefaultConfiguration(options);
|
89 |
|
90 | this.cli = config.cli;
|
91 | this.log = this.cli ? new CLILogger() : new APILogger();
|
92 | if (projectPath === api_1.JSPM_GLOBAL_PATH)
|
93 | this.checkGlobalBin();
|
94 |
|
95 |
|
96 | this.defaultRegistry = config.defaultRegistry;
|
97 |
|
98 | this.defaultRegistry = 'npm';
|
99 | mkdirp.sync(projectPath);
|
100 | this.config = new config_1.default(projectPath, this);
|
101 | this.globalConfig = global_config_file_1.default;
|
102 | this.confirm = this.cli ? ui_1.confirm : (_msg, def) => Promise.resolve(typeof def === 'boolean' ? def : undefined);
|
103 | this.input = this.cli ? ui_1.input : (_msg, def) => Promise.resolve(typeof def === 'string' ? def : undefined);
|
104 | this.userInput = config.userInput;
|
105 | this.offline = config.offline;
|
106 | this.preferOffline = config.preferOffline;
|
107 | this.cacheDir = config.cacheDir;
|
108 | this.fetch = new fetch_1.default(this);
|
109 | this.registryManager = new registry_manager_1.default({
|
110 | cacheDir: this.cacheDir,
|
111 | defaultRegistry: this.defaultRegistry,
|
112 | Cache: cache_1.default,
|
113 | timeouts: {
|
114 | resolve: config.timeouts.resolve,
|
115 | download: config.timeouts.download
|
116 | },
|
117 | offline: this.offline,
|
118 | preferOffline: this.preferOffline,
|
119 | userInput: this.userInput,
|
120 | strictSSL: config.strictSSL,
|
121 | log: this.log,
|
122 | confirm: this.confirm,
|
123 | input: this.input,
|
124 | fetch: this.fetch,
|
125 | registries: config.registries
|
126 | });
|
127 |
|
128 |
|
129 | this.registryManager.loadEndpoints();
|
130 | cjs_convert_1.init();
|
131 | this.installer = new install_1.Installer(this);
|
132 | }
|
133 | checkGlobalBin() {
|
134 | if (this.checkedGlobalBin)
|
135 | return;
|
136 | const globalBin = path.join(api_1.JSPM_GLOBAL_PATH, 'jspm_packages', '.bin');
|
137 | if (process.env[common_1.PATH].indexOf(globalBin) === -1)
|
138 | this.log.warn(`The global jspm bin folder ${common_1.highlight(globalBin)} is not currently in your PATH, add this for native jspm bin support.`);
|
139 | this.checkedGlobalBin = true;
|
140 | }
|
141 | dispose() {
|
142 | return Promise.all([
|
143 | this.config.dispose(),
|
144 | this.registryManager.dispose(),
|
145 | cjs_convert_1.dispose()
|
146 | ]);
|
147 | }
|
148 | async save() {
|
149 | return await this.config.save();
|
150 | }
|
151 | |
152 |
|
153 |
|
154 | async update(selectors, opts) {
|
155 | const taskEnd = this.log.taskStart('Updating...');
|
156 | try {
|
157 | var changed = await this.installer.update(selectors, opts);
|
158 | }
|
159 | finally {
|
160 | taskEnd();
|
161 | }
|
162 |
|
163 | if (changed)
|
164 | this.log.ok('Update complete.');
|
165 | else
|
166 | this.log.ok('Already up to date.');
|
167 | }
|
168 | async install(installs, opts = {}) {
|
169 | const taskEnd = this.log.taskStart('Installing...');
|
170 | try {
|
171 | await runHook(this, 'preinstall');
|
172 | if (installs.length === 0) {
|
173 | opts.lock = true;
|
174 | if (opts.latest) {
|
175 | opts.latest = false;
|
176 | this.log.warn(`${common_1.bold('--latest')} flag does not apply to package lock install.`);
|
177 | }
|
178 | }
|
179 | var changed = await this.installer.install(installs, opts);
|
180 | await runHook(this, 'postinstall');
|
181 | }
|
182 | finally {
|
183 | taskEnd();
|
184 | }
|
185 |
|
186 | if (changed)
|
187 | this.log.ok('Install complete.');
|
188 | else
|
189 | this.log.ok('Already installed.');
|
190 | }
|
191 | async uninstall(names) {
|
192 | const taskEnd = this.log.taskStart('Uninstalling...');
|
193 | try {
|
194 | await this.installer.uninstall(names);
|
195 | }
|
196 | finally {
|
197 | taskEnd();
|
198 | }
|
199 | this.log.ok('Uninstalled successfully.');
|
200 | }
|
201 | async checkout(names) {
|
202 | const taskEnd = this.log.taskStart('Checking out...');
|
203 | try {
|
204 | await this.installer.checkout(names);
|
205 | }
|
206 | finally {
|
207 | taskEnd();
|
208 | }
|
209 | }
|
210 | async link(pkg, source, opts) {
|
211 | const taskEnd = this.log.taskStart('Linking...');
|
212 | try {
|
213 | await runHook(this, 'preinstall');
|
214 | var changed = await this.installer.link(pkg, source, opts);
|
215 | await runHook(this, 'postinstall');
|
216 | }
|
217 | finally {
|
218 | taskEnd();
|
219 | }
|
220 | if (changed)
|
221 | this.log.ok('Linked Successfully.');
|
222 | else
|
223 | this.log.ok('Already linked.');
|
224 | }
|
225 | async clean() {
|
226 | const taskEnd = this.log.taskStart('Cleaning...');
|
227 | try {
|
228 | await this.installer.clean(true);
|
229 | }
|
230 | finally {
|
231 | taskEnd();
|
232 | }
|
233 | this.log.ok('Project cleaned successfully.');
|
234 | }
|
235 | |
236 |
|
237 |
|
238 |
|
239 |
|
240 |
|
241 |
|
242 |
|
243 |
|
244 |
|
245 |
|
246 |
|
247 |
|
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 |
|
254 | async init(basePath) {
|
255 | if (basePath)
|
256 | process.env.jspmConfigPath = path.resolve(basePath, 'package.json');
|
257 | let relBase = path.relative(process.cwd(), path.dirname(process.env.jspmConfigPath || ''));
|
258 | if (relBase !== '')
|
259 | this.log.msg(`Initializing package at ${common_1.highlight(relBase)}\nUse ${common_1.bold(`jspm init .`)} to intialize into the current folder.`);
|
260 | |
261 |
|
262 |
|
263 |
|
264 |
|
265 |
|
266 |
|
267 |
|
268 |
|
269 | }
|
270 | async registryConfig(name) {
|
271 | return this.registryManager.configure(name);
|
272 | }
|
273 | async clearCache() {
|
274 | await new Promise((resolve, reject) => rimraf(this.cacheDir, err => err ? reject(err) : resolve()));
|
275 | this.log.warn(`Global cache cleared. ${common_1.underline(`All jspm projects for this system user will now have broken symlinks due to the shared global package cache.`)}`);
|
276 | this.log.info(`${common_1.bold(`jspm install <packageName> -f`)} is equivalent to running a cache clear for that specific install tree.`);
|
277 | this.log.info(`Please post an issue if you suspect the cache isn't invalidating properly.`);
|
278 | }
|
279 | async run(name, args) {
|
280 | const scripts = this.config.pjson.scripts;
|
281 | const script = scripts[name];
|
282 | if (!script)
|
283 | throw new common_1.JspmUserError(`No package.json ${common_1.highlight('"scripts"')} entry for command ${common_1.bold(name)}`);
|
284 | const doPrePost = !name.startsWith('pre') && !name.startsWith('post');
|
285 | const cmds = [];
|
286 | if (doPrePost) {
|
287 | const pre = scripts[`pre${name}`];
|
288 | if (pre)
|
289 | cmds.push(pre);
|
290 | cmds.push(script);
|
291 | const post = scripts[`post${name}`];
|
292 | if (post)
|
293 | cmds.push(post);
|
294 | }
|
295 | else {
|
296 | cmds.push(script);
|
297 | }
|
298 |
|
299 | this.config.dispose();
|
300 | this.config = undefined;
|
301 | let exitCode = 0;
|
302 | await Promise.all(cmds.map(async (cmd) => {
|
303 | if (args.length)
|
304 | cmd += joinArgs(args);
|
305 | cmd = cmd.replace('npm ', 'jspm ');
|
306 | const cmdCode = await run_cmd_1.runCmd(cmd, this.projectPath);
|
307 | if (cmdCode !== 0)
|
308 | exitCode = cmdCode;
|
309 | }));
|
310 | return exitCode;
|
311 | }
|
312 | }
|
313 | exports.Project = Project;
|
314 | const dblQuoteRegEx = /"/g;
|
315 | function joinArgs(args) {
|
316 | return args.reduce((str, arg) => `${str} "${arg.replace(dblQuoteRegEx, '\\"')}"`, '');
|
317 | }
|
318 | async function runHook(project, name) {
|
319 | var hooks = project.config.pjson.hooks;
|
320 | if (!hooks || !hooks[name])
|
321 | return;
|
322 | try {
|
323 | let m = require(hooks[name]);
|
324 | if (!m.default || typeof m.default !== 'function')
|
325 | throw new Error(`Hook ${common_1.bold(name)} doesn't contain a default export hook function.`);
|
326 | await m.default();
|
327 | }
|
328 | catch (e) {
|
329 | project.log.err(`Error running ${common_1.bold(name)} hook.`);
|
330 | project.log.err(e.stack || e);
|
331 | }
|
332 | }
|
333 | exports.runHook = runHook;
|
334 | class APILogger extends events.EventEmitter {
|
335 | newline() { }
|
336 | msg(msg) {
|
337 | this.emit('msg', msg);
|
338 | }
|
339 | errMsg(msg) {
|
340 | this.emit('errMsg', msg);
|
341 | }
|
342 | err(msg) {
|
343 | this.emit('err', msg);
|
344 | }
|
345 | debug(msg) {
|
346 | this.emit('debug', msg);
|
347 | }
|
348 | info(msg) {
|
349 | this.emit('info', msg);
|
350 | }
|
351 | warn(msg) {
|
352 | this.emit('warn', msg);
|
353 | }
|
354 | ok(msg) {
|
355 | this.emit('ok', msg);
|
356 | }
|
357 | taskStart(name) {
|
358 | this.emit('taskStart', name);
|
359 | return () => this.taskEnd(name);
|
360 | }
|
361 | taskEnd(name) {
|
362 | this.emit('taskEnd', name);
|
363 | }
|
364 | }
|
365 | ;
|
366 | class CLILogger {
|
367 | constructor() {
|
368 | this.tasks = [];
|
369 | this.lastTask = undefined;
|
370 | }
|
371 | newline() {
|
372 | ui_1.log('');
|
373 | }
|
374 | msg(msg) {
|
375 | ui_1.log(msg);
|
376 | }
|
377 | errMsg(msg) {
|
378 | if (msg instanceof Error) {
|
379 | if (msg.hideStack)
|
380 | msg = msg.message;
|
381 | else
|
382 | msg = msg.stack || msg && msg.toString();
|
383 | }
|
384 | ui_1.logErr(msg);
|
385 | }
|
386 | err(msg) {
|
387 | if (msg instanceof Error) {
|
388 | if (msg.hideStack)
|
389 | msg = msg.message;
|
390 | else
|
391 | msg = msg.stack || msg && msg.toString();
|
392 | }
|
393 | ui_1.log(msg, ui_1.LogType.err);
|
394 | }
|
395 | debug(msg) {
|
396 | ui_1.log(msg, ui_1.LogType.debug);
|
397 | }
|
398 | info(msg) {
|
399 | ui_1.log(msg, ui_1.LogType.info);
|
400 | }
|
401 | warn(msg) {
|
402 | ui_1.log(msg, ui_1.LogType.warn);
|
403 | }
|
404 | ok(msg) {
|
405 | ui_1.log(msg, ui_1.LogType.ok);
|
406 | }
|
407 | taskStart(name) {
|
408 | this.tasks.push(name);
|
409 | ui_1.log(this.tasks[this.tasks.length - 1], ui_1.LogType.status);
|
410 | if (this.tasks.length === 1)
|
411 | ui_1.startSpinner();
|
412 |
|
413 | if (ui_1.logLevel === ui_1.LogType.debug && this.lastTask)
|
414 | ui_1.log(this.lastTask, ui_1.LogType.debug);
|
415 | this.lastTask = name;
|
416 | return this.taskEnd.bind(this, name);
|
417 | }
|
418 | taskEnd(name) {
|
419 | const taskIndex = this.tasks.indexOf(name);
|
420 | if (taskIndex === -1)
|
421 | return;
|
422 | this.tasks.splice(taskIndex, 1);
|
423 | if (this.tasks.length)
|
424 | ui_1.log(this.tasks[this.tasks.length - 1], ui_1.LogType.status);
|
425 | else
|
426 | ui_1.stopSpinner();
|
427 | if (ui_1.logLevel === ui_1.LogType.debug && this.lastTask && this.lastTask !== this.tasks[this.tasks.length - 1]) {
|
428 | ui_1.log(this.lastTask, ui_1.LogType.debug);
|
429 | this.lastTask = undefined;
|
430 | }
|
431 | }
|
432 | }
|
433 | ;
|
434 |
|
\ | No newline at end of file |