UNPKG

ember-auto-import

Version:
285 lines 13.3 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const splitter_1 = __importDefault(require("./splitter")); const bundler_1 = require("./bundler"); const analyzer_1 = __importDefault(require("./analyzer")); const package_1 = __importDefault(require("./package")); const broccoli_debug_1 = __importDefault(require("broccoli-debug")); const bundle_config_1 = __importDefault(require("./bundle-config")); const leader_1 = require("./leader"); const shared_internals_1 = require("@embroider/shared-internals"); const webpack_1 = __importDefault(require("./webpack")); const typescript_memoize_1 = require("typescript-memoize"); const broccoli_source_1 = require("broccoli-source"); const inserter_1 = require("./inserter"); const broccoli_merge_trees_1 = __importDefault(require("broccoli-merge-trees")); const resolve_1 = __importDefault(require("resolve")); const resolve_package_path_1 = __importDefault(require("resolve-package-path")); const semver_1 = __importDefault(require("semver")); const analyzer_syntax_1 = require("./analyzer-syntax"); const path_1 = __importDefault(require("path")); const broccoli_funnel_1 = __importDefault(require("broccoli-funnel")); const debug_1 = __importDefault(require("debug")); const reverse_exports_1 = require("@embroider/reverse-exports"); const debugTree = broccoli_debug_1.default.buildDebugCallback('ember-auto-import'); const debugWatch = (0, debug_1.default)('ember-auto-import:watch'); class AutoImport { static register(addon) { leader_1.LeaderChooser.for(addon).register(addon, () => new AutoImport(addon)); } static lookup(addon) { return leader_1.LeaderChooser.for(addon).leader; } constructor(addonInstance) { this.packages = new Set(); this.analyzers = new Map(); // maps packageName to packageRoot this.v2Addons = new Map(); let topmostAddon = (0, shared_internals_1.findTopmostAddon)(addonInstance); this.packageCache = shared_internals_1.PackageCache.shared('ember-auto-import', topmostAddon.project.root); this.packages.add(package_1.default.lookupParentOf(topmostAddon, this.v2AddonResolver)); let host = topmostAddon.app; this.installAppFilter(host); this.env = host.env; this.bundles = new bundle_config_1.default(host.options.outputPaths); if (!this.env) { throw new Error('Bug in ember-auto-import: did not discover environment'); } this.consoleWrite = (...args) => addonInstance.project.ui.write(...args); } installAppFilter(_host) { // TODO upstream this type change to @embroider/shared-internals let host = _host; if (this.rootPackage.allowAppImports.length) { host.trees.app = (0, broccoli_funnel_1.default)(host.trees.app, { exclude: this.rootPackage.allowAppImports, }); } } // we don't actually call this ourselves anymore, but earlier versions of // ember-auto-import will still call it on us. For them the answer is always // false. isPrimary(_addon) { return false; } analyze(tree, addon, treeType, supportsFastAnalyzer) { let pack = package_1.default.lookupParentOf(addon, this.v2AddonResolver); this.packages.add(pack); let analyzer = new analyzer_1.default(debugTree(tree, `preprocessor:input-${this.analyzers.size}`), pack, treeType, supportsFastAnalyzer); this.analyzers.set(analyzer, pack); return analyzer; } registerV2Addon(packageName, packageRoot, options = {}) { this.v2Addons.set(packageName, { root: packageRoot, options }); } get v2AddonResolver() { return { hasV2Addon: (name) => { return this.v2Addons.has(name); }, v2AddonRoot: (name) => { var _a; return (_a = this.v2Addons.get(name)) === null || _a === void 0 ? void 0 : _a.root; }, handleRenaming: (name) => { let hit = this.renamedModules().get(name); if (hit) { return hit; } hit = this.renamedModules().get(name + '.js'); if (hit) { return hit; } hit = this.renamedModules().get(name + '/index.js'); if (hit) { return hit; } return name; }, implicitImports: (kind, packageRoot) => { var _a, _b; let output = []; for (let dep of this.packageCache.get(packageRoot).dependencies) { if (dep.isV2Addon()) { let meta = dep.meta; let customize = (_b = (_a = this.v2Addons.get(dep.name)) === null || _a === void 0 ? void 0 : _a.options) === null || _b === void 0 ? void 0 : _b.customizeMeta; if (customize) { // json here is just a super simple clone so the hook can't mutate // our cache unintentionally meta = customize(JSON.parse(JSON.stringify(meta))); } let implicitModules = meta[kind]; if (implicitModules) { for (let localPath of implicitModules) { let specifier = (0, reverse_exports_1.externalName)(dep.packageJSON, localPath); if (!specifier) { throw new Error(`${dep.name} declared implicit-module ${localPath} but that is not accessible outside the package`); } if (meta['renamed-modules']) { for (let [renamed, original] of Object.entries(meta['renamed-modules'])) { if (specifier === original) { specifier = renamed; } } } if (specifier.endsWith('.js')) { specifier = specifier.slice(0, -3); } output.push(specifier); } } } } return output; }, }; } renamedModules() { if (!this._renamedModules) { this._renamedModules = new Map(); for (let { root, options } of this.v2Addons.values()) { let pkg = this.packageCache.get(root); if (pkg.isV2Addon()) { let meta = pkg.meta; if (options.customizeMeta) { // json here is just a super simple clone so the hook can't mutate // our cache unintentionally meta = options.customizeMeta(JSON.parse(JSON.stringify(meta))); } let renamedModules = meta['renamed-modules']; if (renamedModules) { for (let [from, to] of Object.entries(renamedModules)) { this._renamedModules.set(from, to); } } } } } return this._renamedModules; } makeBundler(allAppTree) { // The Splitter takes the set of imports from the Analyzer and // decides which ones to include in which bundles let splitter = new splitter_1.default({ analyzers: this.analyzers, bundles: this.bundles, }); let webpack; const pkg = (0, resolve_package_path_1.default)('webpack', this.rootPackage.root); // eslint-disable-next-line @typescript-eslint/no-var-requires if (pkg && semver_1.default.satisfies(require(pkg).version, '^5.0.0')) { // eslint-disable-next-line @typescript-eslint/no-var-requires webpack = require(resolve_1.default.sync('webpack', { basedir: this.rootPackage.root, })); } else { throw new Error(`[ember-auto-import] this version of ember-auto-import requires the app to have a dependency on webpack 5`); } // The Bundler asks the splitter for deps it should include and // is responsible for packaging those deps up. return new webpack_1.default(depsFor(allAppTree, this.packages), { splitter, environment: this.env, packages: this.packages, consoleWrite: this.consoleWrite, bundles: this.bundles, webpack, rootPackage: this.rootPackage, v2AddonResolver: this.v2AddonResolver, }); } get rootPackage() { let rootPackage = [...this.packages.values()].find((pkg) => !pkg.isAddon); if (!rootPackage) { throw new Error(`bug in ember-auto-import, there should always be a Package representing the app`); } return rootPackage; } addTo(allAppTree) { let bundler = (0, bundler_1.debugBundler)(this.makeBundler(allAppTree), 'output'); let inserter = new inserter_1.Inserter(allAppTree, bundler, this.bundles, { publicAssetURL: this.rootPackage.publicAssetURL(), insertScriptsAt: this.rootPackage.insertScriptsAt, insertStylesAt: this.rootPackage.insertStylesAt, }); let trees = [allAppTree, bundler, inserter]; return (0, broccoli_merge_trees_1.default)(trees, { overwrite: true }); } // CAUTION: versions <= 2.1.0 only invoked this method on the app's copy of // ember-auto-import, whereas we now invoke it on every copy. That means you // can't guarantee this will be called for an addon that is using one of those // older versions. included(addonInstance) { this.installBabelPlugin(addonInstance); if (!(0, shared_internals_1.isDeepAddonInstance)(addonInstance)) { this.configureFingerprints(addonInstance.app); } } installBabelPlugin(addonInstance) { let parent; if ((0, shared_internals_1.isDeepAddonInstance)(addonInstance)) { parent = addonInstance.parent; } else { parent = addonInstance.app; } let babelOptions = (parent.options.babel = parent.options.babel || {}); let babelPlugins = (babelOptions.plugins = babelOptions.plugins || []); if (!babelPlugins.some(isAnalyzerPlugin)) { // the MARKER is included so that babel caches will invalidate if the // MARKER changes babelPlugins.unshift([require.resolve('./analyzer-plugin'), { MARKER: analyzer_syntax_1.MARKER }]); } } // We need to disable fingerprinting of chunks, because (1) they already // have their own webpack-generated hashes and (2) the runtime loader code // can't easily be told about broccoli-asset-rev's hashes. configureFingerprints(host) { let patterns = ['assets/chunk.*.js', 'assets/chunk.*.css']; if (!host.options.fingerprint) { host.options.fingerprint = {}; } if (!('exclude' in host.options.fingerprint)) { host.options.fingerprint.exclude = patterns; } else { for (let pattern of patterns) { host.options.fingerprint.exclude.push(pattern); } } } } exports.default = AutoImport; __decorate([ (0, typescript_memoize_1.Memoize)() ], AutoImport.prototype, "rootPackage", null); function depsFor(allAppTree, packages) { let deps = [allAppTree]; for (let pkg of packages) { let watched = pkg.watchedDirectories; if (watched) { deps = deps.concat(watched.map((dir) => new broccoli_source_1.WatchedDir(dir))); debugWatch(`Adding watched directories: ${watched.join(', ')}`); } } return deps; } function isAnalyzerPlugin(entry) { const suffix = path_1.default.join('ember-auto-import', 'js', 'analyzer-plugin.js'); return ((typeof entry === 'string' && entry.endsWith(suffix)) || (Array.isArray(entry) && typeof entry[0] === 'string' && entry[0].endsWith(suffix))); } //# sourceMappingURL=auto-import.js.map