@dialpad/dialtone 7.27.1 → 7.27.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.
- package/package.json +6 -12
- package/lib/build/js/dialtone_migration_helper/configs/tokens-migration.mjs +0 -13
- package/lib/build/js/dialtone_migration_helper/helpers.mjs +0 -214
- package/lib/build/js/dialtone_migration_helper/index.mjs +0 -131
- package/lib/dist/js/dialtone_migration_helper/configs/tokens-migration.mjs +0 -13
- package/lib/dist/js/dialtone_migration_helper/helpers.mjs +0 -214
- package/lib/dist/js/dialtone_migration_helper/index.mjs +0 -131
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dialpad/dialtone",
|
|
3
|
-
"version": "7.27.
|
|
3
|
+
"version": "7.27.2",
|
|
4
4
|
"description": "Dialpad's design system",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Dialpad",
|
|
@@ -40,8 +40,7 @@
|
|
|
40
40
|
"dist"
|
|
41
41
|
],
|
|
42
42
|
"bin": {
|
|
43
|
-
"dialtone-health-check": "./lib/dist/js/dialtone_health_check/index.js"
|
|
44
|
-
"dialtone-migration-helper": "./lib/dist/js/dialtone_migration_helper/index.mjs"
|
|
43
|
+
"dialtone-health-check": "./lib/dist/js/dialtone_health_check/index.js"
|
|
45
44
|
},
|
|
46
45
|
"repository": "git@github.com:dialpad/dialtone.git",
|
|
47
46
|
"scripts": {
|
|
@@ -76,14 +75,15 @@
|
|
|
76
75
|
},
|
|
77
76
|
"dependencies": {
|
|
78
77
|
"docopt": "^0.6.2",
|
|
79
|
-
"precss": "^4.0.0"
|
|
78
|
+
"precss": "^4.0.0",
|
|
79
|
+
"yargs": "^17.7.2"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
82
|
"@commitlint/cli": "^17.4.2",
|
|
83
83
|
"@commitlint/config-conventional": "^17.4.2",
|
|
84
84
|
"@dialpad/conventional-changelog-angular": "^1.1.1",
|
|
85
85
|
"@dialpad/dialtone-combinator": "^0.3.1",
|
|
86
|
-
"@dialpad/dialtone-tokens": "^1.
|
|
86
|
+
"@dialpad/dialtone-tokens": "^1.20.0",
|
|
87
87
|
"@dialpad/dialtone-vue": "^3.69.0",
|
|
88
88
|
"@dialpad/postcss-responsive-variations": "^1.1.5",
|
|
89
89
|
"@dialpad/semantic-release-changelog-json": "^1.0.0",
|
|
@@ -143,15 +143,9 @@
|
|
|
143
143
|
"through2": "^4.0.2",
|
|
144
144
|
"vuepress": "2.0.0-beta.60",
|
|
145
145
|
"vuepress-plugin-seo2": "2.0.0-beta.124",
|
|
146
|
-
"vuepress-plugin-sitemap2": "2.0.0-beta.174"
|
|
147
|
-
"yargs": "^17.6.2"
|
|
146
|
+
"vuepress-plugin-sitemap2": "2.0.0-beta.174"
|
|
148
147
|
},
|
|
149
148
|
"resolutions": {
|
|
150
149
|
"postcss-preset-env": "^7.0.0"
|
|
151
|
-
},
|
|
152
|
-
"peerDependencies": {
|
|
153
|
-
"chalk": "^5.2.0",
|
|
154
|
-
"globby": "^13.1.4",
|
|
155
|
-
"inquirer": "^9.1.5"
|
|
156
150
|
}
|
|
157
151
|
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
description:
|
|
3
|
-
'Updates dialtone 7 variables to dialtone 8 design tokens.\n' +
|
|
4
|
-
'- Replaces var(--{color}-{stop}) with var(--dt-color-{color}-{stop})\n\t' +
|
|
5
|
-
'eg. var(--black-200) with var(--dt-color-black-200)',
|
|
6
|
-
patterns: ['**/*.{css,less,scss,sass,styl,html,vue}'],
|
|
7
|
-
expressions: [
|
|
8
|
-
{
|
|
9
|
-
from: /var\(--(white|black|purple|orange|magenta|gold|green|red|blue|tan)(-[1-9]00)?\)/gi,
|
|
10
|
-
to: 'var(--dt-color-$1$2)',
|
|
11
|
-
},
|
|
12
|
-
],
|
|
13
|
-
};
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import { globby } from 'globby';
|
|
3
|
-
import inquirer from 'inquirer';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import fs from 'fs';
|
|
6
|
-
const { readdir, readFile, writeFile } = fs.promises;
|
|
7
|
-
|
|
8
|
-
// confirm prompt for starting operations, display warning and y/n dialog
|
|
9
|
-
export const confirmStart = () => {
|
|
10
|
-
return new Promise((resolve, reject) => {
|
|
11
|
-
inquirer
|
|
12
|
-
.prompt([
|
|
13
|
-
{
|
|
14
|
-
type: 'confirm',
|
|
15
|
-
name: 'yesno',
|
|
16
|
-
prefix: `
|
|
17
|
-
${chalk.bgRed(
|
|
18
|
-
'┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ !!! CAUTION !!! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓',
|
|
19
|
-
)}
|
|
20
|
-
${chalk.bgRed(
|
|
21
|
-
'┃',
|
|
22
|
-
)} Please be sure you are running this in a code repository where changes can be rolled back. ${chalk.bgRed(
|
|
23
|
-
'┃',
|
|
24
|
-
)}
|
|
25
|
-
${chalk.bgRed(
|
|
26
|
-
'┃',
|
|
27
|
-
)} Modifications will occur to files listed above. Proceed at your own risk. ${chalk.bgRed(
|
|
28
|
-
'┃',
|
|
29
|
-
)}
|
|
30
|
-
${chalk.bgRed(
|
|
31
|
-
'┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛',
|
|
32
|
-
)}\n
|
|
33
|
-
`,
|
|
34
|
-
message: 'Start modification?',
|
|
35
|
-
default: true,
|
|
36
|
-
},
|
|
37
|
-
])
|
|
38
|
-
.then((choice) => {
|
|
39
|
-
resolve(choice.yesno);
|
|
40
|
-
})
|
|
41
|
-
.catch((err) => {
|
|
42
|
-
reject(err);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
// return array of all globby pattern matches in one level
|
|
48
|
-
export const doPatternSearch = async (config) => {
|
|
49
|
-
const res = [];
|
|
50
|
-
for (const p of config.patterns) {
|
|
51
|
-
res.push(
|
|
52
|
-
...(await getGlob(p, config.globbyConfig).catch((err) => error('doPatternSearch: ' + err))),
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
return res;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// error and quit
|
|
59
|
-
export const error = (message) => {
|
|
60
|
-
console.log(`\n${chalk.red('!!')} Error: ${message}\n`);
|
|
61
|
-
process.exit(1);
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
export const findMatchedFiles = async (fileList, config) => {
|
|
65
|
-
return getAllFileContents(fileList, config.globbyConfig.cwd).then((globbed) => {
|
|
66
|
-
// filter out minified files
|
|
67
|
-
const filtered = globbed
|
|
68
|
-
.filter((f) => {
|
|
69
|
-
return (f.data.match(/[\n\r]/g) || []).length > 3;
|
|
70
|
-
})
|
|
71
|
-
.filter((f) => {
|
|
72
|
-
config.expressions.forEach((e) => {
|
|
73
|
-
if (e.from.test(f.data)) f.matches++;
|
|
74
|
-
});
|
|
75
|
-
return f.matches > 0;
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
const matchedFiles = filtered.reduce((prev, current) => {
|
|
79
|
-
const fn = path.relative(config.globbyConfig.cwd, current.file);
|
|
80
|
-
return [...prev, fn];
|
|
81
|
-
}, []);
|
|
82
|
-
|
|
83
|
-
return matchedFiles;
|
|
84
|
-
});
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
// read file contents of all matched files, return filename and data, default matches (0)
|
|
88
|
-
export const getAllFileContents = (fileList, cwd) => {
|
|
89
|
-
const readPromises = fileList.map(async (file) => {
|
|
90
|
-
file = cwd + path.sep + file;
|
|
91
|
-
return readFile(file, 'utf8')
|
|
92
|
-
.then((data) => {
|
|
93
|
-
return { file, data, matches: 0 };
|
|
94
|
-
})
|
|
95
|
-
.catch((err) => error('getAllFileContents: ' + err));
|
|
96
|
-
});
|
|
97
|
-
return Promise.all(readPromises);
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
// return list of files from path
|
|
101
|
-
export const getConfigFileList = (path) => {
|
|
102
|
-
return new Promise((resolve, reject) => {
|
|
103
|
-
readdir(path)
|
|
104
|
-
.then((files) => {
|
|
105
|
-
resolve(
|
|
106
|
-
files.map((file) => ({
|
|
107
|
-
name: file.replace(/-/g, ' ').split('.')[0],
|
|
108
|
-
value: file,
|
|
109
|
-
})),
|
|
110
|
-
);
|
|
111
|
-
})
|
|
112
|
-
.catch((err) => reject(err));
|
|
113
|
-
});
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
// returns globby promise based on search pattern and configuration
|
|
117
|
-
// https://github.com/sindresorhus/globby
|
|
118
|
-
export const getGlob = (pattern, config) => {
|
|
119
|
-
return new Promise((resolve, reject) => {
|
|
120
|
-
globby(pattern, config)
|
|
121
|
-
.then((matches) => resolve(matches))
|
|
122
|
-
.catch((err) => reject(err));
|
|
123
|
-
});
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
// display list of configuration files retreived by readConfigFile
|
|
127
|
-
export const inquireForFile = (folder, options) => {
|
|
128
|
-
return new Promise((resolve, reject) => {
|
|
129
|
-
inquirer
|
|
130
|
-
.prompt([
|
|
131
|
-
{
|
|
132
|
-
type: 'list',
|
|
133
|
-
name: 'file',
|
|
134
|
-
choices: options,
|
|
135
|
-
pageSize: 4,
|
|
136
|
-
prefix: `\n${chalk.green('?')} Choose a migration configuration to use:\n`,
|
|
137
|
-
},
|
|
138
|
-
])
|
|
139
|
-
.then((choice) => {
|
|
140
|
-
const configPath = `${folder}/${choice.file}`;
|
|
141
|
-
resolve(readConfigFile(configPath));
|
|
142
|
-
})
|
|
143
|
-
.catch((err) => {
|
|
144
|
-
reject(err);
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
// for each expression (string.replace(from, to)) iterate over each file and make
|
|
150
|
-
// changes where a match was found. Records number of matches per file.
|
|
151
|
-
// @TODO: could probably be sped up but it already seems pretty fast.
|
|
152
|
-
export const modifyFileContents = async (content, expr) => {
|
|
153
|
-
// filter out files with less than 3 newlines, likely compressed/minified files
|
|
154
|
-
content
|
|
155
|
-
.filter((f) => {
|
|
156
|
-
return (f.data.match(/[\n\r]/g) || []).length > 3;
|
|
157
|
-
})
|
|
158
|
-
.map((f) => {
|
|
159
|
-
expr.forEach((e) => {
|
|
160
|
-
f.data = f.data.replace(e.from, (match) => {
|
|
161
|
-
f.matches++;
|
|
162
|
-
return match.replace(e.from, e.to);
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
return f;
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
// promise map for writing file to the FS
|
|
169
|
-
const writePromises = content.map(async (content) => {
|
|
170
|
-
if (content.matches > 0) {
|
|
171
|
-
return writeFile(content.file, content.data, 'utf8')
|
|
172
|
-
.then(() => {
|
|
173
|
-
return { file: content.file, matches: content.matches };
|
|
174
|
-
})
|
|
175
|
-
.catch((err) => error('writePromises: ' + err));
|
|
176
|
-
} else {
|
|
177
|
-
return { file: content.file, matches: 0 };
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
// write out list of files that changed and how many changes were made
|
|
182
|
-
return await Promise.all(writePromises).then((results) => {
|
|
183
|
-
results.forEach((result) => {
|
|
184
|
-
if (result.matches > 0) {
|
|
185
|
-
// gives a shorter name
|
|
186
|
-
const shortname = path.relative(process.cwd(), result.file);
|
|
187
|
-
console.log(
|
|
188
|
-
`${chalk.yellow('>>')} ${shortname}${chalk.gray(',')} ${chalk.whiteBright(
|
|
189
|
-
result.matches,
|
|
190
|
-
)} changes`,
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
// read configuration file and return array with data and config filename
|
|
198
|
-
export const readConfigFile = async (file) => {
|
|
199
|
-
const config = await import(file);
|
|
200
|
-
return [config.default, path.basename(file)];
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
export default {
|
|
204
|
-
confirmStart,
|
|
205
|
-
doPatternSearch,
|
|
206
|
-
error,
|
|
207
|
-
findMatchedFiles,
|
|
208
|
-
getAllFileContents,
|
|
209
|
-
getConfigFileList,
|
|
210
|
-
getGlob,
|
|
211
|
-
inquireForFile,
|
|
212
|
-
modifyFileContents,
|
|
213
|
-
readConfigFile,
|
|
214
|
-
};
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import {
|
|
5
|
-
confirmStart,
|
|
6
|
-
doPatternSearch,
|
|
7
|
-
error,
|
|
8
|
-
findMatchedFiles,
|
|
9
|
-
getConfigFileList,
|
|
10
|
-
getAllFileContents,
|
|
11
|
-
inquireForFile,
|
|
12
|
-
modifyFileContents,
|
|
13
|
-
readConfigFile,
|
|
14
|
-
} from './helpers.mjs';
|
|
15
|
-
import ora from 'ora';
|
|
16
|
-
import { dirname, normalize } from 'path';
|
|
17
|
-
import { fileURLToPath } from 'url';
|
|
18
|
-
import { hideBin } from 'yargs/helpers';
|
|
19
|
-
import yargs from 'yargs';
|
|
20
|
-
|
|
21
|
-
// eslint-disable-next-line complexity
|
|
22
|
-
(async () => {
|
|
23
|
-
// get command line args
|
|
24
|
-
const argv = yargs(hideBin(process.argv))
|
|
25
|
-
.scriptName('dialtone-migration-helper')
|
|
26
|
-
.usage(
|
|
27
|
-
'$0 --file migration-config-file.js --cwd "../root/directory --ignore "**/ignored/**", "**/another_ignored/**"',
|
|
28
|
-
)
|
|
29
|
-
.options({
|
|
30
|
-
config: {
|
|
31
|
-
type: 'string',
|
|
32
|
-
description: 'Migration configuration module.',
|
|
33
|
-
},
|
|
34
|
-
cwd: {
|
|
35
|
-
type: 'string',
|
|
36
|
-
description: 'Root directory for scan. Defaults to CWD.',
|
|
37
|
-
default: process.cwd(),
|
|
38
|
-
},
|
|
39
|
-
ignore: {
|
|
40
|
-
type: 'array',
|
|
41
|
-
description: 'Other glob patterns to ignore during search. .gitignore included by default.',
|
|
42
|
-
},
|
|
43
|
-
force: {
|
|
44
|
-
boolean: true,
|
|
45
|
-
description: 'Skip interactive prompts, use caution!',
|
|
46
|
-
default: false,
|
|
47
|
-
},
|
|
48
|
-
})
|
|
49
|
-
.help().argv;
|
|
50
|
-
|
|
51
|
-
// get list of configuration files
|
|
52
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
53
|
-
const __dirname = dirname(__filename);
|
|
54
|
-
const CONFIG_FOLDER = __dirname + '/configs';
|
|
55
|
-
const configList = await getConfigFileList(CONFIG_FOLDER).catch((err) =>
|
|
56
|
-
error('getConfigFileList: ' + err),
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
// load configuration from arg or list
|
|
60
|
-
const [configData, configFile] = !argv.config
|
|
61
|
-
? await inquireForFile(CONFIG_FOLDER, configList).catch((err) =>
|
|
62
|
-
error('inquireForFile: ' + err),
|
|
63
|
-
)
|
|
64
|
-
: await readConfigFile(argv.config).catch((err) => error('readConfigFile: ' + err));
|
|
65
|
-
|
|
66
|
-
// set up some globby defaults
|
|
67
|
-
configData.globbyConfig = configData.globbyConfig || {};
|
|
68
|
-
configData.globbyConfig.gitignore = configData.globbyConfig.gitignore || true;
|
|
69
|
-
|
|
70
|
-
console.log(
|
|
71
|
-
`\n${chalk.green('++')} Configuration Loaded! (${configFile}) ${chalk.green('++')}\n`,
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
// take CWD if specified from command line
|
|
75
|
-
const cwd = !argv.cwd ? process.cwd() : normalize(argv.cwd);
|
|
76
|
-
configData.globbyConfig.cwd = configData.globbyConfig.cwd || cwd;
|
|
77
|
-
// push ignore list to configuration array
|
|
78
|
-
if (argv.ignore) {
|
|
79
|
-
configData.globbyConfig.ignore.push(...argv.ignore);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// run glob search with configData.patterns
|
|
83
|
-
const globSpinner = ora('Performing pattern search').start();
|
|
84
|
-
const files = await doPatternSearch(configData).then((f) => {
|
|
85
|
-
return findMatchedFiles(f, configData);
|
|
86
|
-
});
|
|
87
|
-
if (files.length <= 0) {
|
|
88
|
-
console.log(
|
|
89
|
-
'\n' +
|
|
90
|
-
chalk.cyan('??') +
|
|
91
|
-
' No matches found! Check your patterns and cwd settings if you think this is an error.',
|
|
92
|
-
);
|
|
93
|
-
process.exit(0);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
globSpinner.stop();
|
|
97
|
-
console.log(`[ ${chalk.whiteBright(files.length)} ] files queued for modification:\n`);
|
|
98
|
-
console.log(files);
|
|
99
|
-
console.log(
|
|
100
|
-
`\n${chalk.yellow('Configuration Description')}${chalk.gray(':')}\n${configData.description}\n`,
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
// kick off file search and replace
|
|
104
|
-
const startModification = () => {
|
|
105
|
-
console.log(`\n${chalk.blue('__')} Starting ...`);
|
|
106
|
-
|
|
107
|
-
getAllFileContents(files, configData.globbyConfig.cwd)
|
|
108
|
-
.then((content) => {
|
|
109
|
-
modifyFileContents(content, configData.expressions).then(() => {
|
|
110
|
-
console.log(`${chalk.magenta('==')} Modification complete!\n`);
|
|
111
|
-
});
|
|
112
|
-
})
|
|
113
|
-
.catch((err) => error('getAllFileContents: ' + err));
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
// begin file modification based on configuration rules
|
|
117
|
-
// start automatically if --force is specified
|
|
118
|
-
if (!argv.force) {
|
|
119
|
-
confirmStart()
|
|
120
|
-
.then((val) => {
|
|
121
|
-
if (val) {
|
|
122
|
-
startModification();
|
|
123
|
-
} else {
|
|
124
|
-
console.log(`\n${chalk.red('__')} Cancelling ...\n`);
|
|
125
|
-
}
|
|
126
|
-
})
|
|
127
|
-
.catch((err) => error('confirmStart ' + err));
|
|
128
|
-
} else {
|
|
129
|
-
startModification();
|
|
130
|
-
}
|
|
131
|
-
})();
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export default {
|
|
2
|
-
description:
|
|
3
|
-
'Updates dialtone 7 variables to dialtone 8 design tokens.\n' +
|
|
4
|
-
'- Replaces var(--{color}-{stop}) with var(--dt-color-{color}-{stop})\n\t' +
|
|
5
|
-
'eg. var(--black-200) with var(--dt-color-black-200)',
|
|
6
|
-
patterns: ['**/*.{css,less,scss,sass,styl,html,vue}'],
|
|
7
|
-
expressions: [
|
|
8
|
-
{
|
|
9
|
-
from: /var\(--(white|black|purple|orange|magenta|gold|green|red|blue|tan)(-[1-9]00)?\)/gi,
|
|
10
|
-
to: 'var(--dt-color-$1$2)',
|
|
11
|
-
},
|
|
12
|
-
],
|
|
13
|
-
};
|
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
|
-
import { globby } from 'globby';
|
|
3
|
-
import inquirer from 'inquirer';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import fs from 'fs';
|
|
6
|
-
const { readdir, readFile, writeFile } = fs.promises;
|
|
7
|
-
|
|
8
|
-
// confirm prompt for starting operations, display warning and y/n dialog
|
|
9
|
-
export const confirmStart = () => {
|
|
10
|
-
return new Promise((resolve, reject) => {
|
|
11
|
-
inquirer
|
|
12
|
-
.prompt([
|
|
13
|
-
{
|
|
14
|
-
type: 'confirm',
|
|
15
|
-
name: 'yesno',
|
|
16
|
-
prefix: `
|
|
17
|
-
${chalk.bgRed(
|
|
18
|
-
'┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ !!! CAUTION !!! ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓',
|
|
19
|
-
)}
|
|
20
|
-
${chalk.bgRed(
|
|
21
|
-
'┃',
|
|
22
|
-
)} Please be sure you are running this in a code repository where changes can be rolled back. ${chalk.bgRed(
|
|
23
|
-
'┃',
|
|
24
|
-
)}
|
|
25
|
-
${chalk.bgRed(
|
|
26
|
-
'┃',
|
|
27
|
-
)} Modifications will occur to files listed above. Proceed at your own risk. ${chalk.bgRed(
|
|
28
|
-
'┃',
|
|
29
|
-
)}
|
|
30
|
-
${chalk.bgRed(
|
|
31
|
-
'┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛',
|
|
32
|
-
)}\n
|
|
33
|
-
`,
|
|
34
|
-
message: 'Start modification?',
|
|
35
|
-
default: true,
|
|
36
|
-
},
|
|
37
|
-
])
|
|
38
|
-
.then((choice) => {
|
|
39
|
-
resolve(choice.yesno);
|
|
40
|
-
})
|
|
41
|
-
.catch((err) => {
|
|
42
|
-
reject(err);
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
// return array of all globby pattern matches in one level
|
|
48
|
-
export const doPatternSearch = async (config) => {
|
|
49
|
-
const res = [];
|
|
50
|
-
for (const p of config.patterns) {
|
|
51
|
-
res.push(
|
|
52
|
-
...(await getGlob(p, config.globbyConfig).catch((err) => error('doPatternSearch: ' + err))),
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
return res;
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// error and quit
|
|
59
|
-
export const error = (message) => {
|
|
60
|
-
console.log(`\n${chalk.red('!!')} Error: ${message}\n`);
|
|
61
|
-
process.exit(1);
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
export const findMatchedFiles = async (fileList, config) => {
|
|
65
|
-
return getAllFileContents(fileList, config.globbyConfig.cwd).then((globbed) => {
|
|
66
|
-
// filter out minified files
|
|
67
|
-
const filtered = globbed
|
|
68
|
-
.filter((f) => {
|
|
69
|
-
return (f.data.match(/[\n\r]/g) || []).length > 3;
|
|
70
|
-
})
|
|
71
|
-
.filter((f) => {
|
|
72
|
-
config.expressions.forEach((e) => {
|
|
73
|
-
if (e.from.test(f.data)) f.matches++;
|
|
74
|
-
});
|
|
75
|
-
return f.matches > 0;
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
const matchedFiles = filtered.reduce((prev, current) => {
|
|
79
|
-
const fn = path.relative(config.globbyConfig.cwd, current.file);
|
|
80
|
-
return [...prev, fn];
|
|
81
|
-
}, []);
|
|
82
|
-
|
|
83
|
-
return matchedFiles;
|
|
84
|
-
});
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
// read file contents of all matched files, return filename and data, default matches (0)
|
|
88
|
-
export const getAllFileContents = (fileList, cwd) => {
|
|
89
|
-
const readPromises = fileList.map(async (file) => {
|
|
90
|
-
file = cwd + path.sep + file;
|
|
91
|
-
return readFile(file, 'utf8')
|
|
92
|
-
.then((data) => {
|
|
93
|
-
return { file, data, matches: 0 };
|
|
94
|
-
})
|
|
95
|
-
.catch((err) => error('getAllFileContents: ' + err));
|
|
96
|
-
});
|
|
97
|
-
return Promise.all(readPromises);
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
// return list of files from path
|
|
101
|
-
export const getConfigFileList = (path) => {
|
|
102
|
-
return new Promise((resolve, reject) => {
|
|
103
|
-
readdir(path)
|
|
104
|
-
.then((files) => {
|
|
105
|
-
resolve(
|
|
106
|
-
files.map((file) => ({
|
|
107
|
-
name: file.replace(/-/g, ' ').split('.')[0],
|
|
108
|
-
value: file,
|
|
109
|
-
})),
|
|
110
|
-
);
|
|
111
|
-
})
|
|
112
|
-
.catch((err) => reject(err));
|
|
113
|
-
});
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
// returns globby promise based on search pattern and configuration
|
|
117
|
-
// https://github.com/sindresorhus/globby
|
|
118
|
-
export const getGlob = (pattern, config) => {
|
|
119
|
-
return new Promise((resolve, reject) => {
|
|
120
|
-
globby(pattern, config)
|
|
121
|
-
.then((matches) => resolve(matches))
|
|
122
|
-
.catch((err) => reject(err));
|
|
123
|
-
});
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
// display list of configuration files retreived by readConfigFile
|
|
127
|
-
export const inquireForFile = (folder, options) => {
|
|
128
|
-
return new Promise((resolve, reject) => {
|
|
129
|
-
inquirer
|
|
130
|
-
.prompt([
|
|
131
|
-
{
|
|
132
|
-
type: 'list',
|
|
133
|
-
name: 'file',
|
|
134
|
-
choices: options,
|
|
135
|
-
pageSize: 4,
|
|
136
|
-
prefix: `\n${chalk.green('?')} Choose a migration configuration to use:\n`,
|
|
137
|
-
},
|
|
138
|
-
])
|
|
139
|
-
.then((choice) => {
|
|
140
|
-
const configPath = `${folder}/${choice.file}`;
|
|
141
|
-
resolve(readConfigFile(configPath));
|
|
142
|
-
})
|
|
143
|
-
.catch((err) => {
|
|
144
|
-
reject(err);
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
// for each expression (string.replace(from, to)) iterate over each file and make
|
|
150
|
-
// changes where a match was found. Records number of matches per file.
|
|
151
|
-
// @TODO: could probably be sped up but it already seems pretty fast.
|
|
152
|
-
export const modifyFileContents = async (content, expr) => {
|
|
153
|
-
// filter out files with less than 3 newlines, likely compressed/minified files
|
|
154
|
-
content
|
|
155
|
-
.filter((f) => {
|
|
156
|
-
return (f.data.match(/[\n\r]/g) || []).length > 3;
|
|
157
|
-
})
|
|
158
|
-
.map((f) => {
|
|
159
|
-
expr.forEach((e) => {
|
|
160
|
-
f.data = f.data.replace(e.from, (match) => {
|
|
161
|
-
f.matches++;
|
|
162
|
-
return match.replace(e.from, e.to);
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
return f;
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
// promise map for writing file to the FS
|
|
169
|
-
const writePromises = content.map(async (content) => {
|
|
170
|
-
if (content.matches > 0) {
|
|
171
|
-
return writeFile(content.file, content.data, 'utf8')
|
|
172
|
-
.then(() => {
|
|
173
|
-
return { file: content.file, matches: content.matches };
|
|
174
|
-
})
|
|
175
|
-
.catch((err) => error('writePromises: ' + err));
|
|
176
|
-
} else {
|
|
177
|
-
return { file: content.file, matches: 0 };
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
// write out list of files that changed and how many changes were made
|
|
182
|
-
return await Promise.all(writePromises).then((results) => {
|
|
183
|
-
results.forEach((result) => {
|
|
184
|
-
if (result.matches > 0) {
|
|
185
|
-
// gives a shorter name
|
|
186
|
-
const shortname = path.relative(process.cwd(), result.file);
|
|
187
|
-
console.log(
|
|
188
|
-
`${chalk.yellow('>>')} ${shortname}${chalk.gray(',')} ${chalk.whiteBright(
|
|
189
|
-
result.matches,
|
|
190
|
-
)} changes`,
|
|
191
|
-
);
|
|
192
|
-
}
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
// read configuration file and return array with data and config filename
|
|
198
|
-
export const readConfigFile = async (file) => {
|
|
199
|
-
const config = await import(file);
|
|
200
|
-
return [config.default, path.basename(file)];
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
export default {
|
|
204
|
-
confirmStart,
|
|
205
|
-
doPatternSearch,
|
|
206
|
-
error,
|
|
207
|
-
findMatchedFiles,
|
|
208
|
-
getAllFileContents,
|
|
209
|
-
getConfigFileList,
|
|
210
|
-
getGlob,
|
|
211
|
-
inquireForFile,
|
|
212
|
-
modifyFileContents,
|
|
213
|
-
readConfigFile,
|
|
214
|
-
};
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import chalk from 'chalk';
|
|
4
|
-
import {
|
|
5
|
-
confirmStart,
|
|
6
|
-
doPatternSearch,
|
|
7
|
-
error,
|
|
8
|
-
findMatchedFiles,
|
|
9
|
-
getConfigFileList,
|
|
10
|
-
getAllFileContents,
|
|
11
|
-
inquireForFile,
|
|
12
|
-
modifyFileContents,
|
|
13
|
-
readConfigFile,
|
|
14
|
-
} from './helpers.mjs';
|
|
15
|
-
import ora from 'ora';
|
|
16
|
-
import { dirname, normalize } from 'path';
|
|
17
|
-
import { fileURLToPath } from 'url';
|
|
18
|
-
import { hideBin } from 'yargs/helpers';
|
|
19
|
-
import yargs from 'yargs';
|
|
20
|
-
|
|
21
|
-
// eslint-disable-next-line complexity
|
|
22
|
-
(async () => {
|
|
23
|
-
// get command line args
|
|
24
|
-
const argv = yargs(hideBin(process.argv))
|
|
25
|
-
.scriptName('dialtone-migration-helper')
|
|
26
|
-
.usage(
|
|
27
|
-
'$0 --file migration-config-file.js --cwd "../root/directory --ignore "**/ignored/**", "**/another_ignored/**"',
|
|
28
|
-
)
|
|
29
|
-
.options({
|
|
30
|
-
config: {
|
|
31
|
-
type: 'string',
|
|
32
|
-
description: 'Migration configuration module.',
|
|
33
|
-
},
|
|
34
|
-
cwd: {
|
|
35
|
-
type: 'string',
|
|
36
|
-
description: 'Root directory for scan. Defaults to CWD.',
|
|
37
|
-
default: process.cwd(),
|
|
38
|
-
},
|
|
39
|
-
ignore: {
|
|
40
|
-
type: 'array',
|
|
41
|
-
description: 'Other glob patterns to ignore during search. .gitignore included by default.',
|
|
42
|
-
},
|
|
43
|
-
force: {
|
|
44
|
-
boolean: true,
|
|
45
|
-
description: 'Skip interactive prompts, use caution!',
|
|
46
|
-
default: false,
|
|
47
|
-
},
|
|
48
|
-
})
|
|
49
|
-
.help().argv;
|
|
50
|
-
|
|
51
|
-
// get list of configuration files
|
|
52
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
53
|
-
const __dirname = dirname(__filename);
|
|
54
|
-
const CONFIG_FOLDER = __dirname + '/configs';
|
|
55
|
-
const configList = await getConfigFileList(CONFIG_FOLDER).catch((err) =>
|
|
56
|
-
error('getConfigFileList: ' + err),
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
// load configuration from arg or list
|
|
60
|
-
const [configData, configFile] = !argv.config
|
|
61
|
-
? await inquireForFile(CONFIG_FOLDER, configList).catch((err) =>
|
|
62
|
-
error('inquireForFile: ' + err),
|
|
63
|
-
)
|
|
64
|
-
: await readConfigFile(argv.config).catch((err) => error('readConfigFile: ' + err));
|
|
65
|
-
|
|
66
|
-
// set up some globby defaults
|
|
67
|
-
configData.globbyConfig = configData.globbyConfig || {};
|
|
68
|
-
configData.globbyConfig.gitignore = configData.globbyConfig.gitignore || true;
|
|
69
|
-
|
|
70
|
-
console.log(
|
|
71
|
-
`\n${chalk.green('++')} Configuration Loaded! (${configFile}) ${chalk.green('++')}\n`,
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
// take CWD if specified from command line
|
|
75
|
-
const cwd = !argv.cwd ? process.cwd() : normalize(argv.cwd);
|
|
76
|
-
configData.globbyConfig.cwd = configData.globbyConfig.cwd || cwd;
|
|
77
|
-
// push ignore list to configuration array
|
|
78
|
-
if (argv.ignore) {
|
|
79
|
-
configData.globbyConfig.ignore.push(...argv.ignore);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// run glob search with configData.patterns
|
|
83
|
-
const globSpinner = ora('Performing pattern search').start();
|
|
84
|
-
const files = await doPatternSearch(configData).then((f) => {
|
|
85
|
-
return findMatchedFiles(f, configData);
|
|
86
|
-
});
|
|
87
|
-
if (files.length <= 0) {
|
|
88
|
-
console.log(
|
|
89
|
-
'\n' +
|
|
90
|
-
chalk.cyan('??') +
|
|
91
|
-
' No matches found! Check your patterns and cwd settings if you think this is an error.',
|
|
92
|
-
);
|
|
93
|
-
process.exit(0);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
globSpinner.stop();
|
|
97
|
-
console.log(`[ ${chalk.whiteBright(files.length)} ] files queued for modification:\n`);
|
|
98
|
-
console.log(files);
|
|
99
|
-
console.log(
|
|
100
|
-
`\n${chalk.yellow('Configuration Description')}${chalk.gray(':')}\n${configData.description}\n`,
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
// kick off file search and replace
|
|
104
|
-
const startModification = () => {
|
|
105
|
-
console.log(`\n${chalk.blue('__')} Starting ...`);
|
|
106
|
-
|
|
107
|
-
getAllFileContents(files, configData.globbyConfig.cwd)
|
|
108
|
-
.then((content) => {
|
|
109
|
-
modifyFileContents(content, configData.expressions).then(() => {
|
|
110
|
-
console.log(`${chalk.magenta('==')} Modification complete!\n`);
|
|
111
|
-
});
|
|
112
|
-
})
|
|
113
|
-
.catch((err) => error('getAllFileContents: ' + err));
|
|
114
|
-
};
|
|
115
|
-
|
|
116
|
-
// begin file modification based on configuration rules
|
|
117
|
-
// start automatically if --force is specified
|
|
118
|
-
if (!argv.force) {
|
|
119
|
-
confirmStart()
|
|
120
|
-
.then((val) => {
|
|
121
|
-
if (val) {
|
|
122
|
-
startModification();
|
|
123
|
-
} else {
|
|
124
|
-
console.log(`\n${chalk.red('__')} Cancelling ...\n`);
|
|
125
|
-
}
|
|
126
|
-
})
|
|
127
|
-
.catch((err) => error('confirmStart ' + err));
|
|
128
|
-
} else {
|
|
129
|
-
startModification();
|
|
130
|
-
}
|
|
131
|
-
})();
|