ember-codemod-v1-to-v2 0.1.3 → 0.1.5

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 (33) hide show
  1. package/bin/ember-codemod-v1-to-v2.js +2 -2
  2. package/package.json +3 -2
  3. package/src/blueprints/ember-addon/__addonLocation__/rollup.config.js +2 -2
  4. package/src/blueprints/ember-addon/__addonLocation__/rollup.config.mjs +2 -2
  5. package/src/blueprints/ember-addon/__addonLocation__/unpublished-development-types/index.d.ts +4 -3
  6. package/src/blueprints/ember-addon/package.json +9 -9
  7. package/src/index.js +2 -2
  8. package/src/migration/ember-addon/index.js +14 -14
  9. package/src/migration/ember-addon/steps/analyze-addon.js +18 -4
  10. package/src/migration/ember-addon/steps/create-files-from-blueprint.js +1 -1
  11. package/src/migration/ember-addon/steps/{augment-options.js → create-options.js} +11 -11
  12. package/src/migration/ember-addon/steps/index.js +1 -1
  13. package/src/migration/ember-addon/steps/move-addon-files.js +2 -8
  14. package/src/migration/ember-addon/steps/move-project-root-files.js +10 -15
  15. package/src/migration/ember-addon/steps/move-test-app-files.js +1 -2
  16. package/src/migration/ember-addon/steps/update-addon-package-json.js +6 -9
  17. package/src/migration/ember-addon/steps/update-addon-tsconfig-json.js +3 -5
  18. package/src/migration/ember-addon/steps/update-test-app-package-json.js +3 -6
  19. package/src/migration/ember-addon/steps/update-test-app-tsconfig-json.js +3 -5
  20. package/src/utils/{decide-version.js → blueprints/decide-version.js} +4 -2
  21. package/src/utils/{process-template.js → blueprints/process-template.js} +3 -3
  22. package/src/utils/blueprints.js +2 -0
  23. package/src/utils/files/copy-files.js +19 -0
  24. package/src/utils/files/create-files.js +17 -0
  25. package/src/utils/{map-file-paths.js → files/map-file-paths.js} +0 -0
  26. package/src/utils/files/move-files.js +22 -0
  27. package/src/utils/files/remove-directory-if-empty.js +19 -0
  28. package/src/utils/files/remove-files.js +15 -0
  29. package/src/utils/files.js +6 -88
  30. package/src/utils/json/convert-to-map.js +3 -0
  31. package/src/utils/{convert-json-object.js → json/convert-to-object.js} +0 -4
  32. package/src/utils/json/sanitize-json.js +7 -0
  33. package/src/utils/json.js +3 -0
@@ -32,11 +32,11 @@ function castEmptyStringToUndefined(string) {
32
32
  return string === '' ? undefined : string;
33
33
  }
34
34
 
