create-webiny-project 0.0.0-ee-vpcs.549378cf03
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/LICENSE +21 -0
- package/README.md +130 -0
- package/bin.js +49 -0
- package/index.js +94 -0
- package/package.json +39 -0
- package/utils/checkProjectName.js +22 -0
- package/utils/createProject.js +314 -0
- package/utils/getPackageJson.js +5 -0
- package/utils/getPackageVersion.js +24 -0
- package/utils/getYarnVersion.js +10 -0
- package/utils/verifyConfig.js +20 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Webiny
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# create-webiny-project
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/create-webiny-project)
|
|
4
|
+
[](https://www.npmjs.com/package/create-webiny-project)
|
|
5
|
+
[](https://github.com/prettier/prettier)
|
|
6
|
+
[](http://makeapullrequest.com)
|
|
7
|
+
|
|
8
|
+
A tool for setting up a new Webiny project.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
#### Simple:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
npx create-webiny-project@beta my-test-project --tag beta
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
#### Advanced:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
npx create-webiny-project@beta my-test-project
|
|
22
|
+
--tag beta --no-interactive
|
|
23
|
+
--assign-to-yarnrc '{"npmRegistryServer":"http://localhost:4873","unsafeHttpWhitelist":["localhost"]}'
|
|
24
|
+
--template-options '{"region":"eu-central-1","vpc":false}'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
This usage is more ideal for CI/CD environments, where interactivity is not available.
|
|
28
|
+
|
|
29
|
+
But do note that this is probably more useful to us, Webiny developers, than for actual Webiny projects. This is simply because in real project's CI/CD pipelines, users would simply start off by cloning the project from their private repository, and not create a new one with the above command.
|
|
30
|
+
|
|
31
|
+
## Development Notes
|
|
32
|
+
|
|
33
|
+
Testing this, and related packages (like [cwp-template-aws](./../cwp-template-aws)) is a bit complicated, because in order to get the best results, it's recommended to test everything with packages published to a real NPM.
|
|
34
|
+
|
|
35
|
+
But of course, publishing to NPM just to test something is not ideal, and that's why, we use [Verdaccio](https://verdaccio.org/) instead, which is, basically, an NPM-like service you can run locally. So, instead of publishing packages to NPM, you publish them to Verdaccio, which is much cleaner, because everything stays on your laptop.
|
|
36
|
+
|
|
37
|
+
#### Usage
|
|
38
|
+
|
|
39
|
+
So, you've made some changes, and now you'd like to see the `create-webiny-project` in action.
|
|
40
|
+
|
|
41
|
+
The following steps show how to do it.
|
|
42
|
+
|
|
43
|
+
#### 1. Start Verdaccio
|
|
44
|
+
|
|
45
|
+
Start by running the `yarn verdaccio:start` command, which will, as the script name itself suggests, spin up Verdaccio locally.
|
|
46
|
+
|
|
47
|
+
> All of the files uploaded to Verdaccio service will be stored in the `.verdaccio` folder, located in your project root.
|
|
48
|
+
|
|
49
|
+
#### 2. Set default NPM registry
|
|
50
|
+
|
|
51
|
+
Once you have Verdaccio up and running, you'll also need to change the default NPM registry. Meaning, when you run `npx create-webiny-project ...`, you want it to start fetching packages from Verdaccio, not real NPM. Verdaccio runs on localhost, on port 4873, so, in your terminal, run the following command:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
npm config set registry http://localhost:4873
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Note that this will only help you with `npx`, but won't help you when a new project foundation is created, and the dependencies start to get pulled. This is because we're using yarn2, which actually doesn't respect the values that were written by the `npm config set ...` command we just executed.
|
|
58
|
+
|
|
59
|
+
It's super important that, when you're testing your npx project, you also pass the following argument:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
--assign-to-yarnrc '{"npmRegistryServer":"http://localhost:4873","unsafeHttpWhitelist":["localhost"]}'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
This will set the necessary values in yarn2 config file, which will be located in your newly created project. But don't worry about it right now, this will be revisited in step 4.
|
|
66
|
+
|
|
67
|
+
> Yarn2 projects don't rely on global configurations and is not installed globally, but on per-project basis. This allows having multiple versions of yarn2, for different projects.
|
|
68
|
+
|
|
69
|
+
#### 3. Release
|
|
70
|
+
|
|
71
|
+
Commit (no need to push it if you don't want to) all of the code changes, and execute the following command:
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
yarn release --type=verdaccio
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### 4. Test
|
|
79
|
+
|
|
80
|
+
Test your changes with the following command:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
npx create-webiny-project@next my-test-project --tag next --assign-to-yarnrc '{"npmRegistryServer":"http://localhost:4873","unsafeHttpWhitelist":["localhost"]}'
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
This should create a project, with all of the packages pulled from Verdaccio.
|
|
87
|
+
|
|
88
|
+
#### 5. Cleanup
|
|
89
|
+
|
|
90
|
+
Once you're done, do the following:
|
|
91
|
+
|
|
92
|
+
1. Reset NPM registry with `npm config set registry https://registry.npmjs.org/`
|
|
93
|
+
2. Remove `.verdaccio` folder
|
|
94
|
+
|
|
95
|
+
### Commands Cheat Sheet
|
|
96
|
+
|
|
97
|
+
| Description | Command |
|
|
98
|
+
|-----------------------------------------------| ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
99
|
+
| Remove `.verdaccio` folder | `rm -rf .verdaccio` |
|
|
100
|
+
| List all v5\* tags | `git tag -l "v5*"` |
|
|
101
|
+
| Remove specific tag | `git tag -d "v5.0.0-next.5"` |
|
|
102
|
+
| Set Verdaccio as the NPM registry | `npm config set registry http://localhost:4873` |
|
|
103
|
+
| Reset NPM registry | `npm config set registry https://registry.npmjs.org/` |
|
|
104
|
+
| Start Verdaccio | `yarn verdaccio:start` |
|
|
105
|
+
| Release to Verdaccio | `yarn release --type=verdaccio` |
|
|
106
|
+
| Create a new Webiny project | `npx create-webiny-project@next my-test-project --tag next --assign-to-yarnrc '{"npmRegistryServer":"http://localhost:4873","unsafeHttpWhitelist":["localhost"]}'` |
|
|
107
|
+
| Revert versioning commit | `git reset HEAD~ && git reset --hard HEAD` |
|
|
108
|
+
|
|
109
|
+
## Troubleshooting
|
|
110
|
+
|
|
111
|
+
#### I made a new release to Verdaccio, but I still receive old code.
|
|
112
|
+
|
|
113
|
+
This is probably because of one of the Yarn package caching mechanisms.
|
|
114
|
+
|
|
115
|
+
Yarn has two levels of cache - local and shared.
|
|
116
|
+
|
|
117
|
+
When you install a package, it gets cached in the local cache folder (located in your project), and in the shared cache folder. This makes it much faster when you're working on a couple of projects on your local machine, and you're pulling the same package in each. If the package doesn't exist in local cache, it will be pulled from shared cache.
|
|
118
|
+
|
|
119
|
+
On Windows, the shared cache folder should be located in: `C:\Users\{USER-NAME}\AppData\Local\Yarn`.
|
|
120
|
+
On Linux/Mac, the shared cache folder should be located in: `/Users/adrian/Library/Caches/Yarn`.
|
|
121
|
+
|
|
122
|
+
In these folders, most probably, you'll also have the `\Berry\cache` folder. But, there were also cases where this folder did not exist.
|
|
123
|
+
|
|
124
|
+
Deleting the mentioned cache folders should help with the issue of still receiving old packages in your testing sessions.
|
|
125
|
+
|
|
126
|
+
With all of this being said, you can also try the [following command](https://yarnpkg.com/features/offline-cache#cleaning-the-cache):
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
yarn cache clean --mirror
|
|
130
|
+
````
|
package/bin.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
const semver = require("semver");
|
|
5
|
+
const chalk = require("chalk");
|
|
6
|
+
const getYarnVersion = require("./utils/getYarnVersion");
|
|
7
|
+
const verifyConfig = require("./utils/verifyConfig");
|
|
8
|
+
|
|
9
|
+
(async () => {
|
|
10
|
+
const nodeVersion = process.versions.node;
|
|
11
|
+
if (!semver.satisfies(nodeVersion, ">=14")) {
|
|
12
|
+
console.error(
|
|
13
|
+
chalk.red(
|
|
14
|
+
[
|
|
15
|
+
`You are running Node.js ${nodeVersion}, but Webiny requires version 14 or higher.`,
|
|
16
|
+
`Please switch to one of the required versions and try again.`,
|
|
17
|
+
"For more information, please visit https://docs.webiny.com/docs/tutorials/install-webiny#prerequisites."
|
|
18
|
+
].join(" ")
|
|
19
|
+
)
|
|
20
|
+
);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const yarnVersion = await getYarnVersion();
|
|
26
|
+
if (!semver.satisfies(yarnVersion, ">=1.22.0")) {
|
|
27
|
+
console.error(
|
|
28
|
+
chalk.red(
|
|
29
|
+
[
|
|
30
|
+
`Webiny requires yarn@^1.22.0 or higher.`,
|
|
31
|
+
`Please visit https://yarnpkg.com/ to install ${chalk.green("yarn")}.`
|
|
32
|
+
].join("\n")
|
|
33
|
+
)
|
|
34
|
+
);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
} catch (err) {
|
|
38
|
+
console.error(
|
|
39
|
+
chalk.red(`Webiny depends on "yarn" and its built-in support for workspaces.`)
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
console.log(`Please visit https://yarnpkg.com/ to install ${chalk.green("yarn")}.`);
|
|
43
|
+
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
await verifyConfig();
|
|
48
|
+
require("./index");
|
|
49
|
+
})();
|
package/index.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const yargs = require("yargs");
|
|
3
|
+
const packageJson = require("./package.json");
|
|
4
|
+
const createProject = require("./utils/createProject");
|
|
5
|
+
|
|
6
|
+
process.on("unhandledRejection", err => {
|
|
7
|
+
throw err;
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
yargs
|
|
11
|
+
.usage("Usage: create-webiny-project <project-name> [options]")
|
|
12
|
+
.version(packageJson.version)
|
|
13
|
+
.demandCommand(1)
|
|
14
|
+
.help()
|
|
15
|
+
.alias("help", "h")
|
|
16
|
+
.scriptName("create-webiny-project")
|
|
17
|
+
.fail(function (msg, err) {
|
|
18
|
+
if (msg) {
|
|
19
|
+
console.log(msg);
|
|
20
|
+
}
|
|
21
|
+
if (err) {
|
|
22
|
+
console.log(err);
|
|
23
|
+
}
|
|
24
|
+
process.exit(1);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// noinspection BadExpressionStatementJS
|
|
28
|
+
yargs.command(
|
|
29
|
+
"$0 <project-name> [options]",
|
|
30
|
+
"Name of application and template to use",
|
|
31
|
+
yargs => {
|
|
32
|
+
yargs.positional("project-name", {
|
|
33
|
+
describe: "Project name"
|
|
34
|
+
});
|
|
35
|
+
yargs.option("force", {
|
|
36
|
+
describe: "All project creation within an existing folder",
|
|
37
|
+
default: false,
|
|
38
|
+
type: "boolean",
|
|
39
|
+
demandOption: false
|
|
40
|
+
});
|
|
41
|
+
yargs.option("template", {
|
|
42
|
+
describe: `Name of template to use, if no template is provided it will default to "aws" template`,
|
|
43
|
+
alias: "t",
|
|
44
|
+
type: "string",
|
|
45
|
+
default: "aws",
|
|
46
|
+
demandOption: false
|
|
47
|
+
});
|
|
48
|
+
yargs.option("template-options", {
|
|
49
|
+
describe: `A JSON containing template-specific options (usually used in non-interactive environments)`,
|
|
50
|
+
default: null,
|
|
51
|
+
type: "string",
|
|
52
|
+
demandOption: false
|
|
53
|
+
});
|
|
54
|
+
yargs.option("assign-to-yarnrc", {
|
|
55
|
+
describe: `A JSON containing additional options that will be assigned into the "yarnrc.yml" configuration file`,
|
|
56
|
+
default: null,
|
|
57
|
+
type: "string",
|
|
58
|
+
demandOption: false
|
|
59
|
+
});
|
|
60
|
+
yargs.option("tag", {
|
|
61
|
+
describe: "NPM tag to use for @webiny packages",
|
|
62
|
+
type: "string",
|
|
63
|
+
default: "latest",
|
|
64
|
+
demandOption: false
|
|
65
|
+
});
|
|
66
|
+
yargs.option("interactive", {
|
|
67
|
+
describe: "Enable interactive mode for all commands",
|
|
68
|
+
default: true,
|
|
69
|
+
type: "boolean",
|
|
70
|
+
demandOption: false
|
|
71
|
+
});
|
|
72
|
+
yargs.option("log", {
|
|
73
|
+
describe:
|
|
74
|
+
"Creates a log file to see output of installation. Defaults to creating cwp-logs.txt in current directory",
|
|
75
|
+
alias: "l",
|
|
76
|
+
default: "cwp-logs.txt",
|
|
77
|
+
type: "string",
|
|
78
|
+
demandOption: false
|
|
79
|
+
});
|
|
80
|
+
yargs.option("cleanup", {
|
|
81
|
+
describe: "If an error occurs upon project creation, deletes all generated files",
|
|
82
|
+
alias: "c",
|
|
83
|
+
default: true,
|
|
84
|
+
type: "boolean",
|
|
85
|
+
demandOption: false
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
yargs.example("$0 <project-name>");
|
|
89
|
+
yargs.example("$0 <project-name> --template=aws");
|
|
90
|
+
yargs.example("$0 <project-name> --template=../path/to/template");
|
|
91
|
+
yargs.example("$0 <project-name> --log=./my-logs.txt");
|
|
92
|
+
},
|
|
93
|
+
argv => createProject(argv)
|
|
94
|
+
).argv;
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-webiny-project",
|
|
3
|
+
"version": "0.0.0-ee-vpcs.549378cf03",
|
|
4
|
+
"description": "Webiny project bootstrap tool.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"bin": "./bin.js",
|
|
10
|
+
"keywords": [
|
|
11
|
+
"Webiny"
|
|
12
|
+
],
|
|
13
|
+
"author": "Webiny Ltd.",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"@webiny/telemetry": "0.0.0-ee-vpcs.549378cf03",
|
|
17
|
+
"chalk": "4.1.0",
|
|
18
|
+
"execa": "5.1.1",
|
|
19
|
+
"find-up": "5.0.0",
|
|
20
|
+
"fs-extra": "9.1.0",
|
|
21
|
+
"js-yaml": "3.14.1",
|
|
22
|
+
"listr": "0.14.3",
|
|
23
|
+
"load-json-file": "6.2.0",
|
|
24
|
+
"node-fetch": "2.6.1",
|
|
25
|
+
"os": "0.1.1",
|
|
26
|
+
"p-retry": "4.2.0",
|
|
27
|
+
"rimraf": "3.0.2",
|
|
28
|
+
"semver": "7.3.8",
|
|
29
|
+
"uuid": "8.3.2",
|
|
30
|
+
"validate-npm-package-name": "3.0.0",
|
|
31
|
+
"write-json-file": "4.3.0",
|
|
32
|
+
"yargs": "17.6.0"
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public",
|
|
36
|
+
"directory": "."
|
|
37
|
+
},
|
|
38
|
+
"gitHead": "549378cf03fcd27845fc3fa23d1dc6b32896f630"
|
|
39
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const { red, green } = require("chalk");
|
|
2
|
+
const validateProjectName = require("validate-npm-package-name");
|
|
3
|
+
|
|
4
|
+
module.exports = projectName => {
|
|
5
|
+
const validationResult = validateProjectName(projectName);
|
|
6
|
+
if (!validationResult.validForNewPackages) {
|
|
7
|
+
console.error(
|
|
8
|
+
red(
|
|
9
|
+
`Cannot create a project named ${green(
|
|
10
|
+
`"${projectName}"`
|
|
11
|
+
)} because of npm naming restrictions:\n`
|
|
12
|
+
)
|
|
13
|
+
);
|
|
14
|
+
[...(validationResult.errors || []), ...(validationResult.warnings || [])].forEach(
|
|
15
|
+
error => {
|
|
16
|
+
console.error(red(` * ${error}`));
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
console.error(red("\nPlease choose a different project name."));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { yellow, red, green, gray } = require("chalk");
|
|
3
|
+
const execa = require("execa");
|
|
4
|
+
const fs = require("fs-extra");
|
|
5
|
+
const Listr = require("listr");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
const writeJson = require("write-json-file");
|
|
8
|
+
const rimraf = require("rimraf");
|
|
9
|
+
const { sendEvent } = require("@webiny/telemetry/cli");
|
|
10
|
+
const getPackageJson = require("./getPackageJson");
|
|
11
|
+
const checkProjectName = require("./checkProjectName");
|
|
12
|
+
const yaml = require("js-yaml");
|
|
13
|
+
const findUp = require("find-up");
|
|
14
|
+
|
|
15
|
+
const NOT_APPLICABLE = gray("N/A");
|
|
16
|
+
|
|
17
|
+
module.exports = async function createProject({
|
|
18
|
+
projectName,
|
|
19
|
+
force,
|
|
20
|
+
template,
|
|
21
|
+
tag,
|
|
22
|
+
log,
|
|
23
|
+
cleanup,
|
|
24
|
+
interactive,
|
|
25
|
+
templateOptions,
|
|
26
|
+
assignToYarnrc: assignToYarnRc
|
|
27
|
+
}) {
|
|
28
|
+
if (!projectName) {
|
|
29
|
+
throw Error("You must provide a name for the project to use.");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const projectRoot = path.resolve(projectName).replace(/\\/g, "/");
|
|
33
|
+
projectName = path.basename(projectRoot);
|
|
34
|
+
|
|
35
|
+
if (fs.existsSync(projectRoot)) {
|
|
36
|
+
if (!force) {
|
|
37
|
+
console.log(
|
|
38
|
+
`Cannot continue because the target folder ${red(projectName)} already exists.`
|
|
39
|
+
);
|
|
40
|
+
console.log(
|
|
41
|
+
`If you still wish to proceed, run the same command with the ${red(
|
|
42
|
+
"--force"
|
|
43
|
+
)} flag.`
|
|
44
|
+
);
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Before create any files, check if there are yarn.lock or package.json anywhere up in the tree.
|
|
50
|
+
await Promise.all([findUp("yarn.lock"), findUp("package.json")])
|
|
51
|
+
.then(files => files.filter(Boolean))
|
|
52
|
+
.then(files => {
|
|
53
|
+
if (files.length) {
|
|
54
|
+
const messages = [
|
|
55
|
+
"\nThe following file(s) will cause problems with project root detection:\n",
|
|
56
|
+
...files.map(file => red(file) + "\n"),
|
|
57
|
+
`\nMake sure you delete all ${red("yarn.lock")} and ${red(
|
|
58
|
+
"package.json"
|
|
59
|
+
)} files higher in the hierarchy.`
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
console.log(messages.join(""));
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Check if @webiny/cli is installed globally and warn user
|
|
68
|
+
try {
|
|
69
|
+
await execa("npm", ["list", "-g", "@webiny/cli"]);
|
|
70
|
+
console.log(
|
|
71
|
+
[
|
|
72
|
+
"",
|
|
73
|
+
"🚨 IMPORTANT NOTICE:",
|
|
74
|
+
"----------------------------------------",
|
|
75
|
+
`We've detected a global installation of ${green(
|
|
76
|
+
"@webiny/cli"
|
|
77
|
+
)}. This might not play well with your new project.`,
|
|
78
|
+
`We recommend you do one of the following things:\n`,
|
|
79
|
+
` - uninstall the global @webiny/cli package by running ${green(
|
|
80
|
+
"npm rm -g @webiny/cli"
|
|
81
|
+
)} or`,
|
|
82
|
+
` - run webiny commands using ${green(
|
|
83
|
+
"yarn webiny"
|
|
84
|
+
)} so that the package is always resolved to your project dependencies\n`,
|
|
85
|
+
`The second option is also recommended if you have an older version of Webiny project you want to keep using.`,
|
|
86
|
+
"----------------------------------------",
|
|
87
|
+
""
|
|
88
|
+
].join("\n")
|
|
89
|
+
);
|
|
90
|
+
} catch (err) {
|
|
91
|
+
// @webiny/cli is not installed globally
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
console.log(`Initializing a new Webiny project in ${green(projectRoot)}...`);
|
|
95
|
+
|
|
96
|
+
await sendEvent({ event: "create-webiny-project-start" });
|
|
97
|
+
|
|
98
|
+
let isGitAvailable = false;
|
|
99
|
+
try {
|
|
100
|
+
await execa("git", ["--version"]);
|
|
101
|
+
isGitAvailable = true;
|
|
102
|
+
} catch {
|
|
103
|
+
// Git is not available.
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const tasks = new Listr(
|
|
107
|
+
[
|
|
108
|
+
{
|
|
109
|
+
// Creates root package.json.
|
|
110
|
+
title: "Prepare project folder",
|
|
111
|
+
task: () => {
|
|
112
|
+
checkProjectName(projectName);
|
|
113
|
+
fs.ensureDirSync(projectName);
|
|
114
|
+
writeJson.sync(
|
|
115
|
+
path.join(projectRoot, "package.json"),
|
|
116
|
+
getPackageJson(projectName)
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
// Setup yarn
|
|
122
|
+
title: "Setup yarn",
|
|
123
|
+
task: async () => {
|
|
124
|
+
await execa("yarn", ["set", "version", "berry"], { cwd: projectRoot });
|
|
125
|
+
|
|
126
|
+
const yamlPath = path.join(projectRoot, ".yarnrc.yml");
|
|
127
|
+
const parsedYaml = yaml.load(fs.readFileSync(yamlPath, "utf-8"));
|
|
128
|
+
|
|
129
|
+
// Default settings are applied here. Currently we only apply the `nodeLinker` param.
|
|
130
|
+
parsedYaml.nodeLinker = "node-modules";
|
|
131
|
+
|
|
132
|
+
// Enables adding additional params into the `.yarnrc.yml` file.
|
|
133
|
+
if (assignToYarnRc) {
|
|
134
|
+
let parsedAssignToYarnRc;
|
|
135
|
+
try {
|
|
136
|
+
parsedAssignToYarnRc = JSON.parse(assignToYarnRc);
|
|
137
|
+
} catch {
|
|
138
|
+
console.log(
|
|
139
|
+
yellow("Warning: could not parse provided --assign-to-yarnrc JSON.")
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (parsedAssignToYarnRc) {
|
|
144
|
+
Object.assign(parsedYaml, parsedAssignToYarnRc);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
fs.writeFileSync(yamlPath, yaml.dump(parsedYaml));
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
// "yarn adds" given template which can be either a real package or a path of a local package.
|
|
153
|
+
title: `Install template package`,
|
|
154
|
+
task: async context => {
|
|
155
|
+
let add;
|
|
156
|
+
let templateName = `@webiny/cwp-template-${template}`;
|
|
157
|
+
|
|
158
|
+
if (template.startsWith(".") || template.startsWith("file:")) {
|
|
159
|
+
templateName =
|
|
160
|
+
"file:" + path.relative(projectName, template.replace("file:", ""));
|
|
161
|
+
add = templateName;
|
|
162
|
+
} else {
|
|
163
|
+
add = `${templateName}@${tag}`;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Assign template name to context.
|
|
167
|
+
context.templateName = templateName;
|
|
168
|
+
|
|
169
|
+
await execa("yarn", ["add", add], { cwd: projectRoot });
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
isGitAvailable
|
|
173
|
+
? {
|
|
174
|
+
// Initialize `git` by executing `git init` in project directory.
|
|
175
|
+
title: `Initialize git`,
|
|
176
|
+
task: (ctx, task) => {
|
|
177
|
+
try {
|
|
178
|
+
execa.sync("git", ["--version"]);
|
|
179
|
+
execa.sync("git", ["init"], { cwd: projectRoot });
|
|
180
|
+
fs.writeFileSync(
|
|
181
|
+
path.join(projectRoot, ".gitignore"),
|
|
182
|
+
"node_modules/"
|
|
183
|
+
);
|
|
184
|
+
} catch (err) {
|
|
185
|
+
task.skip("Git repo not initialized", err);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
: null
|
|
190
|
+
].filter(Boolean)
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
// The `context` object will be filled with additional values in the `tasks.run` process.
|
|
194
|
+
const context = {};
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
await tasks.run(context);
|
|
198
|
+
|
|
199
|
+
let templateName = context.templateName;
|
|
200
|
+
|
|
201
|
+
console.log(`Starting ${green(templateName)} template ...`);
|
|
202
|
+
if (templateName.startsWith("file:")) {
|
|
203
|
+
templateName = templateName.replace("file:", "");
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const templatePath = path.dirname(
|
|
207
|
+
require.resolve(path.join(templateName, "package.json"), {
|
|
208
|
+
paths: [projectRoot]
|
|
209
|
+
})
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
await new Promise(resolve => {
|
|
213
|
+
setTimeout(() => {
|
|
214
|
+
resolve();
|
|
215
|
+
}, 500);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
let parsedTemplateOptions = {};
|
|
219
|
+
if (templateOptions) {
|
|
220
|
+
try {
|
|
221
|
+
parsedTemplateOptions = JSON.parse(templateOptions);
|
|
222
|
+
} catch {
|
|
223
|
+
console.log(yellow("Warning: could not parse provided --template-options JSON."));
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
console.log();
|
|
228
|
+
await require(templatePath)({
|
|
229
|
+
log,
|
|
230
|
+
isGitAvailable,
|
|
231
|
+
projectName,
|
|
232
|
+
projectRoot,
|
|
233
|
+
interactive,
|
|
234
|
+
templateOptions: parsedTemplateOptions
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
await sendEvent({ event: "create-webiny-project-end" });
|
|
238
|
+
} catch (err) {
|
|
239
|
+
await sendEvent({
|
|
240
|
+
event: "create-webiny-project-error",
|
|
241
|
+
properties: {
|
|
242
|
+
errorMessage: err.message,
|
|
243
|
+
errorStack: err.stack
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const node = process.versions.node;
|
|
248
|
+
const os = process.platform;
|
|
249
|
+
|
|
250
|
+
let yarn = NOT_APPLICABLE;
|
|
251
|
+
try {
|
|
252
|
+
const subprocess = await execa("yarn", ["--version"], { cwd: projectRoot });
|
|
253
|
+
yarn = subprocess.stdout;
|
|
254
|
+
} catch {}
|
|
255
|
+
|
|
256
|
+
let cwp = NOT_APPLICABLE;
|
|
257
|
+
try {
|
|
258
|
+
const subprocess = await execa("npx", ["create-webiny-project", "--version"]);
|
|
259
|
+
cwp = subprocess.stdout;
|
|
260
|
+
} catch {}
|
|
261
|
+
|
|
262
|
+
let cwpTemplate = NOT_APPLICABLE;
|
|
263
|
+
try {
|
|
264
|
+
const subprocess = await execa("yarn", ["info", "@webiny/cwp-template-aws", "--json"], {
|
|
265
|
+
cwd: projectRoot
|
|
266
|
+
});
|
|
267
|
+
const data = JSON.parse(subprocess.stdout);
|
|
268
|
+
cwpTemplate = `@webiny/cwp-template-${template}@${data.children.Version}`;
|
|
269
|
+
} catch {}
|
|
270
|
+
|
|
271
|
+
let templateOptionsJson = "{}";
|
|
272
|
+
if (templateOptions) {
|
|
273
|
+
try {
|
|
274
|
+
templateOptionsJson = JSON.stringify(templateOptions);
|
|
275
|
+
} catch {}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
console.log(
|
|
279
|
+
[
|
|
280
|
+
"",
|
|
281
|
+
`${green("ERROR OUTPUT: ")}`,
|
|
282
|
+
"----------------------------------------",
|
|
283
|
+
err.message,
|
|
284
|
+
"",
|
|
285
|
+
`${green("SYSTEM INFORMATION: ")}`,
|
|
286
|
+
"----------------------------------------",
|
|
287
|
+
`Operating System: ${os}`,
|
|
288
|
+
`Node: ${node}`,
|
|
289
|
+
`Yarn: ${yarn}`,
|
|
290
|
+
`create-webiny-project: ${cwp}`,
|
|
291
|
+
`Template: ${cwpTemplate}`,
|
|
292
|
+
`Template Options: ${templateOptionsJson}`,
|
|
293
|
+
"",
|
|
294
|
+
"Please open an issue including the error output at https://github.com/webiny/webiny-js/issues/new.",
|
|
295
|
+
"You can also get in touch with us on our Slack Community: https://www.webiny.com/slack",
|
|
296
|
+
""
|
|
297
|
+
].join("\n")
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
console.log(`Writing log to ${green(path.resolve(log))}...`);
|
|
301
|
+
fs.writeFileSync(path.resolve(log), err.toString());
|
|
302
|
+
|
|
303
|
+
if (cleanup) {
|
|
304
|
+
console.log("Cleaning up generated files and folders...");
|
|
305
|
+
rimraf.sync(projectRoot);
|
|
306
|
+
console.log("Done.");
|
|
307
|
+
} else {
|
|
308
|
+
console.log("Project cleanup skipped.");
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
await sendEvent({ event: "create-webiny-project-end" });
|
|
312
|
+
process.exit(1);
|
|
313
|
+
}
|
|
314
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const fetch = require("node-fetch");
|
|
2
|
+
const pRetry = require("p-retry");
|
|
3
|
+
const semver = require("semver");
|
|
4
|
+
const execa = require("execa");
|
|
5
|
+
|
|
6
|
+
module.exports = function getPackageVersion(name, tag = "latest") {
|
|
7
|
+
if (semver.valid(tag)) {
|
|
8
|
+
return tag;
|
|
9
|
+
}
|
|
10
|
+
const getVersion = async () => {
|
|
11
|
+
const { stdout: registry } = await execa("npm", ["config", "get", "registry"]);
|
|
12
|
+
const res = await fetch(`${registry}${name}`);
|
|
13
|
+
const json = await res.json();
|
|
14
|
+
|
|
15
|
+
const tagVersion = json["dist-tags"][tag];
|
|
16
|
+
if (!tagVersion || semver.lte(tagVersion, json["dist-tags"]["latest"])) {
|
|
17
|
+
return json["dist-tags"]["latest"];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return tagVersion;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
return pRetry(getVersion, { retries: 5 });
|
|
24
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const os = require("os");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
const readJson = require("load-json-file");
|
|
4
|
+
const writeJson = require("write-json-file");
|
|
5
|
+
|
|
6
|
+
const configPath = path.join(os.homedir(), ".webiny", "config");
|
|
7
|
+
|
|
8
|
+
module.exports = async () => {
|
|
9
|
+
// Check user ID
|
|
10
|
+
try {
|
|
11
|
+
const config = await readJson(configPath);
|
|
12
|
+
if (!config.id) {
|
|
13
|
+
throw Error("Invalid Webiny config!");
|
|
14
|
+
}
|
|
15
|
+
} catch (e) {
|
|
16
|
+
const { v4: uuidv4 } = require("uuid");
|
|
17
|
+
// A new config file is written if it doesn't exist or is invalid.
|
|
18
|
+
writeJson.sync(configPath, { id: uuidv4(), telemetry: true });
|
|
19
|
+
}
|
|
20
|
+
};
|