1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | require('core-js/es6/string');
|
18 |
|
19 | var request = require('request');
|
20 | var ui = require('./ui');
|
21 | var semver = require('./semver');
|
22 | var asp = require('bluebird').Promise.promisify;
|
23 | var config = require('./config');
|
24 | var mkdirp = require('mkdirp');
|
25 | var rimraf = require('rimraf');
|
26 | var path = require('path');
|
27 | var registry = require('./registry');
|
28 | var PackageName = require('./package-name');
|
29 | var globalConfig = require('./config/global-config');
|
30 | var readJSON = require('./common').readJSON;
|
31 | var ncp = require('ncp');
|
32 | var fs = require('graceful-fs');
|
33 | var glob = require('glob');
|
34 | var minimatch = require('minimatch');
|
35 | var md5 = require('./common').md5;
|
36 | var processDeps = require('./common').processDeps;
|
37 | var extend = require('./common').extend;
|
38 | var HOME = require('./common').HOME;
|
39 | var Promise = require('bluebird');
|
40 | var newLine = require('./common').newLine;
|
41 |
|
42 | var jspmVersion = require('../package.json').version.split('.').splice(0, 2).join('.');
|
43 |
|
44 |
|
45 | var registryCache = exports.registryCache = {};
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 | var locateCache = {};
|
55 |
|
56 | exports.locate = locate;
|
57 | function locate(target) {
|
58 | if (!target.registry) {
|
59 | target = new PackageName(target.exactName);
|
60 | target.setRegistry(globalConfig.config.defaultRegistry);
|
61 | }
|
62 |
|
63 | var endpoint = registry.load(target.registry);
|
64 |
|
65 | if (!endpoint.locate)
|
66 | return Promise.resolve(target);
|
67 |
|
68 | locateCache[target.registry] = locateCache[target.registry] || {};
|
69 |
|
70 |
|
71 | return Promise.resolve()
|
72 | .then(function() {
|
73 | if (locateCache[target.registry][target.package])
|
74 | return locateCache[target.registry][target.package];
|
75 |
|
76 | return (locateCache[target.registry][target.package] = Promise.resolve(endpoint.locate(target.package))
|
77 | .then(function(located) {
|
78 |
|
79 | if (target.registry === globalConfig.config.defaultRegistry)
|
80 | registryCache[target.package] = located.redirect;
|
81 | return located;
|
82 | }));
|
83 | })
|
84 | .then(function(located) {
|
85 | if (!located)
|
86 | return target;
|
87 |
|
88 | if (located.redirect) {
|
89 | var redirectPkg = new PackageName(located.redirect);
|
90 |
|
91 |
|
92 |
|
93 | target.setRegistry(redirectPkg.registry);
|
94 | target.setPackage(redirectPkg.package);
|
95 |
|
96 | return locate(target);
|
97 | }
|
98 |
|
99 | if (located.notfound)
|
100 | throw 'Repo `' + target.name + '` not found.' +
|
101 | (target.registry != 'npm' && target.package.split('/').length == 1 ? ' Perhaps try %jspm install npm:' + target.package + '%.' : '');
|
102 |
|
103 | throw 'Invalid registry locate response for %' + target.registry + '%';
|
104 | }, function(e) {
|
105 | if (e)
|
106 | ui.log('err', e.stack || e);
|
107 | throw 'Error locating `' + target.name + '`.';
|
108 | });
|
109 | }
|
110 |
|
111 | var lookupPromises = {};
|
112 | var lookups = {};
|
113 |
|
114 | exports.lookup = lookup;
|
115 | function lookup(pkg, edge) {
|
116 | return Promise.resolve()
|
117 |
|
118 | .then(function() {
|
119 |
|
120 | if (lookups[pkg.name])
|
121 | return { versions: lookups[pkg.name] };
|
122 |
|
123 |
|
124 | if (lookupPromises[pkg.name])
|
125 | return lookupPromises[pkg.name];
|
126 |
|
127 | ui.log('debug', 'Looking up `' + pkg.name + '`');
|
128 | return (lookupPromises[pkg.name] = Promise.resolve(registry.load(pkg.registry).lookup(pkg.package)));
|
129 | })
|
130 | .then(function(lookup) {
|
131 | if (lookup.notfound)
|
132 | throw 'Repo `' + pkg.name + '` not found!';
|
133 |
|
134 | if (!lookup.versions)
|
135 | throw 'Invalid registry lookup response for %' + pkg.registry + '%';
|
136 |
|
137 | lookups[pkg.name] = lookup.versions;
|
138 |
|
139 | return function(version) {
|
140 | var opts = {edge: edge, latestVersion: lookup.latest};
|
141 | var lookupObj = getVersionMatch(version, lookup.versions, opts);
|
142 | if (!lookupObj)
|
143 | return;
|
144 |
|
145 | return new PackageName(pkg.name + '@' + lookupObj.version);
|
146 | };
|
147 | }, function(e) {
|
148 | if (e)
|
149 | ui.log('err', e.stack || e);
|
150 |
|
151 | throw 'Error looking up `' + pkg.name + '`.';
|
152 | });
|
153 | }
|
154 |
|
155 |
|
156 | exports.getVersionMatch = getVersionMatch;
|
157 | function getVersionMatch(pkgVersion, versions, options) {
|
158 |
|
159 | if (pkgVersion)
|
160 | pkgVersion = decodeURIComponent(pkgVersion);
|
161 |
|
162 | if (versions[pkgVersion]) {
|
163 | versions[pkgVersion].version = pkgVersion;
|
164 | return versions[pkgVersion];
|
165 | }
|
166 |
|
167 | var version;
|
168 | var stableSemver = [];
|
169 | var unstableSemver = [];
|
170 | var stableExact = [];
|
171 | var unstableExact = [];
|
172 | var edge = options && options.edge;
|
173 |
|
174 | Object.keys(versions).forEach(function(v) {
|
175 | version = versions[v];
|
176 | var stable = version.stable;
|
177 | var semverMatch = v.match(semver.semverRegEx);
|
178 | var valid = semverMatch && semverMatch[1] && semverMatch[2] && semverMatch[3];
|
179 | var pre = valid && semverMatch[4];
|
180 |
|
181 |
|
182 | version.version = v;
|
183 |
|
184 |
|
185 | if (!valid) {
|
186 |
|
187 | if (stable && !edge)
|
188 | stableExact.push(v);
|
189 | else
|
190 | unstableExact.push(v);
|
191 | }
|
192 |
|
193 |
|
194 | else if (!edge && (stable === false || (stable !== true && pre)))
|
195 | unstableSemver.push(v);
|
196 | else
|
197 | stableSemver.push(v);
|
198 | });
|
199 |
|
200 | function compareDesc(a, b) {
|
201 | return semver.compare(b, a);
|
202 | }
|
203 |
|
204 | if (!pkgVersion) {
|
205 | var latest = options && options.latestVersion && versions[options.latestVersion];
|
206 | if (!edge && latest)
|
207 | return latest;
|
208 | stableSemver.sort(compareDesc);
|
209 |
|
210 | if (stableSemver[0])
|
211 | return versions[stableSemver[0]];
|
212 |
|
213 | unstableSemver.sort(compareDesc);
|
214 | if (unstableSemver[0])
|
215 | return versions[unstableSemver[0]];
|
216 |
|
217 | if (latest)
|
218 | return latest;
|
219 |
|
220 | stableExact.sort();
|
221 | if (stableExact[0])
|
222 | return versions[stableExact[0]];
|
223 |
|
224 |
|
225 | if (versions.master)
|
226 | return versions.master;
|
227 |
|
228 | unstableExact.sort();
|
229 | if (unstableExact[0])
|
230 | return versions[unstableExact[0]];
|
231 | }
|
232 | else {
|
233 | var i, ver;
|
234 | stableSemver.sort(compareDesc);
|
235 |
|
236 | for (i = 0; i < stableSemver.length; i++) {
|
237 | ver = stableSemver[i];
|
238 | var match = edge ? semver.matchUnstable : semver.match;
|
239 | if (match(pkgVersion, ver))
|
240 | return versions[ver];
|
241 | }
|
242 | unstableSemver.sort(compareDesc);
|
243 | for (i = 0; i < unstableSemver.length; i++) {
|
244 | ver = unstableSemver[i];
|
245 | if (semver.match(pkgVersion, ver))
|
246 | return versions[ver];
|
247 | }
|
248 | }
|
249 | }
|
250 |
|
251 | function getOverride(pkg, manualOverride, alreadyInstalled) {
|
252 | return Promise.resolve()
|
253 | .then(function() {
|
254 |
|
255 | var existingOverride = config.pjson.overrides[pkg.exactName];
|
256 | if (!alreadyInstalled && !existingOverride) {
|
257 | var existingOverrideVersion = Object.keys(config.pjson.overrides)
|
258 | .filter(function(overrideName) {
|
259 | return overrideName.startsWith(pkg.name + '@');
|
260 | })
|
261 | .map(function(overrideName) {
|
262 | return overrideName.split('@').pop();
|
263 | })
|
264 | .filter(function(overrideVersion) {
|
265 | return semver.match('^' + overrideVersion, pkg.version);
|
266 | })
|
267 | .sort(semver.compare).pop();
|
268 | if (existingOverrideVersion)
|
269 | existingOverride = JSON.parse(JSON.stringify(config.pjson.overrides[pkg.name + '@' + existingOverrideVersion]));
|
270 | }
|
271 |
|
272 | if ((alreadyInstalled || existingOverride) && !manualOverride)
|
273 | return Promise.resolve(config.pjson.overrides[pkg.exactName] = existingOverride || {});
|
274 |
|
275 |
|
276 | var endpoint = registry.load(globalConfig.config.defaultRegistry);
|
277 | return endpoint.getOverride(pkg.registry, pkg.package, pkg.version, manualOverride)
|
278 | .then(function(override) {
|
279 | for (var p in override)
|
280 | if (override[p] === undefined)
|
281 | delete override[p];
|
282 |
|
283 | override = override || {};
|
284 |
|
285 | config.pjson.overrides[pkg.exactName] = override;
|
286 | return override;
|
287 | });
|
288 | })
|
289 | .then(function(override) {
|
290 | var packageConfig = typeof override.systemjs == 'object' ? override.systemjs : override;
|
291 | upgradePackageConfig(packageConfig);
|
292 | return override;
|
293 | });
|
294 | }
|
295 |
|
296 | exports.upgradePackageConfig = upgradePackageConfig;
|
297 | function upgradePackageConfig(packageConfig) {
|
298 |
|
299 |
|
300 | if (packageConfig.shim) {
|
301 | packageConfig.meta = packageConfig.meta || {};
|
302 |
|
303 | for (var s in packageConfig.shim) {
|
304 |
|
305 | if (packageConfig.meta[s + '.js'])
|
306 | continue;
|
307 |
|
308 | var curShim = packageConfig.shim[s];
|
309 | var curMeta = packageConfig.meta[s + '.js'] = {};
|
310 |
|
311 | if (curShim instanceof Array) {
|
312 | curMeta.deps = curShim;
|
313 | }
|
314 | else if (typeof curShim == 'object') {
|
315 | if (curShim.deps)
|
316 | curMeta.deps = curShim.deps;
|
317 | else if (curShim.imports)
|
318 | curMeta.deps = curShim.imports;
|
319 |
|
320 | if (curShim.exports)
|
321 | curMeta.exports = curShim.exports;
|
322 | }
|
323 |
|
324 | curMeta.format = 'global';
|
325 |
|
326 | if (typeof curMeta.deps === 'string')
|
327 | curMeta.deps = [curMeta.deps];
|
328 | }
|
329 | delete packageConfig.shim;
|
330 | }
|
331 | }
|
332 |
|
333 | var injecting = {};
|
334 | exports.inject = function(pkg, depLoad) {
|
335 | if (injecting[pkg.exactName]) {
|
336 | injecting[pkg.exactName].depLoad.then(function(depMap) {
|
337 | depLoad(depMap);
|
338 | return depMap;
|
339 | });
|
340 | return injecting[pkg.exactName].promise;
|
341 | }
|
342 |
|
343 | injecting[pkg.exactName] = {};
|
344 |
|
345 | var depResolve, depReject;
|
346 | injecting[pkg.exactName].depLoad = new Promise(function(resolve, reject) {
|
347 | depResolve = resolve;
|
348 | depReject = reject;
|
349 | })
|
350 | .then(function(depMap) {
|
351 | depLoad(depMap);
|
352 | return depMap;
|
353 | });
|
354 |
|
355 | var remote = registry.load(pkg.registry).remote;
|
356 |
|
357 | if (!remote)
|
358 | throw 'Cannot inject from registry %' + pkg.registry + '% as it has no remote.';
|
359 |
|
360 |
|
361 | var url = remote + (remote.endsWith('/') ? '' : '/') + pkg.exactName.substr(pkg.exactName.indexOf(':') + 1) + '/.jspm.json';
|
362 | injecting[pkg.exactName].promise = asp(request)({
|
363 | method: 'get',
|
364 | url: url,
|
365 | rejectUnauthorized: false
|
366 | }).then(function(res) {
|
367 | if (res.statusCode !== 200)
|
368 | throw new Error('Error requesting package config for `' + pkg.exactName + '` at %' + url + '%.');
|
369 |
|
370 | try {
|
371 | return JSON.parse(res.body);
|
372 | }
|
373 | catch(e) {
|
374 | throw new Error('Unable to parse package config');
|
375 | }
|
376 | })
|
377 | .then(function(pjson) {
|
378 | depResolve(processDeps(pjson.dependencies, pjson.registry));
|
379 | return pjson;
|
380 | }, depReject);
|
381 | return injecting[pkg.exactName].promise;
|
382 | };
|
383 |
|
384 |
|
385 |
|
386 |
|
387 | var downloading = {};
|
388 |
|
389 |
|
390 |
|
391 |
|
392 | exports.download = function(pkg, options, depsCallback) {
|
393 |
|
394 | if (downloading[pkg.exactName]) {
|
395 | downloading[pkg.exactName].preloadCallbacks.push(depsCallback);
|
396 | downloading[pkg.exactName].postloadCallbacks.push(depsCallback);
|
397 | return downloading[pkg.exactName].promise;
|
398 | }
|
399 |
|
400 |
|
401 | var sentDeps = [];
|
402 | function doDepsCallback(depRanges) {
|
403 | var sendRanges = { deps: {}, peerDeps: {} };
|
404 | Object.keys(depRanges.deps).forEach(function(dep) {
|
405 | if (sentDeps.indexOf(dep) == -1)
|
406 | sendRanges.deps[dep] = depRanges.deps[dep];
|
407 | });
|
408 | Object.keys(depRanges.peerDeps).forEach(function(dep) {
|
409 | if (sentDeps.indexOf(dep) == -1)
|
410 | sendRanges.peerDeps[dep] = depRanges.peerDeps[dep];
|
411 | });
|
412 | sentDeps = sentDeps.concat(Object.keys(sendRanges.deps)).concat(Object.keys(sendRanges.peerDeps));
|
413 | depsCallback(sendRanges);
|
414 | }
|
415 |
|
416 |
|
417 |
|
418 | var preloadCallbacks = [doDepsCallback];
|
419 | var postloadCallbacks = [doDepsCallback];
|
420 | function preloadResolve(depRanges) {
|
421 | preloadCallbacks.forEach(function(cb) {
|
422 | cb(depRanges);
|
423 | });
|
424 | }
|
425 | function postloadResolve(depRanges) {
|
426 | postloadCallbacks.forEach(function(cb) {
|
427 | cb(depRanges);
|
428 | });
|
429 | }
|
430 |
|
431 | downloading[pkg.exactName] = {
|
432 | preloadCallbacks: preloadCallbacks,
|
433 | postloadCallbacks: postloadCallbacks
|
434 | };
|
435 |
|
436 |
|
437 | var downloadDir = pkg.getPath();
|
438 | var getPackageConfigError;
|
439 | var getPackageConfigPromise;
|
440 | var override;
|
441 |
|
442 | return (downloading[pkg.exactName].promise = Promise.resolve()
|
443 | .then(function() {
|
444 |
|
445 | return getOverride(pkg, options.override, options.alreadyInstalled);
|
446 | })
|
447 | .then(function(_override) {
|
448 | override = _override;
|
449 |
|
450 |
|
451 | return new Promise(function(resolve) {
|
452 | fs.exists(downloadDir, resolve);
|
453 | });
|
454 | })
|
455 | .then(function(dirExists) {
|
456 |
|
457 | if (options.quick && !options.override && dirExists)
|
458 | return true;
|
459 |
|
460 | var fullHash, cfgHash;
|
461 |
|
462 |
|
463 | return Promise.resolve()
|
464 | .then(function() {
|
465 |
|
466 | if (!lookups[pkg.name] && !options.linked)
|
467 | return lookup(pkg);
|
468 | })
|
469 | .then(function() {
|
470 | if ((!lookups[pkg.name] || !lookups[pkg.name][pkg.version]) && !options.linked)
|
471 | throw 'Unable to resolve version %' + pkg.version + '% for `' + pkg.package + '`.';
|
472 |
|
473 | return getPackageHash(downloadDir);
|
474 | })
|
475 | .then(function(hashes) {
|
476 |
|
477 |
|
478 |
|
479 | if (hashes[1]) {
|
480 | return readJSON(downloadDir + '.json')
|
481 | .then(function(pkgConfig) {
|
482 | if (computeConfigHash(pkgConfig) == hashes[1])
|
483 | return;
|
484 |
|
485 | for (var c in pkgConfig) {
|
486 | if (JSON.stringify(pkgConfig[c]) !== JSON.stringify(override[c]))
|
487 | override[c] = pkgConfig[c];
|
488 | }
|
489 |
|
490 |
|
491 |
|
492 |
|
493 | if (!override.format)
|
494 | override.format = 'detect';
|
495 | if (!override.meta)
|
496 | override.meta = {};
|
497 | if (!override.map)
|
498 | override.map = {};
|
499 |
|
500 | ui.log('ok', 'The package configuration file `' + path.relative(path.dirname(config.pjsonPath), downloadDir + '.json') +
|
501 | '` has been edited manually. To avoid overwriting the change, it has been added to the package.json overrides.');
|
502 |
|
503 | return hashes[0];
|
504 | }, function(err) {
|
505 | if (typeof err === 'string' && err.startsWith('Error parsing') || err.code == 'ENOENT')
|
506 | return null;
|
507 | throw err;
|
508 | });
|
509 | }
|
510 |
|
511 | return hashes[0];
|
512 | })
|
513 | .then(function(pkgHash) {
|
514 | if (options.force)
|
515 | return false;
|
516 |
|
517 | fullHash = computePackageHash(pkg, override);
|
518 |
|
519 | return pkgHash === fullHash;
|
520 | })
|
521 | .then(function(fresh) {
|
522 | if (fresh && config[pkg.exactName]) {
|
523 |
|
524 | preloadResolve(config.deps[pkg.exactName]);
|
525 | return true;
|
526 | }
|
527 |
|
528 |
|
529 | delete config.deps[pkg.exactName];
|
530 |
|
531 |
|
532 | if (options.linked && !options.unlink) {
|
533 | ui.log('info', 'Processing linked package `' + pkg.exactName + '`');
|
534 |
|
535 | return Promise.resolve(readJSON(path.resolve(downloadDir, 'package.json')))
|
536 | .then(function(packageConfig) {
|
537 | return derivePackageConfig(pkg, packageConfig, override);
|
538 | })
|
539 | .then(function(packageConfig) {
|
540 | return processPackage(pkg, downloadDir, packageConfig, options.linked);
|
541 | }, function(err) {
|
542 | if (err)
|
543 | ui.log('err', err && err.stack || err);
|
544 | throw 'Error processing linked package `' + pkg.exactName + '`.';
|
545 | })
|
546 | .then(function(packageConfig) {
|
547 | return createLoaderConfig(pkg, packageConfig, downloadDir)
|
548 | .then(function() {
|
549 | postloadResolve(getDepRanges(pkg, packageConfig));
|
550 | });
|
551 | })
|
552 | .then(function() {
|
553 | return false;
|
554 | });
|
555 | }
|
556 |
|
557 | if (pkg.registry == 'local')
|
558 | throw '`' + pkg.exactName + '` must be linked to be used in installs.';
|
559 |
|
560 | var cacheDir = pkg.getPath(path.resolve(HOME, '.jspm', 'packages'));
|
561 |
|
562 |
|
563 | return Promise.resolve()
|
564 | .then(function() {
|
565 | if (config.force)
|
566 | return false;
|
567 |
|
568 | return getPackageHash(cacheDir)
|
569 | .then(function(hashes) {
|
570 | return hashes[0] && hashes[0] === fullHash;
|
571 | });
|
572 | })
|
573 | .then(function(cacheFresh) {
|
574 |
|
575 |
|
576 | if (cacheFresh)
|
577 | return readJSON(cacheDir + '.deps.json')
|
578 | .then(function(depJSON) {
|
579 | var depRanges = getDepRanges(pkg, depJSON);
|
580 | if (!depRanges.deps)
|
581 | throw new TypeError('Invalid deps format!');
|
582 | preloadResolve(depRanges);
|
583 | return null;
|
584 | });
|
585 |
|
586 | ui.log('info', 'Downloading `' + pkg.exactName + '`');
|
587 |
|
588 | var endpoint = registry.load(pkg.registry);
|
589 | var lookupObj = lookups[pkg.name][pkg.version];
|
590 |
|
591 | getPackageConfigPromise = Promise.resolve()
|
592 | .then(function() {
|
593 | if (endpoint.getPackageConfig)
|
594 | return endpoint.getPackageConfig(pkg.package, pkg.version, lookupObj.hash, lookupObj.meta);
|
595 | })
|
596 | .then(function(packageConfig) {
|
597 | if (!packageConfig)
|
598 | return;
|
599 | return derivePackageConfig(pkg, packageConfig, override)
|
600 | .then(function(packageConfig) {
|
601 | preloadResolve(getDepRanges(pkg, packageConfig));
|
602 | return packageConfig;
|
603 | });
|
604 | })
|
605 | .catch(function(err) {
|
606 | getPackageConfigError = err;
|
607 | });
|
608 |
|
609 | return Promise.resolve(cacheDir)
|
610 |
|
611 | .then(asp(mkdirp))
|
612 |
|
613 | .then(function() {
|
614 | return asp(rimraf)(cacheDir);
|
615 | })
|
616 | .then(function() {
|
617 | try {
|
618 | fs.unlinkSync(cacheDir + '.js');
|
619 | }
|
620 | catch(e) {}
|
621 | })
|
622 |
|
623 | .then(function() {
|
624 | return asp(mkdirp)(cacheDir);
|
625 | })
|
626 |
|
627 | .then(function() {
|
628 | return endpoint.download(pkg.package, pkg.version, lookupObj.hash, lookupObj.meta, cacheDir);
|
629 | })
|
630 |
|
631 |
|
632 | .then(function(downloadPackageConfig) {
|
633 | if (getPackageConfigError)
|
634 | return Promise.reject(getPackageConfigError);
|
635 |
|
636 | return getPackageConfigPromise
|
637 | .then(function(packageConfig) {
|
638 |
|
639 | if (packageConfig)
|
640 | return packageConfig;
|
641 |
|
642 |
|
643 | return Promise.resolve(downloadPackageConfig || readJSON(path.resolve(cacheDir, 'package.json')))
|
644 | .then(function(packageConfig) {
|
645 | return derivePackageConfig(pkg, packageConfig, override)
|
646 | .then(function(packageConfig) {
|
647 | preloadResolve(getDepRanges(pkg, packageConfig));
|
648 | return packageConfig;
|
649 | });
|
650 | });
|
651 | });
|
652 | })
|
653 | .then(function(packageConfig) {
|
654 |
|
655 | fullHash = computePackageHash(pkg, override);
|
656 | return processPackage(pkg, cacheDir, packageConfig);
|
657 | })
|
658 |
|
659 | .then(function(packageConfig) {
|
660 | return createLoaderConfig(pkg, packageConfig, cacheDir)
|
661 | .then(function(loaderConfig) {
|
662 | cfgHash = computeConfigHash(loaderConfig);
|
663 | return packageConfig;
|
664 | });
|
665 | })
|
666 |
|
667 | .then(function(packageConfig) {
|
668 | var depRanges = getDepRanges(pkg, packageConfig);
|
669 | var rangeMap = { dependencies: {}, peerDependencies: {} };
|
670 | Object.keys(depRanges.deps).forEach(function(dep) {
|
671 | rangeMap.dependencies[dep] = depRanges.deps[dep].exactName;
|
672 | });
|
673 | Object.keys(depRanges.peerDeps).forEach(function(dep) {
|
674 | rangeMap.peerDependencies[dep] = depRanges.peerDeps[dep].exactName;
|
675 | });
|
676 | fs.writeFileSync(cacheDir + '.deps.json', JSON.stringify(rangeMap, null, 2));
|
677 | fs.writeFileSync(path.resolve(cacheDir, '.jspm-hash'), fullHash + newLine + cfgHash);
|
678 |
|
679 |
|
680 | postloadResolve(depRanges);
|
681 | return null;
|
682 | });
|
683 | })
|
684 |
|
685 |
|
686 |
|
687 | .then(function() {
|
688 |
|
689 | try {
|
690 | fs.unlinkSync(downloadDir);
|
691 | }
|
692 | catch(e) {
|
693 | if (e.code === 'EISDIR' || e.code === 'EPERM' || e.code === 'ENOENT')
|
694 | return;
|
695 | throw e;
|
696 | }
|
697 | })
|
698 | .then(function() {
|
699 | return asp(mkdirp)(downloadDir);
|
700 | })
|
701 | .then(function() {
|
702 | return asp(rimraf)(downloadDir);
|
703 | })
|
704 | .then(function() {
|
705 | return asp(ncp)(cacheDir, downloadDir);
|
706 | })
|
707 | .then(function() {
|
708 |
|
709 | return asp(ncp)(cacheDir + '.json', downloadDir + '.json');
|
710 | })
|
711 | .then(function() {
|
712 |
|
713 | return asp(fs.utimes)(path.resolve(downloadDir, '.jspm-hash'), new Date() / 1000, new Date() / 1000);
|
714 | })
|
715 | .then(function() {
|
716 | return fresh;
|
717 | });
|
718 | });
|
719 | }));
|
720 | };
|
721 |
|
722 | function getPackageHash(dir) {
|
723 | return new Promise(function(resolve) {
|
724 | fs.exists(dir + '.json', function(exists) {
|
725 | resolve(exists);
|
726 | });
|
727 | })
|
728 | .then(function(hasConfig) {
|
729 | if (!hasConfig)
|
730 | return [];
|
731 |
|
732 |
|
733 | return asp(fs.readFile)(path.resolve(dir, '.jspm-hash'))
|
734 | .then(function(hash) {
|
735 | return hash.toString().split(/\n|\r/);
|
736 | }, function(err) {
|
737 | if (err.code === 'ENOENT')
|
738 | return [];
|
739 | throw err;
|
740 | });
|
741 | });
|
742 | }
|
743 |
|
744 | function computePackageHash(pkg, override) {
|
745 |
|
746 | var hash = lookups[pkg.name] && lookups[pkg.name][pkg.version].hash || 'link';
|
747 | var endpoint = registry.load(pkg.registry);
|
748 |
|
749 | return hash + md5(JSON.stringify(override)) + endpoint.versionString + 'jspm@' + jspmVersion;
|
750 | }
|
751 |
|
752 | function computeConfigHash(pkgConfig) {
|
753 | return md5(JSON.stringify(pkgConfig));
|
754 | }
|
755 |
|
756 |
|
757 |
|
758 |
|
759 |
|
760 |
|
761 | function getDepRanges(pkg, packageConfig) {
|
762 | var depRanges = config.deps[pkg.exactName] = config.deps[pkg.exactName] || { deps: {}, peerDeps: {} };
|
763 |
|
764 | var mainDepRanges = processDeps(packageConfig.dependencies, packageConfig.registry, pkg.exactName);
|
765 | var peerDepRanges = processDeps(packageConfig.peerDependencies, packageConfig.registry, pkg.exactName);
|
766 |
|
767 |
|
768 |
|
769 |
|
770 | var optionalDepRanges = processDeps(packageConfig.optionalDependencies, packageConfig.registry, pkg.exactName);
|
771 | Object.keys(optionalDepRanges).forEach(function(dep) {
|
772 | if (!peerDepRanges[dep])
|
773 | peerDepRanges[dep] = optionalDepRanges[dep];
|
774 | });
|
775 |
|
776 |
|
777 | Object.keys(peerDepRanges).forEach(function(dep) {
|
778 | if (mainDepRanges[dep])
|
779 | delete mainDepRanges[dep];
|
780 | });
|
781 |
|
782 |
|
783 |
|
784 | Object.keys(mainDepRanges).forEach(function(dep) {
|
785 | if (depRanges.deps[dep])
|
786 | return;
|
787 | depRanges.deps[dep] = mainDepRanges[dep];
|
788 | });
|
789 | Object.keys(peerDepRanges).forEach(function(dep) {
|
790 | if (depRanges.peerDeps[dep])
|
791 | return;
|
792 | depRanges.peerDeps[dep] = peerDepRanges[dep];
|
793 | });
|
794 |
|
795 | return depRanges;
|
796 | }
|
797 |
|
798 |
|
799 |
|
800 | function derivePackageConfig(pkg, packageConfig, override) {
|
801 | packageConfig = extend({}, packageConfig);
|
802 |
|
803 |
|
804 | if (override || packageConfig.jspm)
|
805 | packageConfig.jspm = extend({}, packageConfig.jspm || {});
|
806 |
|
807 | if (override) {
|
808 |
|
809 |
|
810 | for (var p in override) {
|
811 | var stringified = JSON.stringify(override[p]);
|
812 | if (p in packageConfig.jspm ? JSON.stringify(packageConfig.jspm[p]) !== stringified : JSON.stringify(packageConfig[p]) !== stringified)
|
813 | packageConfig.jspm[p] = JSON.parse(stringified);
|
814 | else
|
815 | delete override[p];
|
816 | }
|
817 | }
|
818 |
|
819 |
|
820 | if (packageConfig.jspm)
|
821 | extend(packageConfig, packageConfig.jspm);
|
822 |
|
823 | var endpoint = registry.load(packageConfig.registry || pkg.registry);
|
824 | return Promise.resolve()
|
825 | .then(function() {
|
826 | if (endpoint.processPackageConfig)
|
827 | return endpoint.processPackageConfig(packageConfig, pkg.exactName);
|
828 |
|
829 | return packageConfig;
|
830 | })
|
831 | .then(function(packageConfig) {
|
832 | if (!packageConfig)
|
833 | throw new Error('processPackageConfig must return the processed configuration object.');
|
834 | packageConfig.registry = packageConfig.registry || pkg.registry || 'jspm';
|
835 | return packageConfig;
|
836 | });
|
837 | }
|
838 |
|
839 |
|
840 |
|
841 | function processPackage(pkg, dir, packageConfig, linked) {
|
842 |
|
843 | var timeout = setTimeout(function() {
|
844 | ui.log('warn', 'It\'s taking a long time to process the dependencies of `' + pkg.exactName + '`.\n' +
|
845 | 'This package may need an %ignore% property to indicate test or example folders for jspm to skip.\n');
|
846 | }, 10000);
|
847 | var endpoint = registry.load(packageConfig.registry || pkg.registry);
|
848 |
|
849 | return Promise.resolve()
|
850 | .then(function() {
|
851 | if (linked)
|
852 | return;
|
853 |
|
854 | return filterIgnoreAndFiles(dir, packageConfig.ignore, packageConfig.files);
|
855 | })
|
856 | .then(function() {
|
857 | if (linked)
|
858 | return;
|
859 |
|
860 | var distDir;
|
861 |
|
862 | if (packageConfig.directories)
|
863 | distDir = packageConfig.directories.dist || packageConfig.directories.lib;
|
864 |
|
865 | if (distDir)
|
866 | return collapseDistDir(dir, distDir);
|
867 | })
|
868 | .then(function() {
|
869 |
|
870 | if (endpoint.processPackage)
|
871 | return endpoint.processPackage(packageConfig, pkg.exactName, dir)
|
872 | .catch(function(e) {
|
873 | throw 'Error building package `' + pkg.exactName + '`.\n' + (e && e.stack || e);
|
874 | })
|
875 | .then(function(packageConfig) {
|
876 | if (!packageConfig)
|
877 | throw new Error('Registry endpoint processPackage of ' + pkg.exactName + ' did not return package config.');
|
878 | return packageConfig;
|
879 | });
|
880 | else
|
881 | return packageConfig;
|
882 | })
|
883 |
|
884 | .then(function(packageConfig) {
|
885 |
|
886 | upgradePackageConfig(packageConfig);
|
887 |
|
888 | clearTimeout(timeout);
|
889 | return packageConfig;
|
890 | });
|
891 | }
|
892 |
|
893 |
|
894 | var inDir = require('./common').inDir;
|
895 | function filterIgnoreAndFiles(dir, ignore, files) {
|
896 | if (!ignore && !files)
|
897 | return Promise.resolve();
|
898 |
|
899 | return asp(glob)(dir + path.sep + '**' + path.sep + '*', {dot: true})
|
900 | .then(function(allFiles) {
|
901 | var removeFiles = [];
|
902 |
|
903 | allFiles.forEach(function(file) {
|
904 | var fileName = path.relative(dir, file).replace(/\\/g, '/');
|
905 |
|
906 |
|
907 | if (files && !files.some(function(keepFile) {
|
908 | if (typeof keepFile != 'string')
|
909 | return;
|
910 | if (keepFile.startsWith('./'))
|
911 | keepFile = keepFile.substr(2);
|
912 | if (keepFile.endsWith('/*') && keepFile[keepFile.length - 3] != '*')
|
913 | keepFile = keepFile.substr(0, keepFile.length - 2) + '/**/*';
|
914 |
|
915 |
|
916 | if (inDir(fileName, keepFile, false, '/') || minimatch(fileName, keepFile, { dot: true }))
|
917 | return true;
|
918 | }))
|
919 | return removeFiles.push(fileName);
|
920 |
|
921 |
|
922 | if (ignore && ignore.some(function(ignoreFile) {
|
923 | if (typeof ignoreFile != 'string')
|
924 | return;
|
925 | if (ignoreFile.startsWith('./'))
|
926 | ignoreFile = ignoreFile.substr(2);
|
927 |
|
928 | if (inDir(fileName, ignoreFile, false) || minimatch(fileName, ignoreFile))
|
929 | return true;
|
930 | }))
|
931 | removeFiles.push(fileName);
|
932 | });
|
933 |
|
934 |
|
935 | return Promise.all(removeFiles.map(function(removeFile) {
|
936 | return asp(fs.unlink)(path.resolve(dir, removeFile)).catch(function(e) {
|
937 | if (e.code === 'EPERM' || e.code === 'EISDIR' || e.code === 'ENOENT')
|
938 | return;
|
939 | throw e;
|
940 | });
|
941 | }));
|
942 | });
|
943 | }
|
944 | function collapseDistDir(dir, subDir) {
|
945 | if (subDir.endsWith('/'))
|
946 | subDir = subDir.substr(0, subDir.length - 1);
|
947 |
|
948 | var tmpDir = path.resolve(dir, '..', '.tmp-' + dir.split(path.sep).pop());
|
949 |
|
950 |
|
951 | fs.renameSync(path.normalize(dir + path.sep + subDir), tmpDir);
|
952 |
|
953 |
|
954 | return asp(rimraf)(dir)
|
955 | .then(function() {
|
956 | fs.renameSync(tmpDir, dir);
|
957 | });
|
958 | }
|
959 |
|
960 |
|
961 | var loaderConfigProperties = ['baseDir', 'defaultExtension', 'format', 'meta', 'map', 'main'];
|
962 |
|
963 | function createLoaderConfig(pkg, packageConfig, downloadDir) {
|
964 |
|
965 | if (typeof packageConfig.systemjs == 'object')
|
966 | packageConfig = packageConfig.systemjs;
|
967 |
|
968 | var loaderConfig = {};
|
969 | for (var p in packageConfig)
|
970 | if (loaderConfigProperties.indexOf(p) != -1)
|
971 | loaderConfig[p] = packageConfig[p];
|
972 |
|
973 | if (packageConfig.modules && !packageConfig.meta)
|
974 | loaderConfig.meta = packageConfig.modules;
|
975 |
|
976 | if (!packageConfig.main) {
|
977 | if (packageConfig.main === false)
|
978 | delete loaderConfig.main;
|
979 | else
|
980 | ui.log('warn', 'Package `' + pkg.exactName + '` has no "main" entry point set in its package config.');
|
981 | }
|
982 |
|
983 | fs.writeFileSync(downloadDir + '.json', JSON.stringify(loaderConfig, null, 2));
|
984 | return Promise.resolve(loaderConfig);
|
985 | }
|