ember-codemod-add-component-signatures 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +141 -0
  3. package/dist/bin/ember-codemod-add-component-signatures.js +38 -0
  4. package/dist/src/blueprints/ember-cli/template-only-component.ts +8 -0
  5. package/dist/src/index.js +14 -0
  6. package/dist/src/steps/analyze-project/analyze-components/find-arguments.js +98 -0
  7. package/dist/src/steps/analyze-project/analyze-components/find-blocks.js +27 -0
  8. package/dist/src/steps/analyze-project/analyze-components/find-element.js +21 -0
  9. package/dist/src/steps/analyze-project/analyze-components/index.js +3 -0
  10. package/dist/src/steps/analyze-project/analyze-components.js +66 -0
  11. package/dist/src/steps/analyze-project/filter-components.js +29 -0
  12. package/dist/src/steps/analyze-project/find-components.js +25 -0
  13. package/dist/src/steps/analyze-project/index.js +3 -0
  14. package/dist/src/steps/analyze-project.js +10 -0
  15. package/dist/src/steps/convert-to-typescript.js +22 -0
  16. package/dist/src/steps/create-options.js +22 -0
  17. package/dist/src/steps/create-registries/create-registry.js +17 -0
  18. package/dist/src/steps/create-registries/has-registry.js +18 -0
  19. package/dist/src/steps/create-registries/index.js +3 -0
  20. package/dist/src/steps/create-registries/rename-component/index.js +2 -0
  21. package/dist/src/steps/create-registries/rename-component/pass-component-name-to-base-component.js +56 -0
  22. package/dist/src/steps/create-registries/rename-component/update-references.js +34 -0
  23. package/dist/src/steps/create-registries/rename-component.js +17 -0
  24. package/dist/src/steps/create-registries.js +49 -0
  25. package/dist/src/steps/create-signatures/create-signature/builders.js +18 -0
  26. package/dist/src/steps/create-signatures/create-signature/index.js +3 -0
  27. package/dist/src/steps/create-signatures/create-signature/is-signature.js +7 -0
  28. package/dist/src/steps/create-signatures/create-signature/pass-signature-to-base-component.js +204 -0
  29. package/dist/src/steps/create-signatures/create-signature/update-constructor.js +19 -0
  30. package/dist/src/steps/create-signatures/create-signature/update-reference.js +42 -0
  31. package/dist/src/steps/create-signatures/create-signature.js +23 -0
  32. package/dist/src/steps/create-signatures/index.js +1 -0
  33. package/dist/src/steps/create-signatures.js +40 -0
  34. package/dist/src/steps/create-template-only-components.js +27 -0
  35. package/dist/src/steps/index.js +7 -0
  36. package/dist/src/steps/update-signatures/builders.js +60 -0
  37. package/dist/src/steps/update-signatures/index.js +1 -0
  38. package/dist/src/steps/update-signatures/update-signature.js +37 -0
  39. package/dist/src/steps/update-signatures.js +42 -0
  40. package/dist/src/types/index.js +1 -0
  41. package/dist/src/utils/blueprints/blueprints-root.js +4 -0
  42. package/dist/src/utils/blueprints.js +1 -0
  43. package/dist/src/utils/components/get-base-component.js +41 -0
  44. package/dist/src/utils/components/get-block-parameter.type.js +14 -0
  45. package/dist/src/utils/components/get-class-path.js +15 -0
  46. package/dist/src/utils/components/get-extension-map.js +15 -0
  47. package/dist/src/utils/components/get-html-interface.js +64 -0
  48. package/dist/src/utils/components/get-template-path.js +11 -0
  49. package/dist/src/utils/components/normalize-block-name.js +14 -0
  50. package/dist/src/utils/components.js +7 -0
  51. package/package.json +70 -0