35
- const options = {
35
+ const codemodOptions = {
36
36
  addonLocation: castEmptyStringToUndefined(argv['addon-location']),
37
37
  projectRoot: argv['root'] ?? process.cwd(),
38
38
  testAppLocation: castEmptyStringToUndefined(argv['test-app-location']),
39
39
  testAppName: castEmptyStringToUndefined(argv['test-app-name']),
40
40
  };
41
41
 
42
- runCodemod(options);
42
+ runCodemod(codemodOptions);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-codemod-v1-to-v2",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Codemod to convert Ember addons to v2 addon format",
5
5
  "keywords": [
6
6
  "codemod",
@@ -49,6 +49,7 @@
49
49
  "@babel/eslint-parser": "^7.19.1",
50
50
  "glob": "^8.1.0",
51
51
  "lodash.template": "^4.5.0",
52
+ "strip-json-comments": "^5.0.0",
52
53
  "yargs": "^17.6.2"
53
54
  },
54
55
  "devDependencies": {
@@ -56,7 +57,7 @@
56
57
  "eslint": "^8.32.0",
57
58
  "eslint-config-prettier": "^8.6.0",
58
59
  "eslint-plugin-prettier": "^4.2.1",
59
- "eslint-plugin-simple-import-sort": "^8.0.0",
60
+ "eslint-plugin-simple-import-sort": "^9.0.0",
60
61
  "fixturify": "^3.0.0",
61
62
  "lerna-changelog": "^2.2.0",
62
63
  "prettier": "^2.8.3"
@@ -15,12 +15,12 @@ export default {
15
15
  plugins: [
16
16
  // These are the modules that users should be able to import from your
17
17
  // addon. Anything not listed here may get optimized away.
18
- addon.publicEntrypoints([<%= context.publicEntrypoints.map((filePath) => `'${filePath}'`).join(', ') %>]),
18
+ addon.publicEntrypoints([<%= context.addon.publicEntrypoints.map((filePath) => `'${filePath}'`).join(', ') %>]),
19
19
 
20
20
  // These are the modules that should get reexported into the traditional
21
21
  // "app" tree. Things in here should also be in publicEntrypoints above, but
22
22
  // not everything in publicEntrypoints necessarily needs to go here.
23
- addon.appReexports([<%= context.appReexports.map((filePath) => `'${filePath}'`).join(', ') %>]),
23
+ addon.appReexports([<%= context.addon.appReexports.map((filePath) => `'${filePath}'`).join(', ') %>]),
24
24
 
25
25
  // Follow the V2 Addon rules about dependencies. Your code can import from
26
26
  // `dependencies` and `peerDependencies` as well as standard Ember-provided
@@ -15,12 +15,12 @@ export default {
15
15
  plugins: [
16
16
  // These are the modules that users should be able to import from your
17
17
  // addon. Anything not listed here may get optimized away.
18
- addon.publicEntrypoints([<%= context.publicEntrypoints.map((filePath) => `'${filePath}'`).join(', ') %>]),
18
+ addon.publicEntrypoints([<%= context.addon.publicEntrypoints.map((filePath) => `'${filePath}'`).join(', ') %>]),
19
19
 
20
20
  // These are the modules that should get reexported into the traditional
21
21
  // "app" tree. Things in here should also be in publicEntrypoints above, but
22
22
  // not everything in publicEntrypoints necessarily needs to go here.
23
- addon.appReexports([<%= context.appReexports.map((filePath) => `'${filePath}'`).join(', ') %>]),
23
+ addon.appReexports([<%= context.addon.appReexports.map((filePath) => `'${filePath}'`).join(', ') %>]),
24
24
 
25
25
  // Follow the V2 Addon rules about dependencies. Your code can import from
26
26
  // `dependencies` and `peerDependencies` as well as standard Ember-provided
@@ -1,7 +1,7 @@
1
1
  // Add any types here that you need for local development only.
2
2
  // These will *not* be published as part of your addon, so be careful that your published code does not rely on them!
3
-
4
- <% if (options.packages.addon.hasGlint) { %>import '@glint/environment-ember-loose';
3
+ <% if (options.packages.addon.hasGlint) { %>
4
+ import '@glint/environment-ember-loose';
5
5
 
6
6
  declare module '@glint/environment-ember-loose/registry' {
7
7
  // Remove this once entries have been added! 👇
@@ -10,4 +10,5 @@ declare module '@glint/environment-ember-loose/registry' {
10
10
  // Add any registry entries from other addons here that your addon itself uses (in non-strict mode templates)
11
11
  // See https://typed-ember.gitbook.io/glint/using-glint/ember/using-addons
12
12
  }
13
- }<% } %>
13
+ }
14
+ <% } %>
@@ -16,12 +16,12 @@
16
16
  "prepare": "npm run build",
17
17
  "start": "concurrently 'npm:start:*' --restart-after 5000 --prefix-colors cyan,white,yellow",
18
18
  "start:addon": "npm start --workspace <%= options.packages.addon.name %>",
19
- "start:tests": "npm start --workspace <%= options.packages.testApp.name %>",
19
+ "start:test-app": "npm start --workspace <%= options.packages.testApp.name %>",
20
20
  "test": "npm run test --workspaces --if-present"
21
21
  },
22
22
  "devDependencies": {
23
- "concurrently": "<%= options.packages.addon.dependencies.get('concurrently') ?? '^7.6.0' %>",
24
- "prettier": "<%= options.packages.addon.dependencies.get('prettier') ?? '^2.8.3' %>"
23
+ "concurrently": "<%= context.projectRoot.devDependencies['concurrently'] %>",
24
+ "prettier": "<%= context.projectRoot.devDependencies['prettier'] %>"
25
25
  }
26
26
  }<% } else if (options.packageManager.isPnpm) { %>{
27
27
  "name": "<%= options.packages.addon.name %>",
@@ -41,12 +41,12 @@
41
41
  "prepare": "pnpm build",
42
42
  "start": "concurrently 'npm:start:*' --restart-after 5000 --prefix-colors cyan,white,yellow",
43
43
  "start:addon": "pnpm --filter <%= options.packages.addon.name %> start",
44
- "start:test": "pnpm --filter <%= options.packages.testApp.name %> start",
44
+ "start:test-app": "pnpm --filter <%= options.packages.testApp.name %> start",
45
45
  "test": "pnpm --filter '*' test"
46
46
  },
47
47
  "devDependencies": {
48
- "concurrently": "<%= options.packages.addon.dependencies.get('concurrently') ?? '^7.6.0' %>",
49
- "prettier": "<%= options.packages.addon.dependencies.get('prettier') ?? '^2.8.3' %>"
48
+ "concurrently": "<%= context.projectRoot.devDependencies['concurrently'] %>",
49
+ "prettier": "<%= context.projectRoot.devDependencies['prettier'] %>"
50
50
  }
51
51
  }<% } else if (options.packageManager.isYarn) { %>{
52
52
  "name": "<%= options.packages.addon.name %>",
@@ -66,11 +66,11 @@
66
66
  "prepare": "yarn build",
67
67
  "start": "concurrently 'npm:start:*' --restart-after 5000 --prefix-colors cyan,white,yellow",
68
68
  "start:addon": "yarn workspace <%= options.packages.addon.name %> run start",
69
- "start:test": "yarn workspace <%= options.packages.testApp.name %> run start",
69
+ "start:test-app": "yarn workspace <%= options.packages.testApp.name %> run start",
70
70
  "test": "yarn workspaces run test"
71
71
  },
72
72
  "devDependencies": {
73
- "concurrently": "<%= options.packages.addon.dependencies.get('concurrently') ?? '^7.6.0' %>",
74
- "prettier": "<%= options.packages.addon.dependencies.get('prettier') ?? '^2.8.3' %>"
73
+ "concurrently": "<%= context.projectRoot.devDependencies['concurrently'] %>",
74
+ "prettier": "<%= context.projectRoot.devDependencies['prettier'] %>"
75
75
  }
76
76
  }<% } %>
