create-astro 0.0.0-ui-20221007132109
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 +61 -0
- package/README.md +114 -0
- package/create-astro.mjs +14 -0
- package/dist/actions/check-cwd.js +12 -0
- package/dist/actions/copy-template.js +53 -0
- package/dist/actions/initialize-git.js +4 -0
- package/dist/actions/install-deps.js +8 -0
- package/dist/actions/setup-typescript.js +25 -0
- package/dist/actions/shared.js +44 -0
- package/dist/index.js +195 -0
- package/dist/messages.js +95 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Fred K. Schott
|
|
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.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
"""
|
|
25
|
+
This license applies to parts of the `packages/create-astro` and `packages/astro` subdirectories originating from the https://github.com/sveltejs/kit repository:
|
|
26
|
+
|
|
27
|
+
Copyright (c) 2020 [these people](https://github.com/sveltejs/kit/graphs/contributors)
|
|
28
|
+
|
|
29
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
30
|
+
|
|
31
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
32
|
+
|
|
33
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
This license applies to parts of the `packages/create-astro` and `packages/astro` subdirectories originating from the https://github.com/vitejs/vite repository:
|
|
39
|
+
|
|
40
|
+
MIT License
|
|
41
|
+
|
|
42
|
+
Copyright (c) 2019-present, Yuxi (Evan) You and Vite contributors
|
|
43
|
+
|
|
44
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
45
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
46
|
+
in the Software without restriction, including without limitation the rights
|
|
47
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
48
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
49
|
+
furnished to do so, subject to the following conditions:
|
|
50
|
+
|
|
51
|
+
The above copyright notice and this permission notice shall be included in all
|
|
52
|
+
copies or substantial portions of the Software.
|
|
53
|
+
|
|
54
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
55
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
56
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
57
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
58
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
59
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
60
|
+
SOFTWARE.
|
|
61
|
+
"""
|
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# `create-astro`
|
|
2
|
+
|
|
3
|
+
`create-astro` is the fastest way to start a new Astro project from scratch. It will walk you through every step of setting up your new Astro project. It allows you to choose from a few different starter templates or provide your own using the `--template` argument.
|
|
4
|
+
|
|
5
|
+
## Interactive Mode
|
|
6
|
+
|
|
7
|
+
Run the following command in your terminal to start our handy install wizard in interactive mode.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# create a new project with npm
|
|
11
|
+
npm create astro@latest
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# create a new project with pnpm
|
|
16
|
+
pnpm create astro@latest
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# create a new project with yarn
|
|
21
|
+
yarn create astro
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
You can run `create-astro` anywhere on your machine, so there’s no need to create a new empty directory for your project before you begin. If you don’t have an empty directory yet for your new project, the wizard will help create one for you automatically.
|
|
25
|
+
|
|
26
|
+
## Advanced Usage
|
|
27
|
+
|
|
28
|
+
`create-astro` supports some handy CLI arguments for advanced users.
|
|
29
|
+
|
|
30
|
+
### Directory
|
|
31
|
+
|
|
32
|
+
The first argument will be treated as your target directory.
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# create a new project in a new `my-project/` directory
|
|
36
|
+
npm create astro@latest my-project
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Template
|
|
40
|
+
|
|
41
|
+
The `--template` flag can be passed to specify any [official starter template](https://github.com/withastro/astro/tree/main/examples) available on GitHub.
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# create a new project from the `minimal` starter template
|
|
45
|
+
npm create astro@latest --template minimal
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Any GitHub repo can be used as a template, following the `user/repo` format.
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
npm create astro@latest --template mayank99/astro-minimal-starter
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Yes / No
|
|
55
|
+
|
|
56
|
+
The `--yes` (or `-y`) flag can be used to bypass any confirmation prompts and proceed with the default answer.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm create astro@latest -y
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The `--no` (or `-n`) flag can be used to bypass any confirmations prompts and proceed without executing any actions.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm create astro@latest -n
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Combined with the above directory and template arguments, `create-astro` becomes fully non-interactive for a super quick start.
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# copy minimal to my-project/ and confirm all prompts
|
|
72
|
+
npm create astro@latest my-project --template minimal -y
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# copy minimal to my-project/ and dismiss all prompts
|
|
77
|
+
npm create astro@latest my-project --template minimal -n
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Dry Run
|
|
81
|
+
|
|
82
|
+
Just looking to get the hang of `create-astro`? You can pass the `--dry-run` flag to ensure no files will be created.
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
npm create astro@latest --dry-run
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Install
|
|
89
|
+
|
|
90
|
+
Dependency installation can be controlled with the `--install` or `--no-install` flags to bypass the installation prompt.
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
npm create astro@latest --install
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Git
|
|
97
|
+
|
|
98
|
+
Git initialization can be controlled with the `--git` or `--no-git` flags to bypass the git prompt.
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm create astro@latest --git
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### TypeScript
|
|
105
|
+
|
|
106
|
+
TypeScript customization can be controlled with the `--typescript` flag. Valid options are `strict`, `strictest`, and `relaxed`.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npm create astro@latest --typescript strictest
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Acknowledgements
|
|
113
|
+
|
|
114
|
+
- Huge thanks to [`giget`](https://github.com/unjs/giget) for handling template downloads!
|
package/create-astro.mjs
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const currentVersion = process.versions.node;
|
|
5
|
+
const requiredMajorVersion = parseInt(currentVersion.split('.')[0], 10);
|
|
6
|
+
const minimumMajorVersion = 14;
|
|
7
|
+
|
|
8
|
+
if (requiredMajorVersion < minimumMajorVersion) {
|
|
9
|
+
console.error(`Node.js v${currentVersion} is out of date and unsupported!`);
|
|
10
|
+
console.error(`Please use Node.js v${minimumMajorVersion} or higher.`);
|
|
11
|
+
process.exit(1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
import('./dist/index.js').then(({ main }) => main());
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/* eslint no-console: 'off' */
|
|
2
|
+
import { isEmpty } from "./shared.js";
|
|
3
|
+
import { info } from "../messages.js";
|
|
4
|
+
import { color } from "@astrojs/cli-kit";
|
|
5
|
+
export default async function checkCwd(cwd) {
|
|
6
|
+
const empty = cwd && isEmpty(cwd);
|
|
7
|
+
if (empty) {
|
|
8
|
+
console.log('');
|
|
9
|
+
await info('dir', `Using ${color.reset(cwd)}${color.dim(' as project directory')}`);
|
|
10
|
+
}
|
|
11
|
+
return empty;
|
|
12
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/* eslint no-console: 'off' */
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { color } from "@astrojs/cli-kit";
|
|
5
|
+
import { downloadTemplate } from 'giget';
|
|
6
|
+
import { error } from '../messages.js';
|
|
7
|
+
// some files are only needed for online editors when using astro.new. Remove for create-astro installs.
|
|
8
|
+
const FILES_TO_REMOVE = ['sandbox.config.json', 'CHANGELOG.md'];
|
|
9
|
+
const FILES_TO_UPDATE = {
|
|
10
|
+
'package.json': (file, overrides) => fs.promises.readFile(file, 'utf-8').then(value => (fs.promises.writeFile(file, JSON.stringify(Object.assign(JSON.parse(value), Object.assign(overrides, { private: undefined })), null, '\t'), 'utf-8')))
|
|
11
|
+
};
|
|
12
|
+
export default async function copyTemplate(template, { name, flags, cwd, pkgManager }) {
|
|
13
|
+
const ref = flags.commit ? `#${flags.commit}` : '';
|
|
14
|
+
const isThirdParty = template.includes('/');
|
|
15
|
+
const templateTarget = isThirdParty
|
|
16
|
+
? template
|
|
17
|
+
: `github:withastro/astro/examples/${template}#latest`;
|
|
18
|
+
// Copy
|
|
19
|
+
if (!flags.dryRun) {
|
|
20
|
+
try {
|
|
21
|
+
await downloadTemplate(`${templateTarget}${ref}`, {
|
|
22
|
+
force: true,
|
|
23
|
+
provider: 'github',
|
|
24
|
+
cwd,
|
|
25
|
+
dir: '.',
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
fs.rmdirSync(cwd);
|
|
30
|
+
if (err.message.includes('404')) {
|
|
31
|
+
await error('Error', `Template ${color.reset(template)} ${color.dim('does not exist!')}`);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
console.error(err.message);
|
|
35
|
+
}
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
// Post-process in parallel
|
|
39
|
+
const removeFiles = FILES_TO_REMOVE.map(async (file) => {
|
|
40
|
+
const fileLoc = path.resolve(path.join(cwd, file));
|
|
41
|
+
if (fs.existsSync(fileLoc)) {
|
|
42
|
+
return fs.promises.rm(fileLoc, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
const updateFiles = Object.entries(FILES_TO_UPDATE).map(async ([file, update]) => {
|
|
46
|
+
const fileLoc = path.resolve(path.join(cwd, file));
|
|
47
|
+
if (fs.existsSync(fileLoc)) {
|
|
48
|
+
return update(fileLoc, { name });
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
await Promise.all([...removeFiles, ...updateFiles]);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { execa } from 'execa';
|
|
2
|
+
export default async function installDeps({ pkgManager, cwd }) {
|
|
3
|
+
const installExec = execa(pkgManager, ['install'], { cwd });
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
installExec.on('error', (error) => reject(error));
|
|
6
|
+
installExec.on('close', () => resolve());
|
|
7
|
+
});
|
|
8
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { assign, parse, stringify } from 'comment-json';
|
|
4
|
+
export default async function setupTypeScript(value, { cwd }) {
|
|
5
|
+
if (value === 'default')
|
|
6
|
+
return;
|
|
7
|
+
const templateTSConfigPath = path.join(cwd, 'tsconfig.json');
|
|
8
|
+
fs.readFile(templateTSConfigPath, (err, data) => {
|
|
9
|
+
if (err && err.code === 'ENOENT') {
|
|
10
|
+
// If the template doesn't have a tsconfig.json, let's add one instead
|
|
11
|
+
fs.writeFileSync(templateTSConfigPath, stringify({ extends: `astro/tsconfigs/${value}` }, null, 2));
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const templateTSConfig = parse(data.toString());
|
|
15
|
+
if (templateTSConfig && typeof templateTSConfig === 'object') {
|
|
16
|
+
const result = assign(templateTSConfig, {
|
|
17
|
+
extends: `astro/tsconfigs/${value}`,
|
|
18
|
+
});
|
|
19
|
+
fs.writeFileSync(templateTSConfigPath, stringify(result, null, 2));
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
throw new Error("There was an error applying the requested TypeScript settings. This could be because the template's tsconfig.json is malformed");
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
// Some existing files and directories can be safely ignored when checking if a directory is a valid project directory.
|
|
3
|
+
// https://github.com/facebook/create-react-app/blob/d960b9e38c062584ff6cfb1a70e1512509a966e7/packages/create-react-app/createReactApp.js#L907-L934
|
|
4
|
+
const VALID_PROJECT_DIRECTORY_SAFE_LIST = [
|
|
5
|
+
'.DS_Store',
|
|
6
|
+
'.git',
|
|
7
|
+
'.gitkeep',
|
|
8
|
+
'.gitattributes',
|
|
9
|
+
'.gitignore',
|
|
10
|
+
'.gitlab-ci.yml',
|
|
11
|
+
'.hg',
|
|
12
|
+
'.hgcheck',
|
|
13
|
+
'.hgignore',
|
|
14
|
+
'.idea',
|
|
15
|
+
'.npmignore',
|
|
16
|
+
'.travis.yml',
|
|
17
|
+
'.yarn',
|
|
18
|
+
'.yarnrc.yml',
|
|
19
|
+
'docs',
|
|
20
|
+
'LICENSE',
|
|
21
|
+
'mkdocs.yml',
|
|
22
|
+
'Thumbs.db',
|
|
23
|
+
/\.iml$/,
|
|
24
|
+
/^npm-debug\.log/,
|
|
25
|
+
/^yarn-debug\.log/,
|
|
26
|
+
/^yarn-error\.log/,
|
|
27
|
+
];
|
|
28
|
+
export function isEmpty(dirPath) {
|
|
29
|
+
if (!fs.existsSync(dirPath)) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
const conflicts = fs.readdirSync(dirPath).filter((content) => {
|
|
33
|
+
return !VALID_PROJECT_DIRECTORY_SAFE_LIST.some((safeContent) => {
|
|
34
|
+
return typeof safeContent === 'string' ? content === safeContent : safeContent.test(content);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
return conflicts.length === 0;
|
|
38
|
+
}
|
|
39
|
+
export function toValidName(name) {
|
|
40
|
+
return name
|
|
41
|
+
.replace(/^\.\//, '')
|
|
42
|
+
.replace(/[^a-zA-Z0-9-]/g, '-')
|
|
43
|
+
.replace(/(^\-|\-$)+/, '');
|
|
44
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/* eslint no-console: 'off' */
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import yargs from 'yargs-parser';
|
|
5
|
+
import detectPackageManager from 'which-pm-runs';
|
|
6
|
+
import { say, label, color, prompt, generateProjectName, spinner } from '@astrojs/cli-kit';
|
|
7
|
+
import { random, align } from '@astrojs/cli-kit/utils';
|
|
8
|
+
import { banner, getName, getVersion, welcome, info, typescriptByDefault, nextSteps, error } from './messages.js';
|
|
9
|
+
import { isEmpty, toValidName } from './actions/shared.js';
|
|
10
|
+
import checkCwd from './actions/check-cwd.js';
|
|
11
|
+
import copyTemplate from './actions/copy-template.js';
|
|
12
|
+
import installDeps from './actions/install-deps.js';
|
|
13
|
+
import initializeGit from './actions/initialize-git.js';
|
|
14
|
+
import setupTypeScript from './actions/setup-typescript.js';
|
|
15
|
+
// NOTE: In the v7.x version of npm, the default behavior of `npm init` was changed
|
|
16
|
+
// to no longer require `--` to pass args and instead pass `--` directly to us. This
|
|
17
|
+
// broke our arg parser, since `--` is a special kind of flag. Filtering for `--` here
|
|
18
|
+
// fixes the issue so that create-astro now works on all npm versions.
|
|
19
|
+
const cleanArgv = process.argv.filter((arg) => arg !== '--');
|
|
20
|
+
const flags = yargs(cleanArgv, { boolean: ['yes', 'no', 'install', 'git', 'skip-houston'], alias: { 'y': 'yes', 'n': 'no' } });
|
|
21
|
+
const title = (text) => align(label(text), 'end', 7) + ' ';
|
|
22
|
+
// Please also update the installation instructions in the docs at https://github.com/withastro/docs/blob/main/src/pages/en/install/auto.md if you make any changes to the flow or wording here.
|
|
23
|
+
export async function main() {
|
|
24
|
+
const pkgManager = detectPackageManager()?.name ?? 'npm';
|
|
25
|
+
const [username, version] = await Promise.all([getName(), getVersion()]);
|
|
26
|
+
let cwd = flags['_'][2];
|
|
27
|
+
let { template, no, yes, install, git: init, typescript, skipHouston } = flags;
|
|
28
|
+
let projectName = cwd;
|
|
29
|
+
if (no) {
|
|
30
|
+
yes = false;
|
|
31
|
+
if (install == undefined)
|
|
32
|
+
install = false;
|
|
33
|
+
if (init == undefined)
|
|
34
|
+
init = false;
|
|
35
|
+
if (typescript == undefined)
|
|
36
|
+
typescript = 'strict';
|
|
37
|
+
}
|
|
38
|
+
skipHouston = skipHouston ?? [yes, no, install, init, typescript].some(v => v !== undefined);
|
|
39
|
+
if (!skipHouston) {
|
|
40
|
+
await say([
|
|
41
|
+
['Welcome', 'to', label('astro', color.bgGreen, color.black), color.green(`v${version}`) + ',', `${username}!`],
|
|
42
|
+
random(welcome),
|
|
43
|
+
]);
|
|
44
|
+
await banner(version);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.log('');
|
|
48
|
+
await banner(version);
|
|
49
|
+
}
|
|
50
|
+
await checkCwd(cwd);
|
|
51
|
+
if (!cwd || !isEmpty(cwd)) {
|
|
52
|
+
if (!isEmpty(cwd)) {
|
|
53
|
+
await info('Hmm...', `${color.reset(`"${cwd}"`)}${color.dim(` is not empty!`)}`);
|
|
54
|
+
}
|
|
55
|
+
const { name } = await prompt({
|
|
56
|
+
name: 'name',
|
|
57
|
+
type: 'text',
|
|
58
|
+
label: title('dir'),
|
|
59
|
+
message: 'Where should we create your new project?',
|
|
60
|
+
initial: `./${generateProjectName()}`,
|
|
61
|
+
validate(value) {
|
|
62
|
+
if (!isEmpty(value)) {
|
|
63
|
+
return `Directory is not empty!`;
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
cwd = name;
|
|
69
|
+
projectName = toValidName(name);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
let name = cwd;
|
|
73
|
+
if (name === '.' || name === './') {
|
|
74
|
+
const parts = process.cwd().split(path.sep);
|
|
75
|
+
name = parts[parts.length - 1];
|
|
76
|
+
}
|
|
77
|
+
projectName = toValidName(name);
|
|
78
|
+
}
|
|
79
|
+
if (!cwd) {
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
if (!template) {
|
|
83
|
+
({ template } = await prompt({
|
|
84
|
+
name: 'template',
|
|
85
|
+
type: 'select',
|
|
86
|
+
label: title('tmpl'),
|
|
87
|
+
message: 'How would you like to start your new project?',
|
|
88
|
+
initial: 'basics',
|
|
89
|
+
choices: [
|
|
90
|
+
{ value: 'basics', label: 'Include sample files', hint: '(recommended)' },
|
|
91
|
+
{ value: 'blog', label: 'Use blog template' },
|
|
92
|
+
{ value: 'minimal', label: 'Empty' },
|
|
93
|
+
],
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
await info('tmpl', `Using ${color.reset(template)}${color.dim(' as project template')}`);
|
|
98
|
+
}
|
|
99
|
+
if (flags.dryRun) {
|
|
100
|
+
await info('--dry-run', `Skipping template copying`);
|
|
101
|
+
}
|
|
102
|
+
else if (template) {
|
|
103
|
+
await spinner({
|
|
104
|
+
start: 'Template copying...',
|
|
105
|
+
end: 'Template copied',
|
|
106
|
+
while: () => copyTemplate(template, { name: projectName, flags, cwd, pkgManager })
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
let deps = install ?? yes;
|
|
113
|
+
if (deps === undefined) {
|
|
114
|
+
({ deps } = await prompt({
|
|
115
|
+
name: 'deps',
|
|
116
|
+
type: 'confirm',
|
|
117
|
+
label: title('deps'),
|
|
118
|
+
message: `Install dependencies?`,
|
|
119
|
+
hint: 'recommended',
|
|
120
|
+
initial: true
|
|
121
|
+
}));
|
|
122
|
+
}
|
|
123
|
+
if (flags.dryRun) {
|
|
124
|
+
await info('--dry-run', `Skipping dependency installation`);
|
|
125
|
+
}
|
|
126
|
+
else if (deps) {
|
|
127
|
+
await spinner({ start: `Dependencies installing with ${pkgManager}...`, end: 'Dependencies installed', while: () => installDeps({ pkgManager, cwd }) });
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
await info(typeof install === 'boolean' ? 'deps [skip]' : 'No problem!', 'Remember to install dependencies after setup.');
|
|
131
|
+
}
|
|
132
|
+
let git = init ?? yes;
|
|
133
|
+
if (git === undefined) {
|
|
134
|
+
({ git } = await prompt({
|
|
135
|
+
name: 'git',
|
|
136
|
+
type: 'confirm',
|
|
137
|
+
label: title('git'),
|
|
138
|
+
message: `Initialize a new git repository?`,
|
|
139
|
+
hint: 'optional',
|
|
140
|
+
initial: true
|
|
141
|
+
}));
|
|
142
|
+
}
|
|
143
|
+
if (flags.dryRun) {
|
|
144
|
+
await info('--dry-run', `Skipping Git initialization`);
|
|
145
|
+
}
|
|
146
|
+
else if (git) {
|
|
147
|
+
await spinner({ start: 'Git initializing...', end: 'Git initialized', while: () => initializeGit({ cwd }) });
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
await info(typeof init === 'boolean' ? 'git [skip]' : 'Sounds good!', `You can always run ${color.reset('git init')}${color.dim(' manually.')}`);
|
|
151
|
+
}
|
|
152
|
+
let ts = typescript ?? (yes ? 'strict' : yes);
|
|
153
|
+
if (ts === undefined) {
|
|
154
|
+
({ ts } = await prompt({
|
|
155
|
+
name: 'ts',
|
|
156
|
+
type: 'select',
|
|
157
|
+
label: title('ts'),
|
|
158
|
+
message: `Customize TypeScript?`,
|
|
159
|
+
initial: 'strict',
|
|
160
|
+
choices: [
|
|
161
|
+
{ value: 'strict', label: 'Strict', hint: `(recommended)` },
|
|
162
|
+
{ value: 'strictest', label: 'Strictest' },
|
|
163
|
+
{ value: 'default', label: 'Relaxed' },
|
|
164
|
+
{ value: 'unsure', label: `Hmm... I'm not sure` },
|
|
165
|
+
]
|
|
166
|
+
}));
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
if (!['strict', 'strictest', 'relaxed', 'default'].includes(ts)) {
|
|
170
|
+
if (!flags.dryRun) {
|
|
171
|
+
fs.rmSync(cwd, { recursive: true, force: true });
|
|
172
|
+
}
|
|
173
|
+
error('Error', `Unknown TypeScript option ${color.reset(ts)}${color.dim('! Expected strict | strictest | relaxed')}`);
|
|
174
|
+
process.exit(1);
|
|
175
|
+
}
|
|
176
|
+
await info('ts', `Using ${color.reset(ts)}${color.dim(' TypeScript configuration')}`);
|
|
177
|
+
}
|
|
178
|
+
if (flags.dryRun) {
|
|
179
|
+
await info('--dry-run', `Skipping TypeScript setup`);
|
|
180
|
+
}
|
|
181
|
+
else if (ts && ts !== 'unsure') {
|
|
182
|
+
if (ts === 'relaxed') {
|
|
183
|
+
ts = 'default';
|
|
184
|
+
}
|
|
185
|
+
await spinner({ start: 'TypeScript customizing...', end: 'TypeScript customized', while: () => setupTypeScript(ts, { cwd }) });
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
await typescriptByDefault();
|
|
189
|
+
}
|
|
190
|
+
let projectDir = path.relative(process.cwd(), cwd);
|
|
191
|
+
const devCmd = pkgManager === 'npm' ? 'npm run dev' : `${pkgManager} dev`;
|
|
192
|
+
await nextSteps({ projectDir, devCmd });
|
|
193
|
+
await say(['Good luck out there, astronaut! 🚀']);
|
|
194
|
+
process.exit(0);
|
|
195
|
+
}
|
package/dist/messages.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/* eslint no-console: 'off' */
|
|
2
|
+
import { exec } from 'node:child_process';
|
|
3
|
+
import { get } from 'node:https';
|
|
4
|
+
import { color, label } from '@astrojs/cli-kit';
|
|
5
|
+
import { sleep } from '@astrojs/cli-kit/utils';
|
|
6
|
+
import stripAnsi from 'strip-ansi';
|
|
7
|
+
export const welcome = [
|
|
8
|
+
`Let's claim your corner of the internet.`,
|
|
9
|
+
`I'll be your assistant today.`,
|
|
10
|
+
`Let's build something awesome!`,
|
|
11
|
+
`Let's build something great!`,
|
|
12
|
+
`Let's build something fast!`,
|
|
13
|
+
`Let's make the web weird!`,
|
|
14
|
+
`Let's make the web a better place!`,
|
|
15
|
+
`Let's create a new project!`,
|
|
16
|
+
`Let's create something unqiue!`,
|
|
17
|
+
`Time to build a new website.`,
|
|
18
|
+
`Time to build a faster website.`,
|
|
19
|
+
`Time to build a sweet new website.`,
|
|
20
|
+
`We're glad to have you on board.`,
|
|
21
|
+
`Keeping the internet weird since 2021.`,
|
|
22
|
+
`Initiating launch sequence...`,
|
|
23
|
+
`Initiating launch sequence... right... now!`,
|
|
24
|
+
`Awaiting further instructions.`,
|
|
25
|
+
];
|
|
26
|
+
export const getName = () => new Promise((resolve) => {
|
|
27
|
+
exec('git config user.name', { encoding: 'utf-8' }, (_1, gitName, _2) => {
|
|
28
|
+
if (gitName.trim()) {
|
|
29
|
+
return resolve(gitName.split(' ')[0].trim());
|
|
30
|
+
}
|
|
31
|
+
exec('whoami', { encoding: 'utf-8' }, (_3, whoami, _4) => {
|
|
32
|
+
if (whoami.trim()) {
|
|
33
|
+
return resolve(whoami.split(' ')[0].trim());
|
|
34
|
+
}
|
|
35
|
+
return resolve('astronaut');
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
let v;
|
|
40
|
+
export const getVersion = () => new Promise((resolve) => {
|
|
41
|
+
if (v)
|
|
42
|
+
return resolve(v);
|
|
43
|
+
get('https://registry.npmjs.org/astro/latest', (res) => {
|
|
44
|
+
let body = '';
|
|
45
|
+
res.on('data', chunk => body += chunk);
|
|
46
|
+
res.on('end', () => {
|
|
47
|
+
const { version } = JSON.parse(body);
|
|
48
|
+
v = version;
|
|
49
|
+
resolve(version);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
export const banner = async (version) => console.log(`\n${label('astro', color.bgGreen, color.black)} ${color.green(color.bold(`v${version}`))} ${color.bold('Launch sequence initiated.')}`);
|
|
54
|
+
export const info = async (prefix, text) => {
|
|
55
|
+
await sleep(100);
|
|
56
|
+
if (process.stdout.columns < 80) {
|
|
57
|
+
console.log(`${' '.repeat(5)} ${color.cyan('◼')} ${color.cyan(prefix)}`);
|
|
58
|
+
console.log(`${' '.repeat(9)}${color.dim(text)}`);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
console.log(`${' '.repeat(5)} ${color.cyan('◼')} ${color.cyan(prefix)} ${color.dim(text)}`);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
export const error = async (prefix, text) => {
|
|
65
|
+
if (process.stdout.columns < 80) {
|
|
66
|
+
console.log(`${' '.repeat(5)} ${color.red('▲')} ${color.red(prefix)}`);
|
|
67
|
+
console.log(`${' '.repeat(9)}${color.dim(text)}`);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
console.log(`${' '.repeat(5)} ${color.red('▲')} ${color.red(prefix)} ${color.dim(text)}`);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
export const typescriptByDefault = async () => {
|
|
74
|
+
await info(`That\'s fine!`, 'Astro comes with TypeScript enabled by default.');
|
|
75
|
+
console.log(`${' '.repeat(9)}${color.dim(`We'll use the most relaxed settings for you.`)}`);
|
|
76
|
+
await sleep(300);
|
|
77
|
+
};
|
|
78
|
+
export const nextSteps = async ({ projectDir, devCmd }) => {
|
|
79
|
+
const max = process.stdout.columns;
|
|
80
|
+
const prefix = max < 80 ? ' ' : ' '.repeat(9);
|
|
81
|
+
await sleep(200);
|
|
82
|
+
console.log(`\n ${color.bgCyan(` ${color.black('next')} `)} ${color.bold('Liftoff confirmed. Explore your project!')}`);
|
|
83
|
+
await sleep(100);
|
|
84
|
+
if (projectDir !== '') {
|
|
85
|
+
const enter = [`\n${prefix}Enter your project directory using`, color.cyan(`cd ./${projectDir}`, '')];
|
|
86
|
+
const len = enter[0].length + stripAnsi(enter[1]).length;
|
|
87
|
+
console.log(enter.join((len > max) ? '\n' + prefix : ' '));
|
|
88
|
+
}
|
|
89
|
+
console.log(`${prefix}Run ${color.cyan(devCmd)} to start the dev server. ${color.cyan('CTRL+C')} to stop.`);
|
|
90
|
+
await sleep(100);
|
|
91
|
+
console.log(`${prefix}Add frameworks like ${color.cyan(`react`)} or ${color.cyan('tailwind')} using ${color.cyan('astro add')}.`);
|
|
92
|
+
await sleep(100);
|
|
93
|
+
console.log(`\n${prefix}Stuck? Join us at ${color.cyan(`https://astro.build/chat`)}.`);
|
|
94
|
+
await sleep(200);
|
|
95
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-astro",
|
|
3
|
+
"version": "0.0.0-ui-20221007132109",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"author": "withastro",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/withastro/astro.git",
|
|
10
|
+
"directory": "packages/create-astro"
|
|
11
|
+
},
|
|
12
|
+
"bugs": "https://github.com/withastro/astro/issues",
|
|
13
|
+
"homepage": "https://astro.build",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": "./create-astro.mjs"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"create-astro": "./create-astro.mjs"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"create-astro.js",
|
|
23
|
+
"tsconfigs"
|
|
24
|
+
],
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@astrojs/cli-kit": "^0.0.3",
|
|
27
|
+
"comment-json": "^4.2.3",
|
|
28
|
+
"execa": "^6.1.0",
|
|
29
|
+
"giget": "^0.1.7",
|
|
30
|
+
"strip-ansi": "^7.0.1",
|
|
31
|
+
"which-pm-runs": "^1.1.0",
|
|
32
|
+
"yargs-parser": "^21.0.1"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/which-pm-runs": "^1.0.0",
|
|
36
|
+
"@types/yargs-parser": "^21.0.0",
|
|
37
|
+
"astro-scripts": "0.0.8",
|
|
38
|
+
"cli-testing-library": "^2.0.0",
|
|
39
|
+
"vitest": "^0.20.3"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": "^14.18.0 || >=16.12.0"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "astro-scripts build \"src/**/*.ts\" && tsc",
|
|
46
|
+
"build:ci": "astro-scripts build \"src/**/*.ts\"",
|
|
47
|
+
"dev": "astro-scripts dev \"src/**/*.ts\"",
|
|
48
|
+
"test": "vitest"
|
|
49
|
+
}
|
|
50
|
+
}
|