jspm 2.0.0-beta.7 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +26 -32
  3. package/dist/cli.js +1391 -0
  4. package/jspm.js +10 -0
  5. package/package.json +32 -60
  6. package/CHANGELOG.md +0 -25
  7. package/bin/jspm +0 -46
  8. package/lib/api.d.ts +0 -10
  9. package/lib/api.js +0 -71
  10. package/lib/api.js.map +0 -1
  11. package/lib/build/index.d.ts +0 -24
  12. package/lib/build/index.js +0 -163
  13. package/lib/build/index.js.map +0 -1
  14. package/lib/cli.d.ts +0 -1
  15. package/lib/cli.js +0 -701
  16. package/lib/cli.js.map +0 -1
  17. package/lib/compile/cjs-convert.d.ts +0 -7
  18. package/lib/compile/cjs-convert.js +0 -375
  19. package/lib/compile/cjs-convert.js.map +0 -1
  20. package/lib/compile/dew-resolve.d.ts +0 -9
  21. package/lib/compile/dew-resolve.js +0 -117
  22. package/lib/compile/dew-resolve.js.map +0 -1
  23. package/lib/compile/dew-worker.d.ts +0 -1
  24. package/lib/compile/dew-worker.js +0 -302
  25. package/lib/compile/dew-worker.js.map +0 -1
  26. package/lib/config/config-file.d.ts +0 -67
  27. package/lib/config/config-file.js +0 -591
  28. package/lib/config/config-file.js.map +0 -1
  29. package/lib/config/global-config-file.d.ts +0 -8
  30. package/lib/config/global-config-file.js +0 -89
  31. package/lib/config/global-config-file.js.map +0 -1
  32. package/lib/config/index.d.ts +0 -15
  33. package/lib/config/index.js +0 -59
  34. package/lib/config/index.js.map +0 -1
  35. package/lib/config/jspm-file.d.ts +0 -8
  36. package/lib/config/jspm-file.js +0 -84
  37. package/lib/config/jspm-file.js.map +0 -1
  38. package/lib/config/package-json-file.d.ts +0 -49
  39. package/lib/config/package-json-file.js +0 -332
  40. package/lib/config/package-json-file.js.map +0 -1
  41. package/lib/exec/index.d.ts +0 -12
  42. package/lib/exec/index.js +0 -117
  43. package/lib/exec/index.js.map +0 -1
  44. package/lib/install/bin.d.ts +0 -2
  45. package/lib/install/bin.js +0 -85
  46. package/lib/install/bin.js.map +0 -1
  47. package/lib/install/binary-build.d.ts +0 -2
  48. package/lib/install/binary-build.js +0 -89
  49. package/lib/install/binary-build.js.map +0 -1
  50. package/lib/install/fetch.d.ts +0 -53
  51. package/lib/install/fetch.js +0 -270
  52. package/lib/install/fetch.js.map +0 -1
  53. package/lib/install/index.d.ts +0 -66
  54. package/lib/install/index.js +0 -1164
  55. package/lib/install/index.js.map +0 -1
  56. package/lib/install/package.d.ts +0 -142
  57. package/lib/install/package.js +0 -625
  58. package/lib/install/package.js.map +0 -1
  59. package/lib/install/publish.d.ts +0 -14
  60. package/lib/install/publish.js +0 -186
  61. package/lib/install/publish.js.map +0 -1
  62. package/lib/install/registry-manager.d.ts +0 -134
  63. package/lib/install/registry-manager.js +0 -521
  64. package/lib/install/registry-manager.js.map +0 -1
  65. package/lib/install/source.d.ts +0 -10
  66. package/lib/install/source.js +0 -378
  67. package/lib/install/source.js.map +0 -1
  68. package/lib/map/common.d.ts +0 -12
  69. package/lib/map/common.js +0 -182
  70. package/lib/map/common.js.map +0 -1
  71. package/lib/map/esm-lexer.d.ts +0 -17
  72. package/lib/map/esm-lexer.js +0 -506
  73. package/lib/map/esm-lexer.js.map +0 -1
  74. package/lib/map/index.d.ts +0 -15
  75. package/lib/map/index.js +0 -336
  76. package/lib/map/index.js.map +0 -1
  77. package/lib/map/utils.d.ts +0 -10
  78. package/lib/map/utils.js +0 -169
  79. package/lib/map/utils.js.map +0 -1
  80. package/lib/overrides.d.ts +0 -3
  81. package/lib/overrides.js +0 -29
  82. package/lib/overrides.js.map +0 -1
  83. package/lib/project.d.ts +0 -71
  84. package/lib/project.js +0 -434
  85. package/lib/project.js.map +0 -1
  86. package/lib/utils/cache.d.ts +0 -11
  87. package/lib/utils/cache.js +0 -121
  88. package/lib/utils/cache.js.map +0 -1
  89. package/lib/utils/common.d.ts +0 -55
  90. package/lib/utils/common.js +0 -267
  91. package/lib/utils/common.js.map +0 -1
  92. package/lib/utils/opts.d.ts +0 -6
  93. package/lib/utils/opts.js +0 -200
  94. package/lib/utils/opts.js.map +0 -1
  95. package/lib/utils/run-cmd.d.ts +0 -4
  96. package/lib/utils/run-cmd.js +0 -39
  97. package/lib/utils/run-cmd.js.map +0 -1
  98. package/lib/utils/ui.d.ts +0 -38
  99. package/lib/utils/ui.js +0 -496
  100. package/lib/utils/ui.js.map +0 -1
