Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 658aebe

Browse files
SimenBljharb
authored andcommittedJan 30, 2021
[New] add readPackage and readPackageSync
1 parent 4bece07 commit 658aebe

File tree

5 files changed

+152
-15
lines changed

5 files changed

+152
-15
lines changed
 

‎lib/async.js

+21-6
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,20 @@ var maybeRealpath = function maybeRealpath(realpath, x, opts, cb) {
4242
}
4343
};
4444

45+
var defaultReadPackage = function defaultReadPackage(readFile, pkgfile, cb) {
46+
readFile(pkgfile, function (readFileErr, body) {
47+
if (readFileErr) cb(readFileErr);
48+
else {
49+
try {
50+
var pkg = JSON.parse(body);
51+
cb(null, pkg);
52+
} catch (jsonErr) {
53+
cb(null);
54+
}
55+
}
56+
});
57+
};
58+
4559
var getPackageCandidates = function getPackageCandidates(x, start, opts) {
4660
var dirs = nodeModulesPaths(start, opts, x);
4761
for (var i = 0; i < dirs.length; i++) {
@@ -70,6 +84,7 @@ module.exports = function resolve(x, options, callback) {
7084
var isDirectory = opts.isDirectory || defaultIsDir;
7185
var readFile = opts.readFile || fs.readFile;
7286
var realpath = opts.realpath || defaultRealpath;
87+
var readPackage = opts.readPackage || defaultReadPackage;
7388
var packageIterator = opts.packageIterator;
7489

7590
var extensions = opts.extensions || ['.js'];
@@ -211,9 +226,10 @@ module.exports = function resolve(x, options, callback) {
211226
// on err, ex is false
212227
if (!ex) return loadpkg(path.dirname(dir), cb);
213228

214-
readFile(pkgfile, function (err, body) {
229+
readPackage(readFile, pkgfile, function (err, pkgParam) {
215230
if (err) cb(err);
216-
try { var pkg = JSON.parse(body); } catch (jsonErr) {}
231+
232+
var pkg = pkgParam;
217233

218234
if (pkg && opts.packageFilter) {
219235
pkg = opts.packageFilter(pkg, pkgfile, dir);
@@ -239,11 +255,10 @@ module.exports = function resolve(x, options, callback) {
239255
if (err) return cb(err);
240256
if (!ex) return loadAsFile(path.join(x, 'index'), fpkg, cb);
241257

242-
readFile(pkgfile, function (err, body) {
258+
readPackage(readFile, pkgfile, function (err, pkgParam) {
243259
if (err) return cb(err);
244-
try {
245-
var pkg = JSON.parse(body);
246-
} catch (jsonErr) {}
260+
261+
var pkg = pkgParam;
247262

248263
if (pkg && opts.packageFilter) {
249264
pkg = opts.packageFilter(pkg, pkgfile, pkgdir);

‎lib/sync.js

+11-7
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ var maybeRealpathSync = function maybeRealpathSync(realpathSync, x, opts) {
4545
return x;
4646
};
4747

48+
var defaultReadPackageSync = function defaultReadPackageSync(readFileSync, pkgfile) {
49+
var body = readFileSync(pkgfile);
50+
try {
51+
var pkg = JSON.parse(body);
52+
return pkg;
53+
} catch (jsonErr) {}
54+
};
55+
4856
var getPackageCandidates = function getPackageCandidates(x, start, opts) {
4957
var dirs = nodeModulesPaths(start, opts, x);
5058
for (var i = 0; i < dirs.length; i++) {
@@ -63,6 +71,7 @@ module.exports = function resolveSync(x, options) {
6371
var isDirectory = opts.isDirectory || defaultIsDir;
6472
var readFileSync = opts.readFileSync || fs.readFileSync;
6573
var realpathSync = opts.realpathSync || defaultRealpathSync;
74+
var readPackageSync = opts.readPackageSync || defaultReadPackageSync;
6675
var packageIterator = opts.packageIterator;
6776

6877
var extensions = opts.extensions || ['.js'];
@@ -133,11 +142,7 @@ module.exports = function resolveSync(x, options) {
133142
return loadpkg(path.dirname(dir));
134143
}
135144

136-
var body = readFileSync(pkgfile);
137-
138-
try {
139-
var pkg = JSON.parse(body);
140-
} catch (jsonErr) {}
145+
var pkg = readPackageSync(readFileSync, pkgfile);
141146

142147
if (pkg && opts.packageFilter) {
143148
pkg = opts.packageFilter(pkg, pkgfile, dir);
@@ -150,8 +155,7 @@ module.exports = function resolveSync(x, options) {
150155
var pkgfile = path.join(isDirectory(x) ? maybeRealpathSync(realpathSync, x, opts) : x, '/package.json');
151156
if (isFile(pkgfile)) {
152157
try {
153-
var body = readFileSync(pkgfile, 'UTF8');
154-
var pkg = JSON.parse(body);
158+
var pkg = readPackageSync(readFileSync, pkgfile);
155159
} catch (e) {}
156160

157161
if (pkg && opts.packageFilter) {

‎readme.markdown

+29-2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,10 @@ options are:
7171

7272
* opts.realpath - function to asynchronously resolve a potential symlink to its real path
7373

74-
* opts.realpath - function to asynchronously resolve a potential symlink to its real path
74+
* `opts.readPackage(readFile, pkgfile, cb)` - function to asynchronously read and parse a package.json file
75+
* readFile - the passed `opts.readFile` or `fs.readFile` if not specified
76+
* pkgfile - path to package.json
77+
* cb - callback
7578

7679
* `opts.packageFilter(pkg, pkgfile, dir)` - transform the parsed package.json contents before looking at the "main" field
7780
* pkg - package data
@@ -137,6 +140,19 @@ default `opts` values:
137140
else cb(null, realPathErr ? file : realPath);
138141
});
139142
},
143+
readPackage: function defaultReadPackage(readFile, pkgfile, cb) {
144+
readFile(pkgfile, function (readFileErr, body) {
145+
if (readFileErr) cb(readFileErr);
146+
else {
147+
try {
148+
var pkg = JSON.parse(body);
149+
cb(null, pkg);
150+
} catch (jsonErr) {
151+
cb(null);
152+
}
153+
}
154+
});
155+
},
140156
moduleDirectory: 'node_modules',
141157
preserveSymlinks: false
142158
}
@@ -155,14 +171,18 @@ options are:
155171

156172
* opts.includeCoreModules - set to `false` to exclude node core modules (e.g. `fs`) from the search
157173

158-
* opts.readFile - how to read files synchronously
174+
* opts.readFileSync - how to read files synchronously
159175

160176
* opts.isFile - function to synchronously test whether a file exists
161177

162178
* opts.isDirectory - function to synchronously test whether a file exists and is a directory
163179

164180
* opts.realpathSync - function to synchronously resolve a potential symlink to its real path
165181

182+
* `opts.readPackageSync(readFileSync, pkgfile)` - function to synchronously read and parse a package.json file
183+
* readFileSync - the passed `opts.readFileSync` or `fs.readFileSync` if not specified
184+
* pkgfile - path to package.json
185+
166186
* `opts.packageFilter(pkg, pkgfile, dir)` - transform the parsed package.json contents before looking at the "main" field
167187
* pkg - package data
168188
* pkgfile - path to package.json
@@ -231,6 +251,13 @@ default `opts` values:
231251
}
232252
return file;
233253
},
254+
readPackageSync: function defaultReadPackageSync(readFileSync, pkgfile) {
255+
var body = readFileSync(pkgfile);
256+
try {
257+
var pkg = JSON.parse(body);
258+
return pkg;
259+
} catch (jsonErr) {}
260+
},
234261
moduleDirectory: 'node_modules',
235262
preserveSymlinks: false
236263
}

‎test/mock.js

+46
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,49 @@ test('symlinked', function (t) {
237237
t.equal(pkg, undefined);
238238
});
239239
});
240+
241+
test('readPackage', function (t) {
242+
t.plan(2);
243+
244+
var files = {};
245+
files[path.resolve('/foo/node_modules/bar/something-else.js')] = 'beep';
246+
files[path.resolve('/foo/node_modules/bar/package.json')] = JSON.stringify({
247+
main: './baz.js'
248+
});
249+
250+
var dirs = {};
251+
dirs[path.resolve('/foo')] = true;
252+
dirs[path.resolve('/foo/node_modules')] = true;
253+
254+
function opts(basedir) {
255+
return {
256+
basedir: path.resolve(basedir),
257+
isFile: function (file, cb) {
258+
cb(null, Object.prototype.hasOwnProperty.call(files, path.resolve(file)));
259+
},
260+
isDirectory: function (dir, cb) {
261+
cb(null, !!dirs[path.resolve(dir)]);
262+
},
263+
'package': { main: 'bar' },
264+
readFile: function (file, cb) {
265+
cb(null, files[path.resolve(file)]);
266+
},
267+
realpath: function (file, cb) {
268+
cb(null, file);
269+
},
270+
readPackage: function (readFile, file, cb) {
271+
if (file.indexOf(path.join('bar', 'package.json')) >= 0) {
272+
cb(null, { main: './something-else.js' });
273+
} else {
274+
cb(null, JSON.parse(files[path.resolve(file)]));
275+
}
276+
}
277+
};
278+
}
279+
280+
resolve('bar', opts('/foo'), function (err, res, pkg) {
281+
if (err) return t.fail(err);
282+
t.equal(res, path.resolve('/foo/node_modules/bar/something-else.js'));
283+
t.equal(pkg && pkg.main, './something-else.js');
284+
});
285+
});

‎test/mock_sync.js

+45
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,48 @@ test('symlinked', function (t) {
140140
path.resolve('/foo/bar/symlinked/baz.js')
141141
);
142142
});
143+
144+
test('readPackageSync', function (t) {
145+
t.plan(1);
146+
147+
var files = {};
148+
files[path.resolve('/foo/node_modules/bar/something-else.js')] = 'beep';
149+
files[path.resolve('/foo/node_modules/bar/package.json')] = JSON.stringify({
150+
main: './baz.js'
151+
});
152+
153+
var dirs = {};
154+
dirs[path.resolve('/foo')] = true;
155+
dirs[path.resolve('/foo/node_modules')] = true;
156+
157+
function opts(basedir) {
158+
return {
159+
basedir: path.resolve(basedir),
160+
isFile: function (file) {
161+
return Object.prototype.hasOwnProperty.call(files, path.resolve(file));
162+
},
163+
isDirectory: function (dir) {
164+
return !!dirs[path.resolve(dir)];
165+
},
166+
readFileSync: function (file) {
167+
return files[path.resolve(file)];
168+
},
169+
realpathSync: function (file) {
170+
return file;
171+
},
172+
readPackageSync: function (readFileSync, file) {
173+
if (file.indexOf(path.join('bar', 'package.json')) >= 0) {
174+
return { main: './something-else.js' };
175+
} else {
176+
return JSON.parse(files[path.resolve(file)]);
177+
}
178+
}
179+
};
180+
}
181+
182+
t.equal(
183+
resolve.sync('bar', opts('/foo')),
184+
path.resolve('/foo/node_modules/bar/something-else.js')
185+
);
186+
});
187+

0 commit comments

Comments
 (0)
Please sign in to comment.