@elliemae/ds-codemods 3.60.0-next.28 → 3.60.0-next.29
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.
- package/bin/cli/code-mods/command-arguments/getLegacyDeprecation26dot3Questions.mjs +25 -0
- package/bin/cli/code-mods/command-arguments/promptCheckEmPackagesInconsistencies.mjs +1 -1
- package/bin/cli/code-mods/command-logics/execute-commands-map.mjs +4 -0
- package/bin/cli/code-mods/command-logics/legacy-deprecation-26-3/index.mjs +52 -0
- package/bin/cli/code-mods/command-logics/legacy-deprecation-26-3/legacy26dot3ImportMap.mjs +228 -0
- package/bin/cli/code-mods/command-logics/legacy-deprecation-26-3/packageJsonReplaceLogic.mjs +124 -0
- package/bin/cli/code-mods/commands.mjs +1 -0
- package/bin/cli/code-mods/inquirer-questions-prompter.mjs +5 -0
- package/bin/cli/utils/filepathsMatchers.mjs +4 -1
- package/package.json +1 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const getLegacyDeprecation26dot3Questions = (originalOptions) => {
|
|
2
|
+
const extraOptions = [];
|
|
3
|
+
const { startingDirPath, gitIgnorePath } = originalOptions;
|
|
4
|
+
if (!startingDirPath && startingDirPath !== '') {
|
|
5
|
+
extraOptions.push({
|
|
6
|
+
type: 'input',
|
|
7
|
+
name: 'startingDirPath',
|
|
8
|
+
message: 'Please provide the project root directory (where node_modules folder lives)',
|
|
9
|
+
default: './',
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
if (!gitIgnorePath && gitIgnorePath !== '') {
|
|
13
|
+
extraOptions.push({
|
|
14
|
+
type: 'input',
|
|
15
|
+
name: 'gitIgnorePath',
|
|
16
|
+
message:
|
|
17
|
+
'Please provide the path to the .gitignore file' +
|
|
18
|
+
'(if a non-matching path is provided, node_modules, dist and build will be ignored)',
|
|
19
|
+
default: './.gitignore',
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
// --debug is a CLI flag, not available as a question.
|
|
23
|
+
|
|
24
|
+
return extraOptions;
|
|
25
|
+
};
|
|
@@ -7,7 +7,7 @@ export const getPackagesInconsistenciesQuestions = (originalOptions) => {
|
|
|
7
7
|
name: 'globPattern',
|
|
8
8
|
message:
|
|
9
9
|
'Please provide a comma separated list of globPatterns catching the file in which to check for inconsistencies',
|
|
10
|
-
default: './package.json', // './packages/ds-codemods/test-ables/check-packages-inconsistencies/package.json.test'
|
|
10
|
+
default: './package.json', // './packages/ds-codemods/test-ables/check-packages-inconsistencies/package.json.test'
|
|
11
11
|
});
|
|
12
12
|
}
|
|
13
13
|
if (!globPatternIgnore && globPatternIgnore !== '') {
|
|
@@ -5,6 +5,7 @@ import { checkDeprecatedPackages } from './check-deprecated-packages/index.mjs';
|
|
|
5
5
|
import { helpMigrateToV3 } from './help-migrate-to-v3/index.mjs';
|
|
6
6
|
import { deprecatedComponentsUsageReport } from './deprecated-components-usage-report/index.mjs';
|
|
7
7
|
import { componentsUsageReport } from './components-usage-report/index.mjs';
|
|
8
|
+
import { legacyDeprecation26dot3 } from './legacy-deprecation-26-3/index.mjs';
|
|
8
9
|
import { COMMANDS } from '../commands.mjs';
|
|
9
10
|
|
|
10
11
|
export async function executeCommandsMap(args, options) {
|
|
@@ -33,6 +34,9 @@ export async function executeCommandsMap(args, options) {
|
|
|
33
34
|
case COMMANDS.COMPONENT_USAGE_REPORT:
|
|
34
35
|
componentsUsageReport(options);
|
|
35
36
|
break;
|
|
37
|
+
case COMMANDS.LEGACY_DEPRECATION_26DOT3:
|
|
38
|
+
legacyDeprecation26dot3(options);
|
|
39
|
+
break;
|
|
36
40
|
default:
|
|
37
41
|
break;
|
|
38
42
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import fse from 'fs-extra';
|
|
3
|
+
import { filePathsWithGitIgnore } from '../../../utils/filepathsMatchers.mjs';
|
|
4
|
+
import { legacy26dot3ImportMap, executeMapReplacement } from './legacy26dot3ImportMap.mjs';
|
|
5
|
+
import { packageJsonReplaceLogic } from './packageJsonReplaceLogic.mjs';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* generates a report of deprecated components usage
|
|
9
|
+
* @param {object} options - options *
|
|
10
|
+
* @param {string} options.startingDirPath - path to the project root directory (where node_modules folder lives)
|
|
11
|
+
* @param {string} options.gitIgnorePath - path to the .gitignore file
|
|
12
|
+
* @param {boolean} options.debug - debug flag
|
|
13
|
+
* @param {string} options.fileExtensions - comma separated list of file extensions to filter by
|
|
14
|
+
*
|
|
15
|
+
* @returns {void}
|
|
16
|
+
*/
|
|
17
|
+
export const legacyDeprecation26dot3 = (options) => {
|
|
18
|
+
// 1- get all the "raw" code file paths using gitignore blacklist and file extension filter
|
|
19
|
+
const filesToParse = filePathsWithGitIgnore(options);
|
|
20
|
+
if (options.debug) console.log('legacy26dot3ImportMap :>> ', legacy26dot3ImportMap);
|
|
21
|
+
// 2- for each file, replace the imports from the legacy components with the new ones
|
|
22
|
+
filesToParse.forEach((path) => {
|
|
23
|
+
const fileContent = fs.readFileSync(path, {
|
|
24
|
+
encoding: 'utf8',
|
|
25
|
+
flag: 'r',
|
|
26
|
+
});
|
|
27
|
+
if (fileContent && typeof fileContent === 'string') {
|
|
28
|
+
const { finalString, matchesFound } = executeMapReplacement(fileContent);
|
|
29
|
+
const didChangeSomething = matchesFound.length > 0;
|
|
30
|
+
if (didChangeSomething) {
|
|
31
|
+
if (!options.debug) fse.outputFileSync(path, finalString);
|
|
32
|
+
else {
|
|
33
|
+
console.log(`File: ${path} - import(s) replacement(s) found!`);
|
|
34
|
+
console.log('matchesFound :>> ', matchesFound);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
// 3- do something similar, but with opinionated "package.json" files and logic
|
|
40
|
+
// in particular:
|
|
41
|
+
// - we get the package.json files (multiple for monorepos?) and we parse them as json.
|
|
42
|
+
// - check the dependencies and devDependencies and peerDependencies for any legacy component
|
|
43
|
+
// (keyof legacy26dot3ImportMap) and replace it with the new one (value of legacy26dot3ImportMap)
|
|
44
|
+
const packageJsonPendingReplacements = packageJsonReplaceLogic(options);
|
|
45
|
+
if (options.debug) console.log('packageJsonPendingReplacements :>> ', packageJsonPendingReplacements);
|
|
46
|
+
else
|
|
47
|
+
Object.entries(packageJsonPendingReplacements).forEach(([path, newContent]) => {
|
|
48
|
+
fse.outputFileSync(path, newContent);
|
|
49
|
+
});
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export default legacyDeprecation26dot3;
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/* eslint-disable max-lines */
|
|
2
|
+
/*
|
|
3
|
+
we need an exact match of the imports, we can't do a lose match
|
|
4
|
+
why?
|
|
5
|
+
we have packages that are the old package name with a different append
|
|
6
|
+
E.G. @elliemae/ds-button (legacy) and @elliemae/ds-button-v2 (new)
|
|
7
|
+
we can't replace
|
|
8
|
+
@elliemae/ds-button-v2 to @elliemae/ds-legacy-button-v2
|
|
9
|
+
because @elliemae/ds-button is a substring of @elliemae/ds-button-v2
|
|
10
|
+
how do we solve this?
|
|
11
|
+
key: exact match of the imports
|
|
12
|
+
value:{
|
|
13
|
+
matchChange: string; // the new package name to replace with
|
|
14
|
+
regexp
|
|
15
|
+
regexp: RegExp; // new Regexp(/(['"])(${key})(['"])/)
|
|
16
|
+
}
|
|
17
|
+
this will allow regexp match and replace based on group capture, so we can keep the same quotes as the original import
|
|
18
|
+
E.G. we can replace
|
|
19
|
+
from '@elliemae/ds-button' to '@elliemae/ds-legacy-button'
|
|
20
|
+
but also
|
|
21
|
+
from "@elliemae/ds-button" to "@elliemae/ds-legacy-button"
|
|
22
|
+
without the risk of replacing
|
|
23
|
+
from '@elliemae/ds-button-v2' to '@elliemae/ds-legacy-button-v2'
|
|
24
|
+
*/
|
|
25
|
+
export const legacy26dot3ImportMap = {
|
|
26
|
+
'@elliemae/ds-button': {
|
|
27
|
+
matchChange: '@elliemae/ds-legacy-button',
|
|
28
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
29
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-button)(['"])/),
|
|
30
|
+
},
|
|
31
|
+
'@elliemae/ds-date-range-picker': {
|
|
32
|
+
matchChange: '@elliemae/ds-legacy-date-range-picker',
|
|
33
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
34
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-date-range-picker)(['"])/),
|
|
35
|
+
},
|
|
36
|
+
'@elliemae/ds-header': {
|
|
37
|
+
matchChange: '@elliemae/ds-legacy-header',
|
|
38
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
39
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-header)(['"])/),
|
|
40
|
+
},
|
|
41
|
+
'@elliemae/ds-number-range-field': {
|
|
42
|
+
matchChange: '@elliemae/ds-legacy-number-range-field',
|
|
43
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
44
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-number-range-field)(['"])/),
|
|
45
|
+
},
|
|
46
|
+
'@elliemae/ds-slider': {
|
|
47
|
+
matchChange: '@elliemae/ds-legacy-slider',
|
|
48
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
49
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-slider)(['"])/),
|
|
50
|
+
},
|
|
51
|
+
'@elliemae/ds-zipcode-search': {
|
|
52
|
+
matchChange: '@elliemae/ds-legacy-zipcode-search',
|
|
53
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
54
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-zipcode-search)(['"])/),
|
|
55
|
+
},
|
|
56
|
+
'@elliemae/ds-button-group': {
|
|
57
|
+
matchChange: '@elliemae/ds-legacy-button-group',
|
|
58
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
59
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-button-group)(['"])/),
|
|
60
|
+
},
|
|
61
|
+
'@elliemae/ds-date-range-selector': {
|
|
62
|
+
matchChange: '@elliemae/ds-legacy-date-range-selector',
|
|
63
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
64
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-date-range-selector)(['"])/),
|
|
65
|
+
},
|
|
66
|
+
'@elliemae/ds-hidden': {
|
|
67
|
+
matchChange: '@elliemae/ds-legacy-hidden',
|
|
68
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
69
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-hidden)(['"])/),
|
|
70
|
+
},
|
|
71
|
+
'@elliemae/ds-page-number': {
|
|
72
|
+
matchChange: '@elliemae/ds-legacy-page-number',
|
|
73
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
74
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-page-number)(['"])/),
|
|
75
|
+
},
|
|
76
|
+
'@elliemae/ds-spinner': {
|
|
77
|
+
matchChange: '@elliemae/ds-legacy-spinner',
|
|
78
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
79
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-spinner)(['"])/),
|
|
80
|
+
},
|
|
81
|
+
'@elliemae/ds-zoom': {
|
|
82
|
+
matchChange: '@elliemae/ds-legacy-zoom',
|
|
83
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
84
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-zoom)(['"])/),
|
|
85
|
+
},
|
|
86
|
+
'@elliemae/ds-button-v1': {
|
|
87
|
+
matchChange: '@elliemae/ds-legacy-button-v1',
|
|
88
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
89
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-button-v1)(['"])/),
|
|
90
|
+
},
|
|
91
|
+
'@elliemae/ds-date-time-recurrence-picker': {
|
|
92
|
+
matchChange: '@elliemae/ds-legacy-date-time-recurrence-picker',
|
|
93
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
94
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-date-time-recurrence-picker)(['"])/),
|
|
95
|
+
},
|
|
96
|
+
'@elliemae/ds-label-value': {
|
|
97
|
+
matchChange: '@elliemae/ds-legacy-label-value',
|
|
98
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
99
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-label-value)(['"])/),
|
|
100
|
+
},
|
|
101
|
+
'@elliemae/ds-pills': {
|
|
102
|
+
matchChange: '@elliemae/ds-legacy-pills',
|
|
103
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
104
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-pills)(['"])/),
|
|
105
|
+
},
|
|
106
|
+
'@elliemae/ds-text-wrapper': {
|
|
107
|
+
matchChange: '@elliemae/ds-legacy-text-wrapper',
|
|
108
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
109
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-text-wrapper)(['"])/),
|
|
110
|
+
},
|
|
111
|
+
'@elliemae/ds-card-array': {
|
|
112
|
+
matchChange: '@elliemae/ds-legacy-card-array',
|
|
113
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
114
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-card-array)(['"])/),
|
|
115
|
+
},
|
|
116
|
+
'@elliemae/ds-dropdownmenu': {
|
|
117
|
+
matchChange: '@elliemae/ds-legacy-dropdownmenu',
|
|
118
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
119
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-dropdownmenu)(['"])/),
|
|
120
|
+
},
|
|
121
|
+
'@elliemae/ds-list-section-header': {
|
|
122
|
+
matchChange: '@elliemae/ds-legacy-list-section-header',
|
|
123
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
124
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-list-section-header)(['"])/),
|
|
125
|
+
},
|
|
126
|
+
'@elliemae/ds-popover': {
|
|
127
|
+
matchChange: '@elliemae/ds-legacy-popover',
|
|
128
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
129
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-popover)(['"])/),
|
|
130
|
+
},
|
|
131
|
+
'@elliemae/ds-time-picker': {
|
|
132
|
+
matchChange: '@elliemae/ds-legacy-time-picker',
|
|
133
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
134
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-time-picker)(['"])/),
|
|
135
|
+
},
|
|
136
|
+
'@elliemae/ds-common': {
|
|
137
|
+
matchChange: '@elliemae/ds-legacy-common',
|
|
138
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
139
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-common)(['"])/),
|
|
140
|
+
},
|
|
141
|
+
'@elliemae/ds-filterbar': {
|
|
142
|
+
matchChange: '@elliemae/ds-legacy-filterbar',
|
|
143
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
144
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-filterbar)(['"])/),
|
|
145
|
+
},
|
|
146
|
+
'@elliemae/ds-menu': {
|
|
147
|
+
matchChange: '@elliemae/ds-legacy-menu',
|
|
148
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
149
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-menu)(['"])/),
|
|
150
|
+
},
|
|
151
|
+
'@elliemae/ds-popper': {
|
|
152
|
+
matchChange: '@elliemae/ds-legacy-popper',
|
|
153
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
154
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-popper)(['"])/),
|
|
155
|
+
},
|
|
156
|
+
'@elliemae/ds-toolbar': {
|
|
157
|
+
matchChange: '@elliemae/ds-legacy-toolbar',
|
|
158
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
159
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-toolbar)(['"])/),
|
|
160
|
+
},
|
|
161
|
+
'@elliemae/ds-datagrids': {
|
|
162
|
+
matchChange: '@elliemae/ds-legacy-datagrids',
|
|
163
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
164
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-datagrids)(['"])/),
|
|
165
|
+
},
|
|
166
|
+
'@elliemae/ds-form': {
|
|
167
|
+
matchChange: '@elliemae/ds-legacy-form',
|
|
168
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
169
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-form)(['"])/),
|
|
170
|
+
},
|
|
171
|
+
'@elliemae/ds-mini-toolbar': {
|
|
172
|
+
matchChange: '@elliemae/ds-legacy-mini-toolbar',
|
|
173
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
174
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-mini-toolbar)(['"])/),
|
|
175
|
+
},
|
|
176
|
+
'@elliemae/ds-search-field': {
|
|
177
|
+
matchChange: '@elliemae/ds-legacy-search-field',
|
|
178
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
179
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-search-field)(['"])/),
|
|
180
|
+
},
|
|
181
|
+
'@elliemae/ds-uploader': {
|
|
182
|
+
matchChange: '@elliemae/ds-legacy-uploader',
|
|
183
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
184
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-uploader)(['"])/),
|
|
185
|
+
},
|
|
186
|
+
'@elliemae/ds-date-picker': {
|
|
187
|
+
matchChange: '@elliemae/ds-legacy-date-picker',
|
|
188
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
189
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-date-picker)(['"])/),
|
|
190
|
+
},
|
|
191
|
+
'@elliemae/ds-group-box': {
|
|
192
|
+
matchChange: '@elliemae/ds-legacy-group-box',
|
|
193
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
194
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-group-box)(['"])/),
|
|
195
|
+
},
|
|
196
|
+
'@elliemae/ds-modal': {
|
|
197
|
+
matchChange: '@elliemae/ds-legacy-modal',
|
|
198
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
199
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-modal)(['"])/),
|
|
200
|
+
},
|
|
201
|
+
'@elliemae/ds-shuttle': {
|
|
202
|
+
matchChange: '@elliemae/ds-legacy-shuttle',
|
|
203
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
204
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-shuttle)(['"])/),
|
|
205
|
+
},
|
|
206
|
+
'@elliemae/ds-wysiwygeditor': {
|
|
207
|
+
matchChange: '@elliemae/ds-legacy-wysiwygeditor',
|
|
208
|
+
// don't use /g nor /y as JavaScript RegExp objects are stateful when they have the global or sticky flags set
|
|
209
|
+
regexp: new RegExp(/(from ['"])(@elliemae\/ds-wysiwygeditor)(['"])/),
|
|
210
|
+
},
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
export const executeMapReplacement = (fullFileStringContent) => {
|
|
214
|
+
if (typeof fullFileStringContent !== 'string') {
|
|
215
|
+
const error = `expected string argument but received ${typeof fullFileStringContent}`;
|
|
216
|
+
console.error(error);
|
|
217
|
+
throw new Error(error);
|
|
218
|
+
}
|
|
219
|
+
let finalString = fullFileStringContent;
|
|
220
|
+
const matchesFound = [];
|
|
221
|
+
Object.entries(legacy26dot3ImportMap).forEach(([key, { matchChange, regexp }]) => {
|
|
222
|
+
if (regexp.test(finalString)) {
|
|
223
|
+
matchesFound.push(key);
|
|
224
|
+
finalString = finalString.replace(regexp, `$1${matchChange}$3`);
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
return { finalString, matchesFound };
|
|
228
|
+
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/* eslint-disable max-statements */
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import { boldRedStr, yellowStr } from '../../../utils/CLI_COLORS.mjs';
|
|
4
|
+
import { filePathsWithGitIgnore } from '../../../utils/filepathsMatchers.mjs';
|
|
5
|
+
import { legacy26dot3ImportMap } from './legacy26dot3ImportMap.mjs';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* parse a package.json, checks the dependencies(dev and peer included) for any legacy component
|
|
10
|
+
*
|
|
11
|
+
* if any legacy component is found,
|
|
12
|
+
* generates a new content for the file with the legacy component replaced with the new one and version set to "latest"
|
|
13
|
+
*
|
|
14
|
+
* @param {string} path - the package.json file path
|
|
15
|
+
* @param {object} options - options *
|
|
16
|
+
* @param {boolean} options.debug - debug flag
|
|
17
|
+
* @returns {string | -1} - the new content (json to string) if any change is needed,
|
|
18
|
+
* or -1 if no change is needed or in case of error
|
|
19
|
+
*/
|
|
20
|
+
// eslint-disable-next-line complexity
|
|
21
|
+
const specificPackageJsonReplaceLogic = (path, options) => {
|
|
22
|
+
const fileContent = fs.readFileSync(path, {
|
|
23
|
+
encoding: 'utf8',
|
|
24
|
+
flag: 'r',
|
|
25
|
+
});
|
|
26
|
+
if (!fileContent || typeof fileContent !== 'string') {
|
|
27
|
+
if (options.debug) console.log(yellowStr(`Empty or invalid content in ${path}`));
|
|
28
|
+
return -1;
|
|
29
|
+
}
|
|
30
|
+
const parsedContent = JSON.parse(fileContent);
|
|
31
|
+
const newDeps = { ...parsedContent.dependencies };
|
|
32
|
+
let depsChanged = false;
|
|
33
|
+
Object.keys(parsedContent.dependencies || {}).forEach((oldPackageString) => {
|
|
34
|
+
if (legacy26dot3ImportMap[oldPackageString]) {
|
|
35
|
+
const newPackageString = legacy26dot3ImportMap[oldPackageString].matchChange;
|
|
36
|
+
newDeps[newPackageString] = 'latest';
|
|
37
|
+
delete newDeps[oldPackageString];
|
|
38
|
+
depsChanged = true;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const newDevDeps = { ...parsedContent.devDependencies };
|
|
43
|
+
let devDepsChanged = false;
|
|
44
|
+
Object.keys(parsedContent.devDependencies || {}).forEach((oldPackageString) => {
|
|
45
|
+
if (legacy26dot3ImportMap[oldPackageString]) {
|
|
46
|
+
const newPackageString = legacy26dot3ImportMap[oldPackageString].matchChange;
|
|
47
|
+
newDevDeps[newPackageString] = 'latest';
|
|
48
|
+
delete newDevDeps[oldPackageString];
|
|
49
|
+
devDepsChanged = true;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
const newPeerDeps = { ...parsedContent.peerDependencies };
|
|
53
|
+
let peerDepsChanged = false;
|
|
54
|
+
Object.keys(parsedContent.peerDependencies || {}).forEach((oldPackageString) => {
|
|
55
|
+
if (legacy26dot3ImportMap[oldPackageString]) {
|
|
56
|
+
const newPackageString = legacy26dot3ImportMap[oldPackageString].matchChange;
|
|
57
|
+
newPeerDeps[newPackageString] = 'latest';
|
|
58
|
+
delete newPeerDeps[oldPackageString];
|
|
59
|
+
peerDepsChanged = true;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
if (!depsChanged && !devDepsChanged && !peerDepsChanged) {
|
|
63
|
+
if (options.debug) console.log(yellowStr(`No legacy dependencies found in ${path}`));
|
|
64
|
+
return -1;
|
|
65
|
+
}
|
|
66
|
+
const newContent = {
|
|
67
|
+
...parsedContent,
|
|
68
|
+
...(depsChanged && { dependencies: newDeps }),
|
|
69
|
+
...(devDepsChanged && { devDependencies: newDevDeps }),
|
|
70
|
+
...(peerDepsChanged && { peerDependencies: newPeerDeps }),
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
return JSON.stringify(newContent, null, 2);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* do something similar, but with opinionated "package.json" files and logic
|
|
78
|
+
*
|
|
79
|
+
* in particular:
|
|
80
|
+
* - we get the package.json files (multiple for monorepos?) and we parse them as json.
|
|
81
|
+
* - check the dependencies and devDependencies and peerDependencies for any legacy component
|
|
82
|
+
* (keyof legacy26dot3ImportMap) and replace it with the new one (value of legacy26dot3ImportMap)
|
|
83
|
+
* - if any change is needed, we return an object so that the caller can decide what to do with it
|
|
84
|
+
* (write it or just log it for the user to review)
|
|
85
|
+
* @param {object} options - options *
|
|
86
|
+
* @param {string} options.startingDirPath - path to the project root directory (where node_modules folder lives)
|
|
87
|
+
* @param {string} options.gitIgnorePath - path to the .gitignore file
|
|
88
|
+
* @param {boolean} options.debug - debug flag
|
|
89
|
+
* @param {string} options.fileExtensions - comma separated list of file extensions to filter by
|
|
90
|
+
* @returns {object} - an object with the (package.json) file path as key and the new content (json to string) as value,
|
|
91
|
+
* for each package.json file that needs changes
|
|
92
|
+
*/
|
|
93
|
+
export const packageJsonReplaceLogic = (options) => {
|
|
94
|
+
// 1- get the package.json files (multiple for monorepos?) paths
|
|
95
|
+
const jsonFilesPaths = filePathsWithGitIgnore({ ...options, fileExtensions: '.json' });
|
|
96
|
+
// the above function doesn't allow for specific filename matching,
|
|
97
|
+
// this is a one-off right now so not extending the function
|
|
98
|
+
// instead we filter the results with a simple string match, to get only the package.json files paths
|
|
99
|
+
const packageJsonFilesPaths = jsonFilesPaths.filter((path) => path.endsWith('package.json'));
|
|
100
|
+
if (packageJsonFilesPaths.length === 0) {
|
|
101
|
+
console.log(boldRedStr('No package.json files! Please check the startingDirPath and gitIgnorePath options.'));
|
|
102
|
+
console.log(
|
|
103
|
+
yellowStr(
|
|
104
|
+
`To make sure migration is successful manually:
|
|
105
|
+
- check for any legacy components in your package.json
|
|
106
|
+
- replace them with the new ones.
|
|
107
|
+
- point them to "latest" version, the legacy library only get updated with critical security fixes and very rarely so.
|
|
108
|
+
- regenerate the lock file ( pnpm i --fix-lockfile or equivalent command/flow for your package manager)
|
|
109
|
+
|
|
110
|
+
The legacy components to look for are:`,
|
|
111
|
+
),
|
|
112
|
+
);
|
|
113
|
+
console.log(legacy26dot3ImportMap);
|
|
114
|
+
return {};
|
|
115
|
+
}
|
|
116
|
+
const filesToChange = {};
|
|
117
|
+
// 2 - parse, check and generate new content for each package.json file
|
|
118
|
+
packageJsonFilesPaths.forEach((path) => {
|
|
119
|
+
if (options.debug) console.log('path :>> ', path);
|
|
120
|
+
const newContent = specificPackageJsonReplaceLogic(path, options);
|
|
121
|
+
if (newContent !== -1) filesToChange[path] = newContent;
|
|
122
|
+
});
|
|
123
|
+
return filesToChange;
|
|
124
|
+
};
|
|
@@ -7,6 +7,7 @@ export const COMMANDS = {
|
|
|
7
7
|
HELP_MIGRATE_TO_V3: 'help-migrate-to-v3',
|
|
8
8
|
DEPRECATED_PACKAGES_USAGE_REPORT: 'deprecated-components-usage-report',
|
|
9
9
|
COMPONENT_USAGE_REPORT: 'components-usage-report',
|
|
10
|
+
LEGACY_DEPRECATION_26DOT3: 'legacy-deprecation-26dot3',
|
|
10
11
|
EXIT: 'exit',
|
|
11
12
|
};
|
|
12
13
|
|
|
@@ -6,7 +6,9 @@ import { getDeprecatedPackagesQuestions } from './command-arguments/promptDeprec
|
|
|
6
6
|
import { getHelpMigrateToV3Questions } from './command-arguments/promptHelpMigrateToV3.mjs';
|
|
7
7
|
import { getMissingPackagesQuestions } from './command-arguments/promptMissingPackages.mjs';
|
|
8
8
|
import { getDeprecatedUsageReportQuestions } from './command-arguments/getDeprecatedUsageReportQuestions.mjs';
|
|
9
|
+
import { getLegacyDeprecation26dot3Questions } from './command-arguments/getLegacyDeprecation26dot3Questions.mjs';
|
|
9
10
|
|
|
11
|
+
// eslint-disable-next-line complexity
|
|
10
12
|
async function promptForMissingScriptSpecificOptions({ originalOptions, promptOptions }) {
|
|
11
13
|
const script = originalOptions.script || promptOptions.script;
|
|
12
14
|
const scriptQuestions = [];
|
|
@@ -31,6 +33,9 @@ async function promptForMissingScriptSpecificOptions({ originalOptions, promptOp
|
|
|
31
33
|
case COMMANDS.DEPRECATED_PACKAGES_USAGE_REPORT:
|
|
32
34
|
scriptQuestions.push(...getDeprecatedUsageReportQuestions(originalOptions));
|
|
33
35
|
break;
|
|
36
|
+
case COMMANDS.LEGACY_DEPRECATION_26DOT3:
|
|
37
|
+
scriptQuestions.push(...getLegacyDeprecation26dot3Questions(originalOptions));
|
|
38
|
+
break;
|
|
34
39
|
default:
|
|
35
40
|
break;
|
|
36
41
|
}
|
|
@@ -18,7 +18,10 @@ const ig = ignore({
|
|
|
18
18
|
* @param {string} pathString the path to convert
|
|
19
19
|
* @returns {string} path with glob compatible POSIX slashes ( \ -- to --> /).
|
|
20
20
|
*/
|
|
21
|
-
const generatePosixPath = (pathString) =>
|
|
21
|
+
const generatePosixPath = (pathString) =>
|
|
22
|
+
pathString
|
|
23
|
+
.replace(/\\/g, '/') // convert backslashes to forward slashes for glob compatibility
|
|
24
|
+
.replace(/\/+/g, '/'); // replace multiple slashes with a single slash for consistency
|
|
22
25
|
|
|
23
26
|
/**
|
|
24
27
|
* prepend process.cwd() to a string and convert to POSIX (glob compatible) slashes ( \ -- to --> /).
|