Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: improve package json typings #955

Merged
merged 1 commit into from
Sep 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions packages/addon-shim/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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}`);
Expand All @@ -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')
);

Expand All @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions packages/compat/src/compat-utils.ts
Original file line number Diff line number Diff line change
@@ -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 = {};
Expand Down
10 changes: 5 additions & 5 deletions packages/compat/src/default-pipeline.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -11,7 +11,7 @@ export interface PipelineOptions<PackagerOptions> extends Options {
}

export default function defaultPipeline<PackagerOptions>(
emberApp: object,
emberApp: EmberAppInstance,
packager?: PackagerConstructor<PackagerOptions>,
options?: PipelineOptions<PackagerOptions>
): Node {
Expand Down Expand Up @@ -52,11 +52,11 @@ export default function defaultPipeline<PackagerOptions>(
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({
Expand Down
40 changes: 25 additions & 15 deletions packages/compat/src/v1-addon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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',
Expand All @@ -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',
Expand Down Expand Up @@ -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<Options>,
protected app: V1App,
private packageCache: PackageCache,
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Copy link
Collaborator Author

@lifeart lifeart Sep 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed one more case here, looks like meta exists on Package class, not package.json payload

pkg['ember-addon'] = meta;

// classic addons don't get to customize their entrypoints like this. We
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,
});
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -977,15 +987,15 @@ 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',
`
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;
}
Expand Down
61 changes: 28 additions & 33 deletions packages/compat/src/v1-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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<string, any>;
_nodeModules: Map<string, { name: string; path: FilePath }>;
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;
Expand All @@ -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 {
Expand All @@ -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.
Expand Down Expand Up @@ -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'],
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here is fix

'ember-addon': addonMeta,
};
writeJSONSync(join(outputPath, 'package.json'), meta, { spaces: 2 });
Expand Down Expand Up @@ -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'],
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here is fix

'ember-addon': addonMeta,
};
writeJSONSync(join(outputPath, 'package.json'), meta, { spaces: 2 });
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -747,7 +742,7 @@ function throwIfMissing<T>(
}

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);
Expand Down
10 changes: 5 additions & 5 deletions packages/compat/src/v1-instance-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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[] {
Expand Down
Loading