UNPKG

@parcel/core

Version:
295 lines (290 loc) • 10.8 kB
"use strict"; 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;