Skip to content

Commit

Permalink
Allowed codemod to set linters for the v2 addon (#82)
Browse files Browse the repository at this point in the history
* feature: Allowed codemod to set development dependencies for addon

* feature: Allowed codemod to configure linters for addon

* refactor: Removed unused step

* chore: Updated move-project-root-files step

* chore: Updated fixtures

* chore: Updated README

---------

Co-authored-by: ijlee2 <ijlee2@users.noreply.github.com>
  • Loading branch information
ijlee2 and ijlee2 authored Apr 26, 2024
1 parent 6abd672 commit 28d104f
Show file tree
Hide file tree
Showing 188 changed files with 1,952 additions and 1,646 deletions.
26 changes: 18 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,43 @@ _Codemod to convert Ember addons to v2 addon format_

## Usage

You can check [`ember-container-query`](https://github.com/ijlee2/ember-container-query/pull/151) as a reference.
For examples, see [`ember-container-query`](https://github.com/ijlee2/ember-container-query/pull/151/commits) and [`ember-render-helpers`](https://github.com/buschtoens/ember-render-helpers/pull/447/commits).

Step 1. Quickly migrate to [v2 format](https://github.com/embroider-build/embroider/blob/main/ADDON-AUTHOR-GUIDE.md).<sup>1</sup>
Step 1. Quickly migrate to [v2 format](https://github.com/embroider-build/embroider/blob/v4.3.1-%40embroider/addon-dev/docs/addon-author-guide.md).

```sh
cd <path/to/your/project>
npx ember-codemod-v1-to-v2 <arguments>
```

> [!IMPORTANT]
>
> Before you run `ember-codemod-v1-to-v2`, I recommend that you address existing tech debts (one at a time). That is, treat the v2 migration as its own thing.
>
> Here are examples of what you may want to work on first:
>
> - [Meet prerequisites for v2 addon](https://github.com/embroider-build/embroider/blob/v4.3.1-%40embroider/addon-dev/docs/porting-addons-to-v2.md#part-3-prerequisites-for-v2-addon).
> - [Un-pod v1 addon](https://github.com/ijlee2/ember-codemod-pod-to-octane).
> - Update dependencies.
> - Switch `npm` or `yarn` to `pnpm`.
Step 2. Review the addon package.

- [x] Update the configuration files.<sup>2</sup>
- [x] Update the configuration files.<sup>1</sup>
- [x] Install missing dependencies.
- [x] Relative import paths must specify the file extension `.js` or `.ts`.
- [x] Colocate stylesheets (if any). Let each component import the relevant stylesheet in the backing class.
- [x] Confirm that you can run all scripts in `package.json`.

Step 3. Review the test-app package.

- [x] Update the configuration files.<sup>2</sup>
- [x] Update the configuration files.<sup>1</sup>
- [x] Rename the remaining instances of `dummy` to `test-app`.
- [x] Confirm that you can run all scripts in `package.json`.

Step 4. Review the workspace root including CI/CD.

<sup>1. Before running `ember-codemod-v1-to-v2`, consider [meeting the prerequisites](https://github.com/embroider-build/embroider/blob/v1.8.3/PORTING-ADDONS-TO-V2.md#part-3-prerequisites-for-v2-addon). You can run [`ember-codemod-pod-to-octane`](https://github.com/ijlee2/ember-codemod-pod-to-octane) to un-pod a v1 addon.</sup>

<sup>2. Files such as `.eslintrc.js`, `.gitignore`, `babel.config.json` (addon only), `config/environment.js` (test-app only), `ember-cli-build.js` (test-app only), `package.json`, `rollup.config.mjs` (addon only), `tsconfig.json`, etc.</sup>
<sup>1. Files such as `.eslintrc.js`, `.gitignore`, `babel.config.json` (addon only), `config/environment.js` (test-app only), `ember-cli-build.js` (test-app only), `package.json`, `rollup.config.mjs` (addon only), `tsconfig.json`, etc.</sup>


### Arguments
Expand Down Expand Up @@ -133,7 +143,7 @@ If you have an open-sourced addon (v1 or v2) that I can use as a reference, reac

## Credits

The codemod steps were based on [Migrating an Ember addon to the next-gen v2 format](https://www.kaliber5.de/de/blog/v2-addon_en) and [Guide: Porting an Addon to v2](https://github.com/embroider-build/embroider/blob/v3.1.3-core/docs/porting-addons-to-v2.md). The blueprints were derived from [`@embroider/addon-blueprint`](https://github.com/embroider-build/addon-blueprint).
The codemod steps were based on [Migrating an Ember addon to the next-gen v2 format](https://www.kaliber5.de/de/blog/v2-addon_en) and [Guide: Porting an Addon to v2](https://github.com/embroider-build/embroider/blob/v4.3.1-%40embroider/addon-dev/docs/porting-addons-to-v2.md). The blueprints were derived from [`@embroider/addon-blueprint`](https://github.com/embroider-build/addon-blueprint).


## License
Expand Down
2 changes: 1 addition & 1 deletion src/blueprints/ember-addon/__addonLocation__/.eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
/blueprints/*/files/

# compiled output
/declarations/
/dist/
/declarations/

# misc
/coverage/
68 changes: 68 additions & 0 deletions src/blueprints/ember-addon/__addonLocation__/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
'use strict';

module.exports = {
root: true,
parser: '<%= options.packages.addon.hasTypeScript ? '@typescript-eslint/parser' : '@babel/eslint-parser' %>',
parserOptions: {
ecmaVersion: 'latest',<% if (!options.packages.addon.hasTypeScript) { %>
sourceType: 'module',
babelOptions: {
root: __dirname,
},<% } %>
},
plugins: ['ember'],
extends: [
'eslint:recommended',
'plugin:ember/recommended',
'plugin:prettier/recommended',
],
env: {
browser: true,
},
rules: {},
overrides: [
<% if (options.packages.addon.hasTypeScript) { %> // ts files
{
files: ['**/*.ts', '**/*.gts'],
extends: [
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
],
rules: {
// Add any custom rules here
},
},
// require relative imports use full extensions
{
files: ['src/**/*.{js,ts,gjs,gts}'],
rules: {
'import/extensions': ['error', 'always', { ignorePackages: true }],
},
},
<% } else { %> // require relative imports use full extensions
{
files: ['src/**/*.{js,gjs}'],
rules: {
'import/extensions': ['error', 'always', { ignorePackages: true }],
},
},
<% } %> // node files
{
files: [
'./.eslintrc.cjs',
'./.prettierrc.cjs',
'./.template-lintrc.cjs',
'./addon-main.cjs',
],
parserOptions: {
sourceType: 'script',
},
env: {
browser: false,
node: true,
},
plugins: ['n'],
extends: ['plugin:n/recommended'],
},
],
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
/blueprints/*/files/

# compiled output
/declarations/
/dist/
/declarations/

# misc
/coverage/
11 changes: 8 additions & 3 deletions src/blueprints/ember-addon/__addonLocation__/__gitignore__
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
# 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
/LICENSE.md

# compiled output
/declarations
/dist
dist/
declarations/

# npm/pnpm/yarn pack output
*.tgz

# deps & caches
node_modules/
.eslintcache
.prettiercache
21 changes: 21 additions & 0 deletions src/blueprints/ember-addon/__addonLocation__/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"extends": "@tsconfig/ember/tsconfig.json",
"compilerOptions": {
"allowImportingTsExtensions": true,
"allowJs": true,
"declarationDir": "declarations",
"emitDeclarationOnly": true,
"noEmit": false,
"noEmitOnError": false,
"rootDir": "./src"
},
"include": [
"src/**/*",
"unpublished-development-types/**/*"
]<% if (options.packages.addon.hasGlint) { %>,
"glint": {
"environment": [
"ember-loose"
]
}<% } %>
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// These will *not* be published as part of your addon, so be careful that your published code does not rely on them!
<% if (options.packages.addon.hasGlint) { %>
import '@glint/environment-ember-loose';
// import '@glint/environment-ember-template-imports';

declare module '@glint/environment-ember-loose/registry' {
// Remove this once entries have been added! 👇
Expand Down
2 changes: 0 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
moveProjectRootFiles,
moveTestAppFiles,
updateAddonPackageJson,
updateAddonTsConfigJson,
updateTestAppPackageJson,
updateTestAppTsConfigJson,
} from './steps/index.js';
Expand Down Expand Up @@ -34,7 +33,6 @@ export function runCodemod(codemodOptions: CodemodOptions): void {

// Fine-tune individual files
updateAddonPackageJson(context, options);
updateAddonTsConfigJson(options);
updateTestAppPackageJson(options);
updateTestAppTsConfigJson(options);
}
1 change: 1 addition & 0 deletions src/steps/create-files-from-blueprints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ function getFilesToSkip(options: Options): string[] {
const files = new Set<string>();

if (!packages.addon.hasTypeScript) {
files.add('__addonLocation__/tsconfig.json');
files.add('__addonLocation__/unpublished-development-types/index.d.ts');
files.add('__testAppLocation__/types/global.d.ts');
}
Expand Down
1 change: 0 additions & 1 deletion src/steps/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@ export * from './move-addon-files.js';
export * from './move-project-root-files.js';
export * from './move-test-app-files.js';
export * from './update-addon-package-json.js';
export * from './update-addon-tsconfig-json.js';
export * from './update-test-app-package-json.js';
export * from './update-test-app-tsconfig-json.js';
24 changes: 8 additions & 16 deletions src/steps/move-project-root-files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,22 +28,7 @@ function copyToAddon(options: Options): void {
function moveToAddonAndTestApp(options: Options): void {
const { locations, projectRoot } = options;

const files = [
'.eslintignore',
'.eslintrc.cjs',
'.eslintrc.js',
'.gitignore',
'.prettierignore',
'.prettierrc.cjs',
'.prettierrc.js',
'.stylelintignore',
'.stylelintrc.cjs',
'.stylelintrc.js',
'.template-lintrc.cjs',
'.template-lintrc.js',
'package.json',
'tsconfig.json',
];
const files = ['.stylelintignore', '.stylelintrc.{cjs,js}', 'package.json'];

const filePaths = findFiles(files, {
projectRoot,
Expand Down Expand Up @@ -71,9 +56,16 @@ function moveToTestApp(options: Options): void {

const files = [
'.ember-cli',
'.eslintignore',
'.eslintrc.{cjs,js}',
'.gitignore',
'.prettierignore',
'.prettierrc.{cjs,js}',
'.template-lintrc.{cjs,js}',
'.watchmanconfig',
'ember-cli-build.js',
'testem.js',
'tsconfig.json',
];

const filePaths = findFiles(files, {
Expand Down
4 changes: 2 additions & 2 deletions src/steps/update-addon-package-json/update-dependencies.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { convertToMap, convertToObject } from '@codemod-utils/json';

import type { Options, PackageJson } from '../../types/index.js';
import { getVersion } from '../../utils/blueprints.js';
import { getLatestVersion } from '../../utils/blueprints.js';

export function updateDependencies(
packageJson: PackageJson,
Expand All @@ -27,7 +27,7 @@ export function updateDependencies(
const packagesToInstall = ['@embroider/addon-shim', 'decorator-transforms'];

packagesToInstall.forEach((packageName) => {
const version = getVersion(packageName, options);
const version = getLatestVersion(packageName);

dependencies.set(packageName, version);
});
Expand Down
35 changes: 25 additions & 10 deletions src/steps/update-addon-package-json/update-dev-dependencies.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { convertToMap, convertToObject } from '@codemod-utils/json';

import type { Options, PackageJson } from '../../types/index.js';
import { getVersion } from '../../utils/blueprints.js';
import { getLatestVersion } from '../../utils/blueprints.js';

export function updateDevDependencies(
packageJson: PackageJson,
Expand All @@ -12,36 +12,51 @@ export function updateDevDependencies(
const devDependencies = convertToMap(packageJson['devDependencies']);

/*
For the time being, we'll take the approach of starting over and
adding back the development dependencies that are required. For
a more conservative approach, we could delete only the following:
- @embroider/macros
- ember-auto-import
- ember-cli-babel
- ember-cli-htmlbars
The codemod sets the development dependencies that v2 addons need.
End-developers must add dependencies that their v1 addon needed.
*/
devDependencies.clear();

const packagesToInstall = new Set([
'@babel/core',
'@babel/eslint-parser',
'@babel/runtime',
'@embroider/addon-dev',
'@rollup/plugin-babel',
'babel-plugin-ember-template-compilation',
'concurrently',
'ember-template-lint',
'eslint',
'eslint-config-prettier',
'eslint-plugin-ember',
'eslint-plugin-import',
'eslint-plugin-n',
'eslint-plugin-prettier',
'prettier',
'rollup',
'rollup-plugin-copy',
]);

if (packages.addon.hasTypeScript) {
packagesToInstall.delete('@babel/eslint-parser');
packagesToInstall.add('@babel/plugin-transform-typescript');
packagesToInstall.add('@tsconfig/ember');
packagesToInstall.add('@types/ember__component');
packagesToInstall.add('@types/ember__object');
packagesToInstall.add('@types/ember__service');
packagesToInstall.add('@typescript-eslint/eslint-plugin');
packagesToInstall.add('@typescript-eslint/parser');
packagesToInstall.add('typescript');
}

if (packages.addon.hasGlint) {
packagesToInstall.add('@glint/core');
packagesToInstall.add('@glint/environment-ember-loose');
packagesToInstall.add('@glint/template');
}

Array.from(packagesToInstall).forEach((packageName) => {
const version = getVersion(packageName, options);
const version = getLatestVersion(packageName);

devDependencies.set(packageName, version);
});
Expand Down
Loading

0 comments on commit 28d104f

Please sign in to comment.