@strapi/upgrade 5.12.0 → 5.12.2

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 (245) hide show
  1. package/dist/cli.js +6 -203
  2. package/dist/cli.js.map +1 -1
  3. package/dist/cli.mjs +5 -202
  4. package/dist/cli.mjs.map +1 -1
  5. package/dist/index.js +4 -155
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +4 -157
  8. package/dist/index.mjs.map +1 -1
  9. package/dist/package.json.js +6 -0
  10. package/dist/package.json.js.map +1 -0
  11. package/dist/package.json.mjs +4 -0
  12. package/dist/package.json.mjs.map +1 -0
  13. package/dist/src/cli/commands/codemods.js +120 -0
  14. package/dist/src/cli/commands/codemods.js.map +1 -0
  15. package/dist/src/cli/commands/codemods.mjs +116 -0
  16. package/dist/src/cli/commands/codemods.mjs.map +1 -0
  17. package/dist/src/cli/commands/upgrade.js +99 -0
  18. package/dist/src/cli/commands/upgrade.js.map +1 -0
  19. package/dist/src/cli/commands/upgrade.mjs +96 -0
  20. package/dist/src/cli/commands/upgrade.mjs.map +1 -0
  21. package/dist/src/cli/errors.js +18 -0
  22. package/dist/src/cli/errors.js.map +1 -0
  23. package/dist/src/cli/errors.mjs +16 -0
  24. package/dist/src/cli/errors.mjs.map +1 -0
  25. package/dist/src/cli/options.js +26 -0
  26. package/dist/src/cli/options.js.map +1 -0
  27. package/dist/src/cli/options.mjs +19 -0
  28. package/dist/src/cli/options.mjs.map +1 -0
  29. package/dist/src/modules/codemod/codemod.js +44 -0
  30. package/dist/src/modules/codemod/codemod.js.map +1 -0
  31. package/dist/src/modules/codemod/codemod.mjs +41 -0
  32. package/dist/src/modules/codemod/codemod.mjs.map +1 -0
  33. package/dist/src/modules/codemod/constants.js +17 -0
  34. package/dist/src/modules/codemod/constants.js.map +1 -0
  35. package/dist/src/modules/codemod/constants.mjs +11 -0
  36. package/dist/src/modules/codemod/constants.mjs.map +1 -0
  37. package/dist/src/modules/codemod/index.js +10 -0
  38. package/dist/src/modules/codemod/index.js.map +1 -0
  39. package/dist/src/modules/codemod/index.mjs +4 -0
  40. package/dist/src/modules/codemod/index.mjs.map +1 -0
  41. package/dist/src/modules/codemod-repository/constants.js +9 -0
  42. package/dist/src/modules/codemod-repository/constants.js.map +1 -0
  43. package/dist/src/modules/codemod-repository/constants.mjs +7 -0
  44. package/dist/src/modules/codemod-repository/constants.mjs.map +1 -0
  45. package/dist/src/modules/codemod-repository/index.js +10 -0
  46. package/dist/src/modules/codemod-repository/index.js.map +1 -0
  47. package/dist/src/modules/codemod-repository/index.mjs +4 -0
  48. package/dist/src/modules/codemod-repository/index.mjs.map +1 -0
  49. package/dist/src/modules/codemod-repository/repository.js +127 -0
  50. package/dist/src/modules/codemod-repository/repository.js.map +1 -0
  51. package/dist/src/modules/codemod-repository/repository.mjs +123 -0
  52. package/dist/src/modules/codemod-repository/repository.mjs.map +1 -0
  53. package/dist/src/modules/codemod-runner/codemod-runner.js +113 -0
  54. package/dist/src/modules/codemod-runner/codemod-runner.js.map +1 -0
  55. package/dist/src/modules/codemod-runner/codemod-runner.mjs +110 -0
  56. package/dist/src/modules/codemod-runner/codemod-runner.mjs.map +1 -0
  57. package/dist/src/modules/error/index.js +11 -0
  58. package/dist/src/modules/error/index.js.map +1 -0
  59. package/dist/src/modules/error/index.mjs +2 -0
  60. package/dist/src/modules/error/index.mjs.map +1 -0
  61. package/dist/src/modules/error/utils.js +33 -0
  62. package/dist/src/modules/error/utils.js.map +1 -0
  63. package/dist/src/modules/error/utils.mjs +28 -0
  64. package/dist/src/modules/error/utils.mjs.map +1 -0
  65. package/dist/src/modules/file-scanner/index.js +8 -0
  66. package/dist/src/modules/file-scanner/index.js.map +1 -0
  67. package/dist/src/modules/file-scanner/index.mjs +2 -0
  68. package/dist/src/modules/file-scanner/index.mjs.map +1 -0
  69. package/dist/src/modules/file-scanner/scanner.js +23 -0
  70. package/dist/src/modules/file-scanner/scanner.js.map +1 -0
  71. package/dist/src/modules/file-scanner/scanner.mjs +20 -0
  72. package/dist/src/modules/file-scanner/scanner.mjs.map +1 -0
  73. package/dist/src/modules/format/formats.js +107 -0
  74. package/dist/src/modules/format/formats.js.map +1 -0
  75. package/dist/src/modules/format/formats.mjs +94 -0
  76. package/dist/src/modules/format/formats.mjs.map +1 -0
  77. package/dist/src/modules/format/index.js +19 -0
  78. package/dist/src/modules/format/index.js.map +1 -0
  79. package/dist/src/modules/format/index.mjs +2 -0
  80. package/dist/src/modules/format/index.mjs.map +1 -0
  81. package/dist/src/modules/index.js +32 -0
  82. package/dist/src/modules/index.js.map +1 -0
  83. package/dist/src/modules/index.mjs +27 -0
  84. package/dist/src/modules/index.mjs.map +1 -0
  85. package/dist/src/modules/json/file.js +16 -0
  86. package/dist/src/modules/json/file.js.map +1 -0
  87. package/dist/src/modules/json/file.mjs +13 -0
  88. package/dist/src/modules/json/file.mjs.map +1 -0
  89. package/dist/src/modules/json/transform-api.js +38 -0
  90. package/dist/src/modules/json/transform-api.js.map +1 -0
  91. package/dist/src/modules/json/transform-api.mjs +35 -0
  92. package/dist/src/modules/json/transform-api.mjs.map +1 -0
  93. package/dist/src/modules/logger/index.js +8 -0
  94. package/dist/src/modules/logger/index.js.map +1 -0
  95. package/dist/src/modules/logger/index.mjs +2 -0
  96. package/dist/src/modules/logger/index.mjs.map +1 -0
  97. package/dist/src/modules/logger/logger.js +76 -0
  98. package/dist/src/modules/logger/logger.js.map +1 -0
  99. package/dist/src/modules/logger/logger.mjs +73 -0
  100. package/dist/src/modules/logger/logger.mjs.map +1 -0
  101. package/dist/src/modules/npm/constants.js +6 -0
  102. package/dist/src/modules/npm/constants.js.map +1 -0
  103. package/dist/src/modules/npm/constants.mjs +4 -0
  104. package/dist/src/modules/npm/constants.mjs.map +1 -0
  105. package/dist/src/modules/npm/package.js +55 -0
  106. package/dist/src/modules/npm/package.js.map +1 -0
  107. package/dist/src/modules/npm/package.mjs +52 -0
  108. package/dist/src/modules/npm/package.mjs.map +1 -0
  109. package/dist/src/modules/project/constants.js +45 -0
  110. package/dist/src/modules/project/constants.js.map +1 -0
  111. package/dist/src/modules/project/constants.mjs +35 -0
  112. package/dist/src/modules/project/constants.mjs.map +1 -0
  113. package/dist/src/modules/project/index.js +15 -0
  114. package/dist/src/modules/project/index.js.map +1 -0
  115. package/dist/src/modules/project/index.mjs +5 -0
  116. package/dist/src/modules/project/index.mjs.map +1 -0
  117. package/dist/src/modules/project/project.js +208 -0
  118. package/dist/src/modules/project/project.js.map +1 -0
  119. package/dist/src/modules/project/project.mjs +203 -0
  120. package/dist/src/modules/project/project.mjs.map +1 -0
  121. package/dist/src/modules/project/utils.js +26 -0
  122. package/dist/src/modules/project/utils.js.map +1 -0
  123. package/dist/src/modules/project/utils.mjs +21 -0
  124. package/dist/src/modules/project/utils.mjs.map +1 -0
  125. package/dist/src/modules/report/index.js +9 -0
  126. package/dist/src/modules/report/index.js.map +1 -0
  127. package/dist/src/modules/report/index.mjs +2 -0
  128. package/dist/src/modules/report/index.mjs.map +1 -0
  129. package/dist/src/modules/report/report.js +13 -0
  130. package/dist/src/modules/report/report.js.map +1 -0
  131. package/dist/src/modules/report/report.mjs +10 -0
  132. package/dist/src/modules/report/report.mjs.map +1 -0
  133. package/dist/src/modules/requirement/index.js +8 -0
  134. package/dist/src/modules/requirement/index.js.map +1 -0
  135. package/dist/src/modules/requirement/index.mjs +2 -0
  136. package/dist/src/modules/requirement/index.mjs.map +1 -0
  137. package/dist/src/modules/requirement/requirement.js +55 -0
  138. package/dist/src/modules/requirement/requirement.js.map +1 -0
  139. package/dist/src/modules/requirement/requirement.mjs +52 -0
  140. package/dist/src/modules/requirement/requirement.mjs.map +1 -0
  141. package/dist/src/modules/runner/code/code.js +21 -0
  142. package/dist/src/modules/runner/code/code.js.map +1 -0
  143. package/dist/src/modules/runner/code/code.mjs +18 -0
  144. package/dist/src/modules/runner/code/code.mjs.map +1 -0
  145. package/dist/src/modules/runner/code/index.js +8 -0
  146. package/dist/src/modules/runner/code/index.js.map +1 -0
  147. package/dist/src/modules/runner/code/index.mjs +2 -0
  148. package/dist/src/modules/runner/code/index.mjs.map +1 -0
  149. package/dist/src/modules/runner/index.js +10 -0
  150. package/dist/src/modules/runner/index.js.map +1 -0
  151. package/dist/src/modules/runner/index.mjs +5 -0
  152. package/dist/src/modules/runner/index.mjs.map +1 -0
  153. package/dist/src/modules/runner/json/index.js +8 -0
  154. package/dist/src/modules/runner/json/index.js.map +1 -0
  155. package/dist/src/modules/runner/json/index.mjs +2 -0
  156. package/dist/src/modules/runner/json/index.mjs.map +1 -0
  157. package/dist/src/modules/runner/json/json.js +21 -0
  158. package/dist/src/modules/runner/json/json.js.map +1 -0
  159. package/dist/src/modules/runner/json/json.mjs +18 -0
  160. package/dist/src/modules/runner/json/json.mjs.map +1 -0
  161. package/dist/src/modules/runner/json/transform.js +85 -0
  162. package/dist/src/modules/runner/json/transform.js.map +1 -0
  163. package/dist/src/modules/runner/json/transform.mjs +83 -0
  164. package/dist/src/modules/runner/json/transform.mjs.map +1 -0
  165. package/dist/src/modules/runner/runner.js +22 -0
  166. package/dist/src/modules/runner/runner.js.map +1 -0
  167. package/dist/src/modules/runner/runner.mjs +20 -0
  168. package/dist/src/modules/runner/runner.mjs.map +1 -0
  169. package/dist/src/modules/timer/constants.js +6 -0
  170. package/dist/src/modules/timer/constants.js.map +1 -0
  171. package/dist/src/modules/timer/constants.mjs +4 -0
  172. package/dist/src/modules/timer/constants.mjs.map +1 -0
  173. package/dist/src/modules/timer/index.js +10 -0
  174. package/dist/src/modules/timer/index.js.map +1 -0
  175. package/dist/src/modules/timer/index.mjs +4 -0
  176. package/dist/src/modules/timer/index.mjs.map +1 -0
  177. package/dist/src/modules/timer/timer.js +33 -0
  178. package/dist/src/modules/timer/timer.js.map +1 -0
  179. package/dist/src/modules/timer/timer.mjs +30 -0
  180. package/dist/src/modules/timer/timer.mjs.map +1 -0
  181. package/dist/src/modules/upgrader/constants.js +6 -0
  182. package/dist/src/modules/upgrader/constants.js.map +1 -0
  183. package/dist/src/modules/upgrader/constants.mjs +4 -0
  184. package/dist/src/modules/upgrader/constants.mjs.map +1 -0
  185. package/dist/src/modules/upgrader/index.js +10 -0
  186. package/dist/src/modules/upgrader/index.js.map +1 -0
  187. package/dist/src/modules/upgrader/index.mjs +4 -0
  188. package/dist/src/modules/upgrader/index.mjs.map +1 -0
  189. package/dist/src/modules/upgrader/upgrader.js +266 -0
  190. package/dist/src/modules/upgrader/upgrader.js.map +1 -0
  191. package/dist/src/modules/upgrader/upgrader.mjs +263 -0
  192. package/dist/src/modules/upgrader/upgrader.mjs.map +1 -0
  193. package/dist/src/modules/version/index.js +20 -0
  194. package/dist/src/modules/version/index.js.map +1 -0
  195. package/dist/src/modules/version/index.mjs +5 -0
  196. package/dist/src/modules/version/index.mjs.map +1 -0
  197. package/dist/src/modules/version/range.js +81 -0
  198. package/dist/src/modules/version/range.js.map +1 -0
  199. package/dist/src/modules/version/range.mjs +75 -0
  200. package/dist/src/modules/version/range.mjs.map +1 -0
  201. package/dist/src/modules/version/semver.js +26 -0
  202. package/dist/src/modules/version/semver.js.map +1 -0
  203. package/dist/src/modules/version/semver.mjs +20 -0
  204. package/dist/src/modules/version/semver.mjs.map +1 -0
  205. package/dist/src/modules/version/types.js +12 -0
  206. package/dist/src/modules/version/types.js.map +1 -0
  207. package/dist/src/modules/version/types.mjs +12 -0
  208. package/dist/src/modules/version/types.mjs.map +1 -0
  209. package/dist/src/tasks/codemods/list-codemods.js +40 -0
  210. package/dist/src/tasks/codemods/list-codemods.js.map +1 -0
  211. package/dist/src/tasks/codemods/list-codemods.mjs +38 -0
  212. package/dist/src/tasks/codemods/list-codemods.mjs.map +1 -0
  213. package/dist/src/tasks/codemods/run-codemods.js +36 -0
  214. package/dist/src/tasks/codemods/run-codemods.js.map +1 -0
  215. package/dist/src/tasks/codemods/run-codemods.mjs +34 -0
  216. package/dist/src/tasks/codemods/run-codemods.mjs.map +1 -0
  217. package/dist/src/tasks/codemods/utils.js +54 -0
  218. package/dist/src/tasks/codemods/utils.js.map +1 -0
  219. package/dist/src/tasks/codemods/utils.mjs +50 -0
  220. package/dist/src/tasks/codemods/utils.mjs.map +1 -0
  221. package/dist/src/tasks/index.js +15 -0
  222. package/dist/src/tasks/index.js.map +1 -0
  223. package/dist/src/tasks/index.mjs +7 -0
  224. package/dist/src/tasks/index.mjs.map +1 -0
  225. package/dist/src/tasks/upgrade/prompts/latest.js +48 -0
  226. package/dist/src/tasks/upgrade/prompts/latest.js.map +1 -0
  227. package/dist/src/tasks/upgrade/prompts/latest.mjs +46 -0
  228. package/dist/src/tasks/upgrade/prompts/latest.mjs.map +1 -0
  229. package/dist/src/tasks/upgrade/requirements/common.js +40 -0
  230. package/dist/src/tasks/upgrade/requirements/common.js.map +1 -0
  231. package/dist/src/tasks/upgrade/requirements/common.mjs +35 -0
  232. package/dist/src/tasks/upgrade/requirements/common.mjs.map +1 -0
  233. package/dist/src/tasks/upgrade/requirements/major.js +29 -0
  234. package/dist/src/tasks/upgrade/requirements/major.js.map +1 -0
  235. package/dist/src/tasks/upgrade/requirements/major.mjs +26 -0
  236. package/dist/src/tasks/upgrade/requirements/major.mjs.map +1 -0
  237. package/dist/src/tasks/upgrade/upgrade.js +69 -0
  238. package/dist/src/tasks/upgrade/upgrade.js.map +1 -0
  239. package/dist/src/tasks/upgrade/upgrade.mjs +67 -0
  240. package/dist/src/tasks/upgrade/upgrade.mjs.map +1 -0
  241. package/package.json +4 -4
  242. package/dist/chunks/logger-DGi224NW.js +0 -1649
  243. package/dist/chunks/logger-DGi224NW.js.map +0 -1
  244. package/dist/chunks/logger-np_r7rTc.mjs +0 -1599
  245. package/dist/chunks/logger-np_r7rTc.mjs.map +0 -1
