diff --git a/packages/addon-shim/src/index.ts b/packages/addon-shim/src/index.ts index e3510ea5f..678ad264e 100644 --- a/packages/addon-shim/src/index.ts +++ b/packages/addon-shim/src/index.ts @@ -4,6 +4,7 @@ import { AddonMeta, AddonInstance, isDeepAddonInstance, + PackageInfo, } from '@embroider/shared-internals'; import buildFunnel from 'broccoli-funnel'; import type { Node } from 'broccoli-node-api'; @@ -13,7 +14,7 @@ export interface ShimOptions { disabled?: (options: any) => boolean; } -function addonMeta(pkgJSON: any): AddonMeta { +function addonMeta(pkgJSON: PackageInfo): AddonMeta { let meta = pkgJSON['ember-addon']; if (meta?.version !== 2 || meta?.type !== 'addon') { throw new Error(`did not find valid v2 addon metadata in ${pkgJSON.name}`); @@ -22,7 +23,7 @@ function addonMeta(pkgJSON: any): AddonMeta { } export function addonV1Shim(directory: string, options: ShimOptions = {}) { - let pkg = JSON.parse( + let pkg: PackageInfo = JSON.parse( readFileSync(resolve(directory, './package.json'), 'utf8') ); @@ -42,7 +43,7 @@ export function addonV1Shim(directory: string, options: ShimOptions = {}) { return { name: pkg.name, included(this: AddonInstance, ...args: unknown[]) { - if (((this.parent.pkg as any)['ember-addon']?.version ?? 1) < 2) { + if ((this.parent.pkg['ember-addon']?.version ?? 1) < 2) { let autoImportVersion = this.parent.addons.find( (a) => a.name === 'ember-auto-import' )?.pkg.version; diff --git a/packages/compat/src/compat-utils.ts b/packages/compat/src/compat-utils.ts index d1a22b508..139bdf19f 100644 --- a/packages/compat/src/compat-utils.ts +++ b/packages/compat/src/compat-utils.ts @@ -1,10 +1,10 @@ import cloneDeep from 'lodash/cloneDeep'; -import { AddonMeta } from '@embroider/core'; +import { AddonMeta, PackageInfo } from '@embroider/core'; import resolve from 'resolve'; import { resolve as pathResolve } from 'path'; import { PluginItem } from '@babel/core'; -export function addPeerDependency(packageJSON: any, packageName: string, version = '*') { +export function addPeerDependency(packageJSON: PackageInfo, packageName: string, version = '*') { let pkg = cloneDeep(packageJSON); if (!pkg.peerDependencies) { pkg.peerDependencies = {}; diff --git a/packages/compat/src/default-pipeline.ts b/packages/compat/src/default-pipeline.ts index 17ce84c89..6dd10e553 100644 --- a/packages/compat/src/default-pipeline.ts +++ b/packages/compat/src/default-pipeline.ts @@ -1,5 +1,5 @@ import { App, Addons as CompatAddons, Options, PrebuiltAddons } from '.'; -import { toBroccoliPlugin, PackagerConstructor, Variant } from '@embroider/core'; +import { toBroccoliPlugin, PackagerConstructor, Variant, EmberAppInstance } from '@embroider/core'; import { Node } from 'broccoli-node-api'; import writeFile from 'broccoli-file-creator'; import mergeTrees from 'broccoli-merge-trees'; @@ -11,7 +11,7 @@ export interface PipelineOptions extends Options { } export default function defaultPipeline( - emberApp: object, + emberApp: EmberAppInstance, packager?: PackagerConstructor, options?: PipelineOptions ): Node { @@ -52,11 +52,11 @@ export default function defaultPipeline( return new BroccoliPackager(embroiderApp, variants, options && options.packagerOptions); } -function hasFastboot(emberApp: any) { - return emberApp.project.addons.find((a: any) => a.name === 'ember-cli-fastboot'); +function hasFastboot(emberApp: EmberAppInstance | EmberAppInstance) { + return emberApp.project.addons.find(a => a.name === 'ember-cli-fastboot'); } -function defaultVariants(emberApp: any): Variant[] { +function defaultVariants(emberApp: EmberAppInstance): Variant[] { let variants: Variant[] = []; if (emberApp.env === 'production') { variants.push({ diff --git a/packages/compat/src/v1-addon.ts b/packages/compat/src/v1-addon.ts index 0aeb5dfcf..c718fc5cc 100644 --- a/packages/compat/src/v1-addon.ts +++ b/packages/compat/src/v1-addon.ts @@ -11,7 +11,16 @@ import mergeTrees from 'broccoli-merge-trees'; import semver from 'semver'; import rewriteAddonTree from './rewrite-addon-tree'; import { mergeWithAppend } from './merges'; -import { AddonMeta, NodeTemplateCompiler, debug, PackageCache, Resolver, extensionsPattern } from '@embroider/core'; +import { + AddonMeta, + NodeTemplateCompiler, + debug, + PackageCache, + Resolver, + extensionsPattern, + AddonInstance, + AddonTreePath, +} from '@embroider/core'; import Options from './options'; import walkSync from 'walk-sync'; import ObserveTree from './observe-tree'; @@ -30,7 +39,7 @@ import { getEmberExports } from '@embroider/core/src/load-ember-template-compile import prepHtmlbarsAstPluginsForUnwrap from './prepare-htmlbars-ast-plugins'; import getRealAddon from './get-real-addon'; -const stockTreeNames = Object.freeze([ +const stockTreeNames: AddonTreePath[] = Object.freeze([ 'addon', 'addon-styles', 'styles', @@ -41,7 +50,7 @@ const stockTreeNames = Object.freeze([ 'vendor', // 'addon-templates' and 'templates are trees too, but they live inside // 'addon' and 'app' and we handle them there. -]); +]) as AddonTreePath[]; const dynamicTreeHooks = Object.freeze([ 'treeFor', @@ -114,7 +123,7 @@ class V1AddonCompatResolver implements Resolver { // v1 addon instance. export default class V1Addon { constructor( - protected addonInstance: any, + protected addonInstance: AddonInstance, protected addonOptions: Required, protected app: V1App, private packageCache: PackageCache, @@ -128,10 +137,10 @@ export default class V1Addon { // this is only defined when there are custom AST transforms that need it @Memoize() private get templateCompiler(): NodeTemplateCompiler | undefined { - let htmlbars = this.addonInstance.addons.find((a: any) => a.name === 'ember-cli-htmlbars'); + let htmlbars = this.addonInstance.addons.find(a => a.name === 'ember-cli-htmlbars'); if (htmlbars) { - let options = htmlbars.htmlbarsOptions() as HTMLBarsOptions; - if (options.plugins && options.plugins.ast) { + let options = (htmlbars as any).htmlbarsOptions() as HTMLBarsOptions; + if (options?.plugins?.ast) { // our macros don't run here in stage1 options.plugins.ast = options.plugins.ast.filter((p: any) => !isEmbroiderMacrosPlugin(p)); prepHtmlbarsAstPluginsForUnwrap(this.addonInstance.registry); @@ -288,7 +297,7 @@ export default class V1Addon { // shallow copy only! This is OK as long as we're only changing top-level // keys in this method let pkg = Object.assign({}, this.packageJSON); - let meta: AddonMeta = Object.assign({}, pkg.meta, this.packageMeta); + let meta: AddonMeta = Object.assign({}, this.packageCache.get(this.root).meta, this.packageMeta); pkg['ember-addon'] = meta; // classic addons don't get to customize their entrypoints like this. We @@ -311,7 +320,7 @@ export default class V1Addon { @Memoize() private get mainModule() { // eslint-disable-next-line @typescript-eslint/no-require-imports - const mod = require(this.addonInstance.constructor._meta_.modulePath); + const mod = require((this.addonInstance as unknown as any).constructor._meta_.modulePath); if (typeof mod === 'function') { return mod.prototype; @@ -373,7 +382,7 @@ export default class V1Addon { } @Memoize() - private hasStockTree(treeName: string): boolean { + private hasStockTree(treeName: AddonTreePath): boolean { if (this.suppressesTree(treeName)) { return false; } @@ -424,7 +433,7 @@ export default class V1Addon { } } - protected stockTree(treeName: string): Node { + protected stockTree(treeName: AddonTreePath): Node { return this.throughTreeCache(treeName, 'stock', () => { // adjust from the legacy "root" to our real root, because our rootTree // uses our real root but the stock trees are defined in terms of the @@ -457,7 +466,7 @@ export default class V1Addon { tree = this.addonInstance.preprocessJs(tree, '/', this.moduleName, { registry: this.addonInstance.registry, }); - if (this.addonInstance.shouldCompileTemplates() && this.addonInstance.registry.load('template').length > 0) { + if (this.addonInstance.shouldCompileTemplates() && this.addonInstance.registry.load('template')?.length > 0) { tree = this.app.preprocessRegistry.preprocessTemplates(tree, { registry: this.addonInstance.registry, }); @@ -574,7 +583,7 @@ export default class V1Addon { // a previous name was uncacheable, so we're entirely uncacheable return undefined; } - let key = this.addonInstance.cacheKeyForTree(name); + let key = this.addonInstance.cacheKeyForTree?.(name); if (key) { return accum + key; } else { @@ -638,6 +647,7 @@ export default class V1Addon { name: string, { neuterPreprocessors } = { neuterPreprocessors: false } ): Node | undefined { + // @ts-expect-error have no idea why throughTreeCache overload is not working here.. return this.throughTreeCache(name, 'original', () => { // get the real addon as we're going to patch and restore `preprocessJs` const realAddon = getRealAddon(this.addonInstance); @@ -977,7 +987,7 @@ export default class V1Addon { // getEngineConfigContents is an arbitrary customizable module, so we can't // easily rewrite it to live inside our conditional, so it's safer in a // separate module. - built.trees.push(writeFile('config/_environment_browser_.js', this.addonInstance.getEngineConfigContents())); + built.trees.push(writeFile('config/_environment_browser_.js', this.addonInstance.getEngineConfigContents?.())); built.trees.push( writeFile( 'config/environment.js', @@ -985,7 +995,7 @@ export default class V1Addon { import { macroCondition, getGlobalConfig, importSync } from '@embroider/macros'; let config; if (macroCondition(getGlobalConfig().fastboot?.isRunning)){ - config = ${JSON.stringify(this.addonInstance.engineConfig(this.app.env, {}), null, 2)}; + config = ${JSON.stringify(this.addonInstance.engineConfig?.(this.app.env, {}), null, 2)}; } else { config = importSync('./_environment_browser_.js').default; } diff --git a/packages/compat/src/v1-app.ts b/packages/compat/src/v1-app.ts index d8a92f7c3..5e35a6c3c 100644 --- a/packages/compat/src/v1-app.ts +++ b/packages/compat/src/v1-app.ts @@ -8,7 +8,17 @@ import resolve from 'resolve'; import { Node } from 'broccoli-node-api'; import { V1Config, WriteV1Config } from './v1-config'; import { WriteV1AppBoot, ReadV1AppBoot } from './v1-appboot'; -import { PackageCache, TemplateCompiler, TemplateCompilerPlugins, AddonMeta, Package } from '@embroider/core'; +import { + PackageCache, + TemplateCompiler, + TemplateCompilerPlugins, + AddonMeta, + Package, + EmberAppInstance, + OutputFileToInputFileMap, + PackageInfo, + AddonInstance, +} from '@embroider/core'; import { writeJSONSync, ensureDirSync, copySync, readdirSync, pathExistsSync, existsSync } from 'fs-extra'; import AddToTree from './add-to-tree'; import DummyPackage, { OwningAddon } from './dummy-package'; @@ -21,32 +31,15 @@ import SynthesizeTemplateOnlyComponents from './synthesize-template-only-compone import { isEmberAutoImportDynamic } from './detect-babel-plugins'; import prepHtmlbarsAstPluginsForUnwrap from './prepare-htmlbars-ast-plugins'; import { readFileSync } from 'fs'; +import type { Options as HTMLBarsOptions } from 'ember-cli-htmlbars'; import semver from 'semver'; // This controls and types the interface between our new world and the classic // v1 app instance. -type FilePath = string; -type OutputFileToInputFileMap = { [filePath: string]: FilePath[] }; - -interface EmberApp { - env: string; - name: string; - _scriptOutputFiles: OutputFileToInputFileMap; - _styleOutputFiles: OutputFileToInputFileMap; - legacyTestFilesToAppend: FilePath[]; - vendorTestStaticStyles: FilePath[]; - _customTransformsMap: Map; - _nodeModules: Map; - options: any; - tests: boolean; - trees: any; - project: any; - registry: any; - testIndex(): Node; - getLintTests(): Node; - otherAssetPaths: any[]; -} +type EmberCliHTMLBarsAddon = AddonInstance & { + htmlbarsOptions(): HTMLBarsOptions; +}; interface Group { outputFiles: OutputFileToInputFileMap; @@ -58,8 +51,8 @@ export default class V1App { // used to signal that this is a dummy app owned by a particular addon owningAddon: Package | undefined; - static create(app: EmberApp, packageCache: PackageCache): V1App { - if (app.project.pkg.keywords && app.project.pkg.keywords.includes('ember-addon')) { + static create(app: EmberAppInstance, packageCache: PackageCache): V1App { + if (app.project.pkg.keywords?.includes('ember-addon')) { // we are a dummy app, which is unfortunately weird and special return new V1DummyApp(app, packageCache); } else { @@ -71,7 +64,7 @@ export default class V1App { private _implicitScripts: string[] = []; private _implicitStyles: string[] = []; - protected constructor(protected app: EmberApp, protected packageCache: PackageCache) {} + protected constructor(protected app: EmberAppInstance, protected packageCache: PackageCache) {} // always the name from package.json. Not the one that apps may have weirdly // customized. @@ -436,10 +429,10 @@ export default class V1App { 'implicit-test-styles': this.app.vendorTestStaticStyles.map(remapAsset), 'public-assets': mapKeys(this._publicAssets, (_, key) => remapAsset(key)), }; - let meta = { + let meta: PackageInfo = { name: '@embroider/synthesized-vendor', version: '0.0.0', - keywords: 'ember-addon', + keywords: ['ember-addon'], 'ember-addon': addonMeta, }; writeJSONSync(join(outputPath, 'package.json'), meta, { spaces: 2 }); @@ -499,10 +492,10 @@ export default class V1App { addonMeta['public-assets']![`./assets/${file}`] = `/assets/${file}`; } } - let meta = { + let meta: PackageInfo = { name: '@embroider/synthesized-styles', version: '0.0.0', - keywords: 'ember-addon', + keywords: ['ember-addon'], 'ember-addon': addonMeta, }; writeJSONSync(join(outputPath, 'package.json'), meta, { spaces: 2 }); @@ -562,15 +555,17 @@ export default class V1App { } get htmlbarsPlugins(): TemplateCompilerPlugins { - let addon = this.app.project.addons.find((a: any) => a.name === 'ember-cli-htmlbars'); + let addon = this.app.project.addons.find( + (a: AddonInstance) => a.name === 'ember-cli-htmlbars' + ) as unknown as EmberCliHTMLBarsAddon; let options = addon.htmlbarsOptions(); - if (options.plugins.ast) { + if (options?.plugins?.ast) { // even if the app was using @embroider/macros, we drop it from the config // here in favor of our globally-configured one. options.plugins.ast = options.plugins.ast.filter((p: any) => !isEmbroiderMacrosPlugin(p)); prepHtmlbarsAstPluginsForUnwrap(this.app.registry); } - return options.plugins; + return options.plugins ?? {}; } // our own appTree. Not to be confused with the one that combines the app js @@ -747,7 +742,7 @@ function throwIfMissing( } class V1DummyApp extends V1App { - constructor(app: EmberApp, packageCache: PackageCache) { + constructor(app: EmberAppInstance, packageCache: PackageCache) { super(app, packageCache); this.owningAddon = new OwningAddon(this.app.project.root, packageCache); this.packageCache.seed(this.owningAddon); diff --git a/packages/compat/src/v1-instance-cache.ts b/packages/compat/src/v1-instance-cache.ts index 170cd7a1c..9897a2681 100644 --- a/packages/compat/src/v1-instance-cache.ts +++ b/packages/compat/src/v1-instance-cache.ts @@ -5,7 +5,7 @@ import V1App from './v1-app'; import V1Addon, { V1AddonConstructor } from './v1-addon'; import { pathExistsSync } from 'fs-extra'; -import { getOrCreate } from '@embroider/core'; +import { AddonInstance, getOrCreate } from '@embroider/core'; import { MovablePackageCache } from './moved-package-cache'; import Options from './options'; import isEqual from 'lodash/isEqual'; @@ -38,12 +38,12 @@ export default class V1InstanceCache { // no reason to do this on demand because oldApp already eagerly loaded // all descendants - (oldApp.project.addons as any[]).forEach(addon => { + (oldApp.project.addons as AddonInstance[]).forEach(addon => { this.addAddon(addon); }); } - private adapterClass(addonInstance: any): V1AddonConstructor { + private adapterClass(addonInstance: AddonInstance): V1AddonConstructor { let packageName = addonInstance.pkg.name; // if the user registered something (including "null", which allows // disabling the built-in adapters), that takes precedence. @@ -72,13 +72,13 @@ export default class V1InstanceCache { return AdapterClass; } - private addAddon(addonInstance: any) { + private addAddon(addonInstance: AddonInstance) { this.orderIdx += 1; let Klass = this.adapterClass(addonInstance); let v1Addon = new Klass(addonInstance, this.options, this.app, this.packageCache, this.orderIdx); let pkgs = getOrCreate(this.addons, v1Addon.root, () => []); pkgs.push(v1Addon); - (addonInstance.addons as any[]).forEach(a => this.addAddon(a)); + addonInstance.addons.forEach(a => this.addAddon(a)); } getAddons(root: string): V1Addon[] { diff --git a/packages/core/src/app.ts b/packages/core/src/app.ts index ff5a0330c..9af58d52e 100644 --- a/packages/core/src/app.ts +++ b/packages/core/src/app.ts @@ -5,6 +5,7 @@ import { AddonPackage, explicitRelative, extensionsPattern, + PackageInfo, } from '@embroider/shared-internals'; import { OutputPaths } from './wait-for-trees'; import { compile } from './js-handlebars'; @@ -624,7 +625,7 @@ export class AppBuilder { @Memoize() private get fastbootConfig(): - | { packageJSON: object; extraAppFiles: string[]; extraVendorFiles: string[] } + | { packageJSON: PackageInfo; extraAppFiles: string[]; extraVendorFiles: string[] } | undefined { if (this.activeFastboot) { // this is relying on work done in stage1 by @embroider/compat/src/compat-adapters/ember-cli-fastboot.ts diff --git a/packages/shared-internals/src/ember-cli-models.ts b/packages/shared-internals/src/ember-cli-models.ts index 02b4428f5..4047b30c7 100644 --- a/packages/shared-internals/src/ember-cli-models.ts +++ b/packages/shared-internals/src/ember-cli-models.ts @@ -1,18 +1,16 @@ +import type { Funnel } from 'broccoli-funnel'; import type { Node } from 'broccoli-node-api'; +import { PackageInfo } from './metadata'; export interface Project { targets: unknown; ui: { write(...args: any[]): void; }; - pkg: { - name: string; - version: string; - dependencies: Record; - devDependencies: Record; - }; + pkg: PackageInfo; root: string; addons: AddonInstance[]; name(): string; + configPath(): string; } export interface AppInstance { @@ -22,18 +20,97 @@ export interface AppInstance { addonPostprocessTree: (which: string, tree: Node) => Node; } +export type FilePath = string; +export type OutputFileToInputFileMap = { [filePath: string]: FilePath[] }; + +interface PreprocessPlugin { + name: string; + ext: string; +} +export interface EmberCliPreprocessRegistry { + extensionsForType(type: string): string[]; + load(type: string): PreprocessPlugin[]; + registeredForType(type: string): PreprocessPlugin[]; + add(type: string, plugin: PreprocessPlugin): void; + remove(type: string, pluginName: string): void; +} + +export interface EmberAppInstance { + env: 'development' | 'test' | 'production'; + name: string; + _scriptOutputFiles: OutputFileToInputFileMap; + _styleOutputFiles: OutputFileToInputFileMap; + legacyTestFilesToAppend: FilePath[]; + vendorTestStaticStyles: FilePath[]; + _customTransformsMap: Map; + _nodeModules: Map; + options: any; + tests: boolean; + trees: any; + project: Project; + registry: EmberCliPreprocessRegistry; + testIndex(): Node; + getLintTests(): Node; + otherAssetPaths: any[]; + addonPostprocessTree: (which: string, tree: Node) => Node; +} + interface BaseAddonInstance { + registry: EmberCliPreprocessRegistry; project: Project; - pkg: { name: string; version: string }; + pkg: PackageInfo; + app: { + options: any; + }; root: string; options: any; addons: AddonInstance[]; name: string; + _name: string; _super: any; + _meta_: any; + _buildFastbootConfigTree(config: any): Node; + _shouldIncludeFiles(): boolean; + outputReady(config: any): any; + moduleName?(): string; + shouldCompileTemplates(): boolean; + isDevelopingAddon?(): boolean; + hintingEnabled(): boolean; + jshintAddonTree(): Node | undefined; + preprocessJs(tree: Node, sep: any, moduleName: any, config: any): Node; + compileStyles(tree: Node): Node; + cacheKeyForTree?(treeName: string): string; + getEngineConfigContents?(): any; + engineConfig?(env: string, config: any): any; treeGenerator(path: string): Node; + treeForFastBoot(tree: Funnel | undefined): Node | undefined; _findHost(): AppInstance; + _treeFor(treeName: string): Node; + treePaths: { + // app: string; + // styles: string; + // templates: string; + // addon: 'addon'; + // 'addon-styles': string; + // 'addon-templates': string; + // vendor: string; + // 'test-support': string; + // 'addon-test-support': string; + // public: string; + + addon: string; + 'addon-styles': string; + styles: string; + 'addon-test-support': string; + 'test-support': string; + app: string; + public: string; + vendor: string; + }; } +export type AddonTreePath = keyof BaseAddonInstance['treePaths']; + export interface DeepAddonInstance extends BaseAddonInstance { // this is how it looks when an addon is beneath another addon parent: AddonInstance; diff --git a/packages/shared-internals/src/index.ts b/packages/shared-internals/src/index.ts index f08fef2af..f36cf2d27 100644 --- a/packages/shared-internals/src/index.ts +++ b/packages/shared-internals/src/index.ts @@ -1,4 +1,4 @@ -export { AppMeta, AddonMeta } from './metadata'; +export { AppMeta, AddonMeta, PackageInfo } from './metadata'; export { explicitRelative, extensionsPattern } from './paths'; export { getOrCreate } from './get-or-create'; export { default as Package, V2AddonPackage as AddonPackage, V2AppPackage as AppPackage, V2Package } from './package'; diff --git a/packages/shared-internals/src/metadata.ts b/packages/shared-internals/src/metadata.ts index e54ce944a..2806816d3 100644 --- a/packages/shared-internals/src/metadata.ts +++ b/packages/shared-internals/src/metadata.ts @@ -6,6 +6,7 @@ type AppRelativeURL = string; export interface AppMeta { type: 'app'; + main?: string; 'auto-upgraded'?: true; assets: Filename[]; babel: { @@ -27,6 +28,7 @@ export interface AppMeta { // addon. export interface AddonMeta { type: 'addon'; + main?: string; 'order-index'?: number; 'lazy-engine'?: boolean; @@ -47,3 +49,27 @@ export interface AddonMeta { 'renamed-modules'?: { [fromName: string]: string }; version: 2; } + +export interface PackageInfo { + keywords?: string[]; + name: string; + version: string; + main?: string; + module?: string; + exports?: Record; + peerDependencies?: Record; + devDependencies?: Record; + dependencies?: Record; + 'ember-addon': + | AddonMeta + | AppMeta + | { + main?: string; + // + version?: 1; + type?: 'addon' | 'app'; + paths?: string[]; + before?: string | string[]; + after?: string | string[]; + }; +} diff --git a/packages/shared-internals/src/package.ts b/packages/shared-internals/src/package.ts index 13e907df5..e9a413edd 100644 --- a/packages/shared-internals/src/package.ts +++ b/packages/shared-internals/src/package.ts @@ -2,10 +2,9 @@ import { Memoize } from 'typescript-memoize'; import { readFileSync, existsSync } from 'fs-extra'; import { join, extname } from 'path'; import get from 'lodash/get'; -import { AddonMeta, AppMeta } from './metadata'; +import { AddonMeta, AppMeta, PackageInfo } from './metadata'; import PackageCache from './package-cache'; import flatMap from 'lodash/flatMap'; - export default class Package { private dependencyKeys: ('dependencies' | 'devDependencies' | 'peerDependencies')[]; @@ -35,7 +34,7 @@ export default class Package { } @Memoize() - get packageJSON() { + get packageJSON(): PackageInfo { let json = this.internalPackageJSON; if (this.nonResolvableDeps) { if (!json.dependencies) { @@ -51,7 +50,7 @@ export default class Package { get meta(): AddonMeta | AppMeta | undefined { let m = this.packageJSON['ember-addon']; if (this.isV2App()) { - return m as AppMeta; + return m as unknown as AppMeta; } if (this.isV2Addon()) { return m as AddonMeta; @@ -69,7 +68,7 @@ export default class Package { } isLazyEngine(): boolean { - return this.isEngine() && this.packageJSON['ember-addon']['lazy-engine']; + return this.isEngine() && get(this.packageJSON, 'ember-addon.lazy-engine'); } isV2Ember(): this is V2Package { @@ -197,7 +196,7 @@ export default class Package { hasDependency(name: string): boolean { for (let section of this.dependencyKeys) { if (this.packageJSON[section]) { - if (this.packageJSON[section][name]) { + if ((this.packageJSON[section] as Record)[name]) { return true; } } diff --git a/types/ember-cli-htmlbars/index.d.ts b/types/ember-cli-htmlbars/index.d.ts index 3492f342d..c1bbb7ebc 100644 --- a/types/ember-cli-htmlbars/index.d.ts +++ b/types/ember-cli-htmlbars/index.d.ts @@ -3,12 +3,15 @@ declare module 'ember-cli-htmlbars' { import { Node } from 'broccoli-node-api'; export interface Options { - templateCompilerPath: string; name?: string; plugins?: { + ast?: never[]; [type: string]: unknown[]; }; - } + templateCompiler: unknown; + templateCompilerPath: string; + }; + export default class HTMLBarsTransform extends Plugin { constructor(inputTree: Node, options: Options);