generator-easy-ui5 3.5.1 → 3.6.0
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/CHANGELOG.md +4 -3
- package/README.md +14 -5
- package/generators/app/index.js +331 -199
- package/package.json +25 -22
- package/plugins/generator-ui5-project.zip +0 -0
- package/generators/app/postinstall.js +0 -143
package/CHANGELOG.md
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
## [3.5.
|
|
1
|
+
## [3.5.2](https://github.com/SAP/generator-easy-ui5/compare/v3.5.1...v3.5.2) (2023-06-09)
|
|
2
2
|
|
|
3
3
|
### Bug Fixes
|
|
4
4
|
|
|
5
|
-
-
|
|
5
|
+
- sort subgen list, remove threshold, fix permission issues ([#123](https://github.com/SAP/generator-easy-ui5/issues/123)) ([c5dd321](https://github.com/SAP/generator-easy-ui5/commit/c5dd3218a26870a61722a9675a81831cc8af50e5)), closes [#122](https://github.com/SAP/generator-easy-ui5/issues/122) [#118](https://github.com/SAP/generator-easy-ui5/issues/118) [#117](https://github.com/SAP/generator-easy-ui5/issues/117) [#111](https://github.com/SAP/generator-easy-ui5/issues/111)
|
|
6
6
|
|
|
7
|
-
## [3.5.
|
|
7
|
+
## [3.5.1](https://github.com/SAP/generator-easy-ui5/compare/v3.2.0...v3.5.1) (2022-09-10)
|
|
8
8
|
|
|
9
9
|
### Bug Fixes
|
|
10
10
|
|
|
11
|
+
- enable for Yeoman UI usage ([03c2e38](https://github.com/SAP/generator-easy-ui5/commit/03c2e38af4eebe108d6076710b74d8aaf7c31d8d))
|
|
11
12
|
- **postinstall:** allow usage of NPM config for ghAuthToken to avoid rate limit ([#104](https://github.com/SAP/generator-easy-ui5/issues/104)) ([371d7fb](https://github.com/SAP/generator-easy-ui5/commit/371d7fbc82b8a59cef896197b99239b505b3cd90)), closes [#100](https://github.com/SAP/generator-easy-ui5/issues/100)
|
|
12
13
|
- **postinstall:** avoid non-existing node_modules ([#98](https://github.com/SAP/generator-easy-ui5/issues/98)) ([f93c7c9](https://github.com/SAP/generator-easy-ui5/commit/f93c7c99b9e5df7af801a085afe72be85e462007))
|
|
13
14
|
- usage of proper gh org for logging and download ([#94](https://github.com/SAP/generator-easy-ui5/issues/94)) ([a88d4db](https://github.com/SAP/generator-easy-ui5/commit/a88d4dbb0a1f5ed3cf60f7ed0297c651222a83fb))
|
package/README.md
CHANGED
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
## Description
|
|
10
10
|
|
|
11
|
-
Easy-ui5 💙 is a [Yeoman](http://yeoman.io/) generator which enables you to create simple [SAPUI5](https://
|
|
11
|
+
Easy UI5 (`easy-ui5`) 💙 is a [Yeoman](http://yeoman.io/) generator which enables you to create simple [SAPUI5](https://ui5.sap.com)/[OpenUI5](https://sdk.openui5.org)-based web-apps and other UI5-related projects within seconds.
|
|
12
12
|
|
|
13
13
|
This generator has been created to simplify the creation of your UI5 prototypes. Now you can scaffold simple UI5 projects from the shell/terminal of your choice. The current best practices (such as [async](https://blogs.sap.com/2018/12/18/ui5ers-buzz-41-best-practices-for-async-loading-in-ui5/)) are already baked into our templates so you don't have to worry about the definition of the metadata files.
|
|
14
14
|
|
|
15
|
-
The purpose of
|
|
15
|
+
The purpose of the `project` subgenerator is to guide you on your first steps with [SAPUI5](https://sapui5.hana.ondemand.com/) and [SAP BTP](https://www.sap.com/products/business-technology-platform.html) deployments. Once you are familiar with those technologies, you might want to tweak the projects to adapt them for productive use-cases (such as continuous deployment pipelines and full i18n).
|
|
16
16
|
|
|
17
|
-
> :warning: Starting with
|
|
17
|
+
> :warning: Starting with Easy UI5 v3, all templates will be outsource to repositories in the [UI5 Community](https://github.com/ui5-community/). This project is from now on a shell that will offer all generators hosted on that GitHub org. Easy UI5 will download and install these repositories when needed.
|
|
18
18
|
>
|
|
19
|
-
> By default, it will download the repository [generator-ui5-project](https://github.com/ui5-community/generator-ui5-project/) which contains the templates that were previously integrated in
|
|
19
|
+
> By default, it will download the repository [generator-ui5-project](https://github.com/ui5-community/generator-ui5-project/) which contains the templates that were previously integrated in Easy UI5 < 3.
|
|
20
20
|
|
|
21
21
|
## Requirements
|
|
22
22
|
|
|
@@ -63,7 +63,8 @@ During the prompting phase, the generator will ask on which target platform your
|
|
|
63
63
|
## More generators
|
|
64
64
|
|
|
65
65
|
And this is just the start!
|
|
66
|
-
|
|
66
|
+
|
|
67
|
+
We made Easy UI5 extensible, so that the entire [UI5 Community](https://github.com/ui5-community/) can build additional plugins to scaffold any UI5-related development activity.
|
|
67
68
|
|
|
68
69
|
By default, this generator comes with the [project-creation-plugin](https://github.com/ui5-community/generator-ui5-project) but there are many others as well:
|
|
69
70
|
|
|
@@ -98,6 +99,14 @@ Run the following command to see all subgenerators of a given plugin
|
|
|
98
99
|
yo easy-ui5 [project|library] <sub-generator-id>
|
|
99
100
|
```
|
|
100
101
|
|
|
102
|
+
## Proxy settings
|
|
103
|
+
|
|
104
|
+
If you are running Easy UI5 behind a coporate proxy, just use the default proxy environment variables for Node.js to configure your corporate proxy:
|
|
105
|
+
|
|
106
|
+
- `HTTP_PROXY`: Specify the value to use as the HTTP proxy for all connections, e.g., `HTTP_PROXY="http://proxy.mycompany.com:8080/"`.
|
|
107
|
+
- `HTTPS_PROXY`: Specify the value to use as the HTTPS proxy for all connections, e.g., `HTTPS_PROXY="https://proxy.mycompany.com:8080/"`.
|
|
108
|
+
- `NO_PROXY`: Define the hosts that should bypass the proxy, e.g., `NO_PROXY="localhost,.mycompany.com,192.168.6.254:80"`.
|
|
109
|
+
|
|
101
110
|
## How to obtain support
|
|
102
111
|
|
|
103
112
|
Please use the GitHub bug tracking system to post questions, bug reports or to create pull requests.
|
package/generators/app/index.js
CHANGED
|
@@ -1,20 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const {
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
import Generator from "yeoman-generator";
|
|
2
|
+
|
|
3
|
+
import path from "path";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import os from "os";
|
|
6
|
+
import url from "url";
|
|
7
|
+
|
|
8
|
+
import { glob } from "glob";
|
|
9
|
+
import chalk from "chalk";
|
|
10
|
+
import yosay from "yosay";
|
|
11
|
+
import libnpmconfig from "libnpmconfig";
|
|
12
|
+
import yarnOrNpm from "yarn-or-npm";
|
|
13
|
+
const { hasYarn } = yarnOrNpm;
|
|
14
|
+
import AdmZip from "adm-zip";
|
|
15
|
+
import { request } from "@octokit/request";
|
|
16
|
+
import { Octokit } from "@octokit/rest";
|
|
17
|
+
import { throttling } from "@octokit/plugin-throttling";
|
|
16
18
|
const MyOctokit = Octokit.plugin(throttling);
|
|
17
|
-
|
|
19
|
+
import spawn from "cross-spawn";
|
|
20
|
+
|
|
21
|
+
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
|
|
22
|
+
|
|
23
|
+
// apply proxy settings to GLOBAL_AGENT to support the proxy configuration
|
|
24
|
+
// provided via the standard Node.js environment varibales (used for fetch API)
|
|
25
|
+
let HTTP_PROXY, HTTPS_PROXY, NO_PROXY;
|
|
26
|
+
if (global?.GLOBAL_AGENT) {
|
|
27
|
+
HTTP_PROXY = global.GLOBAL_AGENT.HTTP_PROXY = process.env.HTTP_PROXY || process.env.http_proxy;
|
|
28
|
+
HTTPS_PROXY = global.GLOBAL_AGENT.HTTPS_PROXY = process.env.HTTPS_PROXY || process.env.https_proxy;
|
|
29
|
+
NO_PROXY = global.GLOBAL_AGENT.NO_PROXY = process.env.NO_PROXY || process.env.no_proxy;
|
|
30
|
+
}
|
|
18
31
|
|
|
19
32
|
// helper to retrieve config entries from npm
|
|
20
33
|
// --> npm config set easy-ui5_addGhOrg XYZ
|
|
@@ -22,13 +35,31 @@ const NPM_CONFIG_PREFIX = "easy-ui5_";
|
|
|
22
35
|
let npmConfig;
|
|
23
36
|
const getNPMConfig = (configName) => {
|
|
24
37
|
if (!npmConfig) {
|
|
25
|
-
npmConfig =
|
|
38
|
+
npmConfig = libnpmconfig.read();
|
|
26
39
|
}
|
|
27
40
|
return npmConfig && npmConfig[`${NPM_CONFIG_PREFIX}${configName}`];
|
|
28
41
|
};
|
|
29
42
|
|
|
30
43
|
// the command line options of the generator
|
|
31
44
|
const generatorOptions = {
|
|
45
|
+
pluginsHome: {
|
|
46
|
+
type: String,
|
|
47
|
+
description: "Home directory of the plugin generators",
|
|
48
|
+
default: path.join(os.homedir(), ".npm", "_generator-easy-ui5", "plugin-generators"),
|
|
49
|
+
hide: true, // shouldn't be needed
|
|
50
|
+
npmConfig: true,
|
|
51
|
+
},
|
|
52
|
+
plugins: {
|
|
53
|
+
type: Boolean,
|
|
54
|
+
alias: "p",
|
|
55
|
+
description: "List detailed information about installed plugin generators",
|
|
56
|
+
},
|
|
57
|
+
ghBaseUrl: {
|
|
58
|
+
type: String,
|
|
59
|
+
description: "Base URL for the Octokit API (defaults to https://api.github.com if undefined)",
|
|
60
|
+
hide: true, // shouldn't be needed
|
|
61
|
+
npmConfig: true,
|
|
62
|
+
},
|
|
32
63
|
ghAuthToken: {
|
|
33
64
|
type: String,
|
|
34
65
|
description: "GitHub authToken to optionally access private generator repositories",
|
|
@@ -40,12 +71,23 @@ const generatorOptions = {
|
|
|
40
71
|
default: "ui5-community",
|
|
41
72
|
hide: true, // we don't want to recommend to use this option
|
|
42
73
|
},
|
|
74
|
+
ghThreshold: {
|
|
75
|
+
type: Number,
|
|
76
|
+
default: 100,
|
|
77
|
+
hide: true, // shouldn't be needed
|
|
78
|
+
},
|
|
43
79
|
subGeneratorPrefix: {
|
|
44
80
|
type: String,
|
|
45
81
|
description: "Prefix used for the lookup of the available generators",
|
|
46
82
|
default: "generator-ui5-",
|
|
47
83
|
hide: true, // we don't want to recommend to use this option
|
|
48
84
|
},
|
|
85
|
+
addGhBaseUrl: {
|
|
86
|
+
type: String,
|
|
87
|
+
description: "Base URL for the Octokit API for the additional generators (defaults to https://api.github.com if undefined)",
|
|
88
|
+
hide: true, // shouldn't be needed
|
|
89
|
+
npmConfig: true,
|
|
90
|
+
},
|
|
49
91
|
addGhOrg: {
|
|
50
92
|
type: String,
|
|
51
93
|
description: "GitHub organization to lookup for additional available generators",
|
|
@@ -59,6 +101,11 @@ const generatorOptions = {
|
|
|
59
101
|
hide: true, // we don't want to recommend to use this option
|
|
60
102
|
npmConfig: true,
|
|
61
103
|
},
|
|
104
|
+
embed: {
|
|
105
|
+
type: Boolean,
|
|
106
|
+
description: "Embeds the selected plugin generator",
|
|
107
|
+
hide: true, // shouldn't be needed
|
|
108
|
+
},
|
|
62
109
|
list: {
|
|
63
110
|
type: Boolean,
|
|
64
111
|
description: "List the available subcommands of the generator",
|
|
@@ -80,14 +127,9 @@ const generatorOptions = {
|
|
|
80
127
|
type: Boolean,
|
|
81
128
|
description: "Enable detailed logging",
|
|
82
129
|
},
|
|
83
|
-
plugins: {
|
|
84
|
-
type: Boolean,
|
|
85
|
-
alias: "p",
|
|
86
|
-
description: "Get detailed version information",
|
|
87
|
-
},
|
|
88
130
|
next: {
|
|
89
131
|
type: Boolean,
|
|
90
|
-
description: "Preview the next mode to consume
|
|
132
|
+
description: "Preview the next mode to consume subgenerators from bestofui5.org",
|
|
91
133
|
},
|
|
92
134
|
};
|
|
93
135
|
|
|
@@ -95,16 +137,16 @@ const generatorArgs = {
|
|
|
95
137
|
generator: {
|
|
96
138
|
type: String,
|
|
97
139
|
required: false,
|
|
98
|
-
description:
|
|
140
|
+
description: `Name of the generator to invoke (without the ${chalk.yellow("generator-ui5-")} prefix)`,
|
|
99
141
|
},
|
|
100
142
|
subcommand: {
|
|
101
143
|
type: String,
|
|
102
144
|
required: false,
|
|
103
|
-
description:
|
|
145
|
+
description: `Name of the subcommand to invoke (without the ${chalk.yellow("generator:")} prefix)`,
|
|
104
146
|
},
|
|
105
147
|
};
|
|
106
148
|
|
|
107
|
-
|
|
149
|
+
export default class extends Generator {
|
|
108
150
|
constructor(args, opts) {
|
|
109
151
|
super(args, opts, {
|
|
110
152
|
// disable the Yeoman 5 package-manager logic (auto install)!
|
|
@@ -151,31 +193,80 @@ module.exports = class extends Generator {
|
|
|
151
193
|
}
|
|
152
194
|
}
|
|
153
195
|
|
|
196
|
+
async _npmInstall(dir) {
|
|
197
|
+
return new Promise(
|
|
198
|
+
function (resolve, reject) {
|
|
199
|
+
spawn(hasYarn() ? "yarn" : "npm", ["install", "--no-progress", "--ignore-engines"], {
|
|
200
|
+
stdio: this.config.verbose ? "inherit" : "ignore",
|
|
201
|
+
cwd: dir,
|
|
202
|
+
env: {
|
|
203
|
+
...process.env,
|
|
204
|
+
NO_UPDATE_NOTIFIER: true,
|
|
205
|
+
},
|
|
206
|
+
})
|
|
207
|
+
.on("exit", function (code) {
|
|
208
|
+
resolve(code);
|
|
209
|
+
})
|
|
210
|
+
.on("error", function (err) {
|
|
211
|
+
reject(err);
|
|
212
|
+
});
|
|
213
|
+
}.bind(this)
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
_unzip(pathOrBuffer, targetPath, zipInternalPath /* used for plugin generators from GitHub (e.g. TS tutorial) */) {
|
|
218
|
+
const zip = new AdmZip(pathOrBuffer);
|
|
219
|
+
const zipEntries = zip.getEntries();
|
|
220
|
+
zipEntries.forEach((entry) => {
|
|
221
|
+
const match = !entry.isDirectory && entry.entryName.match(/[^\/]+(\/.+)/);
|
|
222
|
+
let entryPath;
|
|
223
|
+
if (zipInternalPath && match && match[1].startsWith(zipInternalPath)) {
|
|
224
|
+
entryPath = path.dirname(match[1].substring(zipInternalPath.length));
|
|
225
|
+
} else if (!zipInternalPath && match) {
|
|
226
|
+
entryPath = path.dirname(match[1]);
|
|
227
|
+
}
|
|
228
|
+
if (entryPath) {
|
|
229
|
+
zip.extractEntryTo(entry, path.join(targetPath, entryPath), false, true);
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
determineAppname() {
|
|
235
|
+
return "Easy UI5";
|
|
236
|
+
}
|
|
237
|
+
|
|
154
238
|
async prompting() {
|
|
155
239
|
const home = path.join(__dirname, "..", "..");
|
|
156
|
-
const pkgJson =
|
|
240
|
+
const pkgJson = JSON.parse(fs.readFileSync(path.join(home, "package.json"), "utf8"));
|
|
157
241
|
|
|
158
242
|
// Have Yeoman greet the user.
|
|
159
243
|
if (!this.options.embedded) {
|
|
160
244
|
this.log(yosay(`Welcome to the ${chalk.red("easy-ui5")} ${chalk.yellow(pkgJson.version)} generator!`));
|
|
161
245
|
}
|
|
162
246
|
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
let pluginsHome =
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
console.
|
|
173
|
-
}
|
|
174
|
-
|
|
247
|
+
// by default we install the easy-ui5 plugin generators into the following folder:
|
|
248
|
+
// %user_dir%/.npm/_generator-easy-ui5/plugin-generators
|
|
249
|
+
let pluginsHome = this.options.pluginsHome;
|
|
250
|
+
if (this.options.verbose) {
|
|
251
|
+
console.info(" Context:");
|
|
252
|
+
console.info(` - sourceRoot = ${chalk.green(this.sourceRoot())}`);
|
|
253
|
+
console.info(` - destinationRoot = ${chalk.green(this.destinationRoot())}`);
|
|
254
|
+
console.info(" Options:");
|
|
255
|
+
Object.keys(generatorOptions).forEach((option) => {
|
|
256
|
+
console.info(` - ${option} = ${chalk.green(this.options[option])}`);
|
|
257
|
+
});
|
|
258
|
+
console.info(" Proxy:");
|
|
259
|
+
console.info(` - HTTP_PROXY = ${chalk.green(HTTP_PROXY)}`);
|
|
260
|
+
console.info(` - HTTPS_PROXY = ${chalk.green(HTTPS_PROXY)}`);
|
|
261
|
+
console.info(` - NO_PROXY = ${chalk.green(NO_PROXY)}`);
|
|
175
262
|
}
|
|
263
|
+
fs.mkdirSync(pluginsHome, { recursive: true });
|
|
176
264
|
|
|
177
265
|
// log the plugins and configuration
|
|
178
266
|
if (this.options.plugins) {
|
|
267
|
+
const { createRequire } = await import("node:module");
|
|
268
|
+
const require = createRequire(import.meta.url);
|
|
269
|
+
|
|
179
270
|
const yeoman = require("yeoman-environment/package.json");
|
|
180
271
|
|
|
181
272
|
const components = {
|
|
@@ -206,9 +297,11 @@ module.exports = class extends Generator {
|
|
|
206
297
|
if (this.options.offline) {
|
|
207
298
|
this.log(`Running in ${chalk.yellow("offline")} mode!`);
|
|
208
299
|
} else {
|
|
209
|
-
|
|
300
|
+
// define the options for the Octokit API
|
|
301
|
+
const octokitOptions = {
|
|
210
302
|
userAgent: `${this.rootGeneratorName()}:${this.rootGeneratorVersion()}`,
|
|
211
303
|
auth: this.options.ghAuthToken,
|
|
304
|
+
baseUrl: this.options.ghBaseUrl,
|
|
212
305
|
throttle: {
|
|
213
306
|
onRateLimit: (retryAfter, options) => {
|
|
214
307
|
this.log(`${chalk.yellow("Hit the GitHub API limit!")} Request quota exhausted for this request.`);
|
|
@@ -220,12 +313,14 @@ module.exports = class extends Generator {
|
|
|
220
313
|
return true;
|
|
221
314
|
}
|
|
222
315
|
},
|
|
223
|
-
|
|
316
|
+
onSecondaryRateLimit: () => {
|
|
224
317
|
// does not retry, only logs a warning
|
|
225
318
|
this.log(`${chalk.red("Hit the GitHub API limit again!")} Please supply an auth token with the \`--ghAuthToken\` option. For more details, run \`yo easy-ui5 --help\` `);
|
|
226
319
|
},
|
|
227
320
|
},
|
|
228
|
-
}
|
|
321
|
+
};
|
|
322
|
+
// create the octokit instance
|
|
323
|
+
octokit = new MyOctokit(octokitOptions);
|
|
229
324
|
}
|
|
230
325
|
|
|
231
326
|
// helper for filtering repos with corresponding subGenerator prefix
|
|
@@ -246,9 +341,12 @@ module.exports = class extends Generator {
|
|
|
246
341
|
};
|
|
247
342
|
|
|
248
343
|
// helper to retrieve the available repositories for a GH org
|
|
249
|
-
const listGeneratorsForOrg = async (ghOrg, subGeneratorPrefix) => {
|
|
344
|
+
const listGeneratorsForOrg = async (ghOrg, subGeneratorPrefix, threshold) => {
|
|
250
345
|
const response = await octokit.repos.listForOrg({
|
|
251
346
|
org: ghOrg,
|
|
347
|
+
sort: "name",
|
|
348
|
+
// eslint-disable-next-line camelcase
|
|
349
|
+
per_page: threshold,
|
|
252
350
|
});
|
|
253
351
|
return filterReposWithSubGeneratorPrefix(response?.data, subGeneratorPrefix);
|
|
254
352
|
};
|
|
@@ -257,6 +355,9 @@ module.exports = class extends Generator {
|
|
|
257
355
|
const listGeneratorsForUser = async (ghUser, subGeneratorPrefix) => {
|
|
258
356
|
const response = await octokit.repos.listForUser({
|
|
259
357
|
username: ghUser,
|
|
358
|
+
sort: "name",
|
|
359
|
+
// eslint-disable-next-line camelcase
|
|
360
|
+
per_page: threshold,
|
|
260
361
|
});
|
|
261
362
|
return filterReposWithSubGeneratorPrefix(response?.data, subGeneratorPrefix);
|
|
262
363
|
};
|
|
@@ -276,12 +377,14 @@ module.exports = class extends Generator {
|
|
|
276
377
|
if (matchGenerator) {
|
|
277
378
|
// derive and path the generator information from command line
|
|
278
379
|
const [owner, repo, dir = "/generator", branch] = matchGenerator.slice(1);
|
|
380
|
+
// the plugin path is derived from the owner, repo, dir and branch
|
|
381
|
+
const pluginPath = `_/${owner}/${repo}${dir.replace(/[\/\\]/g, "_")}${branch ? `#${branch.replace(/[\/\\]/g, "_")}` : ""}`;
|
|
279
382
|
generator = {
|
|
280
383
|
org: owner,
|
|
281
384
|
name: repo,
|
|
282
385
|
branch,
|
|
283
386
|
dir,
|
|
284
|
-
pluginPath
|
|
387
|
+
pluginPath,
|
|
285
388
|
};
|
|
286
389
|
// log which generator is being used!
|
|
287
390
|
if (this.options.verbose) {
|
|
@@ -293,6 +396,29 @@ module.exports = class extends Generator {
|
|
|
293
396
|
// retrieve the available repositories (if no generator is specified specified directly)
|
|
294
397
|
let availGenerators;
|
|
295
398
|
if (!generator) {
|
|
399
|
+
// lookup the non-installed embedded generator(s)
|
|
400
|
+
const generatorsToBeInstalled = glob
|
|
401
|
+
.sync(`${path.join(__dirname, "../../plugins")}/generator-*.zip`)
|
|
402
|
+
.map((file) => {
|
|
403
|
+
const generatorName = path.basename(file, ".zip");
|
|
404
|
+
const generatorPath = path.join(pluginsHome, generatorName);
|
|
405
|
+
return {
|
|
406
|
+
file,
|
|
407
|
+
generatorName,
|
|
408
|
+
generatorPath,
|
|
409
|
+
};
|
|
410
|
+
})
|
|
411
|
+
.filter(({ generatorPath }) => !fs.existsSync(generatorPath));
|
|
412
|
+
// install (unzip) the missing embedded generator(s)
|
|
413
|
+
if (generatorsToBeInstalled.length > 0) {
|
|
414
|
+
this._showBusy(" Installing embedded subgenerators...");
|
|
415
|
+
generatorsToBeInstalled.map(({ file, generatorName, generatorPath }) => {
|
|
416
|
+
this._showBusy(` Installing embedded subgenerator ${chalk.yellow(generatorName)}...`);
|
|
417
|
+
this._unzip(file, generatorPath);
|
|
418
|
+
});
|
|
419
|
+
this._clearBusy(true);
|
|
420
|
+
}
|
|
421
|
+
// offline mode means local generators only versus only mode
|
|
296
422
|
if (this.options.offline) {
|
|
297
423
|
availGenerators = glob.sync(`${pluginsHome}/generator-*/package.json`).map((plugin) => {
|
|
298
424
|
const match = plugin.match(/.*\/(generator-(.+))\/package\.json/);
|
|
@@ -304,6 +430,8 @@ module.exports = class extends Generator {
|
|
|
304
430
|
};
|
|
305
431
|
});
|
|
306
432
|
} else {
|
|
433
|
+
// either lookup the generators from bestofui5.org (next option)
|
|
434
|
+
// or fetch it from the ui5-community gh organization
|
|
307
435
|
if (this.options.next) {
|
|
308
436
|
// check bestofui5.org for generators
|
|
309
437
|
try {
|
|
@@ -334,7 +462,7 @@ module.exports = class extends Generator {
|
|
|
334
462
|
} else {
|
|
335
463
|
// check the main GH org for generators
|
|
336
464
|
try {
|
|
337
|
-
availGenerators = await listGeneratorsForOrg(this.options.ghOrg, this.options.subGeneratorPrefix);
|
|
465
|
+
availGenerators = await listGeneratorsForOrg(this.options.ghOrg, this.options.subGeneratorPrefix, this.options.ghThreshold);
|
|
338
466
|
} catch (e) {
|
|
339
467
|
console.error(`Failed to connect to GitHub to retrieve all available generators for "${this.options.ghOrg}" organization! Run with --verbose for details!`);
|
|
340
468
|
if (this.options.verbose) {
|
|
@@ -346,14 +474,14 @@ module.exports = class extends Generator {
|
|
|
346
474
|
// check the additional GH org for generators with a different prefix
|
|
347
475
|
try {
|
|
348
476
|
if (this.options.addGhOrg && this.options.addSubGeneratorPrefix) {
|
|
349
|
-
availGenerators = availGenerators.concat(await listGeneratorsForOrg(this.options.addGhOrg, this.options.addSubGeneratorPrefix));
|
|
477
|
+
availGenerators = availGenerators.concat(await listGeneratorsForOrg(this.options.addGhOrg, this.options.addSubGeneratorPrefix, this.options.ghThreshold));
|
|
350
478
|
}
|
|
351
479
|
} catch (e) {
|
|
352
480
|
if (this.options.verbose) {
|
|
353
481
|
this.log(`Failed to connect to GitHub retrieve additional generators for "${this.options.addGhOrg}" organization! Try to retrieve for user...`);
|
|
354
482
|
}
|
|
355
483
|
try {
|
|
356
|
-
availGenerators = availGenerators.concat(await listGeneratorsForUser(this.options.addGhOrg, this.options.addSubGeneratorPrefix));
|
|
484
|
+
availGenerators = availGenerators.concat(await listGeneratorsForUser(this.options.addGhOrg, this.options.addSubGeneratorPrefix, this.options.ghThreshold));
|
|
357
485
|
} catch (e1) {
|
|
358
486
|
console.error(`Failed to connect to GitHub to retrieve additional generators for organization or user "${this.options.addGhOrg}"! Run with --verbose for details!`);
|
|
359
487
|
if (this.options.verbose) {
|
|
@@ -423,16 +551,16 @@ module.exports = class extends Generator {
|
|
|
423
551
|
branch: generator.branch,
|
|
424
552
|
});
|
|
425
553
|
commitSHA = reqBranch.data.commit.sha;
|
|
426
|
-
} catch (
|
|
554
|
+
} catch (ex) {
|
|
427
555
|
console.error(chalk.red(`Failed to retrieve the branch "${generator.branch}" for repository "${generator.name}" for "${generator.org}" organization! Run with --verbose for details!`));
|
|
428
556
|
if (this.options.verbose) {
|
|
429
|
-
console.error(chalk.red(
|
|
557
|
+
console.error(chalk.red(ex.message));
|
|
430
558
|
}
|
|
431
559
|
return;
|
|
432
560
|
}
|
|
433
561
|
|
|
434
562
|
if (this.options.verbose) {
|
|
435
|
-
this.log(`Using commit ${commitSHA} from @${generator.org}/${generator.name}#${generator.branch}
|
|
563
|
+
this.log(`Using commit ${commitSHA} from @${generator.org}/${generator.name}#${generator.branch}!`);
|
|
436
564
|
}
|
|
437
565
|
const shaMarker = path.join(generatorPath, `.${commitSHA}`);
|
|
438
566
|
|
|
@@ -440,189 +568,193 @@ module.exports = class extends Generator {
|
|
|
440
568
|
// check if the SHA marker exists to know whether the generator is up-to-date or not
|
|
441
569
|
if (this.options.forceUpdate || !fs.existsSync(shaMarker)) {
|
|
442
570
|
if (this.options.verbose) {
|
|
443
|
-
this.log(`Generator
|
|
571
|
+
this.log(`Generator ${chalk.yellow(generator.name)} in "${generatorPath}" is outdated!`);
|
|
444
572
|
}
|
|
445
573
|
// remove if the SHA marker doesn't exist => outdated!
|
|
446
|
-
this._showBusy(`
|
|
574
|
+
this._showBusy(` Deleting subgenerator ${chalk.yellow(generator.name)}...`);
|
|
447
575
|
await rm(generatorPath, { recursive: true });
|
|
448
576
|
}
|
|
449
577
|
}
|
|
450
578
|
|
|
451
579
|
// re-fetch the generator and extract into local plugin folder
|
|
452
580
|
if (!fs.existsSync(generatorPath)) {
|
|
581
|
+
// unzip the archive
|
|
453
582
|
if (this.options.verbose) {
|
|
454
583
|
this.log(`Extracting ZIP to "${generatorPath}"...`);
|
|
455
584
|
}
|
|
456
|
-
this._showBusy(` Downloading
|
|
585
|
+
this._showBusy(` Downloading subgenerator ${chalk.yellow(generator.name)}...`);
|
|
457
586
|
const reqZIPArchive = await octokit.repos.downloadZipballArchive({
|
|
458
587
|
owner: generator.org,
|
|
459
588
|
repo: generator.name,
|
|
460
589
|
ref: commitSHA,
|
|
461
590
|
});
|
|
591
|
+
|
|
592
|
+
this._showBusy(` Extracting subgenerator ${chalk.yellow(generator.name)}...`);
|
|
462
593
|
const buffer = Buffer.from(new Uint8Array(reqZIPArchive.data));
|
|
463
|
-
|
|
464
|
-
const zipEntries = zip.getEntries();
|
|
465
|
-
zipEntries.forEach((entry) => {
|
|
466
|
-
const match = !entry.isDirectory && entry.entryName.match(/[^\/]+(\/.+)/);
|
|
467
|
-
let entryPath;
|
|
468
|
-
if (generator.dir && match && match[1].startsWith(generator.dir)) {
|
|
469
|
-
entryPath = path.dirname(match[1].substring(generator.dir.length));
|
|
470
|
-
} else if (!generator.dir && match) {
|
|
471
|
-
entryPath = path.dirname(match[1]);
|
|
472
|
-
}
|
|
473
|
-
if (entryPath) {
|
|
474
|
-
zip.extractEntryTo(entry, path.join(generatorPath, entryPath), false, true);
|
|
475
|
-
}
|
|
476
|
-
});
|
|
477
|
-
fs.writeFileSync(shaMarker, commitSHA);
|
|
594
|
+
this._unzip(buffer, generatorPath, generator.dir);
|
|
478
595
|
|
|
479
|
-
//
|
|
480
|
-
|
|
481
|
-
this.log("Installing the plugin dependencies...");
|
|
482
|
-
}
|
|
483
|
-
this._showBusy(` Preparing "${generator.name}"`);
|
|
484
|
-
await new Promise(
|
|
485
|
-
function (resolve, reject) {
|
|
486
|
-
spawn(hasYarn() ? "yarn" : "npm", ["install", "--no-progress", "--ignore-engines"], {
|
|
487
|
-
stdio: this.config.verbose ? "inherit" : "ignore",
|
|
488
|
-
cwd: generatorPath,
|
|
489
|
-
env: {
|
|
490
|
-
...process.env,
|
|
491
|
-
NO_UPDATE_NOTIFIER: true,
|
|
492
|
-
},
|
|
493
|
-
})
|
|
494
|
-
.on("exit", function (code) {
|
|
495
|
-
resolve(code);
|
|
496
|
-
})
|
|
497
|
-
.on("error", function (err) {
|
|
498
|
-
reject(err);
|
|
499
|
-
});
|
|
500
|
-
}.bind(this)
|
|
501
|
-
);
|
|
596
|
+
// write the sha marker
|
|
597
|
+
fs.writeFileSync(shaMarker, commitSHA);
|
|
502
598
|
}
|
|
503
599
|
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
// create the env for the plugin generator
|
|
511
|
-
let env = this.env; // in case of Yeoman UI the env is injected!
|
|
512
|
-
if (!env) {
|
|
513
|
-
const yeoman = require("yeoman-environment");
|
|
514
|
-
env = yeoman.createEnv(this.args, opts);
|
|
600
|
+
// only when embedding we clear the busy state as otherwise
|
|
601
|
+
// the npm install will immediately again show the busy state
|
|
602
|
+
if (this.options.embed) {
|
|
603
|
+
this._clearBusy(true);
|
|
604
|
+
}
|
|
515
605
|
}
|
|
516
606
|
|
|
517
|
-
//
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
}
|
|
607
|
+
// do not execute the plugin generator during the setup/embed mode
|
|
608
|
+
if (!this.options.embed) {
|
|
609
|
+
// filter the local options and the help command
|
|
610
|
+
const opts = Object.keys(this._options).filter((optionName) => !(generatorOptions.hasOwnProperty(optionName) || optionName === "help"));
|
|
522
611
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
612
|
+
// run yarn/npm install (always for self-healing!)
|
|
613
|
+
if (this.options.verbose) {
|
|
614
|
+
this.log("Installing the subgenerator dependencies...");
|
|
615
|
+
}
|
|
616
|
+
this._showBusy(` Preparing ${chalk.yellow(generator.name)}...`);
|
|
617
|
+
await this._npmInstall(generatorPath);
|
|
618
|
+
this._clearBusy(true);
|
|
529
619
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
maxLength = Math.max(sub.namespace.length, maxLength);
|
|
537
|
-
return sub;
|
|
538
|
-
})
|
|
539
|
-
.reduce((output, sub) => {
|
|
540
|
-
const subGenerator = env.get(sub.namespace);
|
|
541
|
-
const displayName = subGenerator.displayName || "";
|
|
542
|
-
let line = ` ${deriveSubcommand(sub.namespace).padEnd(maxLength + 2)}`;
|
|
543
|
-
if (displayName) {
|
|
544
|
-
line += ` # ${subGenerator.displayName}`;
|
|
545
|
-
}
|
|
546
|
-
return `${output}\n${line}`;
|
|
547
|
-
}, `Subcommands (${subGenerators.length}):`)
|
|
548
|
-
);
|
|
549
|
-
return;
|
|
550
|
-
}
|
|
620
|
+
// create the env for the plugin generator
|
|
621
|
+
let env = this.env; // in case of Yeoman UI the env is injected!
|
|
622
|
+
if (!env) {
|
|
623
|
+
const yeoman = require("yeoman-environment");
|
|
624
|
+
env = yeoman.createEnv(this.args, opts);
|
|
625
|
+
}
|
|
551
626
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
// identify the subgenerator by subcommand
|
|
557
|
-
return new RegExp(`:${this.options.subcommand}$`).test(sub.namespace);
|
|
558
|
-
});
|
|
559
|
-
if (selectedSubGenerator.length == 1) {
|
|
560
|
-
subGenerators = selectedSubGenerator;
|
|
561
|
-
} else {
|
|
562
|
-
this.log(`The generator ${chalk.red(this.options.generator)} has no subcommand ${chalk.red(this.options.subcommand)}. Please select an existing subcommand!`);
|
|
627
|
+
// helper to derive the subcommand
|
|
628
|
+
function deriveSubcommand(namespace) {
|
|
629
|
+
const match = namespace.match(/[^:]+:(.+)/);
|
|
630
|
+
return match ? match[1] : namespace;
|
|
563
631
|
}
|
|
564
|
-
}
|
|
565
632
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
let maxLength = 0;
|
|
570
|
-
subGenerators = subGenerators
|
|
571
|
-
.map((sub) => {
|
|
633
|
+
// filter the hidden subgenerators already
|
|
634
|
+
// -> subgenerators must be found in env as they are returned by lookup!
|
|
635
|
+
let subGenerators = env.lookup({ localOnly: true, packagePaths: generatorPath }).filter((sub) => {
|
|
572
636
|
const subGenerator = env.get(sub.namespace);
|
|
573
|
-
|
|
574
|
-
let displayName = subGenerator.displayName || subcommand;
|
|
575
|
-
maxLength = Math.max(displayName.length, maxLength);
|
|
576
|
-
return {
|
|
577
|
-
subcommand,
|
|
578
|
-
displayName,
|
|
579
|
-
sub,
|
|
580
|
-
};
|
|
581
|
-
})
|
|
582
|
-
.map(({ subcommand, displayName, sub }) => {
|
|
583
|
-
const transformed = {
|
|
584
|
-
name: `${displayName.padEnd(maxLength + 2)} [${subcommand}]`,
|
|
585
|
-
value: sub.namespace,
|
|
586
|
-
};
|
|
587
|
-
if (/:app$/.test(sub.namespace)) {
|
|
588
|
-
defaultSubGenerator = transformed;
|
|
589
|
-
}
|
|
590
|
-
return transformed;
|
|
637
|
+
return !subGenerator.hidden;
|
|
591
638
|
});
|
|
592
639
|
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
)
|
|
640
|
+
// list the available subgenerators in the console (as help)
|
|
641
|
+
if (this.options.list) {
|
|
642
|
+
let maxLength = 0;
|
|
643
|
+
this.log(
|
|
644
|
+
subGenerators
|
|
645
|
+
.map((sub) => {
|
|
646
|
+
maxLength = Math.max(sub.namespace.length, maxLength);
|
|
647
|
+
return sub;
|
|
648
|
+
})
|
|
649
|
+
.reduce((output, sub) => {
|
|
650
|
+
const subGenerator = env.get(sub.namespace);
|
|
651
|
+
const displayName = subGenerator.displayName || "";
|
|
652
|
+
let line = ` ${deriveSubcommand(sub.namespace).padEnd(maxLength + 2)}`;
|
|
653
|
+
if (displayName) {
|
|
654
|
+
line += ` # ${subGenerator.displayName}`;
|
|
655
|
+
}
|
|
656
|
+
return `${output}\n${line}`;
|
|
657
|
+
}, `Subcommands (${subGenerators.length}):`)
|
|
658
|
+
);
|
|
659
|
+
return;
|
|
612
660
|
}
|
|
613
661
|
|
|
614
|
-
if
|
|
615
|
-
|
|
662
|
+
// if a subcommand is provided as argument, identify the matching subgenerator
|
|
663
|
+
// and remove the rest of the subgenerators from the list for later steps
|
|
664
|
+
if (this.options.subcommand) {
|
|
665
|
+
const selectedSubGenerator = subGenerators.filter((sub) => {
|
|
666
|
+
// identify the subgenerator by subcommand
|
|
667
|
+
return new RegExp(`:${this.options.subcommand}$`).test(sub.namespace);
|
|
668
|
+
});
|
|
669
|
+
if (selectedSubGenerator.length == 1) {
|
|
670
|
+
subGenerators = selectedSubGenerator;
|
|
671
|
+
} else {
|
|
672
|
+
this.log(`The generator ${chalk.red(this.options.generator)} has no subcommand ${chalk.red(this.options.subcommand)}. Please select an existing subcommand!`);
|
|
673
|
+
}
|
|
616
674
|
}
|
|
617
675
|
|
|
618
|
-
//
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
676
|
+
// transform the list of the subgenerators and identify the
|
|
677
|
+
// default subgenerator for the default selection
|
|
678
|
+
let defaultSubGenerator;
|
|
679
|
+
let maxLength = 0;
|
|
680
|
+
subGenerators = subGenerators
|
|
681
|
+
.map((sub) => {
|
|
682
|
+
const subGenerator = env.get(sub.namespace);
|
|
683
|
+
let subcommand = deriveSubcommand(sub.namespace);
|
|
684
|
+
let displayName = subGenerator.displayName || subcommand;
|
|
685
|
+
maxLength = Math.max(displayName.length, maxLength);
|
|
686
|
+
return {
|
|
687
|
+
subcommand,
|
|
688
|
+
displayName,
|
|
689
|
+
sub,
|
|
690
|
+
};
|
|
691
|
+
})
|
|
692
|
+
.map(({ subcommand, displayName, sub }) => {
|
|
693
|
+
const transformed = {
|
|
694
|
+
name: `${displayName.padEnd(maxLength + 2)} [${subcommand}]`,
|
|
695
|
+
value: sub.namespace,
|
|
696
|
+
};
|
|
697
|
+
if (/:app$/.test(sub.namespace)) {
|
|
698
|
+
defaultSubGenerator = transformed;
|
|
699
|
+
}
|
|
700
|
+
return transformed;
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
// at least 1 subgenerator must be present
|
|
704
|
+
if (subGenerators.length >= 1) {
|
|
705
|
+
// by default the 1st subgenerator is used
|
|
706
|
+
let subGenerator = subGenerators[0].value;
|
|
707
|
+
|
|
708
|
+
// if more than 1 subgenerator is present
|
|
709
|
+
// ask the developer to select one!
|
|
710
|
+
if (subGenerators.length > 1) {
|
|
711
|
+
subGenerator = (
|
|
712
|
+
await this.prompt([
|
|
713
|
+
{
|
|
714
|
+
type: "list",
|
|
715
|
+
name: "subGenerator",
|
|
716
|
+
message: "What do you want to do?",
|
|
717
|
+
default: defaultSubGenerator && defaultSubGenerator.value,
|
|
718
|
+
choices: subGenerators,
|
|
719
|
+
},
|
|
720
|
+
])
|
|
721
|
+
).subGenerator;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
if (this.options.verbose) {
|
|
725
|
+
this.log(`Calling ${chalk.red(subGenerator)}...\n \\_ in "${generatorPath}"`);
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// finally, run the subgenerator
|
|
729
|
+
env.run(subGenerator, {
|
|
730
|
+
verbose: this.options.verbose,
|
|
731
|
+
embedded: true,
|
|
732
|
+
destinationRoot: this.destinationRoot(),
|
|
733
|
+
});
|
|
734
|
+
} else {
|
|
735
|
+
this.log(`The generator ${chalk.red(this.options.generator)} has no visible subgenerators!`);
|
|
736
|
+
}
|
|
624
737
|
} else {
|
|
625
|
-
|
|
738
|
+
// zip the content of the plugin generator or
|
|
739
|
+
// install the dependencies of the generator
|
|
740
|
+
if (this.options.verbose) {
|
|
741
|
+
this.log(`Embedding plugin generator ${chalk.yellow(generator.name)}...`);
|
|
742
|
+
}
|
|
743
|
+
const generatorZIP = new AdmZip();
|
|
744
|
+
const addLocalFile = (file) => {
|
|
745
|
+
const filePath = path.join(generator.name, path.relative(generatorPath, file));
|
|
746
|
+
generatorZIP.addLocalFile(file, path.dirname(filePath), path.basename(filePath));
|
|
747
|
+
if (this.options.verbose) {
|
|
748
|
+
this.log(` + file: ${file}`);
|
|
749
|
+
}
|
|
750
|
+
};
|
|
751
|
+
glob.sync(`${generatorPath}/*`, { nodir: true, dot: true }).forEach(addLocalFile);
|
|
752
|
+
glob.sync(`${generatorPath}/!(node_modules)/**/*`, { nodir: true, dot: true }).forEach(addLocalFile);
|
|
753
|
+
const generatorZIPPath = path.join(__dirname, "../../plugins", `${generator.name}.zip`);
|
|
754
|
+
generatorZIP.writeZip(generatorZIPPath);
|
|
755
|
+
if (this.options.verbose) {
|
|
756
|
+
this.log(`Stored plugin generator ${chalk.yellow(generator.name)} zip to "${generatorZIPPath}"!`);
|
|
757
|
+
}
|
|
626
758
|
}
|
|
627
759
|
}
|
|
628
|
-
}
|
|
760
|
+
}
|
package/package.json
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "generator-easy-ui5",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.0",
|
|
4
4
|
"description": "Generator for UI5-based project",
|
|
5
5
|
"main": "generators/app/index.js",
|
|
6
|
+
"type": "module",
|
|
6
7
|
"files": [
|
|
7
|
-
"generators"
|
|
8
|
+
"generators",
|
|
9
|
+
"plugins"
|
|
8
10
|
],
|
|
9
11
|
"engines": {
|
|
10
12
|
"node": ">=14.0.0"
|
|
11
13
|
},
|
|
12
14
|
"scripts": {
|
|
13
|
-
"
|
|
15
|
+
"prepublishOnly": "npx yo ./ project --embed",
|
|
14
16
|
"start": "yo easy-ui5 project",
|
|
15
17
|
"test": "mocha",
|
|
16
18
|
"test:subgen:list": "yo easy-ui5 project --list",
|
|
@@ -46,33 +48,33 @@
|
|
|
46
48
|
},
|
|
47
49
|
"homepage": "https://github.com/SAP/generator-easy-ui5#readme",
|
|
48
50
|
"dependencies": {
|
|
49
|
-
"@octokit/plugin-throttling": "^
|
|
50
|
-
"@octokit/rest": "^19.0.
|
|
51
|
-
"adm-zip": "^0.5.
|
|
52
|
-
"chalk": "^
|
|
53
|
-
"colors": "1.4.0",
|
|
54
|
-
"glob": "^
|
|
51
|
+
"@octokit/plugin-throttling": "^5.2.3",
|
|
52
|
+
"@octokit/rest": "^19.0.11",
|
|
53
|
+
"adm-zip": "^0.5.10",
|
|
54
|
+
"chalk": "^5.2.0",
|
|
55
|
+
"colors": "^1.4.0",
|
|
56
|
+
"glob": "^10.2.7",
|
|
55
57
|
"libnpmconfig": "^1.2.1",
|
|
56
|
-
"rimraf": "^
|
|
58
|
+
"rimraf": "^5.0.1",
|
|
57
59
|
"yarn-or-npm": "^3.0.1",
|
|
58
|
-
"yeoman-environment": "^3.
|
|
59
|
-
"yeoman-generator": "^5.
|
|
60
|
+
"yeoman-environment": "^3.19.3",
|
|
61
|
+
"yeoman-generator": "^5.9.0",
|
|
60
62
|
"yosay": "^2.0.2"
|
|
61
63
|
},
|
|
62
64
|
"devDependencies": {
|
|
63
|
-
"@commitlint/cli": "17.
|
|
64
|
-
"@commitlint/config-conventional": "17.
|
|
65
|
-
"conventional-changelog-cli": "^
|
|
66
|
-
"cz-conventional-changelog": "3.3.0",
|
|
67
|
-
"eslint": "^8.
|
|
68
|
-
"husky": "^8.0.
|
|
69
|
-
"lint-staged": "^13.
|
|
70
|
-
"mocha": "^10.
|
|
65
|
+
"@commitlint/cli": "^17.6.5",
|
|
66
|
+
"@commitlint/config-conventional": "^17.6.5",
|
|
67
|
+
"conventional-changelog-cli": "^3.0.0",
|
|
68
|
+
"cz-conventional-changelog": "^3.3.0",
|
|
69
|
+
"eslint": "^8.42.0",
|
|
70
|
+
"husky": "^8.0.3",
|
|
71
|
+
"lint-staged": "^13.2.2",
|
|
72
|
+
"mocha": "^10.2.0",
|
|
71
73
|
"npm-run-all": "^4.1.5",
|
|
72
|
-
"prettier": "2.
|
|
74
|
+
"prettier": "^2.8.8",
|
|
73
75
|
"pretty-quick": "^3.1.3",
|
|
74
76
|
"yeoman-assert": "^3.1.1",
|
|
75
|
-
"yeoman-test": "^
|
|
77
|
+
"yeoman-test": "^7.4.0"
|
|
76
78
|
},
|
|
77
79
|
"config": {
|
|
78
80
|
"commitizen": {
|
|
@@ -85,6 +87,7 @@
|
|
|
85
87
|
]
|
|
86
88
|
},
|
|
87
89
|
"overrides": {
|
|
90
|
+
"http-cache-semantics": "^4.1.1",
|
|
88
91
|
"minimist": "^1.2.6"
|
|
89
92
|
}
|
|
90
93
|
}
|
|
Binary file
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
const spawn = require("cross-spawn");
|
|
3
|
-
const fs = require("fs");
|
|
4
|
-
const { rm } = require("fs").promises;
|
|
5
|
-
const path = require("path");
|
|
6
|
-
const { hasYarn } = require("yarn-or-npm");
|
|
7
|
-
const { Octokit } = require("@octokit/rest");
|
|
8
|
-
const { throttling } = require("@octokit/plugin-throttling");
|
|
9
|
-
const MyOctokit = Octokit.plugin(throttling);
|
|
10
|
-
const AdmZip = require("adm-zip");
|
|
11
|
-
|
|
12
|
-
// helper to retrieve config entries from npm
|
|
13
|
-
// --> npm config set easy-ui5_addGhOrg XYZ
|
|
14
|
-
const NPM_CONFIG_PREFIX = "easy-ui5_";
|
|
15
|
-
let npmConfig;
|
|
16
|
-
const getNPMConfig = (configName) => {
|
|
17
|
-
if (!npmConfig) {
|
|
18
|
-
npmConfig = require("libnpmconfig").read();
|
|
19
|
-
}
|
|
20
|
-
return npmConfig && npmConfig[`${NPM_CONFIG_PREFIX}${configName}`];
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const ghOrg = "ui5-community",
|
|
24
|
-
repoName = "generator-ui5-project",
|
|
25
|
-
branch = "main",
|
|
26
|
-
ghAuthToken = getNPMConfig("ghAuthToken");
|
|
27
|
-
|
|
28
|
-
(async () => {
|
|
29
|
-
let _busy;
|
|
30
|
-
|
|
31
|
-
function showBusy(statusText) {
|
|
32
|
-
clearBusy();
|
|
33
|
-
const progressChars = ["\\", "|", "/", "-"];
|
|
34
|
-
let i = 0;
|
|
35
|
-
process.stdout.write(`\r${statusText} `);
|
|
36
|
-
_busy = {
|
|
37
|
-
text: statusText,
|
|
38
|
-
timer: setInterval(() => {
|
|
39
|
-
process.stdout.write(`\r${statusText} ${progressChars[i++]}`);
|
|
40
|
-
i %= progressChars.length;
|
|
41
|
-
}, 250),
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function clearBusy(newLine) {
|
|
46
|
-
if (_busy) {
|
|
47
|
-
clearInterval(_busy.timer);
|
|
48
|
-
process.stdout.write("\r".padEnd(_busy.text.length + 3) + (newLine ? "\n" : ""));
|
|
49
|
-
_busy = null;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const pkg = require(path.join(__dirname, "../../package.json"));
|
|
54
|
-
console.log(`${pkg.name}:${pkg.version} - ${ghAuthToken}`);
|
|
55
|
-
const octokit = new MyOctokit({
|
|
56
|
-
userAgent: `${pkg.name}:${pkg.version}`,
|
|
57
|
-
auth: ghAuthToken,
|
|
58
|
-
throttle: {
|
|
59
|
-
onRateLimit: (retryAfter, options) => {
|
|
60
|
-
console.log("Hit the GitHub API limit! Request quota exhausted for this request.");
|
|
61
|
-
if (options.request.retryCount === 0) {
|
|
62
|
-
// only retries once
|
|
63
|
-
this.log(`Retrying after ${retryAfter} seconds. Alternatively, you can cancel this operation and supply an auth token with "npm config set easy-ui5_ghAuthToken ghp_xxxx".`);
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
},
|
|
67
|
-
onAbuseLimit: () => {
|
|
68
|
-
// does not retry, only logs a warning
|
|
69
|
-
console.error('Hit the GitHub API limit again! Please supply an auth token with with "npm config set easy-ui5_ghAuthToken ghp_xxxx".');
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
const reqBranch = await octokit.repos.getBranch({
|
|
75
|
-
owner: ghOrg,
|
|
76
|
-
repo: repoName,
|
|
77
|
-
branch,
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
const commitSHA = reqBranch.data.commit.sha;
|
|
81
|
-
|
|
82
|
-
// eslint-disable-next-line
|
|
83
|
-
console.log(`Using commit ${commitSHA} from @${ghOrg}/${repoName}#${branch}...`);
|
|
84
|
-
const generatorPath = path.join(__dirname, "../../plugin-generators", repoName);
|
|
85
|
-
const shaMarker = path.join(generatorPath, `.${commitSHA}`);
|
|
86
|
-
|
|
87
|
-
if (fs.existsSync(generatorPath)) {
|
|
88
|
-
// check if the SHA marker exists to know whether the generator is up-to-date or not
|
|
89
|
-
if (!fs.existsSync(shaMarker)) {
|
|
90
|
-
// eslint-disable-next-line
|
|
91
|
-
console.log(`Fetching new ZIP as the default generator is outdated...`);
|
|
92
|
-
// remove if the SHA marker doesn't exist => outdated!
|
|
93
|
-
showBusy(" Removing old default templates");
|
|
94
|
-
await rm(generatorPath, { recursive: true });
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// re-fetch the generator and extract into local plugin folder
|
|
99
|
-
if (!fs.existsSync(generatorPath)) {
|
|
100
|
-
console.log("Extracting default templates...");
|
|
101
|
-
showBusy(" Downloading and extracting default templates");
|
|
102
|
-
const reqZIPArchive = await octokit.repos.downloadZipballArchive({
|
|
103
|
-
owner: ghOrg,
|
|
104
|
-
repo: repoName,
|
|
105
|
-
ref: commitSHA,
|
|
106
|
-
});
|
|
107
|
-
const buffer = Buffer.from(new Uint8Array(reqZIPArchive.data));
|
|
108
|
-
const zip = new AdmZip(buffer);
|
|
109
|
-
const zipEntries = zip.getEntries();
|
|
110
|
-
zipEntries.forEach((entry) => {
|
|
111
|
-
const match = !entry.isDirectory && entry.entryName.match(/[^\/]+\/(.+)/);
|
|
112
|
-
if (match) {
|
|
113
|
-
const entryPath = match[1].slice(0, entry.name.length * -1);
|
|
114
|
-
zip.extractEntryTo(entry, path.join(generatorPath, entryPath), false, true);
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
fs.writeFileSync(shaMarker, commitSHA);
|
|
118
|
-
|
|
119
|
-
// run yarn/npm install
|
|
120
|
-
console.log("Installing the plugin dependencies...");
|
|
121
|
-
showBusy(" Preparing the default templates");
|
|
122
|
-
await new Promise(
|
|
123
|
-
function (resolve, reject) {
|
|
124
|
-
spawn(hasYarn() ? "yarn" : "npm", ["install", "--no-progress", "--ignore-engines"], {
|
|
125
|
-
stdio: "inherit",
|
|
126
|
-
cwd: generatorPath,
|
|
127
|
-
env: {
|
|
128
|
-
...process.env,
|
|
129
|
-
NO_UPDATE_NOTIFIER: true,
|
|
130
|
-
},
|
|
131
|
-
})
|
|
132
|
-
.on("exit", function (code) {
|
|
133
|
-
resolve(code);
|
|
134
|
-
})
|
|
135
|
-
.on("error", function (err) {
|
|
136
|
-
reject(err);
|
|
137
|
-
});
|
|
138
|
-
}.bind(this)
|
|
139
|
-
);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
clearBusy(true);
|
|
143
|
-
})();
|