@@ -0,0 +1,127 @@
1
+ 'use strict';
2
+
3
+ var assert = require('node:assert');
4
+ var fse = require('fs-extra');
5
+ var semver$1 = require('semver');
6
+ var path = require('node:path');
7
+ var codemod = require('../codemod/codemod.js');
8
+ var constants$1 = require('../codemod/constants.js');
9
+ var semver = require('../version/semver.js');
10
+ var range = require('../version/range.js');
11
+ require('../version/types.js');
12
+ var constants = require('./constants.js');
13
+
14
+ class CodemodRepository {
15
+ refresh() {
16
+ this.refreshAvailableVersions();
17
+ this.refreshAvailableFiles();
18
+ return this;
19
+ }
20
+ count(version) {
21
+ return this.findByVersion(version).length;
22
+ }
23
+ versionExists(version) {
24
+ return version.raw in this.groups;
25
+ }
26
+ has(uid) {
27
+ const result = this.find({
28
+ uids: [
29
+ uid
30
+ ]
31
+ });
32
+ if (result.length !== 1) {
33
+ return false;
34
+ }
35
+ const { codemods } = result[0];
36
+ return codemods.length === 1 && codemods[0].uid === uid;
37
+ }
38
+ find(q) {
39
+ const entries = Object.entries(this.groups);
40
+ return entries// Filter by range if provided in the query
41
+ .filter(maybeFilterByRange)// Transform version/codemods tuples into regular objects
42
+ .map(([version, codemods])=>({
43
+ version: semver.semVerFactory(version),
44
+ // Filter by UID if provided in the query
45
+ codemods: codemods.filter(maybeFilterByUIDs)
46
+ }))// Only return groups with at least 1 codemod
47
+ .filter(({ codemods })=>codemods.length > 0);
48
+ function maybeFilterByRange([version]) {
49
+ if (!range.isRangeInstance(q.range)) {
50
+ return true;
51
+ }
52
+ return q.range.test(version);
53
+ }
54
+ function maybeFilterByUIDs(codemod) {
55
+ if (q.uids === undefined) {
56
+ return true;
57
+ }
58
+ return q.uids.includes(codemod.uid);
59
+ }
60
+ }
61
+ findByVersion(version) {
62
+ const literalVersion = version.raw;
63
+ const codemods = this.groups[literalVersion];
64
+ return codemods ?? [];
65
+ }
66
+ findAll() {
67
+ const entries = Object.entries(this.groups);
68
+ return entries.map(([version, codemods])=>({
69
+ version: semver.semVerFactory(version),
70
+ codemods
71
+ }));
72
+ }
73
+ refreshAvailableVersions() {
74
+ this.versions = fse.readdirSync(this.cwd) // Only keep root directories
75
+ .filter((filename)=>fse.statSync(path.join(this.cwd, filename)).isDirectory())// Paths should be valid semver
76
+ .filter((filename)=>semver$1.valid(filename) !== null)// Transform files names to SemVer instances
77
+ .map((version)=>semver.semVerFactory(version))// Sort versions in ascending order
78
+ .sort(semver$1.compare);
79
+ return this;
80
+ }
81
+ refreshAvailableFiles() {
82
+ this.groups = {};
83
+ for (const version of this.versions){
84
+ this.refreshAvailableFilesForVersion(version);
85
+ }
86
+ }
87
+ refreshAvailableFilesForVersion(version) {
88
+ const literalVersion = version.raw;
89
+ const versionDirectory = path.join(this.cwd, literalVersion);
90
+ // Ignore obsolete versions
91
+ if (!fse.existsSync(versionDirectory)) {
92
+ return;
93
+ }
94
+ this.groups[literalVersion] = fse.readdirSync(versionDirectory)// Make sure the filenames are valid codemod files
95
+ .filter((filename)=>fse.statSync(path.join(versionDirectory, filename)).isFile()).filter((filename)=>constants$1.CODEMOD_FILE_REGEXP.test(filename))// Transform the filenames into Codemod instances
96
+ .map((filename)=>{
97
+ const kind = parseCodemodKindFromFilename(filename);
98
+ const baseDirectory = this.cwd;
99
+ return codemod.codemodFactory({
100
+ kind,
101
+ baseDirectory,
102
+ version,
103
+ filename
104
+ });
105
+ });
106
+ }
107
+ constructor(cwd){
108
+ assert(fse.existsSync(cwd), `Invalid codemods directory provided "${cwd}"`);
109
+ this.cwd = cwd;
110
+ this.groups = {};
111
+ this.versions = [];
112
+ }
113
+ }
114
+ const parseCodemodKindFromFilename = (filename)=>{
115
+ const kind = filename.split('.').at(-2);
116
+ assert(kind !== undefined);
117
+ assert(constants$1.CODEMOD_ALLOWED_SUFFIXES.includes(kind));
118
+ return kind;
119
+ };
120
+ const codemodRepositoryFactory = (cwd = constants.INTERNAL_CODEMODS_DIRECTORY)=>{
121
+ return new CodemodRepository(cwd);
122
+ };
123
+
124
+ exports.CodemodRepository = CodemodRepository;
125
+ exports.codemodRepositoryFactory = codemodRepositoryFactory;
126
+ exports.parseCodemodKindFromFilename = parseCodemodKindFromFilename;
127
+ //# sourceMappingURL=repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.js","sources":["../../../../src/modules/codemod-repository/repository.ts"],"sourcesContent":["import assert from 'node:assert';\nimport fse from 'fs-extra';\nimport semver from 'semver';\nimport path from 'node:path';\n\nimport { codemodFactory, constants } from '../codemod';\nimport { isRangeInstance, semVerFactory } from '../version';\n\nimport { INTERNAL_CODEMODS_DIRECTORY } from './constants';\n\nimport type { Codemod } from '../codemod';\nimport type { Version } from '../version';\n\nimport type { CodemodRepository as CodemodRepositoryInterface, FindQuery } from './types';\n\nexport class CodemodRepository implements CodemodRepositoryInterface {\n private groups: Record<Version.LiteralSemVer, Codemod.Codemod[]>;\n\n private versions: Version.SemVer[];\n\n public cwd: string;\n\n constructor(cwd: string) {\n assert(fse.existsSync(cwd), `Invalid codemods directory provided \"${cwd}\"`);\n\n this.cwd = cwd;\n\n this.groups = {};\n this.versions = [];\n }\n\n refresh() {\n this.refreshAvailableVersions();\n this.refreshAvailableFiles();\n\n return this;\n }\n\n count(version: Version.SemVer) {\n return this.findByVersion(version).length;\n }\n\n versionExists(version: Version.SemVer) {\n return version.raw in this.groups;\n }\n\n has(uid: string) {\n const result = this.find({ uids: [uid] });\n\n if (result.length !== 1) {\n return false;\n }\n\n const { codemods } = result[0];\n\n return codemods.length === 1 && codemods[0].uid === uid;\n }\n\n find(q: FindQuery) {\n const entries = Object.entries(this.groups) as Array<[Version.LiteralSemVer, Codemod.List]>;\n\n return (\n entries\n // Filter by range if provided in the query\n .filter(maybeFilterByRange)\n // Transform version/codemods tuples into regular objects\n .map<Codemod.VersionedCollection>(([version, codemods]) => ({\n version: semVerFactory(version),\n // Filter by UID if provided in the query\n codemods: codemods.filter(maybeFilterByUIDs),\n }))\n // Only return groups with at least 1 codemod\n .filter(({ codemods }) => codemods.length > 0)\n );\n\n function maybeFilterByRange([version]: [Version.LiteralSemVer, Codemod.List]) {\n if (!isRangeInstance(q.range)) {\n return true;\n }\n\n return q.range.test(version);\n }\n\n function maybeFilterByUIDs(codemod: Codemod.Codemod) {\n if (q.uids === undefined) {\n return true;\n }\n\n return q.uids.includes(codemod.uid);\n }\n }\n\n findByVersion(version: Version.SemVer) {\n const literalVersion = version.raw as Version.LiteralSemVer;\n const codemods = this.groups[literalVersion];\n\n return codemods ?? [];\n }\n\n findAll() {\n const entries = Object.entries(this.groups);\n\n return entries.map<Codemod.VersionedCollection>(([version, codemods]) => ({\n version: semVerFactory(version),\n codemods,\n }));\n }\n\n private refreshAvailableVersions() {\n this.versions = fse\n .readdirSync(this.cwd) // Only keep root directories\n .filter((filename) => fse.statSync(path.join(this.cwd, filename)).isDirectory())\n // Paths should be valid semver\n .filter((filename): filename is Version.LiteralSemVer => semver.valid(filename) !== null)\n // Transform files names to SemVer instances\n .map<Version.SemVer>((version) => semVerFactory(version))\n // Sort versions in ascending order\n .sort(semver.compare);\n\n return this;\n }\n\n private refreshAvailableFiles() {\n this.groups = {};\n\n for (const version of this.versions) {\n this.refreshAvailableFilesForVersion(version);\n }\n }\n\n private refreshAvailableFilesForVersion(version: Version.SemVer) {\n const literalVersion = version.raw as Version.LiteralSemVer;\n const versionDirectory = path.join(this.cwd, literalVersion);\n\n // Ignore obsolete versions\n if (!fse.existsSync(versionDirectory)) {\n return;\n }\n\n this.groups[literalVersion] = fse\n .readdirSync(versionDirectory)\n // Make sure the filenames are valid codemod files\n .filter((filename) => fse.statSync(path.join(versionDirectory, filename)).isFile())\n .filter((filename) => constants.CODEMOD_FILE_REGEXP.test(filename))\n // Transform the filenames into Codemod instances\n .map((filename) => {\n const kind = parseCodemodKindFromFilename(filename);\n const baseDirectory = this.cwd;\n\n return codemodFactory({ kind, baseDirectory, version, filename });\n });\n }\n}\n\nexport const parseCodemodKindFromFilename = (filename: string): Codemod.Kind => {\n const kind = filename.split('.').at(-2) as Codemod.Kind | undefined;\n\n assert(kind !== undefined);\n assert(constants.CODEMOD_ALLOWED_SUFFIXES.includes(kind));\n\n return kind;\n};\n\nexport const codemodRepositoryFactory = (cwd: string = INTERNAL_CODEMODS_DIRECTORY) => {\n return new CodemodRepository(cwd);\n};\n"],"names":["CodemodRepository","refresh","refreshAvailableVersions","refreshAvailableFiles","count","version","findByVersion","length","versionExists","raw","groups","has","uid","result","find","uids","codemods","q","entries","Object","filter","maybeFilterByRange","map","semVerFactory","maybeFilterByUIDs","isRangeInstance","range","test","codemod","undefined","includes","literalVersion","findAll","versions","fse","readdirSync","cwd","filename","statSync","path","join","isDirectory","semver","valid","sort","compare","refreshAvailableFilesForVersion","versionDirectory","existsSync","isFile","constants","kind","parseCodemodKindFromFilename","baseDirectory","codemodFactory","constructor","assert","split","at","codemodRepositoryFactory","INTERNAL_CODEMODS_DIRECTORY"],"mappings":"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"}
@@ -0,0 +1,123 @@
1
+ import assert from 'node:assert';
2
+ import fse from 'fs-extra';
3
+ import semver from 'semver';
4
+ import path from 'node:path';
5
+ import { codemodFactory } from '../codemod/codemod.mjs';
6
+ import { CODEMOD_FILE_REGEXP, CODEMOD_ALLOWED_SUFFIXES } from '../codemod/constants.mjs';
7
+ import { semVerFactory } from '../version/semver.mjs';
8
+ import { isRangeInstance } from '../version/range.mjs';
9
+ import '../version/types.mjs';
10
+ import { INTERNAL_CODEMODS_DIRECTORY } from './constants.mjs';
11
+
12
+ class CodemodRepository {
13
+ refresh() {
14
+ this.refreshAvailableVersions();
15
+ this.refreshAvailableFiles();
16
+ return this;
17
+ }
18
+ count(version) {
19
+ return this.findByVersion(version).length;
20
+ }
21
+ versionExists(version) {
22
+ return version.raw in this.groups;
23
+ }
24
+ has(uid) {
25
+ const result = this.find({
26
+ uids: [
27
+ uid
28
+ ]
29
+ });
30
+ if (result.length !== 1) {
31
+ return false;
32
+ }
33
+ const { codemods } = result[0];
34
+ return codemods.length === 1 && codemods[0].uid === uid;
35
+ }
36
+ find(q) {
37
+ const entries = Object.entries(this.groups);
38
+ return entries// Filter by range if provided in the query
39
+ .filter(maybeFilterByRange)// Transform version/codemods tuples into regular objects
40
+ .map(([version, codemods])=>({
41
+ version: semVerFactory(version),
42
+ // Filter by UID if provided in the query
43
+ codemods: codemods.filter(maybeFilterByUIDs)
44
+ }))// Only return groups with at least 1 codemod
45
+ .filter(({ codemods })=>codemods.length > 0);
46
+ function maybeFilterByRange([version]) {
47
+ if (!isRangeInstance(q.range)) {
48
+ return true;
49
+ }
50
+ return q.range.test(version);
51
+ }
52
+ function maybeFilterByUIDs(codemod) {
53
+ if (q.uids === undefined) {
54
+ return true;
55
+ }
56
+ return q.uids.includes(codemod.uid);
57
+ }
58
+ }
59
+ findByVersion(version) {
60
+ const literalVersion = version.raw;
61
+ const codemods = this.groups[literalVersion];
62
+ return codemods ?? [];
63
+ }
64
+ findAll() {
65
+ const entries = Object.entries(this.groups);
66
+ return entries.map(([version, codemods])=>({
67
+ version: semVerFactory(version),
68
+ codemods
69
+ }));
70
+ }
71
+ refreshAvailableVersions() {
72
+ this.versions = fse.readdirSync(this.cwd) // Only keep root directories
73
+ .filter((filename)=>fse.statSync(path.join(this.cwd, filename)).isDirectory())// Paths should be valid semver
74
+ .filter((filename)=>semver.valid(filename) !== null)// Transform files names to SemVer instances
75
+ .map((version)=>semVerFactory(version))// Sort versions in ascending order
76
+ .sort(semver.compare);
77
+ return this;
78
+ }
79
+ refreshAvailableFiles() {
80
+ this.groups = {};
81
+ for (const version of this.versions){
82
+ this.refreshAvailableFilesForVersion(version);
83
+ }
84
+ }
85
+ refreshAvailableFilesForVersion(version) {
86
+ const literalVersion = version.raw;
87
+ const versionDirectory = path.join(this.cwd, literalVersion);
88
+ // Ignore obsolete versions
89
+ if (!fse.existsSync(versionDirectory)) {
90
+ return;
91
+ }
92
+ this.groups[literalVersion] = fse.readdirSync(versionDirectory)// Make sure the filenames are valid codemod files
93
+ .filter((filename)=>fse.statSync(path.join(versionDirectory, filename)).isFile()).filter((filename)=>CODEMOD_FILE_REGEXP.test(filename))// Transform the filenames into Codemod instances
94
+ .map((filename)=>{
95
+ const kind = parseCodemodKindFromFilename(filename);
96
+ const baseDirectory = this.cwd;
97
+ return codemodFactory({
98
+ kind,
99
+ baseDirectory,
100
+ version,
101
+ filename
102
+ });
103
+ });
104
+ }
105
+ constructor(cwd){
106
+ assert(fse.existsSync(cwd), `Invalid codemods directory provided "${cwd}"`);
107
+ this.cwd = cwd;
108
+ this.groups = {};
109
+ this.versions = [];
110
+ }
111
+ }
112
+ const parseCodemodKindFromFilename = (filename)=>{
113
+ const kind = filename.split('.').at(-2);
114
+ assert(kind !== undefined);
115
+ assert(CODEMOD_ALLOWED_SUFFIXES.includes(kind));
116
+ return kind;
117
+ };
118
+ const codemodRepositoryFactory = (cwd = INTERNAL_CODEMODS_DIRECTORY)=>{
119
+ return new CodemodRepository(cwd);
120
+ };
121
+
122
+ export { CodemodRepository, codemodRepositoryFactory, parseCodemodKindFromFilename };
123
+ //# sourceMappingURL=repository.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository.mjs","sources":["../../../../src/modules/codemod-repository/repository.ts"],"sourcesContent":["import assert from 'node:assert';\nimport fse from 'fs-extra';\nimport semver from 'semver';\nimport path from 'node:path';\n\nimport { codemodFactory, constants } from '../codemod';\nimport { isRangeInstance, semVerFactory } from '../version';\n\nimport { INTERNAL_CODEMODS_DIRECTORY } from './constants';\n\nimport type { Codemod } from '../codemod';\nimport type { Version } from '../version';\n\nimport type { CodemodRepository as CodemodRepositoryInterface, FindQuery } from './types';\n\nexport class CodemodRepository implements CodemodRepositoryInterface {\n private groups: Record<Version.LiteralSemVer, Codemod.Codemod[]>;\n\n private versions: Version.SemVer[];\n\n public cwd: string;\n\n constructor(cwd: string) {\n assert(fse.existsSync(cwd), `Invalid codemods directory provided \"${cwd}\"`);\n\n this.cwd = cwd;\n\n this.groups = {};\n this.versions = [];\n }\n\n refresh() {\n this.refreshAvailableVersions();\n this.refreshAvailableFiles();\n\n return this;\n }\n\n count(version: Version.SemVer) {\n return this.findByVersion(version).length;\n }\n\n versionExists(version: Version.SemVer) {\n return version.raw in this.groups;\n }\n\n has(uid: string) {\n const result = this.find({ uids: [uid] });\n\n if (result.length !== 1) {\n return false;\n }\n\n const { codemods } = result[0];\n\n return codemods.length === 1 && codemods[0].uid === uid;\n }\n\n find(q: FindQuery) {\n const entries = Object.entries(this.groups) as Array<[Version.LiteralSemVer, Codemod.List]>;\n\n return (\n entries\n // Filter by range if provided in the query\n .filter(maybeFilterByRange)\n // Transform version/codemods tuples into regular objects\n .map<Codemod.VersionedCollection>(([version, codemods]) => ({\n version: semVerFactory(version),\n // Filter by UID if provided in the query\n codemods: codemods.filter(maybeFilterByUIDs),\n }))\n // Only return groups with at least 1 codemod\n .filter(({ codemods }) => codemods.length > 0)\n );\n\n function maybeFilterByRange([version]: [Version.LiteralSemVer, Codemod.List]) {\n if (!isRangeInstance(q.range)) {\n return true;\n }\n\n return q.range.test(version);\n }\n\n function maybeFilterByUIDs(codemod: Codemod.Codemod) {\n if (q.uids === undefined) {\n return true;\n }\n\n return q.uids.includes(codemod.uid);\n }\n }\n\n findByVersion(version: Version.SemVer) {\n const literalVersion = version.raw as Version.LiteralSemVer;\n const codemods = this.groups[literalVersion];\n\n return codemods ?? [];\n }\n\n findAll() {\n const entries = Object.entries(this.groups);\n\n return entries.map<Codemod.VersionedCollection>(([version, codemods]) => ({\n version: semVerFactory(version),\n codemods,\n }));\n }\n\n private refreshAvailableVersions() {\n this.versions = fse\n .readdirSync(this.cwd) // Only keep root directories\n .filter((filename) => fse.statSync(path.join(this.cwd, filename)).isDirectory())\n // Paths should be valid semver\n .filter((filename): filename is Version.LiteralSemVer => semver.valid(filename) !== null)\n // Transform files names to SemVer instances\n .map<Version.SemVer>((version) => semVerFactory(version))\n // Sort versions in ascending order\n .sort(semver.compare);\n\n return this;\n }\n\n private refreshAvailableFiles() {\n this.groups = {};\n\n for (const version of this.versions) {\n this.refreshAvailableFilesForVersion(version);\n }\n }\n\n private refreshAvailableFilesForVersion(version: Version.SemVer) {\n const literalVersion = version.raw as Version.LiteralSemVer;\n const versionDirectory = path.join(this.cwd, literalVersion);\n\n // Ignore obsolete versions\n if (!fse.existsSync(versionDirectory)) {\n return;\n }\n\n this.groups[literalVersion] = fse\n .readdirSync(versionDirectory)\n // Make sure the filenames are valid codemod files\n .filter((filename) => fse.statSync(path.join(versionDirectory, filename)).isFile())\n .filter((filename) => constants.CODEMOD_FILE_REGEXP.test(filename))\n // Transform the filenames into Codemod instances\n .map((filename) => {\n const kind = parseCodemodKindFromFilename(filename);\n const baseDirectory = this.cwd;\n\n return codemodFactory({ kind, baseDirectory, version, filename });\n });\n }\n}\n\nexport const parseCodemodKindFromFilename = (filename: string): Codemod.Kind => {\n const kind = filename.split('.').at(-2) as Codemod.Kind | undefined;\n\n assert(kind !== undefined);\n assert(constants.CODEMOD_ALLOWED_SUFFIXES.includes(kind));\n\n return kind;\n};\n\nexport const codemodRepositoryFactory = (cwd: string = INTERNAL_CODEMODS_DIRECTORY) => {\n return new CodemodRepository(cwd);\n};\n"],"names":["CodemodRepository","refresh","refreshAvailableVersions","refreshAvailableFiles","count","version","findByVersion","length","versionExists","raw","groups","has","uid","result","find","uids","codemods","q","entries","Object","filter","maybeFilterByRange","map","semVerFactory","maybeFilterByUIDs","isRangeInstance","range","test","codemod","undefined","includes","literalVersion","findAll","versions","fse","readdirSync","cwd","filename","statSync","path","join","isDirectory","semver","valid","sort","compare","refreshAvailableFilesForVersion","versionDirectory","existsSync","isFile","constants","kind","parseCodemodKindFromFilename","baseDirectory","codemodFactory","constructor","assert","split","at","codemodRepositoryFactory","INTERNAL_CODEMODS_DIRECTORY"],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ 'use strict';
2
+
3
+ var fp = require('lodash/fp');
4
+ var repository = require('../codemod-repository/repository.js');
5
+ var constants = require('../codemod-repository/constants.js');
6
+ var utils = require('../error/utils.js');
7
+ var semver = require('../version/semver.js');
8
+ require('semver');
9
+ require('../version/types.js');
10
+ var formats = require('../format/formats.js');
11
+
12
+ class CodemodRunner {
13
+ setRange(range) {
14
+ this.range = range;
15
+ return this;
16
+ }
17
+ setLogger(logger) {
18
+ this.logger = logger;
19
+ return this;
20
+ }
21
+ onSelectCodemods(callback) {
22
+ this.selectCodemodsCallback = callback;
23
+ return this;
24
+ }
25
+ dry(enabled = true) {
26
+ this.isDry = enabled;
27
+ return this;
28
+ }
29
+ createRepository(codemodsDirectory) {
30
+ const repository$1 = repository.codemodRepositoryFactory(codemodsDirectory ?? constants.INTERNAL_CODEMODS_DIRECTORY);
31
+ // Make sure we have access to the latest snapshots of codemods on the system
32
+ repository$1.refresh();
33
+ return repository$1;
34
+ }
35
+ async safeRunAndReport(codemods) {
36
+ if (this.isDry) {
37
+ this.logger?.warn?.('Running the codemods in dry mode. No files will be modified during the process.');
38
+ }
39
+ try {
40
+ const reports = await this.project.runCodemods(codemods, {
41
+ dry: this.isDry
42
+ });
43
+ this.logger?.raw?.(formats.reports(reports));
44
+ if (!this.isDry) {
45
+ const nbAffectedTotal = reports.flatMap((report)=>report.report.ok).reduce((acc, nb)=>acc + nb, 0);
46
+ this.logger?.debug?.(`Successfully ran ${formats.highlight(codemods.length)} codemod(s), ${formats.highlight(nbAffectedTotal)} change(s) have been detected`);
47
+ }
48
+ return successReport();
49
+ } catch (e) {
50
+ return erroredReport(utils.unknownToError(e));
51
+ }
52
+ }
53
+ async runByUID(uid, codemodsDirectory) {
54
+ const repository = this.createRepository(codemodsDirectory);
55
+ if (!repository.has(uid)) {
56
+ throw new Error(`Unknown codemod UID provided: ${uid}`);
57
+ }
58
+ // Note: Ignore the range when running with a UID
59
+ const codemods = repository.find({
60
+ uids: [
61
+ uid
62
+ ]
63
+ }).flatMap(({ codemods })=>codemods);
64
+ return this.safeRunAndReport(codemods);
65
+ }
66
+ async run(codemodsDirectory) {
67
+ const repository = this.createRepository(codemodsDirectory);
68
+ // Find codemods matching the given range
69
+ const codemodsInRange = repository.find({
70
+ range: this.range
71
+ });
72
+ // If a selection callback is set, use it, else keep every codemods found
73
+ const selectedCodemods = this.selectCodemodsCallback ? await this.selectCodemodsCallback(codemodsInRange) : codemodsInRange;
74
+ // If no codemods have been selected (either manually or automatically)
75
+ // Then ignore and return a successful report
76
+ if (selectedCodemods.length === 0) {
77
+ this.logger?.debug?.(`Found no codemods to run for ${formats.versionRange(this.range)}`);
78
+ return successReport();
79
+ }
80
+ // Flatten the collection to a single list of codemods, the original list should already be sorted by version
81
+ const codemods = selectedCodemods.flatMap(({ codemods })=>codemods);
82
+ // Log (debug) the codemods by version
83
+ const codemodsByVersion = fp.groupBy('version', codemods);
84
+ const fRange = formats.versionRange(this.range);
85
+ this.logger?.debug?.(`Found ${formats.highlight(codemods.length)} codemods for ${formats.highlight(fp.size(codemodsByVersion))} version(s) using ${fRange}`);
86
+ for (const [version, codemods] of Object.entries(codemodsByVersion)){
87
+ this.logger?.debug?.(`- ${formats.version(semver.semVerFactory(version))} (${codemods.length})`);
88
+ }
89
+ return this.safeRunAndReport(codemods);
90
+ }
91
+ constructor(project, range){
92
+ this.project = project;
93
+ this.range = range;
94
+ this.isDry = false;
95
+ this.logger = null;
96
+ this.selectCodemodsCallback = null;
97
+ }
98
+ }
99
+ const codemodRunnerFactory = (project, range)=>{
100
+ return new CodemodRunner(project, range);
101
+ };
102
+ const successReport = ()=>({
103
+ success: true,
104
+ error: null
105
+ });
106
+ const erroredReport = (error)=>({
107
+ success: false,
108
+ error
109
+ });
110
+
111
+ exports.CodemodRunner = CodemodRunner;
112
+ exports.codemodRunnerFactory = codemodRunnerFactory;
113
+ //# sourceMappingURL=codemod-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codemod-runner.js","sources":["../../../../src/modules/codemod-runner/codemod-runner.ts"],"sourcesContent":["import { groupBy, size } from 'lodash/fp';\n\nimport {\n codemodRepositoryFactory,\n constants as codemodRepositoryConstants,\n} from '../codemod-repository';\nimport { unknownToError } from '../error';\nimport { semVerFactory } from '../version';\nimport * as f from '../format';\n\nimport type { Codemod } from '../codemod';\nimport type { Logger } from '../logger';\nimport type { Project } from '../project';\nimport type { UpgradeReport } from '../upgrader';\nimport type { CodemodRunnerInterface, CodemodRunnerReport, SelectCodemodsCallback } from './types';\nimport type { Version } from '../version';\n\nexport class CodemodRunner implements CodemodRunnerInterface {\n private readonly project: Project;\n\n private range: Version.Range;\n\n private isDry: boolean;\n\n private logger: Logger | null;\n\n private selectCodemodsCallback: SelectCodemodsCallback | null;\n\n constructor(project: Project, range: Version.Range) {\n this.project = project;\n this.range = range;\n\n this.isDry = false;\n\n this.logger = null;\n this.selectCodemodsCallback = null;\n }\n\n setRange(range: Version.Range) {\n this.range = range;\n return this;\n }\n\n setLogger(logger: Logger) {\n this.logger = logger;\n return this;\n }\n\n onSelectCodemods(callback: SelectCodemodsCallback | null) {\n this.selectCodemodsCallback = callback;\n return this;\n }\n\n dry(enabled: boolean = true) {\n this.isDry = enabled;\n return this;\n }\n\n private createRepository(codemodsDirectory?: string) {\n const repository = codemodRepositoryFactory(\n codemodsDirectory ?? codemodRepositoryConstants.INTERNAL_CODEMODS_DIRECTORY\n );\n\n // Make sure we have access to the latest snapshots of codemods on the system\n repository.refresh();\n\n return repository;\n }\n\n private async safeRunAndReport(codemods: Codemod.List) {\n if (this.isDry) {\n this.logger?.warn?.(\n 'Running the codemods in dry mode. No files will be modified during the process.'\n );\n }\n\n try {\n const reports = await this.project.runCodemods(codemods, { dry: this.isDry });\n\n this.logger?.raw?.(f.reports(reports));\n\n if (!this.isDry) {\n const nbAffectedTotal = reports\n .flatMap((report) => report.report.ok)\n .reduce((acc, nb) => acc + nb, 0);\n\n this.logger?.debug?.(\n `Successfully ran ${f.highlight(codemods.length)} codemod(s), ${f.highlight(nbAffectedTotal)} change(s) have been detected`\n );\n }\n\n return successReport();\n } catch (e: unknown) {\n return erroredReport(unknownToError(e));\n }\n }\n\n async runByUID(uid: string, codemodsDirectory?: string): Promise<CodemodRunnerReport> {\n const repository = this.createRepository(codemodsDirectory);\n\n if (!repository.has(uid)) {\n throw new Error(`Unknown codemod UID provided: ${uid}`);\n }\n\n // Note: Ignore the range when running with a UID\n const codemods = repository.find({ uids: [uid] }).flatMap(({ codemods }) => codemods);\n\n return this.safeRunAndReport(codemods);\n }\n\n async run(codemodsDirectory?: string): Promise<CodemodRunnerReport> {\n const repository = this.createRepository(codemodsDirectory);\n\n // Find codemods matching the given range\n const codemodsInRange = repository.find({ range: this.range });\n\n // If a selection callback is set, use it, else keep every codemods found\n const selectedCodemods = this.selectCodemodsCallback\n ? await this.selectCodemodsCallback(codemodsInRange)\n : codemodsInRange;\n\n // If no codemods have been selected (either manually or automatically)\n // Then ignore and return a successful report\n if (selectedCodemods.length === 0) {\n this.logger?.debug?.(`Found no codemods to run for ${f.versionRange(this.range)}`);\n return successReport();\n }\n\n // Flatten the collection to a single list of codemods, the original list should already be sorted by version\n const codemods = selectedCodemods.flatMap(({ codemods }) => codemods);\n\n // Log (debug) the codemods by version\n const codemodsByVersion = groupBy('version', codemods);\n const fRange = f.versionRange(this.range);\n\n this.logger?.debug?.(\n `Found ${f.highlight(codemods.length)} codemods for ${f.highlight(size(codemodsByVersion))} version(s) using ${fRange}`\n );\n\n for (const [version, codemods] of Object.entries(codemodsByVersion)) {\n this.logger?.debug?.(`- ${f.version(semVerFactory(version))} (${codemods.length})`);\n }\n\n return this.safeRunAndReport(codemods);\n }\n}\n\nexport const codemodRunnerFactory = (project: Project, range: Version.Range) => {\n return new CodemodRunner(project, range);\n};\n\nconst successReport = (): UpgradeReport => ({ success: true, error: null });\nconst erroredReport = (error: Error): UpgradeReport => ({ success: false, error });\n"],"names":["CodemodRunner","setRange","range","setLogger","logger","onSelectCodemods","callback","selectCodemodsCallback","dry","enabled","isDry","createRepository","codemodsDirectory","repository","codemodRepositoryFactory","codemodRepositoryConstants","refresh","safeRunAndReport","codemods","warn","reports","project","runCodemods","raw","f","nbAffectedTotal","flatMap","report","ok","reduce","acc","nb","debug","length","successReport","e","erroredReport","unknownToError","runByUID","uid","has","Error","find","uids","run","codemodsInRange","selectedCodemods","codemodsByVersion","groupBy","fRange","size","version","Object","entries","semVerFactory","constructor","codemodRunnerFactory","success","error"],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ import { groupBy, size } from 'lodash/fp';
2
+ import { codemodRepositoryFactory } from '../codemod-repository/repository.mjs';
3
+ import { INTERNAL_CODEMODS_DIRECTORY } from '../codemod-repository/constants.mjs';
4
+ import { unknownToError } from '../error/utils.mjs';
5
+ import { semVerFactory } from '../version/semver.mjs';
6
+ import 'semver';
7
+ import '../version/types.mjs';
8
+ import { reports, highlight, versionRange, version } from '../format/formats.mjs';
9
+
10
+ class CodemodRunner {
11
+ setRange(range) {
12
+ this.range = range;
13
+ return this;
14
+ }
15
+ setLogger(logger) {
16
+ this.logger = logger;
17
+ return this;
18
+ }
19
+ onSelectCodemods(callback) {
20
+ this.selectCodemodsCallback = callback;
21
+ return this;
22
+ }
23
+ dry(enabled = true) {
24
+ this.isDry = enabled;
25
+ return this;
26
+ }
27
+ createRepository(codemodsDirectory) {
28
+ const repository = codemodRepositoryFactory(codemodsDirectory ?? INTERNAL_CODEMODS_DIRECTORY);
29
+ // Make sure we have access to the latest snapshots of codemods on the system
30
+ repository.refresh();
31
+ return repository;
32
+ }
33
+ async safeRunAndReport(codemods) {
34
+ if (this.isDry) {
35
+ this.logger?.warn?.('Running the codemods in dry mode. No files will be modified during the process.');
36
+ }
37
+ try {
38
+ const reports$1 = await this.project.runCodemods(codemods, {
39
+ dry: this.isDry
40
+ });
41
+ this.logger?.raw?.(reports(reports$1));
42
+ if (!this.isDry) {
43
+ const nbAffectedTotal = reports$1.flatMap((report)=>report.report.ok).reduce((acc, nb)=>acc + nb, 0);
44
+ this.logger?.debug?.(`Successfully ran ${highlight(codemods.length)} codemod(s), ${highlight(nbAffectedTotal)} change(s) have been detected`);
45
+ }
46
+ return successReport();
47
+ } catch (e) {
48
+ return erroredReport(unknownToError(e));
49
+ }
50
+ }
51
+ async runByUID(uid, codemodsDirectory) {
52
+ const repository = this.createRepository(codemodsDirectory);
53
+ if (!repository.has(uid)) {
54
+ throw new Error(`Unknown codemod UID provided: ${uid}`);
55
+ }
56
+ // Note: Ignore the range when running with a UID
57
+ const codemods = repository.find({
58
+ uids: [
59
+ uid
60
+ ]
61
+ }).flatMap(({ codemods })=>codemods);
62
+ return this.safeRunAndReport(codemods);
63
+ }
64
+ async run(codemodsDirectory) {
65
+ const repository = this.createRepository(codemodsDirectory);
66
+ // Find codemods matching the given range
67
+ const codemodsInRange = repository.find({
68
+ range: this.range
69
+ });
70
+ // If a selection callback is set, use it, else keep every codemods found
71
+ const selectedCodemods = this.selectCodemodsCallback ? await this.selectCodemodsCallback(codemodsInRange) : codemodsInRange;
72
+ // If no codemods have been selected (either manually or automatically)
73
+ // Then ignore and return a successful report
74
+ if (selectedCodemods.length === 0) {
75
+ this.logger?.debug?.(`Found no codemods to run for ${versionRange(this.range)}`);
76
+ return successReport();
77
+ }
78
+ // Flatten the collection to a single list of codemods, the original list should already be sorted by version
79
+ const codemods = selectedCodemods.flatMap(({ codemods })=>codemods);
80
+ // Log (debug) the codemods by version
81
+ const codemodsByVersion = groupBy('version', codemods);
82
+ const fRange = versionRange(this.range);
83
+ this.logger?.debug?.(`Found ${highlight(codemods.length)} codemods for ${highlight(size(codemodsByVersion))} version(s) using ${fRange}`);
84
+ for (const [version$1, codemods] of Object.entries(codemodsByVersion)){
85
+ this.logger?.debug?.(`- ${version(semVerFactory(version$1))} (${codemods.length})`);
86
+ }
87
+ return this.safeRunAndReport(codemods);
88
+ }
89
+ constructor(project, range){
90
+ this.project = project;
91
+ this.range = range;
92
+ this.isDry = false;
93
+ this.logger = null;
94
+ this.selectCodemodsCallback = null;
95
+ }
96
+ }
97
+ const codemodRunnerFactory = (project, range)=>{
98
+ return new CodemodRunner(project, range);
99
+ };
100
+ const successReport = ()=>({
101
+ success: true,
102
+ error: null
103
+ });
104
+ const erroredReport = (error)=>({
105
+ success: false,
106
+ error
107
+ });
108
+
109
+ export { CodemodRunner, codemodRunnerFactory };
110
+ //# sourceMappingURL=codemod-runner.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codemod-runner.mjs","sources":["../../../../src/modules/codemod-runner/codemod-runner.ts"],"sourcesContent":["import { groupBy, size } from 'lodash/fp';\n\nimport {\n codemodRepositoryFactory,\n constants as codemodRepositoryConstants,\n} from '../codemod-repository';\nimport { unknownToError } from '../error';\nimport { semVerFactory } from '../version';\nimport * as f from '../format';\n\nimport type { Codemod } from '../codemod';\nimport type { Logger } from '../logger';\nimport type { Project } from '../project';\nimport type { UpgradeReport } from '../upgrader';\nimport type { CodemodRunnerInterface, CodemodRunnerReport, SelectCodemodsCallback } from './types';\nimport type { Version } from '../version';\n\nexport class CodemodRunner implements CodemodRunnerInterface {\n private readonly project: Project;\n\n private range: Version.Range;\n\n private isDry: boolean;\n\n private logger: Logger | null;\n\n private selectCodemodsCallback: SelectCodemodsCallback | null;\n\n constructor(project: Project, range: Version.Range) {\n this.project = project;\n this.range = range;\n\n this.isDry = false;\n\n this.logger = null;\n this.selectCodemodsCallback = null;\n }\n\n setRange(range: Version.Range) {\n this.range = range;\n return this;\n }\n\n setLogger(logger: Logger) {\n this.logger = logger;\n return this;\n }\n\n onSelectCodemods(callback: SelectCodemodsCallback | null) {\n this.selectCodemodsCallback = callback;\n return this;\n }\n\n dry(enabled: boolean = true) {\n this.isDry = enabled;\n return this;\n }\n\n private createRepository(codemodsDirectory?: string) {\n const repository = codemodRepositoryFactory(\n codemodsDirectory ?? codemodRepositoryConstants.INTERNAL_CODEMODS_DIRECTORY\n );\n\n // Make sure we have access to the latest snapshots of codemods on the system\n repository.refresh();\n\n return repository;\n }\n\n private async safeRunAndReport(codemods: Codemod.List) {\n if (this.isDry) {\n this.logger?.warn?.(\n 'Running the codemods in dry mode. No files will be modified during the process.'\n );\n }\n\n try {\n const reports = await this.project.runCodemods(codemods, { dry: this.isDry });\n\n this.logger?.raw?.(f.reports(reports));\n\n if (!this.isDry) {\n const nbAffectedTotal = reports\n .flatMap((report) => report.report.ok)\n .reduce((acc, nb) => acc + nb, 0);\n\n this.logger?.debug?.(\n `Successfully ran ${f.highlight(codemods.length)} codemod(s), ${f.highlight(nbAffectedTotal)} change(s) have been detected`\n );\n }\n\n return successReport();\n } catch (e: unknown) {\n return erroredReport(unknownToError(e));\n }\n }\n\n async runByUID(uid: string, codemodsDirectory?: string): Promise<CodemodRunnerReport> {\n const repository = this.createRepository(codemodsDirectory);\n\n if (!repository.has(uid)) {\n throw new Error(`Unknown codemod UID provided: ${uid}`);\n }\n\n // Note: Ignore the range when running with a UID\n const codemods = repository.find({ uids: [uid] }).flatMap(({ codemods }) => codemods);\n\n return this.safeRunAndReport(codemods);\n }\n\n async run(codemodsDirectory?: string): Promise<CodemodRunnerReport> {\n const repository = this.createRepository(codemodsDirectory);\n\n // Find codemods matching the given range\n const codemodsInRange = repository.find({ range: this.range });\n\n // If a selection callback is set, use it, else keep every codemods found\n const selectedCodemods = this.selectCodemodsCallback\n ? await this.selectCodemodsCallback(codemodsInRange)\n : codemodsInRange;\n\n // If no codemods have been selected (either manually or automatically)\n // Then ignore and return a successful report\n if (selectedCodemods.length === 0) {\n this.logger?.debug?.(`Found no codemods to run for ${f.versionRange(this.range)}`);\n return successReport();\n }\n\n // Flatten the collection to a single list of codemods, the original list should already be sorted by version\n const codemods = selectedCodemods.flatMap(({ codemods }) => codemods);\n\n // Log (debug) the codemods by version\n const codemodsByVersion = groupBy('version', codemods);\n const fRange = f.versionRange(this.range);\n\n this.logger?.debug?.(\n `Found ${f.highlight(codemods.length)} codemods for ${f.highlight(size(codemodsByVersion))} version(s) using ${fRange}`\n );\n\n for (const [version, codemods] of Object.entries(codemodsByVersion)) {\n this.logger?.debug?.(`- ${f.version(semVerFactory(version))} (${codemods.length})`);\n }\n\n return this.safeRunAndReport(codemods);\n }\n}\n\nexport const codemodRunnerFactory = (project: Project, range: Version.Range) => {\n return new CodemodRunner(project, range);\n};\n\nconst successReport = (): UpgradeReport => ({ success: true, error: null });\nconst erroredReport = (error: Error): UpgradeReport => ({ success: false, error });\n"],"names":["CodemodRunner","setRange","range","setLogger","logger","onSelectCodemods","callback","selectCodemodsCallback","dry","enabled","isDry","createRepository","codemodsDirectory","repository","codemodRepositoryFactory","codemodRepositoryConstants","refresh","safeRunAndReport","codemods","warn","reports","project","runCodemods","raw","f","nbAffectedTotal","flatMap","report","ok","reduce","acc","nb","debug","length","successReport","e","erroredReport","unknownToError","runByUID","uid","has","Error","find","uids","run","codemodsInRange","selectedCodemods","codemodsByVersion","groupBy","fRange","size","version","Object","entries","semVerFactory","constructor","codemodRunnerFactory","success","error"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ 'use strict';
2
+
3
+ var utils = require('./utils.js');
4
+
5
+
6
+
7
+ exports.AbortedError = utils.AbortedError;
8
+ exports.NPMCandidateNotFoundError = utils.NPMCandidateNotFoundError;
9
+ exports.UnexpectedError = utils.UnexpectedError;
10
+ exports.unknownToError = utils.unknownToError;
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
@@ -0,0 +1,2 @@
1
+ export { AbortedError, NPMCandidateNotFoundError, UnexpectedError, unknownToError } from './utils.mjs';
2
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,33 @@
1
+ 'use strict';
2
+
3
+ class UnexpectedError extends Error {
4
+ constructor(){
5
+ super('Unexpected Error');
6
+ }
7
+ }
8
+ class NPMCandidateNotFoundError extends Error {
9
+ constructor(target, message = `Couldn't find a valid NPM candidate for "${target}"`){
10
+ super(message);
11
+ this.target = target;
12
+ }
13
+ }
14
+ class AbortedError extends Error {
15
+ constructor(message = 'Upgrade aborted'){
16
+ super(message);
17
+ }
18
+ }
19
+ const unknownToError = (e)=>{
20
+ if (e instanceof Error) {
21
+ return e;
22
+ }
23
+ if (typeof e === 'string') {
24
+ return new Error(e);
25
+ }
26
+ return new UnexpectedError();
27
+ };
28
+
29
+ exports.AbortedError = AbortedError;
30
+ exports.NPMCandidateNotFoundError = NPMCandidateNotFoundError;
31
+ exports.UnexpectedError = UnexpectedError;
32
+ exports.unknownToError = unknownToError;
33
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sources":["../../../../src/modules/error/utils.ts"],"sourcesContent":["import type { Version } from '../version';\n\nexport class UnexpectedError extends Error {\n constructor() {\n super('Unexpected Error');\n }\n}\n\nexport class NPMCandidateNotFoundError extends Error {\n target: Version.SemVer | Version.Range | Version.ReleaseType;\n\n constructor(\n target: Version.SemVer | Version.Range | Version.ReleaseType,\n message: string = `Couldn't find a valid NPM candidate for \"${target}\"`\n ) {\n super(message);\n\n this.target = target;\n }\n}\n\nexport class AbortedError extends Error {\n constructor(message: string = 'Upgrade aborted') {\n super(message);\n }\n}\n\nexport const unknownToError = (e: unknown): Error => {\n if (e instanceof Error) {\n return e;\n }\n\n if (typeof e === 'string') {\n return new Error(e);\n }\n\n return new UnexpectedError();\n};\n"],"names":["UnexpectedError","Error","constructor","NPMCandidateNotFoundError","target","message","AbortedError","unknownToError","e"],"mappings":";;AAEO,MAAMA,eAAwBC,SAAAA,KAAAA,CAAAA;IACnCC,WAAc,EAAA;AACZ,QAAA,KAAK,CAAC,kBAAA,CAAA;AACR;AACF;AAEO,MAAMC,yBAAkCF,SAAAA,KAAAA,CAAAA;IAG7CC,WACEE,CAAAA,MAA4D,EAC5DC,OAAkB,GAAA,CAAC,yCAAyC,EAAED,MAAAA,CAAO,CAAC,CAAC,CACvE;AACA,QAAA,KAAK,CAACC,OAAAA,CAAAA;QAEN,IAAI,CAACD,MAAM,GAAGA,MAAAA;AAChB;AACF;AAEO,MAAME,YAAqBL,SAAAA,KAAAA,CAAAA;IAChCC,WAAYG,CAAAA,OAAAA,GAAkB,iBAAiB,CAAE;AAC/C,QAAA,KAAK,CAACA,OAAAA,CAAAA;AACR;AACF;AAEO,MAAME,iBAAiB,CAACC,CAAAA,GAAAA;AAC7B,IAAA,IAAIA,aAAaP,KAAO,EAAA;QACtB,OAAOO,CAAAA;AACT;IAEA,IAAI,OAAOA,MAAM,QAAU,EAAA;AACzB,QAAA,OAAO,IAAIP,KAAMO,CAAAA,CAAAA,CAAAA;AACnB;AAEA,IAAA,OAAO,IAAIR,eAAAA,EAAAA;AACb;;;;;;;"}