diff --git a/src/blueprints/ember-addon/__addonLocation__/.eslintignore b/src/blueprints/ember-addon/__addonLocation__/.eslintignore index e69140be..b0381f9e 100644 --- a/src/blueprints/ember-addon/__addonLocation__/.eslintignore +++ b/src/blueprints/ember-addon/__addonLocation__/.eslintignore @@ -2,6 +2,7 @@ /blueprints/*/files/ # compiled output +/declarations/ /dist/ # misc diff --git a/src/blueprints/ember-addon/__addonLocation__/__gitignore__ b/src/blueprints/ember-addon/__addonLocation__/__gitignore__ new file mode 100644 index 00000000..43cf961b --- /dev/null +++ b/src/blueprints/ember-addon/__addonLocation__/__gitignore__ @@ -0,0 +1,12 @@ +# The authoritative copies of these live in the monorepo root (because they're +# more useful on github that way), but the build copies them into here so they +# will also appear in published NPM packages. +/LICENSE.md +/README.md + +# compiled output +/declarations/ +/dist/ + +# dependencies +/node_modules/ diff --git a/src/blueprints/ember-addon/__addonLocation__/rollup.config.mjs b/src/blueprints/ember-addon/__addonLocation__/rollup.config.mjs index 14fbf03e..9ff7c91c 100644 --- a/src/blueprints/ember-addon/__addonLocation__/rollup.config.mjs +++ b/src/blueprints/ember-addon/__addonLocation__/rollup.config.mjs @@ -1,12 +1,16 @@ -<% if (options.packages.addon.hasTypeScript) { %>import typescript from 'rollup-plugin-ts';<% } else { %>import { babel } from '@rollup/plugin-babel';<% } %> -import copy from 'rollup-plugin-copy'; import { Addon } from '@embroider/addon-dev/rollup'; +import { babel } from '@rollup/plugin-babel'; +import { nodeResolve } from '@rollup/plugin-node-resolve'; +import copy from 'rollup-plugin-copy'; const addon = new Addon({ srcDir: 'src', destDir: 'dist', }); +// Add extensions here, such as ts, gjs, etc that you may import +const extensions = ['.js'<% if (options.packages.addon.hasTypeScript) { %>, '.ts'<% } %>]; + export default { // This provides defaults that work well alongside `publicEntrypoints` below. // You can augment this if you need to. @@ -27,13 +31,7 @@ export default { // package names. addon.dependencies(), -<% if (options.packages.addon.hasTypeScript) { %> // compile TypeScript to latest JavaScript, including Babel transpilation - typescript({ - transpiler: 'babel', - browserslist: false, - transpileOnly: false, - }), -<% } else { %> // This babel config should *not* apply presets or compile away ES modules. + // This babel config should *not* apply presets or compile away ES modules. // It exists only to provide development niceties for you, like automatic // template colocation. // @@ -41,8 +39,14 @@ export default { // babel.config.json. babel({ babelHelpers: 'bundled', + extensions, }), -<% } %> + + // Allows rollup to resolve imports of files with the specified extensions + nodeResolve({ + extensions, + }), + // Ensure that standalone .hbs files are properly integrated as Javascript. addon.hbs(), diff --git a/src/blueprints/ember-addon/__gitignore__ b/src/blueprints/ember-addon/__gitignore__ index 2f6fd049..e622ec28 100644 --- a/src/blueprints/ember-addon/__gitignore__ +++ b/src/blueprints/ember-addon/__gitignore__ @@ -1,24 +1,11 @@ # compiled output -/dist/ +dist/ # dependencies -/node_modules/ +node_modules/ # misc /.env* -/.pnp* -/.eslintcache -/coverage/ +/.pnpm-debug.log /npm-debug.log* -/testem.log /yarn-error.log - -# ember-try -/.node_modules.ember-try/ -/npm-shrinkwrap.json.ember-try -/package.json.ember-try -/package-lock.json.ember-try -/yarn.lock.ember-try - -# broccoli-debug -/DEBUG/ diff --git a/src/migration/ember-addon/steps/update-addon-package-json.ts b/src/migration/ember-addon/steps/update-addon-package-json.ts index 2c5fd9d5..772122ef 100644 --- a/src/migration/ember-addon/steps/update-addon-package-json.ts +++ b/src/migration/ember-addon/steps/update-addon-package-json.ts @@ -62,14 +62,14 @@ function updateDevDependencies( '@babel/runtime', '@embroider/addon-dev', '@rollup/plugin-babel', + '@rollup/plugin-node-resolve', + 'concurrently', 'rollup', 'rollup-plugin-copy', ]); if (packages.addon.hasTypeScript) { packagesToInstall.add('@babel/preset-typescript'); - packagesToInstall.add('rollup-plugin-ts'); - packagesToInstall.delete('@rollup/plugin-babel'); } Array.from(packagesToInstall) @@ -122,12 +122,15 @@ function updateOtherFields( if (packages.addon.hasTypeScript) { packageJson['exports'] = { - '.': './dist/index.js', + '.': { + types: './declarations/index.d.ts', + default: './dist/index.js', + }, './*': { /* This object has an order dependency. The `default` key must appear last. */ - types: './dist/*.d.ts', + types: './declarations/*.d.ts', default: './dist/*.js', }, './addon-main.js': './addon-main.cjs', @@ -140,31 +143,69 @@ function updateOtherFields( }; } + const files = new Set(['addon-main.cjs', 'dist']); + if (hasPublicAssets) { - packageJson['files'] = ['addon-main.cjs', 'dist', 'public']; - } else { - packageJson['files'] = ['addon-main.cjs', 'dist']; + files.add('public'); } + if (packages.addon.hasTypeScript) { + files.add('declarations'); + } + + packageJson['files'] = Array.from(files).sort(); + if (packages.addon.hasTypeScript) { packageJson['typesVersions'] = { '*': { - '*': ['dist/*'], + '*': ['declarations/*'], }, }; } } -function updateScripts(packageJson: PackageJson): void { +function updateScripts(packageJson: PackageJson, options: Options): void { + const { packages } = options; + const scripts = convertToMap(packageJson['scripts']); - scripts.set('build', 'rollup --config'); - scripts.set('prepack', 'rollup --config'); - scripts.set('start', 'rollup --config --watch'); - scripts.set( - 'test', - "echo 'A v2 addon does not have tests, run tests in test-app'", - ); + if (packages.addon.hasTypeScript) { + scripts.set('build', 'concurrently "npm:build:*" --names "build:"'); + scripts.set('build:js', 'rollup --config'); + scripts.set( + 'build:types', + packages.addon.hasGlint ? 'glint --declaration' : 'tsc', + ); + + scripts.set( + 'lint:types', + packages.addon.hasGlint + ? 'glint' + : 'tsc --emitDeclarationOnly false --noEmit', + ); + + scripts.set('prepack', 'rollup --config'); + + scripts.set('start', 'concurrently "npm:start:*" --names "start:"'); + scripts.set('start:js', 'rollup --config --watch --no-watch.clearScreen'); + scripts.set( + 'start:types', + packages.addon.hasGlint ? 'glint --declaration --watch' : 'tsc --watch', + ); + + scripts.set( + 'test', + "echo 'A v2 addon does not have tests, run tests in test-app'", + ); + } else { + scripts.set('build', 'rollup --config'); + scripts.set('prepack', 'rollup --config'); + scripts.set('start', 'rollup --config --watch'); + scripts.set( + 'test', + "echo 'A v2 addon does not have tests, run tests in test-app'", + ); + } packageJson['scripts'] = convertToObject(scripts); } @@ -181,7 +222,7 @@ export function updateAddonPackageJson( updateDependencies(packageJson, options); updateDevDependencies(packageJson, options); - updateScripts(packageJson); + updateScripts(packageJson, options); updateOtherFields(packageJson, context, options); const destination = join(projectRoot, locations.addon, 'package.json'); diff --git a/src/migration/ember-addon/steps/update-addon-tsconfig-json.ts b/src/migration/ember-addon/steps/update-addon-tsconfig-json.ts index ecd69e28..025670f3 100644 --- a/src/migration/ember-addon/steps/update-addon-tsconfig-json.ts +++ b/src/migration/ember-addon/steps/update-addon-tsconfig-json.ts @@ -6,12 +6,26 @@ import { convertToMap, convertToObject } from '@codemod-utils/json'; import type { Options, TsConfigJson } from '../../../types/index.js'; import { sanitizeJson } from '../../../utils/json.js'; -function updateCompilerOptions(tsConfigJson: TsConfigJson): void { +function updateCompilerOptions( + tsConfigJson: TsConfigJson, + options: Options, +): void { + const { packages } = options; + const compilerOptions = convertToMap(tsConfigJson['compilerOptions']); compilerOptions.delete('baseUrl'); compilerOptions.delete('paths'); + if (packages.addon.hasGlint) { + compilerOptions.set('declarationDir', 'declarations'); + } else { + compilerOptions.set('declaration', true); + compilerOptions.set('declarationDir', 'declarations'); + compilerOptions.set('emitDeclarationOnly', true); + compilerOptions.set('noEmit', false); + } + tsConfigJson['compilerOptions'] = convertToObject(compilerOptions); } @@ -30,7 +44,7 @@ export function updateAddonTsConfigJson(options: Options): void { const oldFile = readFileSync(oldPath, 'utf8'); const tsConfigJson = JSON.parse(sanitizeJson(oldFile)); - updateCompilerOptions(tsConfigJson); + updateCompilerOptions(tsConfigJson, options); updateInclude(tsConfigJson); const newFile = JSON.stringify(tsConfigJson, null, 2) + '\n'; diff --git a/src/utils/blueprints/get-version.ts b/src/utils/blueprints/get-version.ts index 0c78e4b0..1c028e4c 100644 --- a/src/utils/blueprints/get-version.ts +++ b/src/utils/blueprints/get-version.ts @@ -11,13 +11,13 @@ const latestVersions = new Map([ ['@embroider/addon-dev', '3.1.1'], ['@embroider/addon-shim', '1.8.5'], ['@rollup/plugin-babel', '6.0.3'], + ['@rollup/plugin-node-resolve', '15.1.0'], ['concurrently', '8.2.0'], ['ember-auto-import', '2.6.3'], ['ember-cli-babel', '7.26.11'], ['ember-cli-htmlbars', '6.2.0'], ['rollup', '3.26.0'], ['rollup-plugin-copy', '3.4.0'], - ['rollup-plugin-ts', '3.2.0'], ]); export function getVersion(packageName: string, options: Options): string {