@@ -0,0 +1 @@
1
+ export * from './blueprints/blueprints-root.js';
@@ -0,0 +1,41 @@
1
+ import { AST } from '@codemod-utils/ast-javascript';
2
+ export function getBaseComponent(file) {
3
+ const traverse = AST.traverse(true);
4
+ let baseComponentName;
5
+ let importPath;
6
+ traverse(file, {
7
+ visitImportDeclaration(path) {
8
+ switch (path.node.source.value) {
9
+ case '@ember/component':
10
+ case '@ember/component/template-only':
11
+ case '@glimmer/component': {
12
+ const defaultImport = path.node.specifiers.find(({ type }) => {
13
+ return type === 'ImportDefaultSpecifier';
14
+ });
15
+ if (!defaultImport) {
16
+ return false;
17
+ }
18
+ baseComponentName = defaultImport.local.name;
19
+ importPath = path.node.source.value;
20
+ return false;
21
+ }
22
+ case '@ember/template-compiler': {
23
+ const namedImport = path.node.specifiers.find(({ type }) => {
24
+ return type === 'ImportSpecifier';
25
+ });
26
+ if (!namedImport) {
27
+ return false;
28
+ }
29
+ baseComponentName = namedImport.local.name;
30
+ importPath = path.node.source.value;
31
+ return false;
32
+ }
33
+ }
34
+ return false;
35
+ },
36
+ });
37
+ return {
38
+ baseComponentName,
39
+ importPath,
40
+ };
41
+ }
@@ -0,0 +1,14 @@
1
+ const defaultTsType = 'unknown';
2
+ const mapping = new Map([
3
+ ['BooleanLiteral', 'boolean'],
4
+ ['NullLiteral', 'null'],
5
+ ['NumberLiteral', 'number'],
6
+ ['PathExpression', 'unknown'],
7
+ ['StringLiteral', 'string'],
8
+ ['SubExpression', 'unknown'],
9
+ ['UndefinedLiteral', 'undefined'],
10
+ ]);
11
+ export function getBlockParameterType(recastType) {
12
+ const tsType = mapping.get(recastType);
13
+ return tsType ?? defaultTsType;
14
+ }
@@ -0,0 +1,15 @@
1
+ import { join } from 'node:path';
2
+ export function getClassPath(componentName, extensions, options) {
3
+ const { componentStructure, src } = options;
4
+ const filePath = componentStructure === 'nested'
5
+ ? join(src, componentName, 'index')
6
+ : join(src, componentName);
7
+ if (extensions.has('.gts')) {
8
+ return `${filePath}.gts`;
9
+ }
10
+ if (extensions.has('.ts')) {
11
+ return `${filePath}.ts`;
12
+ }
13
+ // hbs file only. The blueprint for template-only component is in `*.ts`.
14
+ return `${filePath}.ts`;
15
+ }
@@ -0,0 +1,15 @@
1
+ import { join } from 'node:path';
2
+ import { parseFilePath } from '@codemod-utils/files';
3
+ export function getExtensionMap(filePaths) {
4
+ const extensionMap = new Map();
5
+ filePaths.forEach((filePath) => {
6
+ const { dir, ext, name } = parseFilePath(filePath);
7
+ const componentName = join(dir, name);
8
+ if (extensionMap.has(componentName)) {
9
+ extensionMap.get(componentName).add(ext);
10
+ return;
11
+ }
12
+ extensionMap.set(componentName, new Set([ext]));
13
+ });
14
+ return extensionMap;
15
+ }
@@ -0,0 +1,64 @@
1
+ /* https://developer.mozilla.org/docs/Web/API/HTML_DOM_API#html_dom_api_interfaces */
2
+ const defaultHtmlInterface = 'HTMLElement';
3
+ const mapping = new Map([
4
+ ['a', 'HTMLAnchorElement'],
5
+ ['article', 'HTMLElement'],
6
+ ['aside', 'HTMLElement'],
7
+ ['audio', 'HTMLAudioElement'],
8
+ ['b', 'HTMLElement'],
9
+ ['blockquote', 'HTMLQuoteElement'],
10
+ ['button', 'HTMLButtonElement'],
11
+ ['canvas', 'HTMLCanvasElement'],
12
+ ['caption', 'HTMLElement'],
13
+ ['code', 'HTMLElement'],
14
+ ['dialog', 'HTMLDialogElement'],
15
+ ['div', 'HTMLDivElement'],
16
+ ['em', 'HTMLElement'],
17
+ ['fieldset', 'HTMLFieldSetElement'],
18
+ ['figcaption', 'HTMLElement'],
19
+ ['footer', 'HTMLElement'],
20
+ ['form', 'HTMLFormElement'],
21
+ ['h1', 'HTMLHeadingElement'],
22
+ ['h2', 'HTMLHeadingElement'],
23
+ ['h3', 'HTMLHeadingElement'],
24
+ ['h4', 'HTMLHeadingElement'],
25
+ ['h5', 'HTMLHeadingElement'],
26
+ ['h6', 'HTMLHeadingElement'],
27
+ ['header', 'HTMLElement'],
28
+ ['i', 'HTMLElement'],
29
+ ['iframe', 'HTMLIFrameElement'],
30
+ ['img', 'HTMLImageElement'],
31
+ ['input', 'HTMLInputElement'],
32
+ ['label', 'HTMLLabelElement'],
33
+ ['legend', 'HTMLLegendElement'],
34
+ ['li', 'HTMLLIElement'],
35
+ ['main', 'HTMLElement'],
36
+ ['nav', 'HTMLElement'],
37
+ ['ol', 'HTMLOListElement'],
38
+ ['optgroup', 'HTMLOptGroupElement'],
39
+ ['option', 'HTMLOptionElement'],
40
+ ['p', 'HTMLParagraphElement'],
41
+ ['picture', 'HTMLPictureElement'],
42
+ ['pre', 'HTMLElement'],
43
+ ['q', 'HTMLQuoteElement'],
44
+ ['section', 'HTMLElement'],
45
+ ['select', 'HTMLSelectElement'],
46
+ ['span', 'HTMLSpanElement'],
47
+ ['strong', 'HTMLElement'],
48
+ ['svg', 'SVGElement'],
49
+ ['table', 'HTMLTableElement'],
50
+ ['tbody', 'HTMLTableSectionElement'],
51
+ ['td', 'HTMLTableCellElement'],
52
+ ['textarea', 'HTMLTextAreaElement'],
53
+ ['tfoot', 'HTMLTableSectionElement'],
54
+ ['th', 'HTMLTableCellElement'],
55
+ ['thead', 'HTMLTableSectionElement'],
56
+ ['time', 'HTMLTimeElement'],
57
+ ['tr', 'HTMLTableRowElement'],
58
+ ['ul', 'HTMLUListElement'],
59
+ ['video', 'HTMLVideoElement'],
60
+ ]);
61
+ export function getHtmlInterface(elementTag) {
62
+ const htmlInterface = mapping.get(elementTag);
63
+ return htmlInterface ?? defaultHtmlInterface;
64
+ }
@@ -0,0 +1,11 @@
1
+ import { join } from 'node:path';
2
+ export function getTemplatePath(componentName, extensions, options) {
3
+ const { componentStructure, src } = options;
4
+ const filePath = componentStructure === 'nested'
5
+ ? join(src, componentName, 'index')
6
+ : join(src, componentName);
7
+ if (!extensions.has('.hbs')) {
8
+ throw new RangeError('extensions must include `.hbs`');
9
+ }
10
+ return `${filePath}.hbs`;
11
+ }
@@ -0,0 +1,14 @@
1
+ export function normalizeBlockName(blockName) {
2
+ switch (blockName) {
3
+ case undefined: {
4
+ return 'default';
5
+ }
6
+ case 'else':
7
+ case 'inverse': {
8
+ return 'else';
9
+ }
10
+ default: {
11
+ return blockName;
12
+ }
13
+ }
14
+ }
@@ -0,0 +1,7 @@
1
+ export * from './components/get-base-component.js';
2
+ export * from './components/get-block-parameter.type.js';
3
+ export * from './components/get-class-path.js';
4
+ export * from './components/get-extension-map.js';
5
+ export * from './components/get-html-interface.js';
6
+ export * from './components/get-template-path.js';
7
+ export * from './components/normalize-block-name.js';
package/package.json ADDED
@@ -0,0 +1,70 @@
1
+ {
2
+ "name": "ember-codemod-add-component-signatures",
3
+ "version": "4.0.0",
4
+ "description": "Codemod to add component signatures",
5
+ "keywords": [
6
+ "codemod",
7
+ "ember-codemod",
8
+ "ember-octane",
9
+ "ember-polaris",
10
+ "emberjs",
11
+ "embroider",
12
+ "glint"
13
+ ],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/ijlee2/ember-codemod-add-component-signatures.git"
17
+ },
18
+ "license": "MIT",
19
+ "author": "Isaac J. Lee",
20
+ "type": "module",
21
+ "main": "dist/src/index.js",
22
+ "bin": "dist/bin/ember-codemod-add-component-signatures.js",
23
+ "directories": {
24
+ "test": "tests"
25
+ },
26
+ "files": [
27
+ "dist"
28
+ ],
29
+ "dependencies": {
30
+ "@codemod-utils/ast-javascript": "^2.0.7",
31
+ "@codemod-utils/ast-template": "^2.0.3",
32
+ "@codemod-utils/ast-template-tag": "^0.6.0",
33
+ "@codemod-utils/blueprints": "^2.0.3",
34
+ "@codemod-utils/ember": "^3.0.3",
35
+ "@codemod-utils/files": "^3.0.5",
36
+ "yargs": "^18.0.0"
37
+ },
38
+ "devDependencies": {
39
+ "@changesets/cli": "^2.29.7",
40
+ "@changesets/get-github-info": "^0.6.0",
41
+ "@codemod-utils/tests": "^2.0.4",
42
+ "@ijlee2-frontend-configs/eslint-config-node": "^2.1.2",
43
+ "@ijlee2-frontend-configs/prettier": "^2.1.1",
44
+ "@sondr3/minitest": "^0.1.2",
45
+ "@tsconfig/node20": "^20.1.6",
46
+ "@tsconfig/strictest": "^2.0.5",
47
+ "@types/node": "^20.19.13",
48
+ "@types/yargs": "^17.0.33",
49
+ "concurrently": "^9.2.1",
50
+ "eslint": "^9.35.0",
51
+ "prettier": "^3.6.2",
52
+ "typescript": "^5.9.2"
53
+ },
54
+ "engines": {
55
+ "node": "20.* || >= 22"
56
+ },
57
+ "scripts": {
58
+ "build": "./build.sh --production",
59
+ "format": "prettier . --cache --write",
60
+ "lint": "concurrently \"pnpm:lint:*(!fix)\" --names \"lint:\"",
61
+ "lint:fix": "concurrently \"pnpm:lint:*:fix\" --names \"fix:\" && pnpm format",
62
+ "lint:format": "prettier . --cache --check",
63
+ "lint:js": "eslint . --cache",
64
+ "lint:js:fix": "eslint . --fix",
65
+ "lint:types": "tsc --noEmit",
66
+ "release:prepare": "changeset version",
67
+ "release:publish": "pnpm build && changeset publish",
68
+ "test": "./build.sh --test && mt dist-for-testing --quiet"
69
+ }
70
+ }