@rancher/create-extension 0.2.1-rc.1 → 1.0.0-rc.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/app/app.package.json +2 -1
- package/app/init +38 -5
- package/app/package.json +1 -1
- package/init +49 -21
- package/migrate/config.js +7 -0
- package/migrate/ignore.js +14 -0
- package/migrate/init +35 -0
- package/migrate/package.json +23 -0
- package/migrate/params.js +7 -0
- package/migrate/stats.js +13 -0
- package/migrate/tasks/eslintUpdates.js +70 -0
- package/migrate/tasks/index.js +19 -0
- package/migrate/tasks/nvmUpdates.js +51 -0
- package/migrate/tasks/packageUpdates.js +242 -0
- package/migrate/tasks/routerUpdates.js +23 -0
- package/migrate/tasks/stylesUpdates.js +19 -0
- package/migrate/tasks/tsUpdates.js +19 -0
- package/migrate/tasks/vueConfigUpdates.js +30 -0
- package/migrate/tasks/vueSyntaxUpdates.js +148 -0
- package/migrate/utils/content.js +165 -0
- package/migrate/utils/index.js +4 -0
- package/migrate/utils/vueSyntax.js +126 -0
- package/package.json +10 -6
- package/pkg/files/tsconfig.json +3 -3
- package/pkg/init +7 -70
- package/pkg/package.json +1 -1
- package/update/init +16 -11
- package/update/package.json +1 -1
- package/update/upgrade +4 -4
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Vue syntax specific utilities
|
|
3
|
+
*/
|
|
4
|
+
const isSimpleIdentifier = (str) => /^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(str.trim());
|
|
5
|
+
const isBracketedExpression = (str) => str.trim().startsWith('[') && str.trim().endsWith(']');
|
|
6
|
+
const isStringLiteral = (str) => /^['"].*['"]$/.test(str.trim());
|
|
7
|
+
// Extracts the key expression from a v-for directive.
|
|
8
|
+
const extractKeyExpression = (vForContent) => {
|
|
9
|
+
const vForMatch = vForContent.match(/^\s*\(([^,]+),\s*([^)]+)\)\s+in\s+(.*)$/);
|
|
10
|
+
let keyExpression = null;
|
|
11
|
+
|
|
12
|
+
if (vForMatch) {
|
|
13
|
+
// v-for="(item, key) in items"
|
|
14
|
+
keyExpression = vForMatch[2].trim();
|
|
15
|
+
} else {
|
|
16
|
+
const simpleVForMatch = vForContent.match(/^\s*([^\s]+)\s+in\s+(.*)$/);
|
|
17
|
+
|
|
18
|
+
if (simpleVForMatch) {
|
|
19
|
+
// v-for="item in items"
|
|
20
|
+
// Use 'item' as key if it's a simple identifier
|
|
21
|
+
keyExpression = isSimpleIdentifier(simpleVForMatch[1].trim()) ? simpleVForMatch[1].trim() : null;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return keyExpression;
|
|
26
|
+
};
|
|
27
|
+
// Adds the :key attribute to a tag if it doesn't already have one.
|
|
28
|
+
const addKeyAttribute = (tag, keyExpression) => {
|
|
29
|
+
// Add space if necessary
|
|
30
|
+
const space = tag.endsWith(' ') ? '' : ' ';
|
|
31
|
+
|
|
32
|
+
return `${ tag }${ space }:key="${ keyExpression }"`;
|
|
33
|
+
};
|
|
34
|
+
const vueSetReplacement = (match, obj, prop, val) => {
|
|
35
|
+
prop = prop.trim();
|
|
36
|
+
obj = obj.trim();
|
|
37
|
+
val = val.trim();
|
|
38
|
+
|
|
39
|
+
if (isBracketedExpression(prop)) {
|
|
40
|
+
return `${ obj }${ prop } = ${ val }`;
|
|
41
|
+
} else if (isStringLiteral(prop)) {
|
|
42
|
+
return `${ obj }[${ prop }] = ${ val }`;
|
|
43
|
+
} else if (isSimpleIdentifier(prop)) {
|
|
44
|
+
return `${ obj }.${ prop } = ${ val }`;
|
|
45
|
+
} else {
|
|
46
|
+
return `${ obj }[${ prop }] = ${ val }`;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
const vueDeleteReplacement = (match, obj, prop) => {
|
|
50
|
+
prop = prop.trim();
|
|
51
|
+
obj = obj.trim();
|
|
52
|
+
|
|
53
|
+
if (isBracketedExpression(prop)) {
|
|
54
|
+
return `delete ${ obj }${ prop }`;
|
|
55
|
+
} else if (isStringLiteral(prop)) {
|
|
56
|
+
return `delete ${ obj }[${ prop }]`;
|
|
57
|
+
} else if (isSimpleIdentifier(prop)) {
|
|
58
|
+
return `delete ${ obj }.${ prop }`;
|
|
59
|
+
} else {
|
|
60
|
+
return `delete ${ obj }[${ prop }]`;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const vueKeyReplacement = (match, beforeTagEnd, vForContent, tagClose) => {
|
|
64
|
+
// Check if :key exists in the tag
|
|
65
|
+
if (beforeTagEnd.includes(':key=')) {
|
|
66
|
+
return match; // :key already exists, do not modify
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const keyExpression = extractKeyExpression(vForContent);
|
|
70
|
+
|
|
71
|
+
if (keyExpression) {
|
|
72
|
+
const updatedTag = addKeyAttribute(beforeTagEnd, keyExpression);
|
|
73
|
+
|
|
74
|
+
return `${ updatedTag }${ tagClose }`;
|
|
75
|
+
} else {
|
|
76
|
+
// Cannot safely determine a key, so do not add one
|
|
77
|
+
return match;
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
const vueTemplateKeyReplacement = (match, templateStart, templateContent, templateEnd) => {
|
|
81
|
+
// Check if :key is on the <template> tag
|
|
82
|
+
const hasKeyOnTemplate = /:key=/.test(templateStart);
|
|
83
|
+
|
|
84
|
+
// Find any :key on direct child elements
|
|
85
|
+
const childWithKeyRegex = /(<\w+[^>]*)(\s+:key="([^"]+)")([^>]*>)/g;
|
|
86
|
+
let updatedContent = templateContent;
|
|
87
|
+
let movedKey = null;
|
|
88
|
+
|
|
89
|
+
updatedContent = updatedContent.replace(childWithKeyRegex, (childMatch, beforeKey, keyAttr, keyValue, afterKey) => {
|
|
90
|
+
if (!hasKeyOnTemplate && !movedKey) {
|
|
91
|
+
// Move the first encountered :key to the template
|
|
92
|
+
movedKey = keyValue;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Remove :key from child element
|
|
96
|
+
return `${ beforeKey }${ afterKey }`;
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
if (!hasKeyOnTemplate && movedKey) {
|
|
100
|
+
// Add :key to the <template> tag
|
|
101
|
+
const updatedTemplateStart = `${ addKeyAttribute(templateStart.replace(/>$/, ''), movedKey) }>`;
|
|
102
|
+
|
|
103
|
+
return `${ updatedTemplateStart }${ updatedContent }${ templateEnd }`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return `${ templateStart }${ updatedContent }${ templateEnd }`;
|
|
107
|
+
};
|
|
108
|
+
const vueTemplateKeyRemoval = (match, templateStart, templateContent, templateEnd) => {
|
|
109
|
+
const childWithKeyRegex = /(<\w+[^>]*)(\s+:key="[^"]+")([^>]*>)/g;
|
|
110
|
+
const updatedContent = templateContent.replace(childWithKeyRegex, '$1$3');
|
|
111
|
+
|
|
112
|
+
return `${ templateStart }${ updatedContent }${ templateEnd }`;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
module.exports = {
|
|
116
|
+
isSimpleIdentifier,
|
|
117
|
+
isBracketedExpression,
|
|
118
|
+
isStringLiteral,
|
|
119
|
+
extractKeyExpression,
|
|
120
|
+
addKeyAttribute,
|
|
121
|
+
vueSetReplacement,
|
|
122
|
+
vueDeleteReplacement,
|
|
123
|
+
vueKeyReplacement,
|
|
124
|
+
vueTemplateKeyReplacement,
|
|
125
|
+
vueTemplateKeyRemoval
|
|
126
|
+
};
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rancher/create-extension",
|
|
3
3
|
"description": "Rancher UI Extension generator",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "1.0.0-rc.2",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "SUSE",
|
|
7
|
-
"packageManager": "yarn@4.
|
|
7
|
+
"packageManager": "yarn@4.5.0",
|
|
8
8
|
"bin": {
|
|
9
9
|
"create-extension": "./init"
|
|
10
10
|
},
|
|
@@ -13,15 +13,19 @@
|
|
|
13
13
|
"init"
|
|
14
14
|
],
|
|
15
15
|
"engines": {
|
|
16
|
-
"node": ">=
|
|
16
|
+
"node": ">=20"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"
|
|
19
|
+
"diff": "^7.0.0",
|
|
20
|
+
"fs-extra": "^10.0.0",
|
|
21
|
+
"glob": "^11.0.0",
|
|
22
|
+
"path": "^0.12.7",
|
|
23
|
+
"semver": "^7.6.3"
|
|
20
24
|
},
|
|
21
25
|
"_pkgs": {
|
|
22
|
-
"core-js": "3.
|
|
26
|
+
"core-js": "3.25.3",
|
|
23
27
|
"css-loader": "6.7.3",
|
|
24
28
|
"@types/lodash": "4.14.184",
|
|
25
|
-
"@rancher/components": "0.
|
|
29
|
+
"@rancher/components": "0.3.0-alpha.1"
|
|
26
30
|
}
|
|
27
31
|
}
|
package/pkg/files/tsconfig.json
CHANGED
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
"skipLibCheck": true,
|
|
11
11
|
"esModuleInterop": true,
|
|
12
12
|
"allowSyntheticDefaultImports": true,
|
|
13
|
-
"sourceMap":
|
|
13
|
+
"sourceMap": true,
|
|
14
14
|
"baseUrl": ".",
|
|
15
15
|
"preserveSymlinks": true,
|
|
16
16
|
"typeRoots": [
|
|
17
17
|
"../../node_modules",
|
|
18
18
|
"../../node_modules/@rancher/shell/types"
|
|
19
|
-
],
|
|
19
|
+
],
|
|
20
20
|
"types": [
|
|
21
21
|
"node",
|
|
22
22
|
"webpack-env",
|
|
@@ -50,4 +50,4 @@
|
|
|
50
50
|
"exclude": [
|
|
51
51
|
"../../node_modules"
|
|
52
52
|
]
|
|
53
|
-
}
|
|
53
|
+
}
|
package/pkg/init
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable no-console */
|
|
2
3
|
|
|
4
|
+
const { execSync } = require('child_process');
|
|
3
5
|
const fs = require('fs-extra');
|
|
4
6
|
const path = require('path');
|
|
5
7
|
const https = require('https');
|
|
6
8
|
|
|
7
|
-
const targets = {
|
|
8
|
-
dev: './node_modules/.bin/nuxt dev',
|
|
9
|
-
nuxt: './node_modules/.bin/nuxt',
|
|
10
|
-
};
|
|
11
|
-
|
|
12
9
|
const files = [
|
|
13
10
|
'tsconfig.json',
|
|
14
11
|
'vue.config.js',
|
|
@@ -31,39 +28,26 @@ const typeFolders = [
|
|
|
31
28
|
'detail'
|
|
32
29
|
];
|
|
33
30
|
|
|
34
|
-
const shellPkgPath = 'node_modules/@rancher/shell';
|
|
35
|
-
|
|
36
31
|
console.log('');
|
|
37
32
|
console.log('Creating Skeleton UI Package');
|
|
38
33
|
|
|
39
34
|
const args = process.argv;
|
|
40
35
|
|
|
41
|
-
if (args.length !== 3) {
|
|
42
|
-
console.log('Expected single argument of package name');
|
|
43
|
-
}
|
|
44
|
-
|
|
45
36
|
const name = args[2];
|
|
46
37
|
const folder = path.resolve('.');
|
|
47
38
|
const pkgFolder = path.join(folder, 'pkg', name);
|
|
48
39
|
let shellVersion = '';
|
|
49
40
|
|
|
50
|
-
let addTypeFolders =
|
|
51
|
-
let addWorkflowFolder = false;
|
|
52
|
-
let ignoreShellPkgPathCheck = false;
|
|
41
|
+
let addTypeFolders = true;
|
|
53
42
|
|
|
54
43
|
if ( args.length >= 3 ) {
|
|
55
44
|
shellVersion = args[3];
|
|
56
45
|
|
|
57
46
|
for ( let i = 3; i < args.length; i++ ) {
|
|
58
47
|
switch (args[i]) {
|
|
48
|
+
case '--skip-templates':
|
|
59
49
|
case '-t':
|
|
60
|
-
addTypeFolders =
|
|
61
|
-
break;
|
|
62
|
-
case '-w':
|
|
63
|
-
addWorkflowFolder = true;
|
|
64
|
-
break;
|
|
65
|
-
case '-i':
|
|
66
|
-
ignoreShellPkgPathCheck = true;
|
|
50
|
+
addTypeFolders = false;
|
|
67
51
|
break;
|
|
68
52
|
default:
|
|
69
53
|
break;
|
|
@@ -71,12 +55,6 @@ if ( args.length >= 3 ) {
|
|
|
71
55
|
}
|
|
72
56
|
}
|
|
73
57
|
|
|
74
|
-
if (!ignoreShellPkgPathCheck && !fs.existsSync(path.join(pkgFolder, `../../${ shellPkgPath }/package.json`))) {
|
|
75
|
-
console.log('');
|
|
76
|
-
console.log('@rancher/shell not found in node_modules! Please do "yarn install" and make sure you run this command from the base folder of your app');
|
|
77
|
-
process.exit(1);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
58
|
const isNodeModulesShell = !fs.existsSync(path.join(folder, 'shell'));
|
|
81
59
|
|
|
82
60
|
if (!isNodeModulesShell) {
|
|
@@ -98,13 +76,6 @@ const pkg = JSON.parse(rawdata);
|
|
|
98
76
|
pkg.name = name;
|
|
99
77
|
pkg.description = `${ name } plugin`;
|
|
100
78
|
|
|
101
|
-
Object.keys(targets).forEach((target) => {
|
|
102
|
-
if (!pkg.scripts[target]) {
|
|
103
|
-
pkg.scripts[target] = targets[target];
|
|
104
|
-
console.log(` Adding script '${ target }' to package.json`);
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
|
|
108
79
|
// Add annotation for the latest Rancher version by default
|
|
109
80
|
function fetchLatestVersion() {
|
|
110
81
|
console.log(' Fetching latest Rancher Version');
|
|
@@ -169,10 +140,6 @@ function fetchLatestVersion() {
|
|
|
169
140
|
fetchLatestVersion();
|
|
170
141
|
writePackageJson();
|
|
171
142
|
|
|
172
|
-
// Add dependencies
|
|
173
|
-
// pkg.dependencies['@rancher/shell'] = '^0.6.2';
|
|
174
|
-
// pkg.dependencies['core-js'] = '3.18.3';
|
|
175
|
-
|
|
176
143
|
function writePackageJson() {
|
|
177
144
|
fs.writeFileSync(path.join(pkgFolder, 'package.json'), JSON.stringify(pkg, null, 2));
|
|
178
145
|
}
|
|
@@ -189,31 +156,6 @@ if (addTypeFolders) {
|
|
|
189
156
|
});
|
|
190
157
|
}
|
|
191
158
|
|
|
192
|
-
// Add workflow folder if needed
|
|
193
|
-
if (addWorkflowFolder) {
|
|
194
|
-
const workflowDir = path.join(folder, '.github/workflows');
|
|
195
|
-
|
|
196
|
-
if (!fs.existsSync(workflowDir)) {
|
|
197
|
-
fs.mkdirSync(workflowDir, { recursive: true });
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const files = [
|
|
201
|
-
'build-extension-catalog.yml',
|
|
202
|
-
'build-extension-charts.yml'
|
|
203
|
-
];
|
|
204
|
-
|
|
205
|
-
files.forEach((fileName) => {
|
|
206
|
-
const file = path.join(workflowDir, fileName);
|
|
207
|
-
|
|
208
|
-
if (!fs.existsSync(file)) {
|
|
209
|
-
const src = path.join(__dirname, 'files/.github/workflows', fileName);
|
|
210
|
-
|
|
211
|
-
console.log(` Adding file ${ fileName } to root workflows`);
|
|
212
|
-
fs.copySync(src, file);
|
|
213
|
-
}
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
|
|
217
159
|
// Copy base files
|
|
218
160
|
files.forEach((file) => {
|
|
219
161
|
const src = path.join(__dirname, 'files', file);
|
|
@@ -225,13 +167,6 @@ files.forEach((file) => {
|
|
|
225
167
|
}
|
|
226
168
|
});
|
|
227
169
|
|
|
228
|
-
// require("child_process").spawn('yarn', ['install'], {
|
|
229
|
-
// cwd: process.cwd(),
|
|
230
|
-
// stdio: "inherit"
|
|
231
|
-
// });
|
|
232
|
-
|
|
233
|
-
// Update tsconfig
|
|
234
|
-
|
|
235
170
|
const topLevelRawdata = fs.readFileSync(path.join(folder, 'package.json'));
|
|
236
171
|
const topLevelPkg = JSON.parse(topLevelRawdata);
|
|
237
172
|
let updated = false;
|
|
@@ -276,3 +211,5 @@ function updateArray(data) {
|
|
|
276
211
|
|
|
277
212
|
return updated;
|
|
278
213
|
}
|
|
214
|
+
|
|
215
|
+
/* eslint-enable no-console */
|
package/pkg/package.json
CHANGED
package/update/init
CHANGED
|
@@ -4,17 +4,18 @@ const path = require('path');
|
|
|
4
4
|
const fs = require('fs-extra');
|
|
5
5
|
const { spawnSync } = require('child_process');
|
|
6
6
|
|
|
7
|
-
const scriptFolder = __dirname;
|
|
7
|
+
const scriptFolder = path.resolve(__dirname, '..');
|
|
8
8
|
const dest = path.resolve('.');
|
|
9
9
|
|
|
10
10
|
// Remove first two args
|
|
11
|
-
|
|
11
|
+
const args = process.argv;
|
|
12
|
+
|
|
12
13
|
args.splice(0, 2);
|
|
13
14
|
|
|
14
|
-
const res = spawnSync(
|
|
15
|
-
cwd:
|
|
15
|
+
const res = spawnSync(path.join(__dirname, 'upgrade'), args, {
|
|
16
|
+
cwd: dest,
|
|
16
17
|
shell: false,
|
|
17
|
-
stdio: [
|
|
18
|
+
stdio: ['ignore', process.stdout, process.stderr],
|
|
18
19
|
});
|
|
19
20
|
|
|
20
21
|
if (res.status !== 0) {
|
|
@@ -34,9 +35,13 @@ rawdata = fs.readFileSync(path.join(scriptFolder, 'package.json'));
|
|
|
34
35
|
const upgradePackage = JSON.parse(rawdata);
|
|
35
36
|
|
|
36
37
|
// Update dependency versions to match the latest from the creator
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
if ( latestPackage.dependencies ) {
|
|
39
|
+
Object.keys(latestPackage.dependencies).forEach((key) => {
|
|
40
|
+
appPackage.dependencies[key] = latestPackage.dependencies[key];
|
|
41
|
+
});
|
|
42
|
+
} else {
|
|
43
|
+
console.warn('No dependencies found in latestPackage.'); // eslint-disable-line no-console
|
|
44
|
+
}
|
|
40
45
|
|
|
41
46
|
// Add in the webpack resolution
|
|
42
47
|
appPackage.resolutions = appPackage.resolutions || {};
|
|
@@ -47,10 +52,10 @@ const shellVersion = upgradePackage.version;
|
|
|
47
52
|
|
|
48
53
|
appPackage.dependencies['@rancher/shell'] = shellVersion;
|
|
49
54
|
|
|
50
|
-
fs.writeFileSync(path.join(dest, 'package.json'), JSON.stringify(appPackage, null, 2)
|
|
55
|
+
fs.writeFileSync(path.join(dest, 'package.json'), `${ JSON.stringify(appPackage, null, 2) }\n`);
|
|
51
56
|
|
|
52
57
|
spawnSync(`yarn`, ['install'], {
|
|
53
|
-
cwd:
|
|
58
|
+
cwd: dest,
|
|
54
59
|
shell: false,
|
|
55
|
-
stdio: [
|
|
60
|
+
stdio: ['ignore', process.stdout, process.stderr],
|
|
56
61
|
});
|
package/update/package.json
CHANGED
package/update/upgrade
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env sh
|
|
2
2
|
|
|
3
|
-
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
|
3
|
+
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )"/.. &> /dev/null && pwd )
|
|
4
4
|
|
|
5
5
|
echo "Upgrading Rancher Shell"
|
|
6
6
|
|
|
@@ -19,13 +19,13 @@ fi
|
|
|
19
19
|
# Check for a clean git repository
|
|
20
20
|
if [ ! -d ".git" ] && [ "${FORCE}" == "false" ]; then
|
|
21
21
|
echo "Not runnning in a git repository. Re-run with -f to ignore this check"
|
|
22
|
-
echo "Note: This action will update
|
|
22
|
+
echo "Note: This action will update your files - running in a git repository will ensure you have visibility over changes made"
|
|
23
23
|
exit 1
|
|
24
24
|
fi
|
|
25
25
|
|
|
26
26
|
if [[ $(git diff --stat) != '' ]] && [ "${FORCE}" == "false" ]; then
|
|
27
27
|
echo "Git repository is not clean. Re-run with -f to ignore this check"
|
|
28
|
-
echo "Note: This action will update
|
|
28
|
+
echo "Note: This action will update your files - running in a clean git repository will ensure you have visibility over changes made"
|
|
29
29
|
exit 1
|
|
30
30
|
fi
|
|
31
31
|
|
|
@@ -42,7 +42,7 @@ if [ "${HAS_SHELL}" != "1" ]; then
|
|
|
42
42
|
fi
|
|
43
43
|
|
|
44
44
|
# Copy files for the top-level folder (from the app creator)
|
|
45
|
-
rsync
|
|
45
|
+
rsync ${SCRIPT_DIR}/app/files/* .
|
|
46
46
|
|
|
47
47
|
# Go through each folder in the pkg folder and update their files
|
|
48
48
|
for pkg in ./pkg/*
|