Skip to content

Commit caac8f6

Browse files
authored
Merge pull request #502 from gitKrystan/object-literal-decorators-improvements
Support legacy decorators in object literals (and related improvements)
2 parents 333fd31 + 9d39196 commit caac8f6

File tree

85 files changed

+3775
-2402
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+3775
-2402
lines changed

.eslintrc.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ module.exports = {
5252
'./.eslintrc.js',
5353
'./.prettierrc.js',
5454
'./bin/**/*.js',
55+
'./jest.config.js',
5556
'./test/run-test.js',
5657
'./transforms/ember-object/test.js',
5758
],
@@ -87,7 +88,7 @@ module.exports = {
8788
files: ['*.ts'],
8889
parser: '@typescript-eslint/parser',
8990
parserOptions: {
90-
project: './tsconfig.json',
91+
project: './tsconfig.lint.json',
9192
allowAutomaticSingleRunInference: true,
9293
},
9394
plugins: ['@typescript-eslint'],

README.md

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,21 @@ following command:
2323
npx ember-native-class-codemod http://localhost:4200/path/to/server [OPTIONS] path/of/files/ or/some**/*glob.js
2424
```
2525

26-
The codemod accepts the following options:
27-
28-
| Option | Value | Default | Details |
29-
| --------------------- | ------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
30-
| `--class-fields` | boolean | `true` | Enable/disable transformation using class fields |
31-
| `--decorators` | boolean | `true` | Enable/disable transformation using decorators |
32-
| `--classic-decorator` | boolean | `true` | Enable/disable adding the [`@classic` decorator](https://github.com/pzuraq/ember-classic-decorator), which helps with transitioning Ember Octane |
33-
| `--type` | String | Empty (match all types in path) | Apply transformation to only passed type. The type can be one of `services`, `routes`, `components`, `controllers` |
34-
| `--quote` | String | `'single'` | Whether to use double or single quotes by default for new statements that are added during the codemod. |
26+
### Options
27+
28+
The codemod accepts the following options, passed as CLI arguments, set in a `.codemods.{json,js,cjs,yml}` file, or set in a `"codemods"` object in `package.json`.
29+
30+
| Option | Type | Default | Details |
31+
| ----------------------------------------------- | ----------------------------------------------------------------------- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
32+
| `--class-fields` / `classFields` | `boolean` | `true` | Enable/disable transformation using class fields |
33+
| `--decorators` / `decorators` | `boolean \| DecoratorsConfig` | `true` | Set to `false` to disable transformation using decorators. Set to `DecoratorsConfig` object (see below) to pass additional decorator options. |
34+
| `--classic-decorator` / `classicDecorator` | `boolean` | `true` | Enable/disable adding the [`@classic` decorator](https://github.com/pzuraq/ember-classic-decorator), which helps with transitioning Ember Octane |
35+
| `--type` / `type` | `'services' \| 'routes' \| 'components' \| 'controllers' \| undefined`' | `undefined` | Apply transformation to only passed type. If `undefined, will match all types in path. |
36+
| `--quote` / `quote` | `'single' \| 'double'` | `'single'` | Whether to use double or single quotes by default for new statements that are added during the codemod. |
37+
| `--partial-transforms` / `partialTransforms` | `boolean` | `true` | If `false`, the entire file will fail validation if any EmberObject within it fails validation. |
38+
| `--ignore-leaking-state` / `ignoreLeakingState` | `string[]` | `['queryParams']` | Allow-list for `ObjectExpression` or `ArrayExpression` properties to ignore issues detailed in [eslint-plugin-ember/avoid-leaking-state-in-ember-objects](https://github.com/ember-cli/eslint-plugin-ember/blob/master/docs/rules/avoid-leaking-state-in-ember-objects.md). In the classic class syntax, using arrays and objects as default properties causes their state to "leak" between instances. If you have custom properties where you know that the shared state won't be a problem (for example, read-only configuration values), you can use this config to ignore them. NOTE: Passing this option will override the defaults, so ensure you include `'queryParams'` in the list unless you explicitly wish to disallow it. |
39+
| `DecoratorsConfig` | An object with the following properties. | See below. | Allow-list for decorators currently applied to object literal properties that can be safely applied to class properties. Pass as a comma-separated string if using as a CLI-option. Otherwise pass as an array of strings. |
40+
| `DecoratorsConfig.inObjectLiterals` | `string \| string[]` | `[]` | Allow-list for decorators currently applied to object literal properties that can be safely applied to class properties. Pass as a comma-separated string if using as a CLI-option. Otherwise pass as an array of strings. NOTE: Decorators on object methods will be allowed by default. |
3541

3642
### Gathering Runtime Data
3743

jest.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// eslint-disable-next-line jsdoc/valid-types
2+
/** @type {import('ts-jest').JestConfigWithTsJest} */
3+
module.exports = {
4+
preset: 'ts-jest',
5+
testEnvironment: 'node',
6+
};

package.json

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@
3131
],
3232
"scripts": {
3333
"release": "release-it",
34-
"prepare": "yarn build",
34+
"prepublishOnly": "yarn build",
3535
"postpublish": "yarn clean",
3636
"build": "tsc",
37-
"clean": "tsc --build --clean",
37+
"clean": "tsc --build --clean && git checkout test/fixtures",
3838
"lint": "concurrently \"npm:lint:*(!fix)\" --names \"lint:\"",
3939
"lint:fix": "concurrently \"npm:lint:*:fix\" --names \"fix:\"",
4040
"lint:js": "eslint . --cache",
@@ -46,21 +46,26 @@
4646
"update-docs": "codemod-cli update-docs"
4747
},
4848
"dependencies": {
49+
"@babel/parser": "^7.20.13",
4950
"camelcase": "^6.3.0",
5051
"codemod-cli": "^3.2.0",
52+
"cosmiconfig": "^8.0.0",
53+
"deepmerge-ts": "^4.3.0",
5154
"ember-codemods-telemetry-helpers": "^3.0.0",
5255
"fs-extra": "^8.0.1",
5356
"git-repo-info": "^2.1.0",
5457
"minimatch": "^3.0.4",
5558
"puppeteer": "^15.3.2",
5659
"sync-disk-cache": "^1.3.3",
5760
"walk-sync": "^2.0.2",
58-
"winston": "^3.2.1"
61+
"winston": "^3.2.1",
62+
"zod": "^3.20.2"
5963
},
6064
"devDependencies": {
6165
"@babel/core": "^7.20.12",
6266
"@babel/eslint-parser": "^7.19.1",
6367
"@babel/preset-env": "^7.20.2",
68+
"@jest/globals": "^29.4.1",
6469
"@tsconfig/node12": "^1.0.11",
6570
"@types/jscodeshift": "^0.11.6",
6671
"@typescript-eslint/eslint-plugin": "^5.48.1",
@@ -73,10 +78,11 @@
7378
"eslint-plugin-node": "^11.1.0",
7479
"eslint-plugin-unicorn": "^45.0.2",
7580
"execa": "^5.0.0",
76-
"jest": "^27.0.1",
81+
"jest": "^29.4.1",
7782
"prettier": "^2.8.2",
7883
"release-it": "^14.2.1",
7984
"release-it-lerna-changelog": "^3.1.0",
85+
"ts-jest": "^29.0.5",
8086
"typescript": "^4.9.4"
8187
},
8288
"engines": {

test/config/config.test.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { describe, expect, test } from '@jest/globals';
2+
import path from 'path';
3+
import getConfig, { mergeConfig } from '../../transforms/helpers/config';
4+
import { DEFAULT_OPTIONS } from '../../transforms/helpers/options';
5+
6+
describe('config', () => {
7+
describe('getConfig', () => {
8+
test('it has default options', () => {
9+
const config = getConfig();
10+
expect(config).toStrictEqual(DEFAULT_OPTIONS);
11+
});
12+
13+
test.each(['json', 'js', 'cjs', 'yml', 'yaml', 'package'])(
14+
'should read %s config',
15+
(fixture) => {
16+
const config = getConfig(pathFor(fixture));
17+
expect(config).toStrictEqual(
18+
mergeConfig(DEFAULT_OPTIONS, {
19+
classFields: false,
20+
quote: 'double',
21+
decorators: {
22+
inObjectLiterals: [`${fixture}DecOne`, `${fixture}DecTwo`],
23+
},
24+
})
25+
);
26+
}
27+
);
28+
});
29+
30+
describe('mergeConfig', () => {
31+
test('it allows overwriting the ignoreLeakingState config', () => {
32+
expect(
33+
mergeConfig(DEFAULT_OPTIONS, {
34+
ignoreLeakingState: ['queryParams', 'ignoreMyLeakyState'],
35+
})
36+
).toStrictEqual({
37+
...DEFAULT_OPTIONS,
38+
ignoreLeakingState: ['queryParams', 'ignoreMyLeakyState'],
39+
});
40+
});
41+
42+
test('it deep merges the decorators config', () => {
43+
expect(
44+
mergeConfig(DEFAULT_OPTIONS, {
45+
decorators: {
46+
inObjectLiterals: ['computer'],
47+
},
48+
})
49+
).toStrictEqual({
50+
...DEFAULT_OPTIONS,
51+
decorators: {
52+
inObjectLiterals: ['computer'],
53+
},
54+
});
55+
});
56+
});
57+
});
58+
59+
function pathFor(extension: string): string {
60+
// eslint-disable-next-line unicorn/prefer-module
61+
return path.resolve(__dirname, `./fixtures/${extension}`);
62+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = {
2+
classFields: false,
3+
quote: 'double',
4+
decorators: {
5+
inObjectLiterals: ['cjsDecOne', 'cjsDecTwo']
6+
}
7+
};

test/config/fixtures/js/.codemods.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = {
2+
classFields: false,
3+
quote: 'double',
4+
decorators: {
5+
inObjectLiterals: ['jsDecOne', 'jsDecTwo']
6+
}
7+
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"classFields": false,
3+
"quote": "double",
4+
"decorators": {
5+
"inObjectLiterals": ["jsonDecOne", "jsonDecTwo"]
6+
}
7+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"codemods": {
3+
"classFields": false,
4+
"quote": "double",
5+
"decorators": {
6+
"inObjectLiterals": ["packageDecOne", "packageDecTwo"]
7+
}
8+
}
9+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
classFields: false
2+
quote: 'double'
3+
decorators:
4+
inObjectLiterals:
5+
- yamlDecOne
6+
- yamlDecTwo

0 commit comments

Comments
 (0)