@@ -1,1164 +0,0 @@
1
- "use strict";
2
- /*
3
- * Copyright 2014-2019 Guy Bedford (http://guybedford.com)
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- const sver_1 = require("sver");
19
- const path = require("path");
20
- const package_1 = require("./package");
21
- const common_1 = require("../utils/common");
22
- const fs = require("graceful-fs");
23
- const ncp = require("ncp");
24
- const rimraf = require("rimraf");
25
- const mkdirp = require("mkdirp");
26
- const bin_1 = require("./bin");
27
- const overrides_1 = require("../overrides");
28
- const fileInstallRegEx = /^(\.[\/\\]|\.\.[\/\\]|\/|\\|~[\/\\])/;
29
- class Installer {
30
- constructor(project) {
31
- this.project = project;
32
- this.config = project.config;
33
- this.registryManager = project.registryManager;
34
- // cache information associated with the current jspm project
35
- // keyed by package path -> package info
36
- this.jspmPackageInstallStateCache = {};
37
- this.binFolderChecked = false;
38
- this.sourceInstalls = {};
39
- this.installs = {};
40
- this.primaryType = undefined;
41
- this.primaryRanges = this.config.pjson.dependencies;
42
- this.updatePrimaryRanges = true;
43
- this.secondaryRanges = {};
44
- this.installTree = this.config.jspm.installed;
45
- this.globalPackagesPath = path.join(project.cacheDir, 'packages');
46
- // ensure registries are loaded
47
- this.registryManager.loadEndpoints();
48
- this.changed = false;
49
- this.busy = false;
50
- }
51
- dispose() {
52
- }
53
- ensureNotBusy() {
54
- if (this.busy)
55
- throw new common_1.JspmUserError('Installer can only install a single top-level install operation at once.');
56
- }
57
- async update(selectors, opts) {
58
- let updateInstalls = [];
59
- selectors.forEach(selector => {
60
- let matches = this.installTree.select(selector);
61
- if (!matches.length)
62
- throw new common_1.JspmUserError(`Package ${common_1.bold(selector)} is not an installed package.`);
63
- if (matches.length > 1) {
64
- // if a secondary, ensure that they all coalesce to the same package
65
- let primary = false;
66
- let exactNames = [];
67
- matches.forEach(match => {
68
- if (primary) {
69
- if (match.parent)
70
- return;
71
- }
72
- else if (!match.parent) {
73
- primary = true;
74
- exactNames = [];
75
- }
76
- const exactResolution = match.parent ? this.installTree.dependencies[match.parent].resolve[match.name] : this.installTree.resolve[match.name];
77
- const exactName = package_1.serializePackageName(exactResolution);
78
- if (exactNames.indexOf(exactName) === -1)
79
- exactNames.push(exactName);
80
- });
81
- if (exactNames.length > 1)
82
- throw new common_1.JspmUserError(`Ambiguous update package ${common_1.bold(selector)} matches multiple packages: ${exactNames.map(name => common_1.highlight(name)).join(', ')}.`);
83
- }
84
- matches.forEach(match => {
85
- const { name, parent } = match;
86
- updateInstalls.push({
87
- name,
88
- parent,
89
- type: package_1.DepType.primary,
90
- target: undefined
91
- });
92
- });
93
- });
94
- await this.ensureInstallRanges();
95
- updateInstalls.forEach(install => {
96
- if (!install.parent) {
97
- const parentRanges = this.primaryRanges[install.name];
98
- if (!parentRanges)
99
- throw new common_1.JspmUserError(`Unable to detect an install range for ${common_1.bold(install.name)}.`);
100
- install.type = parentRanges.type;
101
- install.target = parentRanges.target;
102
- }
103
- else {
104
- const parentObj = this.secondaryRanges[install.parent];
105
- install.target = parentObj && parentObj[install.name];
106
- if (!install.target)
107
- throw new common_1.JspmUserError(`Unable to detect an install range for ${common_1.bold(install.name)} in ${common_1.highlight(install.parent)}.`);
108
- }
109
- });
110
- return this.install(updateInstalls, opts);
111
- }
112
- // could support override here for link to non-link: sources
113
- async link(pkg, source, opts) {
114
- const linkSource = await this.registryManager.resolveSource(source, this.project.projectPath, this.project.projectPath);
115
- const linkInstall = {
116
- name: undefined,
117
- parent: undefined,
118
- target: undefined,
119
- type: undefined
120
- };
121
- let linkPkg;
122
- // find exact or unique matching package in the tree, throwing if not found
123
- try {
124
- linkPkg = package_1.parseExactPackageName(pkg);
125
- }
126
- catch (e) { }
127
- // not a full package name -> select for best name match
128
- if (!linkPkg) {
129
- let matches = this.installTree.select(pkg);
130
- if (!matches.length)
131
- throw new common_1.JspmUserError(`Package ${common_1.bold(pkg)} is not an installed package. Either reference an existing installed package or provide the full package name to link into of the form ${common_1.bold('<registry:name@version>')}`);
132
- // if a secondary, ensure that they all coalesce to the same package
133
- const exactNames = [];
134
- matches.forEach(match => {
135
- const exactResolution = match.parent ? this.installTree.dependencies[match.parent].resolve[match.name] : this.installTree.resolve[match.name];
136
- linkPkg = exactResolution;
137
- const exactName = package_1.serializePackageName(exactResolution);
138
- if (exactNames.indexOf(exactName) === -1)
139
- exactNames.push(exactName);
140
- });
141
- if (exactNames.length > 1)
142
- throw new common_1.JspmUserError(`Ambiguous link package ${common_1.bold(pkg)} matches multiple packages: ${exactNames.map(name => common_1.highlight(name)).join(', ')}.`);
143
- linkInstall.parent = matches[0].parent;
144
- linkInstall.name = matches[0].name;
145
- }
146
- // exact package name -> find it in the tree
147
- else if (this.installTree.visit((pkg, name, parent) => {
148
- if (linkPkg.name !== pkg.name || linkPkg.version !== pkg.version || pkg.registry !== linkPkg.registry)
149
- return false;
150
- linkInstall.name = name;
151
- linkInstall.parent = parent;
152
- return true;
153
- })) { }
154
- // see if the exact package matches a top-level package.json install
155
- // that has not been done
156
- else if (Object.keys(this.primaryRanges).some(name => {
157
- const range = this.primaryRanges[name];
158
- if (typeof range.target !== 'string' && range.target.has(linkPkg)) {
159
- linkInstall.name = name;
160
- linkInstall.type = range.type;
161
- return true;
162
- }
163
- return false;
164
- })) { }
165
- // not existing at all
166
- // -> new primary install to linked
167
- else {
168
- linkInstall.type = package_1.DepType.primary; // check opts type?
169
- linkInstall.target = new package_1.PackageTarget(linkPkg.registry, linkPkg.name, linkPkg.version);
170
- this.installTree.resolve[linkInstall.name] = linkPkg;
171
- }
172
- // set primary range type and target
173
- // type not needed for secondaries and target not needed as lock is used
174
- if (linkInstall.parent === undefined) {
175
- const primaryRange = this.primaryRanges[linkInstall.name];
176
- if (primaryRange) {
177
- linkInstall.type = primaryRange.type;
178
- linkInstall.target = primaryRange.target;
179
- }
180
- else {
181
- linkInstall.type = package_1.DepType.primary;
182
- linkInstall.target = new package_1.PackageTarget(linkPkg.registry, linkPkg.name, linkPkg.version);
183
- }
184
- }
185
- // source set through lock for existing "link over" cases
186
- const linkPkgName = package_1.serializePackageName(linkPkg);
187
- const linkPkgResolved = this.installTree.dependencies[linkPkgName] = this.installTree.dependencies[linkPkgName] || { source: undefined, resolve: {} };
188
- linkPkgResolved.source = linkSource;
189
- opts.lock = true;
190
- return this.install([linkInstall], opts);
191
- }
192
- async checkout(selectors) {
193
- const checkouts = [];
194
- selectors.forEach(selector => {
195
- let matches = this.installTree.select(selector);
196
- if (!matches.length)
197
- throw new common_1.JspmUserError(`Package ${common_1.bold(selector)} is not an installed package.`);
198
- // if a secondary, ensure that they all coalesce to the same package
199
- const exactNames = [];
200
- matches.forEach(match => {
201
- const exactResolution = match.parent ? this.installTree.dependencies[match.parent].resolve[match.name] : this.installTree.resolve[match.name];
202
- const exactName = package_1.serializePackageName(exactResolution);
203
- if (exactNames.indexOf(exactName) === -1)
204
- exactNames.push(exactName);
205
- });
206
- if (exactNames.length > 1)
207
- throw new common_1.JspmUserError(`Ambiguous checkout package ${common_1.bold(selector)} matches multiple packages: ${exactNames.map(name => common_1.highlight(name)).join(', ')}.`);
208
- checkouts.push(exactNames[0]);
209
- });
210
- await Promise.all(checkouts.map(async (checkoutName) => {
211
- const registryIndex = checkoutName.indexOf(':');
212
- const packageInstallState = await this.getPackageInstallState(checkoutName);
213
- let stopReason = '';
214
- if (!packageInstallState.exists)
215
- stopReason = 'not installed';
216
- else if (packageInstallState.linkPath)
217
- stopReason = 'already linked';
218
- // skip if already checked out
219
- else if (!packageInstallState.hash)
220
- return this.project.log.ok(`Package ${common_1.highlight(checkoutName)} is already checked out.`);
221
- if (stopReason)
222
- throw new common_1.JspmUserError(`Unable to checkout ${common_1.highlight(checkoutName)} as it is ${stopReason}.`);
223
- const checkoutPath = path.join(this.config.pjson.packages, checkoutName.substr(0, registryIndex), checkoutName.substr(registryIndex + 1));
224
- const installPath = await new Promise((resolve, reject) => fs.readlink(checkoutPath, (err, path) => err ? reject(err) : resolve(path)));
225
- await new Promise((resolve, reject) => fs.unlink(checkoutPath, err => err ? reject(err) : resolve()));
226
- await new Promise((resolve, reject) => ncp(installPath, checkoutPath, err => err ? reject(err) : resolve()));
227
- this.project.log.ok(`Checked out package ${common_1.highlight(checkoutName)} for local modifications.`);
228
- }));
229
- }
230
- async uninstall(names) {
231
- this.ensureNotBusy();
232
- this.busy = true;
233
- if (names.length === 0)
234
- throw new common_1.JspmUserError(`No package provided to uninstall.`);
235
- names.forEach(name => {
236
- if (!this.primaryRanges[name])
237
- throw new common_1.JspmUserError(`Package ${common_1.bold(name)} doesn\'t match any existing top-level installed packages.`);
238
- if (this.primaryRanges[name]) {
239
- delete this.primaryRanges[name];
240
- this.changed = true;
241
- }
242
- if (this.installTree.resolve[name]) {
243
- delete this.installTree.resolve[name];
244
- this.changed = true;
245
- }
246
- });
247
- await this.clean();
248
- this.busy = false;
249
- return this.config.save();
250
- }
251
- /*
252
- * Install API top-level function
253
- */
254
- async install(installs, opts) {
255
- this.ensureNotBusy();
256
- this.busy = true;
257
- this.opts = opts;
258
- this.changed = false;
259
- if (this.opts.dedupe !== false)
260
- this.opts.dedupe = !this.opts.lock;
261
- this.primaryType = installs.length === 0 ? package_1.DepType.primary : installs[0].type;
262
- // no installs, install from package.json
263
- if (installs.length === 0) {
264
- // maintain existing package.json ranges
265
- this.updatePrimaryRanges = false;
266
- installs = Object.keys(this.primaryRanges).map(dep => {
267
- const entry = this.primaryRanges[dep];
268
- return {
269
- name: dep,
270
- target: entry.target,
271
- type: entry.type,
272
- parent: undefined
273
- };
274
- });
275
- }
276
- // install in parallel
277
- await Promise.all(installs.map(install => {
278
- const target = install.target;
279
- if (typeof target === 'string') {
280
- /*
281
- * File install sugar cases:
282
- * ./local -> file:./local
283
- * /local -> file:/local
284
- * ~/file -> file:~/file
285
- */
286
- if (target.match(fileInstallRegEx)) {
287
- install.target = 'file:' + target;
288
- }
289
- /*
290
- * Plain target install
291
- * Should ideally support a/b/c -> file:a/b/c resource sugar, but for now omitted
292
- */
293
- else if (!target.match(package_1.resourceInstallRegEx)) {
294
- let registryIndex = target.indexOf(':');
295
- let targetString = target;
296
- // a/b -> github:a/b sugar
297
- if (registryIndex === -1 && target.indexOf('/') !== -1 && target[0] !== '@')
298
- targetString = 'github:' + target;
299
- if (registryIndex === -1)
300
- targetString = ':' + targetString;
301
- install.target = package_1.processPackageTarget(install.name, targetString, this.project.defaultRegistry);
302
- }
303
- }
304
- // auto-generate name from target if necessary
305
- if (!install.name) {
306
- if (typeof install.target !== 'string') {
307
- const idx = install.target.name.lastIndexOf(':') + 1;
308
- const substr = install.target.name.substr(idx);
309
- if (substr.match(common_1.validAliasRegEx))
310
- install.name = substr;
311
- else
312
- install.name = substr.split('/').pop();
313
- }
314
- else {
315
- install.name = getResourceName(install.target, this.project.projectPath);
316
- }
317
- }
318
- if (!install.name.match(common_1.validAliasRegEx))
319
- throw new common_1.JspmUserError(`Invalid name ${common_1.bold(install.name)} for install to ${common_1.highlight(install.target.toString())}`);
320
- if (typeof install.target === 'string')
321
- return this.resourceInstall(install);
322
- else
323
- return this.packageInstall(install);
324
- }));
325
- await this.clean();
326
- const configChanged = this.config.save();
327
- this.busy = false;
328
- return configChanged || this.changed;
329
- }
330
- /*
331
- private async installPeer (_install: Install) {
332
- throw new Error('Todo');
333
- }
334
- */
335
- // most general override applies (greater containing range)
336
- // we first check this.config.pjson.overrides, followed by globalOverrides
337
- getOverride(pkg, cut = false) {
338
- if (typeof pkg === 'string') {
339
- const matchIndex = this.config.pjson.overrides.findIndex(({ target }) => target === pkg);
340
- const match = this.config.pjson.overrides[matchIndex];
341
- if (cut && matchIndex !== -1 && !match.fresh)
342
- this.config.pjson.overrides.splice(matchIndex, 1);
343
- return match && match.override;
344
- }
345
- else {
346
- let bestTargetIndex = -1;
347
- let bestTarget;
348
- let bestOverride;
349
- let bestIsFresh;
350
- for (let i = 0; i < this.config.pjson.overrides.length; i++) {
351
- let { target, override, fresh } = this.config.pjson.overrides[i];
352
- if (typeof target === 'string')
353
- continue;
354
- if (target.has(pkg)) {
355
- if (!bestTarget || target.range.gt(bestTarget.range)) {
356
- bestTargetIndex = i;
357
- bestTarget = target;
358
- bestOverride = override;
359
- bestIsFresh = fresh;
360
- }
361
- }
362
- }
363
- if (cut && bestTargetIndex !== -1 && !bestIsFresh)
364
- this.config.pjson.overrides.splice(bestTargetIndex, 1);
365
- if (!bestOverride) {
366
- const pkgs = overrides_1.default[pkg.registry];
367
- if (pkgs) {
368
- const versions = pkgs[pkg.name];
369
- if (versions) {
370
- let bestTargetRange;
371
- for (const v in versions) {
372
- const range = new sver_1.SemverRange(v);
373
- if (range.has(pkg.version)) {
374
- if (!bestTarget || range.gt(bestTargetRange)) {
375
- bestTargetRange = range;
376
- bestOverride = package_1.processPackageConfig(versions[v]);
377
- }
378
- }
379
- }
380
- }
381
- }
382
- }
383
- return bestOverride;
384
- }
385
- }
386
- // get an override and remove it from the override list in the process
387
- // this way an override saved back does not result in duplication
388
- cutOverride(pkg) {
389
- return this.getOverride(pkg, true);
390
- }
391
- setOverride(pkgTarget, override) {
392
- this.config.pjson.overrides.push({
393
- target: pkgTarget,
394
- override,
395
- fresh: true
396
- });
397
- }
398
- async packageInstall(install) {
399
- // first check if already doing this install, to avoid redoing work
400
- // this in turn catches circular installs on the early returns
401
- const installId = `${install.type === package_1.DepType.peer ? undefined : install.parent}|${install.name}`;
402
- const existingPackageInstall = this.installs[installId];
403
- if (existingPackageInstall)
404
- return;
405
- return this.installs[installId] = (async () => {
406
- this.project.log.debug(`Installing ${install.name}${install.parent ? ` for ${install.parent}` : ``}`);
407
- // install information
408
- let target = install.target;
409
- let override = install.override && package_1.validateOverride(install.override, install.name) && package_1.processPackageConfig(install.override);
410
- let source;
411
- let resolvedPkg;
412
- // if a lock install, use existing resolution
413
- if (this.opts.lock)
414
- resolvedPkg = this.installTree.getResolution(install);
415
- // if a non-latest secondary install, use existing resolution or find the best match in the tree
416
- if (install.type === package_1.DepType.secondary && !this.opts.latest)
417
- resolvedPkg = this.installTree.getResolution(install) || this.installTree.getBestMatch(target);
418
- if (resolvedPkg) {
419
- const existingResolutionName = package_1.serializePackageName(resolvedPkg);
420
- const existingResolved = this.installTree.dependencies[existingResolutionName];
421
- // if we found an existing resolution, use it if we have enough information
422
- if (existingResolved && existingResolved.source) {
423
- this.project.log.debug(`${install.name} matched against existing install`);
424
- target = this.setResolution(install, target, resolvedPkg, existingResolved.source);
425
- override = this.cutOverride(resolvedPkg);
426
- override = await this.sourceInstall(resolvedPkg, existingResolved.source, override, undefined);
427
- if (override)
428
- this.setOverride(target, override);
429
- return;
430
- }
431
- // otherwise specifically lookup this exact version
432
- else {
433
- target = new package_1.PackageTarget(resolvedPkg.registry, resolvedPkg.name, resolvedPkg.version);
434
- }
435
- }
436
- // run resolver lookup
437
- let resolution;
438
- try {
439
- resolution = await this.registryManager.resolve(target, override, this.opts.edge);
440
- }
441
- catch (e) {
442
- throw new common_1.JspmError(`Resolving ${common_1.highlight(package_1.serializePackageName(target))}`, undefined, e);
443
- }
444
- if (!resolution)
445
- throw new common_1.JspmUserError(`No resolution found for ${common_1.highlight(package_1.serializePackageName(target).replace(/\@\*$/, ''))}${this.offline ? ' (offline)' : ''}.`);
446
- resolvedPkg = resolution.pkg;
447
- source = resolution.source;
448
- override = resolution.override;
449
- // if there was no install override, get any override from package.json
450
- if (!install.override) {
451
- const existingOverride = this.cutOverride(resolvedPkg);
452
- if (existingOverride) {
453
- if (override)
454
- package_1.overridePackageConfig(override, existingOverride);
455
- else
456
- override = Object.assign({}, existingOverride);
457
- }
458
- }
459
- // immediately store the resolution if necessary
460
- target = this.setResolution(install, new package_1.PackageTarget(resolution.target.registry, resolution.target.name, resolution.target.version), resolution.pkg, source);
461
- // upgrade anything to this resolution which can (this is the orphaning)
462
- if (this.opts.dedupe)
463
- this.upgradePackagesTo(resolvedPkg).catch(() => { });
464
- const sourceInstallPromise = this.sourceInstall(resolvedPkg, source, override, resolution && resolution.deprecated);
465
- if (sourceInstallPromise) {
466
- // override from resolve replaces any existing package.json override which is not used
467
- override = await sourceInstallPromise;
468
- if (override)
469
- this.setOverride(target, override);
470
- }
471
- })();
472
- }
473
- sourceInstall(resolvedPkg, source, override, deprecated) {
474
- const resolvedPkgName = package_1.serializePackageName(resolvedPkg);
475
- const sourceInstallId = `${resolvedPkgName}|${source}`;
476
- let existingSourceInstall = this.sourceInstalls[sourceInstallId];
477
- // avoid circular (ok since a single install tree)
478
- if (existingSourceInstall) {
479
- return;
480
- }
481
- return this.sourceInstalls[sourceInstallId] = (async () => {
482
- // checked out packages stay unless a reset
483
- // and use the configuration from the package.json directly
484
- if (!this.opts.reset && await this.isPackageCheckedOut(resolvedPkgName)) {
485
- const config = await this.readCheckedOutConfig(resolvedPkgName, override);
486
- this.project.log.info(`Skipping reinstall for ${common_1.highlight(resolvedPkgName)} as there is a custom folder checked out in its place. Use the ${common_1.bold('--reset')} install flag to revert to the original source.`);
487
- // override is undefined by definition of checked out.
488
- return this.installDependencies(config, resolvedPkgName);
489
- }
490
- // handle linked packages
491
- if (source.startsWith('link:')) {
492
- if (await this.setPackageToLinked(resolvedPkgName, path.resolve(this.project.projectPath, source.substr(5))))
493
- this.changed = true;
494
- const config = await this.readCheckedOutConfig(resolvedPkgName, override, true);
495
- return this.installDependencies(config, resolvedPkgName);
496
- }
497
- let preloadedDepNames, preloadDepsInstallPromise;
498
- // kick off dependency installs now
499
- if (override) {
500
- preloadDepsInstallPromise = this.installDependencies(override, resolvedPkgName, preloadedDepNames);
501
- preloadDepsInstallPromise.catch(() => { });
502
- }
503
- // install
504
- try {
505
- var installResult = await this.registryManager.ensureInstall(source, override, this.opts.reset ? async () => false : this.createCheckoutPrompt(resolvedPkgName), this.opts.verify);
506
- }
507
- catch (e) {
508
- const errMsg = `Unable to install ${common_1.highlight(resolvedPkgName)}.`;
509
- if (e instanceof common_1.JspmUserError)
510
- throw new common_1.JspmUserError(errMsg, undefined, e);
511
- else
512
- throw new common_1.JspmError(errMsg, undefined, e);
513
- }
514
- // install result is undefined when verification fails and we have a checkout
515
- // then handle like checked out instead
516
- if (!installResult) {
517
- const config = await this.readCheckedOutConfig(resolvedPkgName, override);
518
- return this.installDependencies(config, resolvedPkgName);
519
- }
520
- if (installResult.changed)
521
- this.changed = true;
522
- let config, hash;
523
- ({ config, override, hash } = installResult);
524
- await Promise.all([
525
- // install dependencies, skipping already preloaded
526
- this.installDependencies(config, resolvedPkgName, preloadedDepNames),
527
- // symlink to the global install
528
- (async () => {
529
- if (await this.setPackageToHash(resolvedPkgName, hash)) {
530
- this.changed = true;
531
- // only show deprecation message on first install into jspm_packages
532
- if (deprecated)
533
- this.project.log.warn(`Deprecation warning for ${common_1.highlight(resolvedPkgName)}: ${common_1.bold(deprecated)}`);
534
- }
535
- })(),
536
- this.createBins(config, resolvedPkgName),
537
- preloadDepsInstallPromise
538
- ]);
539
- return override;
540
- })();
541
- }
542
- async createBins(config, resolvedPkgName) {
543
- // NB we should create a queue based on precedence to ensure deterministic ordering
544
- // when there are namespace collissions, but this problem will likely not be hit for a while
545
- if (config.bin) {
546
- const binDir = path.join(this.config.pjson.packages, '.bin');
547
- if (!this.binFolderChecked) {
548
- await new Promise((resolve, reject) => mkdirp(binDir, err => err ? reject(err) : resolve(binDir)));
549
- this.binFolderChecked = true;
550
- }
551
- await Promise.all(Object.keys(config.bin).map(p => bin_1.writeBinScripts(binDir, p, resolvedPkgName.replace(':', path.sep) + path.sep + config.bin[p])));
552
- }
553
- }
554
- // resource install is different to source install in that
555
- // we need to normalize the source string into resolved form and
556
- // we need to install first to find out the name of the package
557
- async resourceInstall(install) {
558
- // first check if already doing this install, to avoid redoing work
559
- // this in turn catches circular installs on the early returns
560
- const installId = `${install.type === package_1.DepType.peer ? undefined : install.parent}|${install.name}`;
561
- const existingPackageInstall = this.installs[installId];
562
- if (existingPackageInstall)
563
- return;
564
- return this.installs[installId] = (async () => {
565
- let override = install.override || this.cutOverride(install.target);
566
- // handle lock lookups for resourceInstall
567
- const existingResolution = this.installTree.getResolution(install);
568
- if (existingResolution) {
569
- const existingResolutionName = package_1.serializePackageName(existingResolution);
570
- const existingResolved = this.installTree.dependencies[existingResolutionName];
571
- if (existingResolved && existingResolved.source) {
572
- this.project.log.debug(`${install.name} matched against existing install`);
573
- this.setResolution(install, install.target, existingResolution, existingResolved.source);
574
- override = await this.sourceInstall(existingResolution, existingResolved.source, override, undefined);
575
- if (override)
576
- this.setOverride(install.target, override);
577
- return;
578
- }
579
- }
580
- this.project.log.debug(`Installing resource ${install.name}${install.parent ? ` for ${install.parent}` : ``}`);
581
- const parentPath = install.parent && install.type !== package_1.DepType.peer ? path.join(this.config.pjson.packages, install.parent.replace(':', path.sep)) : this.project.projectPath;
582
- // first normalize the source
583
- try {
584
- var source = await this.registryManager.resolveSource(install.target, parentPath, this.project.projectPath);
585
- }
586
- catch (e) {
587
- const errMsg = `Unable to locate ${common_1.highlight(install.target)}.`;
588
- if (e instanceof common_1.JspmUserError)
589
- throw new common_1.JspmUserError(errMsg, undefined, e);
590
- else
591
- throw new common_1.JspmError(errMsg, undefined, e);
592
- }
593
- const isLink = source.startsWith('link:');
594
- let config, hash, linkPath;
595
- let registry, name, version;
596
- // link
597
- if (isLink) {
598
- linkPath = path.resolve(this.project.projectPath, source.substr(5));
599
- try {
600
- var json = await common_1.readJSON(path.join(linkPath, 'package.json'));
601
- }
602
- catch (e) { }
603
- config = package_1.processPackageConfig(json || {});
604
- if (override) {
605
- ({ config, override } = package_1.overridePackageConfig(config, override));
606
- if (override)
607
- this.project.log.warn(`The override for ${common_1.highlight(install.target)} is not being applied as it is linked. Rather edit the original package.json file directly instead of applying an override.`);
608
- }
609
- registry = config.registry || this.project.defaultRegistry;
610
- name = config.name || install.name;
611
- version = config.version;
612
- }
613
- // install
614
- else {
615
- try {
616
- var installResult = await this.registryManager.ensureInstall(source, override, async () => false, this.opts.verify);
617
- }
618
- catch (e) {
619
- const errMsg = `Unable to install ${source}.`;
620
- if (e instanceof common_1.JspmUserError)
621
- throw new common_1.JspmUserError(errMsg, undefined, e);
622
- else
623
- throw new common_1.JspmError(errMsg, undefined, e);
624
- }
625
- if (installResult.changed)
626
- this.changed = true;
627
- ({ config, override, hash } = installResult);
628
- registry = config.registry || this.project.defaultRegistry;
629
- name = config.name || install.name;
630
- version = config.version;
631
- if (!version) {
632
- let refIndex = install.target.lastIndexOf('#');
633
- if (refIndex !== -1)
634
- version = install.target.substr(refIndex + 1);
635
- }
636
- }
637
- if (this.project.userInput) {
638
- if (!registry)
639
- registry = 'npm';
640
- if (!version)
641
- version = await this.project.input(`Enter the ${common_1.bold('version')} to ${isLink ? `link as` : `install ${install.target} as`}`, 'master', {
642
- info: 'All installs in jspm need to be assigned a registry, name and version for flat installation.',
643
- validate: (input) => {
644
- if (!input)
645
- return 'A version must be provided.';
646
- }
647
- });
648
- }
649
- else {
650
- let missing = !registry && 'registry' || !name && 'name' || !version && 'version';
651
- if (missing) {
652
- throw new common_1.JspmUserError(`Unable to ${isLink ? `link ${linkPath}` : `install resource target ${install.target}`} as no ${common_1.bold(missing)} property is provided. This should be set in the original package.json or be added with an override to the install if necessary.`);
653
- }
654
- }
655
- const resolvedPkgName = `${registry}:${name}@${version}`;
656
- const resolvedPkg = package_1.parseExactPackageName(resolvedPkgName);
657
- // save resolution
658
- this.setResolution(install, install.target, resolvedPkg, source);
659
- if (override)
660
- this.setOverride(install.target, override);
661
- // if checked out, skip the actual resource install
662
- if (!this.opts.reset && await this.isPackageCheckedOut(resolvedPkgName)) {
663
- const config = await this.readCheckedOutConfig(resolvedPkgName, override);
664
- this.project.log.info(`Skipping reinstall for ${common_1.highlight(resolvedPkgName)} as there is a custom folder checked out in its place. Use the ${common_1.bold('--reset')} install flag to revert to the original source.`);
665
- // override is undefined by definition of checked out.
666
- return this.installDependencies(config, resolvedPkgName);
667
- }
668
- await Promise.all([
669
- this.installDependencies(config, resolvedPkgName),
670
- (async () => {
671
- if (isLink) {
672
- if (await this.setPackageToLinked(resolvedPkgName, linkPath))
673
- this.changed = true;
674
- }
675
- else {
676
- if (await this.setPackageToHash(resolvedPkgName, hash))
677
- this.changed = true;
678
- }
679
- })(),
680
- this.createBins(config, resolvedPkgName)
681
- ]);
682
- })();
683
- }
684
- async installDependencies(config, resolvedPkgName, preloadedDepNames) {
685
- const registry = config.registry || this.project.defaultRegistry;
686
- const preLoad = preloadedDepNames !== undefined && preloadedDepNames.length !== 0;
687
- try {
688
- await Promise.all(depsToInstalls(registry, config, resolvedPkgName, preLoad === false && preloadedDepNames).map(install => {
689
- if (preLoad && preloadedDepNames)
690
- preloadedDepNames.push(install.name);
691
- if (typeof install.target === 'string')
692
- return this.resourceInstall(install);
693
- else
694
- return this.packageInstall(install);
695
- }));
696
- }
697
- catch (e) {
698
- throw new common_1.JspmError(`Installing ${common_1.highlight(resolvedPkgName)}.`, undefined, e);
699
- }
700
- }
701
- setResolution(install, target, resolution, source) {
702
- const exactResolution = {
703
- registry: resolution.registry,
704
- name: resolution.name,
705
- version: resolution.version,
706
- semver: new sver_1.Semver(resolution.version)
707
- };
708
- const resolutionString = package_1.serializePackageName(resolution);
709
- if (!install.parent || install.type === package_1.DepType.peer) {
710
- this.installTree.resolve[install.name] = exactResolution;
711
- // only write in targets when primary range is empty
712
- const existingRange = this.primaryRanges[install.name];
713
- if (!existingRange || this.updatePrimaryRanges === true) {
714
- if (typeof target !== 'string') {
715
- if (target.range.isExact || this.opts.exact)
716
- target = target.fromVersion(resolution.version);
717
- if (sver_1.Semver.isValid(resolution.version)) {
718
- if (target.range.isMajor || target.range.isWildcard)
719
- target = target.fromVersion('^' + resolution.version);
720
- else if (target.range.isStable)
721
- target = target.fromVersion('~' + resolution.version);
722
- }
723
- else {
724
- target = new package_1.PackageTarget(resolution.registry, resolution.name, resolution.version);
725
- }
726
- }
727
- this.changed = true;
728
- if (this.updatePrimaryRanges && !install.parent) {
729
- this.primaryRanges[install.name] = { type: install.type, target };
730
- }
731
- else {
732
- const existingPrimaryAndNotDev = this.primaryRanges[install.name] &&
733
- (this.primaryRanges[install.name].type === package_1.DepType.peer || this.primaryRanges[install.name].type === package_1.DepType.primary);
734
- // peerDependencies install as devDependencies
735
- const type = existingPrimaryAndNotDev ? this.primaryRanges[install.name].type
736
- : install.type === package_1.DepType.peer ? package_1.DepType.dev
737
- : install.parent ? this.primaryType
738
- : install.type;
739
- this.primaryRanges[install.name] = { type, target };
740
- }
741
- }
742
- }
743
- else {
744
- const parentRecord = this.installTree.dependencies[install.parent];
745
- if (!parentRecord)
746
- throw new common_1.JspmError(`No parent in tree for resolution ${resolutionString}.`);
747
- parentRecord.resolve[install.name] = exactResolution;
748
- (this.secondaryRanges[install.parent] = this.secondaryRanges[install.parent] || {})[install.name] = target;
749
- }
750
- const installObj = this.installTree.dependencies[resolutionString];
751
- if (!installObj)
752
- this.installTree.dependencies[resolutionString] = { source, resolve: {} };
753
- else
754
- installObj.source = source;
755
- return target;
756
- }
757
- getPackagePath(name) {
758
- const resolvedPkgName = package_1.serializePackageName(this.config.jspm.installed.resolve[name]);
759
- const registryIndex = resolvedPkgName.indexOf(':');
760
- return path.join(this.config.pjson.packages, resolvedPkgName.substr(0, registryIndex), resolvedPkgName.substr(registryIndex + 1));
761
- }
762
- createCheckoutPrompt(resolvedPkgName) {
763
- const registryIndex = resolvedPkgName.indexOf(':');
764
- const localPackagePath = path.join(this.config.pjson.packages, resolvedPkgName.substr(0, registryIndex), resolvedPkgName.substr(registryIndex + 1));
765
- return async (dir) => {
766
- let checkout = await this.project.confirm(`The global package ${resolvedPkgName} has been modified, do you want to checkout the package now for custom modification, or revert?`, true);
767
- if (checkout) {
768
- await new Promise((resolve, reject) => ncp(dir, localPackagePath, err => err ? reject(err) : resolve()));
769
- await new Promise((resolve, reject) => rimraf(dir, err => err ? reject(err) : resolve()));
770
- }
771
- return checkout;
772
- };
773
- }
774
- async readCheckedOutConfig(resolvedPkgName, override, linked = false) {
775
- const registryIndex = resolvedPkgName.indexOf(':');
776
- const registry = resolvedPkgName.substr(0, registryIndex);
777
- const pkgPath = path.join(this.config.pjson.packages, registry, resolvedPkgName.substr(registryIndex + 1));
778
- var json = await common_1.readJSON(path.join(pkgPath, 'package.json'));
779
- let config = package_1.processPackageConfig(json || {});
780
- if (override) {
781
- ({ config, override } = package_1.overridePackageConfig(config, override));
782
- if (override)
783
- this.project.log.warn(`The override for ${common_1.highlight(resolvedPkgName)} is not being applied as it is ${linked ? 'linked' : 'checked out'}. Rather edit the original package.json file directly instead of applying an override.`);
784
- }
785
- return config;
786
- }
787
- // upgrades any packages in the installing or installed tree to the newly added resolution
788
- async upgradePackagesTo(upgradePkg) {
789
- await this.ensureInstallRanges(upgradePkg);
790
- await this.installTree.visit((pkg, name, parent) => {
791
- let range;
792
- if (parent) {
793
- const parentRanges = this.secondaryRanges[parent];
794
- if (!parentRanges)
795
- return;
796
- range = parentRanges[name];
797
- }
798
- else {
799
- range = this.primaryRanges[name].target;
800
- }
801
- // if theres a rangeless dependency, ignore
802
- if (!range)
803
- return;
804
- if (!range.has(pkg))
805
- return;
806
- if (range.has(upgradePkg) && upgradePkg.semver.gt(pkg.semver)) {
807
- // handle orphaning inflight cancellation?
808
- if (parent)
809
- this.installTree.dependencies[parent][name] = upgradePkg;
810
- else
811
- this.installTree[name] = upgradePkg;
812
- }
813
- });
814
- }
815
- async setPackageToHash(pkgName, hash) {
816
- const packageInstallState = await this.getPackageInstallState(pkgName);
817
- if (packageInstallState.hash === hash)
818
- return false;
819
- const { exists, linkPath } = packageInstallState;
820
- packageInstallState.exists = true;
821
- packageInstallState.hash = hash;
822
- packageInstallState.linkPath = undefined;
823
- const localPackagePath = path.join(this.config.pjson.packages, pkgName.replace(':', path.sep));
824
- if (exists) {
825
- if (hash === undefined && linkPath === undefined) {
826
- this.project.log.info(`Removing checked out package ${pkgName}.`);
827
- await new Promise((resolve, reject) => rimraf(localPackagePath, err => err ? reject(err) : resolve()));
828
- }
829
- else {
830
- if (linkPath !== undefined)
831
- this.project.log.info(`Replacing custom symlink for ${pkgName}.`);
832
- await new Promise((resolve, reject) => fs.unlink(localPackagePath, err => err ? reject(err) : resolve()));
833
- }
834
- }
835
- else {
836
- await new Promise((resolve, reject) => mkdirp(path.dirname(localPackagePath), err => err ? reject(err) : resolve()));
837
- }
838
- const cachePath = path.resolve(this.globalPackagesPath, hash);
839
- await new Promise((resolve, reject) => mkdirp(path.dirname(localPackagePath), err => err ? reject(err) : resolve()));
840
- await new Promise((resolve, reject) => fs.symlink(cachePath, localPackagePath, 'junction', err => err ? reject(err) : resolve()));
841
- return true;
842
- }
843
- async setPackageToLinked(pkgName, linkPath) {
844
- const packageInstallState = await this.getPackageInstallState(pkgName);
845
- if (packageInstallState.linkPath === linkPath)
846
- return false;
847
- const { exists, hash } = packageInstallState;
848
- packageInstallState.exists = true;
849
- packageInstallState.hash = undefined;
850
- packageInstallState.linkPath = linkPath;
851
- const localPackagePath = path.join(this.config.pjson.packages, pkgName.replace(':', path.sep));
852
- if (exists) {
853
- if (hash === undefined && linkPath === undefined) {
854
- this.project.log.info(`Removing checked out package ${pkgName}.`);
855
- await new Promise((resolve, reject) => rimraf(localPackagePath, err => err ? reject(err) : resolve()));
856
- }
857
- else {
858
- if (linkPath !== undefined)
859
- this.project.log.info(`Removing custom symlink for ${pkgName}.`);
860
- await new Promise((resolve, reject) => fs.unlink(localPackagePath, err => err ? reject(err) : resolve()));
861
- }
862
- }
863
- else {
864
- await new Promise((resolve, reject) => mkdirp(path.dirname(localPackagePath), err => err ? reject(err) : resolve()));
865
- }
866
- await new Promise((resolve, reject) => mkdirp(path.dirname(localPackagePath), err => err ? reject(err) : resolve()));
867
- await new Promise((resolve, reject) => fs.symlink(path.relative(path.dirname(localPackagePath), linkPath), localPackagePath, 'junction', err => err ? reject(err) : resolve()));
868
- return true;
869
- }
870
- async packageExists(pkgName) {
871
- const packageInstallState = await this.getPackageInstallState(pkgName);
872
- return packageInstallState.exists;
873
- }
874
- async isPackageCheckedOut(pkgName) {
875
- const packageInstallState = await this.getPackageInstallState(pkgName);
876
- return packageInstallState.exists && packageInstallState.hash === undefined && packageInstallState.linkPath === undefined;
877
- }
878
- async getPackageInstallState(pkgName) {
879
- let packageInstallState = this.jspmPackageInstallStateCache[pkgName];
880
- if (packageInstallState)
881
- return packageInstallState;
882
- const pkgPath = path.join(this.config.pjson.packages, pkgName.replace(':', path.sep));
883
- packageInstallState = {
884
- exists: false,
885
- hash: undefined,
886
- linkPath: undefined
887
- };
888
- const symlinkPath = await new Promise((resolve, reject) => {
889
- fs.readlink(pkgPath, (err, resolvedPath) => {
890
- if (err) {
891
- switch (err.code) {
892
- case 'ENOENT':
893
- resolve();
894
- break;
895
- case 'EINVAL':
896
- resolve('<UNKNOWN>');
897
- break;
898
- case 'UNKNOWN':
899
- resolve(pkgPath);
900
- break;
901
- default:
902
- reject(err);
903
- break;
904
- }
905
- }
906
- else {
907
- resolve(path.resolve(path.dirname(pkgPath), resolvedPath));
908
- }
909
- });
910
- });
911
- if (!symlinkPath)
912
- return this.jspmPackageInstallStateCache[pkgName] = packageInstallState;
913
- packageInstallState.exists = true;
914
- if (symlinkPath.startsWith(this.globalPackagesPath) && symlinkPath[this.globalPackagesPath.length] === path.sep) {
915
- const pathHash = symlinkPath.substring(this.globalPackagesPath.length + 1, symlinkPath.length - 1);
916
- if (pathHash.indexOf(path.sep) === -1) {
917
- packageInstallState.hash = pathHash;
918
- return this.jspmPackageInstallStateCache[pkgName] = packageInstallState;
919
- }
920
- }
921
- if (symlinkPath !== pkgPath)
922
- packageInstallState.linkPath = symlinkPath;
923
- return this.jspmPackageInstallStateCache[pkgName] = packageInstallState;
924
- }
925
- async ensureInstallRanges(exactPkg) {
926
- await this.installTree.visitAsync(async (pkg, name, parent) => {
927
- // where an upgrade package is specified,
928
- // only check ranges that are the same package, but a different version
929
- if (exactPkg && (pkg.registry !== exactPkg.registry || pkg.name !== exactPkg.name || pkg.version === exactPkg.version))
930
- return;
931
- if (parent) {
932
- const secondaryRanges = this.secondaryRanges[parent];
933
- if (secondaryRanges && secondaryRanges[name])
934
- return;
935
- }
936
- else {
937
- const primaryRange = this.primaryRanges[name];
938
- if (primaryRange)
939
- return;
940
- return;
941
- }
942
- const parentDepObj = this.installTree.dependencies[parent];
943
- let config;
944
- if (await this.packageExists(parent)) {
945
- config = await this.readCheckedOutConfig(parent, undefined);
946
- }
947
- else {
948
- // no source -> ignore
949
- if (!parentDepObj || !parentDepObj.source)
950
- return;
951
- // fail gracefully eg for offline
952
- try {
953
- // we dont verify, reset or alter overrides here because we want to be minimally invasive outside of the direct install tree
954
- const override = this.getOverride(package_1.parseExactPackageName(parent));
955
- var installResult = await this.registryManager.ensureInstall(parentDepObj.source, override, this.createCheckoutPrompt(parent), false);
956
- }
957
- catch (e) {
958
- return;
959
- }
960
- if (!installResult) {
961
- config = await this.readCheckedOutConfig(parent, undefined);
962
- }
963
- // we dont persist the updated override or check the jspm_packages symlink, because we dont want to
964
- // alter in any way installed packages not directly on the install tree -> aiming for principle of least surprise to user
965
- else {
966
- if (installResult.changed)
967
- this.changed = true;
968
- ({ config } = installResult);
969
- }
970
- }
971
- const rangeTarget = config.dependencies && config.dependencies[name] ||
972
- config.peerDependencies && config.peerDependencies[name] ||
973
- config.optionalDependencies && config.optionalDependencies[name];
974
- if (!rangeTarget)
975
- return;
976
- this.secondaryRanges[parent] = this.secondaryRanges[parent] || {};
977
- this.secondaryRanges[parent][name] = rangeTarget;
978
- });
979
- }
980
- async clean(save = false) {
981
- const packageList = [];
982
- const addDependentPackages = (pkgName) => {
983
- packageList.push(pkgName);
984
- // get all immediate children of this package
985
- // for those children not already seen (in packages list),
986
- // run getDependentPackages in turn on those
987
- let depObj = this.installTree.dependencies[pkgName];
988
- if (!depObj || !depObj.resolve)
989
- return;
990
- Object.keys(depObj.resolve).forEach(dep => {
991
- const curPkg = depObj.resolve[dep];
992
- const curPkgName = package_1.serializePackageName(curPkg);
993
- if (packageList.indexOf(curPkgName) !== -1)
994
- return;
995
- addDependentPackages(curPkgName);
996
- });
997
- };
998
- // Remove anything not explicitly in package.json
999
- Object.keys(this.installTree.resolve).forEach(name => {
1000
- if (!this.primaryRanges[name])
1001
- delete this.installTree.resolve[name];
1002
- });
1003
- // getDependentPackages for each of baseMap
1004
- Object.keys(this.primaryRanges).forEach(dep => {
1005
- const resolved = this.installTree.resolve[dep];
1006
- if (!resolved)
1007
- return;
1008
- addDependentPackages(package_1.serializePackageName(resolved));
1009
- });
1010
- // now that we have the package list, remove everything not in it
1011
- Object.keys(this.installTree.dependencies).forEach(dep => {
1012
- if (packageList.indexOf(dep) === -1) {
1013
- this.project.log.info(`Removed ${common_1.highlight(dep)}.`);
1014
- delete this.installTree.dependencies[dep];
1015
- }
1016
- });
1017
- // depthCheck returns true to keep going (files being ignored),
1018
- // false to add the dir to the flat list
1019
- const removeNonPackageDirs = async (dir) => {
1020
- let files = await new Promise((resolve, reject) => fs.readdir(dir, (err, files) => err ? reject(err) : resolve(files)));
1021
- let deletedAll = true;
1022
- let relPath = path.relative(this.config.pjson.packages, dir);
1023
- let pkgBase = relPath.replace(path.sep, ':');
1024
- if (common_1.isWindows)
1025
- pkgBase = pkgBase.replace(/\\/g, '/');
1026
- await Promise.all(files.map(async (file) => {
1027
- let filePath = path.resolve(dir, file);
1028
- let pkgName = pkgBase + (pkgBase.indexOf(':') === -1 ? ':' : '/') + file;
1029
- if (packageList.indexOf(pkgName) !== -1 || pkgName === ':.bin') {
1030
- deletedAll = false;
1031
- return;
1032
- }
1033
- let fileInfo = await new Promise((resolve, reject) => fs.lstat(filePath, (err, stats) => err ? reject(err) : resolve(stats)));
1034
- // package folder
1035
- if (file.indexOf('@') > 0) {
1036
- // warn on directory removal
1037
- if (fileInfo.isSymbolicLink()) {
1038
- await new Promise((resolve, reject) => fs.unlink(filePath, err => err ? reject(err) : resolve()));
1039
- }
1040
- else if (fileInfo.isDirectory()) {
1041
- const remove = await this.project.confirm(`The orphaned package at ${common_1.highlight(filePath)} is currently checked out, are you sure you want to remove it?`, true);
1042
- if (remove)
1043
- await new Promise((resolve, reject) => rimraf(filePath, err => err ? reject(err) : resolve()));
1044
- else
1045
- deletedAll = false;
1046
- }
1047
- // ignore rogue files
1048
- else { }
1049
- }
1050
- // non package folder -> traverse
1051
- else if (fileInfo.isDirectory()) {
1052
- if (!(await removeNonPackageDirs(filePath)))
1053
- deletedAll = false;
1054
- }
1055
- // ignore rogue files
1056
- else { }
1057
- }));
1058
- if (deletedAll)
1059
- await new Promise((resolve, reject) => fs.rmdir(dir, err => err ? reject(err) : resolve()));
1060
- return deletedAll;
1061
- };
1062
- await removeNonPackageDirs(this.config.pjson.packages);
1063
- if (save)
1064
- return await this.config.save();
1065
- }
1066
- }
1067
- exports.Installer = Installer;
1068
- function depsToInstalls(defaultRegistry, deps, parent, skipDepsNames) {
1069
- let installs = [];
1070
- if (deps.dependencies)
1071
- Object.keys(deps.dependencies).forEach(name => {
1072
- if (skipDepsNames && skipDepsNames.indexOf(name) !== -1)
1073
- return;
1074
- let target = deps.dependencies[name];
1075
- if (target) {
1076
- if (typeof target !== 'string' && !target.registry)
1077
- target = target.fromRegistry(defaultRegistry);
1078
- installs.push({
1079
- name,
1080
- parent,
1081
- target,
1082
- type: package_1.DepType.secondary
1083
- });
1084
- }
1085
- });
1086
- if (deps.peerDependencies)
1087
- Object.keys(deps.peerDependencies).forEach(name => {
1088
- if (skipDepsNames && skipDepsNames.indexOf(name) !== -1)
1089
- return;
1090
- let target = deps.peerDependencies[name];
1091
- if (target) {
1092
- if (typeof target !== 'string' && !target.registry)
1093
- target = target.fromRegistry(defaultRegistry);
1094
- installs.push({
1095
- name,
1096
- parent,
1097
- target,
1098
- type: package_1.DepType.peer
1099
- });
1100
- }
1101
- });
1102
- if (deps.optionalDependencies)
1103
- Object.keys(deps.optionalDependencies).forEach(name => {
1104
- if (skipDepsNames && skipDepsNames.indexOf(name) !== -1)
1105
- return;
1106
- let target = deps.optionalDependencies[name];
1107
- if (target) {
1108
- if (typeof target !== 'string' && !target.registry)
1109
- target = target.fromRegistry(defaultRegistry);
1110
- installs.push({
1111
- name,
1112
- parent,
1113
- target,
1114
- type: package_1.DepType.secondary
1115
- });
1116
- }
1117
- });
1118
- return installs;
1119
- }
1120
- function getResourceName(source, projectPath) {
1121
- // if the resource is a folder, check the package.json file
1122
- if (source.startsWith('file:') || source.startsWith('link:')) {
1123
- const pjsonPath = path.resolve(projectPath, source.substr(5), 'package.json');
1124
- let pjsonSource;
1125
- try {
1126
- pjsonSource = fs.readFileSync(pjsonPath).toString();
1127
- }
1128
- catch (err) { }
1129
- if (pjsonSource) {
1130
- let pjson;
1131
- try {
1132
- pjson = JSON.parse(pjsonSource);
1133
- }
1134
- catch (err) {
1135
- throw new common_1.JspmUserError(`Invalid JSON parsing ${common_1.highlight(pjsonPath)}.`);
1136
- }
1137
- if (typeof pjson.name === 'string')
1138
- return pjson.name;
1139
- }
1140
- source = source.substr(0, 5) + path.resolve(projectPath, source.substr(5));
1141
- }
1142
- // get name simply from end of resource name
1143
- // name will be validated on install
1144
- const refIndex = source.lastIndexOf('#');
1145
- if (refIndex === -1) {
1146
- let pathIndex = source.lastIndexOf('/');
1147
- if (pathIndex === -1)
1148
- pathIndex = source.lastIndexOf('\\');
1149
- if (pathIndex === -1)
1150
- return source.substr(source.indexOf(':') + 1);
1151
- else
1152
- return source.substr(pathIndex + 1);
1153
- }
1154
- else {
1155
- let pathIndex = source.lastIndexOf('/', refIndex - 1);
1156
- if (pathIndex === -1)
1157
- pathIndex = source.lastIndexOf('\\', refIndex - 1);
1158
- if (pathIndex === -1)
1159
- return source.substring(source.indexOf(':') + 1, refIndex);
1160
- else
1161
- return source.substring(pathIndex + 1, refIndex);
1162
- }
1163
- }
1164
- //# sourceMappingURL=index.js.map