package/src/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { migrateEmberAddon } from './migration/index.js';
2
2
 
3
- export function runCodemod(options) {
4
- migrateEmberAddon(options);
3
+ export function runCodemod(codemodOptions) {
4
+ migrateEmberAddon(codemodOptions);
5
5
  }
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  analyzeAddon,
3
- augmentOptions,
4
3
  createFilesFromBlueprint,
4
+ createOptions,
5
5
  moveAddonFiles,
6
6
  moveProjectRootFiles,
7
7
  moveTestAppFiles,
@@ -12,9 +12,9 @@ import {
12
12
  useRelativePaths,
13
13
  } from './steps/index.js';
14
14
 
15
- export function migrateEmberAddon(options) {
16
- const augmentedOptions = augmentOptions(options);
17
- const { isV1Addon } = augmentedOptions.packages.addon;
15
+ export function migrateEmberAddon(codemodOptions) {
16
+ const options = createOptions(codemodOptions);
17
+ const { isV1Addon } = options.packages.addon;
18
18
 
19
19
  // Guarantee idempotency
20
20
  if (!isV1Addon) {
@@ -22,20 +22,20 @@ export function migrateEmberAddon(options) {
22
22
  }
23
23
 
24
24
  // Prepare for migration
25
- const context = analyzeAddon(augmentedOptions);
26
- useRelativePaths(augmentedOptions);
25
+ const context = analyzeAddon(options);
26
+ useRelativePaths(options);
27
27
 
28
28
  // Preserve code
29
- moveAddonFiles(augmentedOptions);
30
- moveTestAppFiles(augmentedOptions);
31
- moveProjectRootFiles(augmentedOptions);
29
+ moveAddonFiles(options);
30
+ moveTestAppFiles(options);
31
+ moveProjectRootFiles(options);
32
32
 
33
33
  // Get the latest code from blueprint
34
- createFilesFromBlueprint(context, augmentedOptions);
34
+ createFilesFromBlueprint(context, options);
35
35
 
36
36
  // Fine-tune individual files
37
- updateAddonPackageJson(augmentedOptions);
38
- updateAddonTsconfigJson(augmentedOptions);
39
- updateTestAppPackageJson(augmentedOptions);
40
- updateTestAppTsconfigJson(augmentedOptions);
37
+ updateAddonPackageJson(options);
38
+ updateAddonTsconfigJson(options);
39
+ updateTestAppPackageJson(options);
40
+ updateTestAppTsconfigJson(options);
41
41
  }
@@ -2,6 +2,8 @@ import { join } from 'node:path';
2
2
 
3
3
  import glob from 'glob';
4
4
 
5
+ import { decideVersion } from '../../../utils/blueprints.js';
6
+
5
7
  function getAppReexports(options) {
6
8
  const { projectRoot } = options;
7
9
 
@@ -12,6 +14,13 @@ function getAppReexports(options) {
12
14
  return filePaths;
13
15
  }
14
16
 
17
+ function getProjectRootDevDependencies(options) {
18
+ return {
19
+ concurrently: decideVersion('concurrently', options),
20
+ prettier: decideVersion('prettier', options),
21
+ };
22
+ }
23
+
15
24
  function getPublicEntrypoints(options) {
16
25
  const { projectRoot } = options;
17
26
 
@@ -23,8 +32,13 @@ function getPublicEntrypoints(options) {
23
32
  }
24
33
 
25
34
  export function analyzeAddon(options) {
26
- const appReexports = getAppReexports(options);
27
- const publicEntrypoints = getPublicEntrypoints(options);
28
-
29
- return { appReexports, publicEntrypoints };
35
+ return {
36
+ addon: {
37
+ appReexports: getAppReexports(options),
38
+ publicEntrypoints: getPublicEntrypoints(options),
39
+ },
40
+ projectRoot: {
41
+ devDependencies: getProjectRootDevDependencies(options),
42
+ },
43
+ };
30
44
  }
@@ -4,8 +4,8 @@ import { fileURLToPath } from 'node:url';
4
4
 
5
5
  import glob from 'glob';
6
6
 
7
+ import { processTemplate } from '../../../utils/blueprints.js';
7
8
  import { createFiles } from '../../../utils/files.js';
8
- import { processTemplate } from '../../../utils/process-template.js';
9
9
 
10
10
  const __filename = fileURLToPath(import.meta.url);
11
11
  const __dirname = dirname(__filename);
@@ -3,8 +3,8 @@ import { join } from 'node:path';
3
3
 
4
4
  import glob from 'glob';
5
5
 
6
- function analyzePackageJson(options) {
7
- const { projectRoot } = options;
6
+ function analyzePackageJson(codemodOptions) {
7
+ const { projectRoot } = codemodOptions;
8
8
 
9
9
  try {
10
10
  const packageJsonFile = readFileSync(
@@ -48,8 +48,8 @@ function analyzePackageJson(options) {
48
48
  }
49
49
  }
50
50
 
51
- function analyzePackageManager(options) {
52
- const { projectRoot } = options;
51
+ function analyzePackageManager(codemodOptions) {
52
+ const { projectRoot } = codemodOptions;
53
53
 
54
54
  const lockFiles = glob.sync('{package-lock.json,pnpm-lock.yaml,yarn.lock}', {
55
55
  cwd: projectRoot,
@@ -92,22 +92,22 @@ function deriveAddonLocation(addonPackage) {
92
92
  return packageName;
93
93
  }
94
94
 
95
- export function augmentOptions(options) {
96
- const addonPackage = analyzePackageJson(options);
97
- const packageManager = analyzePackageManager(options);
95
+ export function createOptions(codemodOptions) {
96
+ const addonPackage = analyzePackageJson(codemodOptions);
97
+ const packageManager = analyzePackageManager(codemodOptions);
98
98
 
99
99
  return {
100
100
  locations: {
101
- addon: options.addonLocation ?? deriveAddonLocation(addonPackage),
102
- testApp: options.testAppLocation ?? 'test-app',
101
+ addon: codemodOptions.addonLocation ?? deriveAddonLocation(addonPackage),
102
+ testApp: codemodOptions.testAppLocation ?? 'test-app',
103
103
  },
104
104
  packageManager,
105
105
  packages: {
106
106
  addon: addonPackage,
107
107
  testApp: {
108
- name: options.testAppName ?? 'test-app',
108
+ name: codemodOptions.testAppName ?? 'test-app',
109
109
  },
110
110
  },
111
- projectRoot: options.projectRoot,
111
+ projectRoot: codemodOptions.projectRoot,
112
112
  };
113
113
  }
@@ -1,6 +1,6 @@
1
1
  export * from './analyze-addon.js';
2
- export * from './augment-options.js';
3
2
  export * from './create-files-from-blueprint.js';
3
+ export * from './create-options.js';
4
4
  export * from './move-addon-files.js';
5
5
  export * from './move-project-root-files.js';
6
6
  export * from './move-test-app-files.js';
@@ -1,7 +1,6 @@
1
1
  import glob from 'glob';
2
2
 
3
- import { moveFiles, removeFiles } from '../../../utils/files.js';
4
- import { mapFilePaths } from '../../../utils/map-file-paths.js';
3
+ import { mapFilePaths, moveFiles, removeFiles } from '../../../utils/files.js';
5
4
 
6
5
  function moveAddonFolder(options) {
7
6
  const { locations, projectRoot } = options;
@@ -63,12 +62,7 @@ function removeAppFolder(options) {
63
62
  nodir: true,
64
63
  });
65
64
 
66
- const pathMapping = mapFilePaths(filePaths, {
67
- from: 'app',
68
- to: 'app',
69
- });
70
-
71
- removeFiles(pathMapping, options);
65
+ removeFiles(filePaths, options);
72
66
  }
73
67
 
74
68
  export function moveAddonFiles(options) {
@@ -1,7 +1,11 @@
1
1
  import glob from 'glob';
2
2
 
3
- import { copyFiles, moveFiles, removeFiles } from '../../../utils/files.js';
4
- import { mapFilePaths } from '../../../utils/map-file-paths.js';
3
+ import {
4
+ copyFiles,
5
+ mapFilePaths,
6
+ moveFiles,
7
+ removeFiles,
8
+ } from '../../../utils/files.js';
5
9
 
6
10
  function globPattern(files) {
7
11
  if (files.length <= 1) {
@@ -33,6 +37,7 @@ function moveToAddonAndTestApp(options) {
33
37
 
34
38
  const files = packages.addon.hasTypeScript
35
39
  ? [
40
+ '.eslintignore',
36
41
  '.eslintrc.js',
37
42
  '.gitignore',
38
43
  '.prettierignore',
@@ -43,6 +48,7 @@ function moveToAddonAndTestApp(options) {
43
48
  'tsconfig.json',
44
49
  ]
45
50
  : [
51
+ '.eslintignore',
46
52
  '.eslintrc.js',
47
53
  '.gitignore',
48
54
  '.prettierignore',
@@ -70,12 +76,7 @@ function moveToAddonAndTestApp(options) {
70
76
 
71
77
  copyFiles(pathMapping, options);
72
78
 
73
- pathMapping = mapFilePaths(filePaths, {
74
- from: '',
75
- to: '',
76
- });
77
-
78
- removeFiles(pathMapping, options);
79
+ removeFiles(filePaths, options);
79
80
  }
80
81
 
81
82
  function moveToTestApp(options) {
@@ -83,7 +84,6 @@ function moveToTestApp(options) {
83
84
 
84
85
  const files = [
85
86
  '.ember-cli',
86
- '.eslintignore',
87
87
  '.watchmanconfig',
88
88
  'ember-cli-build.js',
89
89
  'testem.js',
@@ -110,12 +110,7 @@ function removeFromProjectRoot(options) {
110
110
  cwd: projectRoot,
111
111
  });
112
112
 
113
- const pathMapping = mapFilePaths(filePaths, {
114
- from: '',
115
- to: '',
116
- });
117
-
118
- removeFiles(pathMapping, options);
113
+ removeFiles(filePaths, options);
119
114
  }
120
115
 
121
116
  export function moveProjectRootFiles(options) {
@@ -3,8 +3,7 @@ import { join } from 'node:path';
3
3
 
4
4
  import glob from 'glob';
5
5
 
6
- import { moveFiles } from '../../../utils/files.js';
7
- import { mapFilePaths } from '../../../utils/map-file-paths.js';
6
+ import { mapFilePaths, moveFiles } from '../../../utils/files.js';
8
7
 
9
8
  function moveTestsFolder(options) {
10
9
  const { locations, projectRoot } = options;
@@ -1,13 +1,10 @@
1
1
  import { readFileSync, writeFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
 
4
- import {
5
- convertToMap,
6
- convertToObject,
7
- } from '../../../utils/convert-json-object.js';
8
- import { decideVersion } from '../../../utils/decide-version.js';
4
+ import { decideVersion } from '../../../utils/blueprints.js';
5
+ import { convertToMap, convertToObject } from '../../../utils/json.js';
9
6
 
10
- function updateDependencies(packageJson) {
7
+ function updateDependencies(packageJson, options) {
11
8
  const dependencies = convertToMap(packageJson['dependencies']);
12
9
 
13
10
  const packagesToDelete = [
@@ -24,7 +21,7 @@ function updateDependencies(packageJson) {
24
21
  const packagesToInstall = ['@embroider/addon-shim'];
25
22
 
26
23
  packagesToInstall.forEach((packageName) => {
27
- const version = decideVersion(packageName, dependencies);
24
+ const version = decideVersion(packageName, options);
28
25
 
29
26
  dependencies.set(packageName, version);
30
27
  });
@@ -71,7 +68,7 @@ function updateDevDependencies(packageJson, options) {
71
68
  ];
72
69
 
73
70
  packagesToInstall.forEach((packageName) => {
74
- const version = decideVersion(packageName, devDependencies);
71
+ const version = decideVersion(packageName, options);
75
72
 
76
73
  devDependencies.set(packageName, version);
77
74
  });
@@ -117,7 +114,7 @@ export function updateAddonPackageJson(options) {
117
114
  const oldFile = readFileSync(oldPath, 'utf8');
118
115
  const packageJson = JSON.parse(oldFile);
119
116
 
120
- updateDependencies(packageJson);
117
+ updateDependencies(packageJson, options);
121
118
  updateDevDependencies(packageJson, options);
122
119
  updateScripts(packageJson);
123
120
  updateOtherFields(packageJson);
@@ -4,7 +4,8 @@ import { join } from 'node:path';
4
4
  import {
5
5
  convertToMap,
6
6
  convertToObject,
7
- } from '../../../utils/convert-json-object.js';
7
+ sanitizeJson,
8
+ } from '../../../utils/json.js';
8
9
 
9
10
  function updateCompilerOptions(tsconfigJson) {
10
11
  const compilerOptions = convertToMap(tsconfigJson['compilerOptions']);
@@ -28,10 +29,7 @@ export function updateAddonTsconfigJson(options) {
28
29
 
29
30
  const oldPath = join(projectRoot, locations.addon, 'tsconfig.json');
30
31
  const oldFile = readFileSync(oldPath, 'utf8');
31
- const tsconfigJson = JSON.parse(
32
- // Remove comments
33
- oldFile.replace(new RegExp('//.*', 'mg'), '')
34
- );
32
+ const tsconfigJson = JSON.parse(sanitizeJson(oldFile));
35
33
 
36
34
  updateCompilerOptions(tsconfigJson);
37
35
  updateInclude(tsconfigJson);
@@ -1,11 +1,8 @@
1
1
  import { readFileSync, writeFileSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
 
4
- import {
5
- convertToMap,
6
- convertToObject,
7
- } from '../../../utils/convert-json-object.js';
8
- import { decideVersion } from '../../../utils/decide-version.js';
4
+ import { decideVersion } from '../../../utils/blueprints.js';
5
+ import { convertToMap, convertToObject } from '../../../utils/json.js';
9
6
 
10
7
  function moveDependenciesToDevDependencies(packageJson, options) {
11
8
  const { packages } = options;
@@ -23,7 +20,7 @@ function moveDependenciesToDevDependencies(packageJson, options) {
23
20
  : ['ember-auto-import', 'ember-cli-babel', 'ember-cli-htmlbars'];
24
21
 
25
22
  packagesToMove.forEach((packageName) => {
26
- const version = decideVersion(packageName, dependencies);
23
+ const version = decideVersion(packageName, options);
27
24
 
28
25
  devDependencies.set(packageName, version);
29
26
 
@@ -4,7 +4,8 @@ import { join } from 'node:path';
4
4
  import {
5
5
  convertToMap,
6
6
  convertToObject,
7
- } from '../../../utils/convert-json-object.js';
7
+ sanitizeJson,
8
+ } from '../../../utils/json.js';
8
9
 
9
10
  function updateCompilerOptions(tsconfigJson, options) {
10
11
  const { packages } = options;
@@ -33,10 +34,7 @@ export function updateTestAppTsconfigJson(options) {
33
34
 
34
35
  const oldPath = join(projectRoot, locations.testApp, 'tsconfig.json');
35
36
  const oldFile = readFileSync(oldPath, 'utf8');
36
- const tsconfigJson = JSON.parse(
37
- // Remove comments
38
- oldFile.replace(new RegExp('//.*', 'mg'), '')
39
- );
37
+ const tsconfigJson = JSON.parse(sanitizeJson(oldFile));
40
38
 
41
39
  updateCompilerOptions(tsconfigJson, options);
42
40
  updateInclude(tsconfigJson);
@@ -16,8 +16,10 @@ const latestVersions = new Map([
16
16
  ['rollup-plugin-ts', '3.1.1'],
17
17
  ]);
18
18
 
19
- export function decideVersion(packageName, projectDependencies) {
20
- const installedVersion = projectDependencies.get(packageName);
19
+ export function decideVersion(packageName, options) {
20
+ const { packages } = options;
21
+
22
+ const installedVersion = packages.addon.dependencies.get(packageName);
21
23
  const latestVersion = `^${latestVersions.get(packageName)}`;
22
24
 
23
25
  return installedVersion ?? latestVersion;
@@ -1,12 +1,12 @@
1
1
  /* https://github.com/ember-cli/ember-cli/blob/v4.9.2/lib/utilities/process-template.js */
2
2
  import template from 'lodash.template';
3
3
 
4
- export function processTemplate(content, context) {
5
- const options = {
4
+ export function processTemplate(file, data) {
5
+ const settings = {
6
6
  escape: /<%-([\s\S]+?)%>/g,
7
7
  evaluate: /<%([\s\S]+?)%>/g,
8
8
  interpolate: /<%=([\s\S]+?)%>/g,
9
9
  };
10
10
 
11
- return template(content, options)(context);
11
+ return template(file, settings)(data);
12
12
  }
@@ -0,0 +1,2 @@
1
+ export * from './blueprints/decide-version.js';
2
+ export * from './blueprints/process-template.js';
@@ -0,0 +1,19 @@
1
+ import { copyFileSync, existsSync, mkdirSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+
4
+ export function copyFiles(pathMapping, options) {
5
+ const { projectRoot } = options;
6
+
7
+ pathMapping.forEach((newPath, oldPath) => {
8
+ const oldAbsolutePath = join(projectRoot, oldPath);
9
+
10
+ const newAbsolutePath = join(projectRoot, newPath);
11
+ const newDirectory = dirname(newAbsolutePath);
12
+
13
+ if (!existsSync(newDirectory)) {
14
+ mkdirSync(newDirectory, { recursive: true });
15
+ }
16
+
17
+ copyFileSync(oldAbsolutePath, newAbsolutePath);
18
+ });
19
+ }
@@ -0,0 +1,17 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+
4
+ export function createFiles(fileMapping, options) {
5
+ const { projectRoot } = options;
6
+
7
+ fileMapping.forEach((file, newPath) => {
8
+ const newAbsolutePath = join(projectRoot, newPath);
9
+ const newDirectory = dirname(newAbsolutePath);
10
+
11
+ if (!existsSync(newDirectory)) {
12
+ mkdirSync(newDirectory, { recursive: true });
13
+ }
14
+
15
+ writeFileSync(newAbsolutePath, file, 'utf8');
16
+ });
17
+ }
@@ -0,0 +1,22 @@
1
+ import { existsSync, mkdirSync, renameSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+
4
+ import { removeDirectoryIfEmpty } from './remove-directory-if-empty.js';
5
+
6
+ export function moveFiles(pathMapping, options) {
7
+ const { projectRoot } = options;
8
+
9
+ pathMapping.forEach((newPath, oldPath) => {
10
+ const oldAbsolutePath = join(projectRoot, oldPath);
11
+
12
+ const newAbsolutePath = join(projectRoot, newPath);
13
+ const newDirectory = dirname(newAbsolutePath);
14
+
15
+ if (!existsSync(newDirectory)) {
16
+ mkdirSync(newDirectory, { recursive: true });
17
+ }
18
+
19
+ renameSync(oldAbsolutePath, newAbsolutePath);
20
+ removeDirectoryIfEmpty({ oldPath, projectRoot });
21
+ });
22
+ }
@@ -0,0 +1,19 @@
1
+ import { readdirSync, rmSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+
4
+ export function removeDirectoryIfEmpty({ oldPath, projectRoot }) {
5
+ const directories = dirname(oldPath).split('/');
6
+ const depth = directories.length;
7
+
8
+ for (let i = 0; i < depth; i++) {
9
+ const directory = join(projectRoot, ...directories);
10
+ const numFilesLeft = readdirSync(directory).length;
11
+
12
+ if (numFilesLeft > 0) {
13
+ continue;
14
+ }
15
+
16
+ rmSync(directory, { recursive: true });
17
+ directories.pop();
18
+ }
19
+ }
@@ -0,0 +1,15 @@
1
+ import { rmSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+
4
+ import { removeDirectoryIfEmpty } from './remove-directory-if-empty.js';
5
+
6
+ export function removeFiles(oldPaths, options) {
7
+ const { projectRoot } = options;
8
+
9
+ oldPaths.forEach((oldPath) => {
10
+ const oldAbsolutePath = join(projectRoot, oldPath);
11
+
12
+ rmSync(oldAbsolutePath);
13
+ removeDirectoryIfEmpty({ oldPath, projectRoot });
14
+ });
15
+ }
@@ -1,88 +1,6 @@
1
- import {
2
- copyFileSync,
3
- existsSync,
4
- mkdirSync,
5
- readdirSync,
6
- renameSync,
7
- rmSync,
8
- writeFileSync,
9
- } from 'node:fs';
10
- import { dirname, join } from 'node:path';
11
-
12
- function removeDirectoryIfEmpty({ oldPath, projectRoot }) {
13
- const directories = dirname(oldPath).split('/');
14
- const depth = directories.length;
15
-
16
- for (let i = 0; i < depth; i++) {
17
- const directory = join(projectRoot, ...directories);
18
- const numFilesLeft = readdirSync(directory).length;
19
-
20
- if (numFilesLeft > 0) {
21
- continue;
22
- }
23
-
24
- rmSync(directory, { recursive: true });
25
- directories.pop();
26
- }
27
- }
28
-
29
- export function copyFiles(pathMapping, options) {
30
- const { projectRoot } = options;
31
-
32
- pathMapping.forEach((newPath, oldPath) => {
33
- const oldAbsolutePath = join(projectRoot, oldPath);
34
-
35
- const newAbsolutePath = join(projectRoot, newPath);
36
- const newDirectory = dirname(newAbsolutePath);
37
-
38
- if (!existsSync(newDirectory)) {
39
- mkdirSync(newDirectory, { recursive: true });
40
- }
41
-
42
- copyFileSync(oldAbsolutePath, newAbsolutePath);
43
- });
44
- }
45
-
46
- export function createFiles(fileMapping, options) {
47
- const { projectRoot } = options;
48
-
49
- fileMapping.forEach((file, newPath) => {
50
- const newAbsolutePath = join(projectRoot, newPath);
51
- const newDirectory = dirname(newAbsolutePath);
52
-
53
- if (!existsSync(newDirectory)) {
54
- mkdirSync(newDirectory, { recursive: true });
55
- }
56
-
57
- writeFileSync(newAbsolutePath, file, 'utf8');
58
- });
59
- }
60
-
61
- export function moveFiles(pathMapping, options) {
62
- const { projectRoot } = options;
63
-
64
- pathMapping.forEach((newPath, oldPath) => {
65
- const oldAbsolutePath = join(projectRoot, oldPath);
66
-
67
- const newAbsolutePath = join(projectRoot, newPath);
68
- const newDirectory = dirname(newAbsolutePath);
69
-
70
- if (!existsSync(newDirectory)) {
71
- mkdirSync(newDirectory, { recursive: true });
72
- }
73
-
74
- renameSync(oldAbsolutePath, newAbsolutePath);
75
- removeDirectoryIfEmpty({ oldPath, projectRoot });
76
- });
77
- }
78
-
79
- export function removeFiles(pathMapping, options) {
80
- const { projectRoot } = options;
81
-
82
- pathMapping.forEach((newPath, oldPath) => {
83
- const oldAbsolutePath = join(projectRoot, oldPath);
84
-
85
- rmSync(oldAbsolutePath);
86
- removeDirectoryIfEmpty({ oldPath, projectRoot });
87
- });
88
- }
1
+ export * from './files/copy-files.js';
2
+ export * from './files/create-files.js';
3
+ export * from './files/map-file-paths.js';
4
+ export * from './files/move-files.js';
5
+ export * from './files/remove-directory-if-empty.js';
6
+ export * from './files/remove-files.js';
@@ -0,0 +1,3 @@
1
+ export function convertToMap(object = {}) {
2
+ return new Map(Object.entries(object));
3
+ }
@@ -1,7 +1,3 @@
1
- export function convertToMap(object = {}) {
2
- return new Map(Object.entries(object));
3
- }
4
-
5
1
  export function convertToObject(map) {
6
2
  const sortedMap = new Map([...map.entries()].sort());
7
3
 
@@ -0,0 +1,7 @@
1
+ import stripJsonComments from 'strip-json-comments';
2
+
3
+ export function sanitizeJson(jsonFile) {
4
+ return stripJsonComments(jsonFile, {
5
+ whitespace: false,
6
+ });
7
+ }
@@ -0,0 +1,3 @@
1
+ export * from './json/convert-to-map.js';
2
+ export * from './json/convert-to-object.js';
3
+ export * from './json/sanitize-json.js';