Skip to content

Commit fb5c001

Browse files
committed
fix(@schematics/update): use npm get for everything except _authToken
For _authToken we read the npmrc in the global. We might need a better global solution for other flags, but this will have to do for now.
1 parent 84a53b0 commit fb5c001

File tree

1 file changed

+76
-23
lines changed
  • packages/schematics/update/update

1 file changed

+76
-23
lines changed

packages/schematics/update/update/npm.ts

Lines changed: 76 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,16 @@ import { logging } from '@angular-devkit/core';
99
import { exec } from 'child_process';
1010
import { readFileSync } from 'fs';
1111
import { Observable, ReplaySubject, concat, of } from 'rxjs';
12-
import { concatMap, defaultIfEmpty, filter, first, map, toArray } from 'rxjs/operators';
12+
import {
13+
catchError,
14+
concatMap,
15+
defaultIfEmpty,
16+
filter,
17+
first,
18+
map,
19+
shareReplay,
20+
toArray,
21+
} from 'rxjs/operators';
1322
import * as url from 'url';
1423
import { NpmRepositoryPackageJson } from './npm-package-json';
1524

@@ -18,6 +27,69 @@ const RegistryClient = require('npm-registry-client');
1827
const npmPackageJsonCache = new Map<string, Observable<NpmRepositoryPackageJson>>();
1928
const npmConfigOptionCache = new Map<string, Observable<string | undefined>>();
2029

30+
31+
function _readNpmRc(): Observable<{ [key: string]: string }> {
32+
return new Observable<{ [key: string]: string }>(subject => {
33+
// TODO: have a way to read options without using fs directly.
34+
const path = require('path');
35+
const fs = require('fs');
36+
37+
let npmrc = '';
38+
if (process.platform === 'win32') {
39+
if (process.env.LOCALAPPDATA) {
40+
npmrc = fs.readFileSync(path.join(process.env.LOCALAPPDATA, '.npmrc')).toString('utf-8');
41+
}
42+
} else {
43+
if (process.env.HOME) {
44+
npmrc = fs.readFileSync(path.join(process.env.HOME, '.npmrc')).toString('utf-8');
45+
}
46+
}
47+
48+
const allOptionsArr = npmrc.split(/\r?\n/).map(x => x.trim());
49+
const allOptions: { [key: string]: string } = {};
50+
51+
allOptionsArr.forEach(x => {
52+
const [key, ...value] = x.split('=');
53+
allOptions[key] = value.join('=');
54+
});
55+
56+
subject.next(allOptions);
57+
subject.complete();
58+
}).pipe(
59+
catchError(() => of({})),
60+
shareReplay(),
61+
);
62+
}
63+
64+
65+
function getOptionFromNpmRc(option: string): Observable<string | undefined> {
66+
return _readNpmRc().pipe(
67+
map(options => options[option]),
68+
);
69+
}
70+
71+
function getOptionFromNpmCli(option: string): Observable<string | undefined> {
72+
return new Observable<string | undefined>(subject => {
73+
exec(`npm get ${option}`, (error, data) => {
74+
if (error) {
75+
throw error;
76+
} else {
77+
data = data.trim();
78+
if (!data || data === 'undefined' || data === 'null') {
79+
subject.next();
80+
} else {
81+
subject.next(data);
82+
}
83+
}
84+
85+
subject.complete();
86+
});
87+
}).pipe(
88+
catchError(() => of()),
89+
shareReplay(),
90+
);
91+
}
92+
2193
function getNpmConfigOption(
2294
option: string,
2395
scope?: string,
@@ -41,29 +113,10 @@ function getNpmConfigOption(
41113
return value;
42114
}
43115

44-
const subject = new ReplaySubject<string | undefined>(1);
45-
46-
try {
47-
exec(`npm get ${fullOption}`, (error, data) => {
48-
if (error) {
49-
subject.next();
50-
} else {
51-
data = data.trim();
52-
if (!data || data === 'undefined' || data === 'null') {
53-
subject.next();
54-
} else {
55-
subject.next(data);
56-
}
57-
}
58-
59-
subject.complete();
60-
});
61-
} catch {
62-
subject.next();
63-
subject.complete();
64-
}
116+
value = option.startsWith('_')
117+
? getOptionFromNpmRc(fullOption)
118+
: getOptionFromNpmCli(fullOption);
65119

66-
value = subject.asObservable();
67120
npmConfigOptionCache.set(fullOption, value);
68121

69122
return value;

0 commit comments

Comments
 (0)