@parcel/core
Version:
295 lines (290 loc) • 10.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.EntryResolver = void 0;
exports.default = createEntryRequest;
function _utils() {
const data = require("@parcel/utils");
_utils = function () {
return data;
};
return data;
}
function _diagnostic() {
const data = _interopRequireWildcard(require("@parcel/diagnostic"));
_diagnostic = function () {
return data;
};
return data;
}
function _path() {
const data = _interopRequireDefault(require("path"));
_path = function () {
return data;
};
return data;
}
function _jsonSourcemap() {
const data = require("@mischnic/json-sourcemap");
_jsonSourcemap = function () {
return data;
};
return data;
}
var _RequestTracker = require("../RequestTracker");
var _projectPath = require("../projectPath");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const type = 'entry_request';
function createEntryRequest(input) {
return {
id: `${type}:${(0, _projectPath.fromProjectPathRelative)(input)}`,
type: _RequestTracker.requestTypes.entry_request,
run,
input
};
}
async function run({
input,
api,
options
}) {
let entryResolver = new EntryResolver(options);
let filePath = (0, _projectPath.fromProjectPath)(options.projectRoot, input);
let result = await entryResolver.resolveEntry(filePath);
// Connect files like package.json that affect the entry
// resolution so we invalidate when they change.
for (let file of result.files) {
api.invalidateOnFileUpdate(file.filePath);
api.invalidateOnFileDelete(file.filePath);
}
// If the entry specifier is a glob, add a glob node so
// we invalidate when a new file matches.
for (let glob of result.globs) {
api.invalidateOnFileCreate({
glob: (0, _projectPath.toProjectPath)(options.projectRoot, glob)
});
}
// Invalidate whenever an entry is deleted.
// If the entry was a glob, we'll re-evaluate it, and otherwise
// a proper entry error will be thrown.
for (let entry of result.entries) {
api.invalidateOnFileDelete(entry.filePath);
}
return result;
}
async function assertFile(fs, entry, relativeSource, pkgFilePath, keyPath, options) {
let source = _path().default.join(entry, relativeSource);
let stat;
try {
stat = await fs.stat(source);
} catch (err) {
let contents = await fs.readFile(pkgFilePath, 'utf8');
let alternatives = await (0, _utils().findAlternativeFiles)(fs, relativeSource, entry, options.projectRoot, false);
throw new (_diagnostic().default)({
diagnostic: {
origin: '@parcel/core',
message: (0, _diagnostic().md)`${_path().default.relative(process.cwd(), source)} does not exist.`,
codeFrames: [{
filePath: pkgFilePath,
codeHighlights: (0, _diagnostic().generateJSONCodeHighlights)(contents, [{
key: keyPath,
type: 'value'
}])
}],
hints: alternatives.map(r => {
return (0, _diagnostic().md)`Did you mean '__${r}__'?`;
})
}
});
}
if (!stat.isFile()) {
let contents = await fs.readFile(pkgFilePath, 'utf8');
throw new (_diagnostic().default)({
diagnostic: {
origin: '@parcel/core',
message: (0, _diagnostic().md)`${_path().default.relative(process.cwd(), source)} is not a file.`,
codeFrames: [{
filePath: pkgFilePath,
codeHighlights: (0, _diagnostic().generateJSONCodeHighlights)(contents, [{
key: keyPath,
type: 'value'
}])
}]
}
});
}
}
class EntryResolver {
constructor(options) {
this.options = options;
}
async resolveEntry(entry) {
let stat;
try {
stat = await this.options.inputFS.stat(entry);
} catch (err) {
if (!(0, _utils().isGlob)(entry)) {
throw new (_diagnostic().default)({
diagnostic: {
message: (0, _diagnostic().md)`Entry ${entry} does not exist`
}
});
}
let files = await (0, _utils().glob)(entry, this.options.inputFS, {
absolute: true,
onlyFiles: false
});
let results = await Promise.all(files.map(f => this.resolveEntry(_path().default.normalize(f))));
return results.reduce((p, res) => ({
entries: p.entries.concat(res.entries),
files: p.files.concat(res.files),
globs: p.globs.concat(res.globs)
}), {
entries: [],
files: [],
globs: [entry]
});
}
if (stat.isDirectory()) {
let pkg = await this.readPackage(entry);
if (pkg) {
let {
filePath
} = pkg;
let entries = [];
let files = [{
filePath: (0, _projectPath.toProjectPath)(this.options.projectRoot, filePath)
}];
let globs = [];
let targetsWithSources = 0;
if (pkg.targets) {
for (let targetName in pkg.targets) {
let target = pkg.targets[targetName];
if (target.source != null) {
targetsWithSources++;
let targetSources = Array.isArray(target.source) ? target.source : [target.source];
let i = 0;
for (let source of targetSources) {
let sources;
if ((0, _utils().isGlob)(source)) {
globs.push(source);
sources = await (0, _utils().glob)(source, this.options.inputFS, {
onlyFiles: true,
cwd: entry
});
} else {
sources = [source];
}
let keyPath = `/targets/${targetName}/source${Array.isArray(target.source) ? `/${i}` : ''}`;
for (let relativeSource of sources) {
let source = _path().default.join(entry, relativeSource);
await assertFile(this.options.inputFS, entry, relativeSource, filePath, keyPath, this.options);
entries.push({
filePath: (0, _projectPath.toProjectPath)(this.options.projectRoot, source),
packagePath: (0, _projectPath.toProjectPath)(this.options.projectRoot, entry),
target: targetName,
loc: {
filePath: (0, _projectPath.toProjectPath)(this.options.projectRoot, pkg.filePath),
...(0, _diagnostic().getJSONSourceLocation)(pkg.map.pointers[keyPath], 'value')
}
});
}
i++;
}
}
}
}
let allTargetsHaveSource = targetsWithSources > 0 && pkg != null && pkg.targets != null && Object.keys(pkg.targets).length === targetsWithSources;
if (!allTargetsHaveSource && pkg.source != null) {
let pkgSources = Array.isArray(pkg.source) ? pkg.source : [pkg.source];
let i = 0;
for (let pkgSource of pkgSources) {
let sources;
if ((0, _utils().isGlob)(pkgSource)) {
globs.push(pkgSource);
sources = await (0, _utils().glob)(pkgSource, this.options.inputFS, {
onlyFiles: true,
cwd: _path().default.dirname(filePath)
});
} else {
sources = [pkgSource];
}
let keyPath = `/source${Array.isArray(pkg.source) ? `/${i}` : ''}`;
for (let relativeSource of sources) {
let source = _path().default.join(_path().default.dirname(filePath), relativeSource);
await assertFile(this.options.inputFS, entry, relativeSource, filePath, keyPath, this.options);
entries.push({
filePath: (0, _projectPath.toProjectPath)(this.options.projectRoot, source),
packagePath: (0, _projectPath.toProjectPath)(this.options.projectRoot, entry),
loc: {
filePath: (0, _projectPath.toProjectPath)(this.options.projectRoot, pkg.filePath),
...(0, _diagnostic().getJSONSourceLocation)(pkg.map.pointers[keyPath], 'value')
}
});
}
i++;
}
}
// Only return if we found any valid entries
if (entries.length && files.length) {
return {
entries,
files,
globs
};
}
}
throw new (_diagnostic().default)({
diagnostic: {
message: (0, _diagnostic().md)`Could not find entry: ${entry}`
}
});
} else if (stat.isFile()) {
let projectRoot = this.options.projectRoot;
let packagePath = (0, _utils().isDirectoryInside)(this.options.inputFS.cwd(), projectRoot) ? this.options.inputFS.cwd() : projectRoot;
return {
entries: [{
filePath: (0, _projectPath.toProjectPath)(this.options.projectRoot, entry),
packagePath: (0, _projectPath.toProjectPath)(this.options.projectRoot, packagePath)
}],
files: [],
globs: []
};
}
throw new (_diagnostic().default)({
diagnostic: {
message: (0, _diagnostic().md)`Unknown entry: ${entry}`
}
});
}
async readPackage(entry) {
let content, pkg;
let pkgFile = _path().default.join(entry, 'package.json');
try {
content = await this.options.inputFS.readFile(pkgFile, 'utf8');
} catch (err) {
return null;
}
try {
pkg = JSON.parse(content);
} catch (err) {
// TODO: code frame?
throw new (_diagnostic().default)({
diagnostic: {
message: (0, _diagnostic().md)`Error parsing ${_path().default.relative(this.options.inputFS.cwd(), pkgFile)}: ${err.message}`
}
});
}
return {
...pkg,
filePath: pkgFile,
map: (0, _jsonSourcemap().parse)(content, undefined, {
tabWidth: 1
})
};
}
}
exports.EntryResolver = EntryResolver;