Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add JS support for appDir, mode/template distinction, project test spec #3

Merged
merged 4 commits into from
Oct 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 21 additions & 107 deletions packages/create-next-app/create-app.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
/* eslint-disable import/no-extraneous-dependencies */
import retry from 'async-retry'
import chalk from 'chalk'
import cpy from 'cpy'
import fs from 'fs'
import os from 'os'
import path from 'path'
import {
downloadAndExtractExample,
Expand All @@ -21,6 +19,13 @@ import { getOnline } from './helpers/is-online'
import { isWriteable } from './helpers/is-writeable'
import type { PackageManager } from './helpers/get-pkg-manager'

import {
getTemplateFile,
installTemplate,
TemplateMode,
TemplateType,
} from './templates'

export class DownloadError extends Error {}

export async function createApp({
Expand All @@ -39,11 +44,8 @@ export async function createApp({
experimentalApp: boolean
}): Promise<void> {
let repoInfo: RepoInfo | undefined
const template = experimentalApp
? 'experimental-app'
: typescript
? 'typescript'
: 'default'
const mode: TemplateMode = typescript ? 'ts' : 'js'
const template: TemplateType = experimentalApp ? 'app' : 'default'

if (example) {
let repoUrl: URL | undefined
Expand Down Expand Up @@ -176,20 +178,20 @@ export async function createApp({
isErrorLike(reason) ? reason.message : reason + ''
)
}
// Copy our default `.gitignore` if the application did not provide one
// Copy `.gitignore` if the application did not provide one
const ignorePath = path.join(root, '.gitignore')
if (!fs.existsSync(ignorePath)) {
fs.copyFileSync(
path.join(__dirname, 'templates', template, 'gitignore'),
getTemplateFile({ template, mode, file: 'gitignore' }),
ignorePath
)
}

// Copy default `next-env.d.ts` to any example that is typescript
// Copy `next-env.d.ts` to any example that is typescript
const tsconfigPath = path.join(root, 'tsconfig.json')
if (fs.existsSync(tsconfigPath)) {
fs.copyFileSync(
path.join(__dirname, 'templates', 'typescript', 'next-env.d.ts'),
getTemplateFile({ template, mode: 'ts', file: 'next-env.d.ts' }),
path.join(root, 'next-env.d.ts')
)
}
Expand All @@ -204,104 +206,16 @@ export async function createApp({
}
} else {
/**
* Otherwise, if an example repository is not provided for cloning, proceed
* If an example repository is not provided for cloning, proceed
* by installing from a template.
*/
console.log(chalk.bold(`Using ${packageManager}.`))
/**
* Create a package.json for the new project.
*/
const packageJson = {
name: appName,
version: '0.1.0',
private: true,
scripts: {
dev: 'next dev',
build: 'next build',
start: 'next start',
lint: 'next lint',
},
}
/**
* Write it to disk.
*/
fs.writeFileSync(
path.join(root, 'package.json'),
JSON.stringify(packageJson, null, 2) + os.EOL
)
/**
* These flags will be passed to `install()`.
*/
const installFlags = { packageManager, isOnline }
/**
* Default dependencies.
*/
const dependencies = ['react', 'react-dom', 'next']
/**
* Default devDependencies.
*/
const devDependencies = ['eslint', 'eslint-config-next']
/**
* TypeScript projects will have type definitions and other devDependencies.
*/
if (template !== 'default') {
devDependencies.push(
'typescript',
'@types/react',
'@types/node',
'@types/react-dom'
)
}
/**
* Install package.json dependencies if they exist.
*/
if (dependencies.length) {
console.log()
console.log('Installing dependencies:')
for (const dependency of dependencies) {
console.log(`- ${chalk.cyan(dependency)}`)
}
console.log()

await install(root, dependencies, installFlags)
}
/**
* Install package.json devDependencies if they exist.
*/
if (devDependencies.length) {
console.log()
console.log('Installing devDependencies:')
for (const devDependency of devDependencies) {
console.log(`- ${chalk.cyan(devDependency)}`)
}
console.log()

const devInstallFlags = { devDependencies: true, ...installFlags }
await install(root, devDependencies, devInstallFlags)
}
console.log('\nInitializing project with template: ', template, '\n')
/**
* Copy the template files to the target directory.
*/
await cpy('**', root, {
parents: true,
cwd: path.join(__dirname, 'templates', template),
rename: (name) => {
switch (name) {
case 'gitignore':
case 'eslintrc.json': {
return '.'.concat(name)
}
// README.md is ignored by webpack-asset-relocator-loader used by ncc:
// https://github.com/vercel/webpack-asset-relocator-loader/blob/e9308683d47ff507253e37c9bcbb99474603192b/src/asset-relocator.js#L227
case 'README-template.md': {
return 'README.md'
}
default: {
return name
}
}
},
await installTemplate({
appName,
root,
template,
mode,
packageManager,
isOnline,
})
}

Expand Down
2 changes: 1 addition & 1 deletion packages/create-next-app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ async function run(): Promise<void> {
* @todo Allow appDir to support TS or JS, currently TS-only and disables all
* --ts, --js features.
*/
if (!program.experimentalApp && !program.typescript && !program.javascript) {
if (!program.typescript && !program.javascript) {
const styledTypeScript = chalk.hex('#007acc')('TypeScript')
const { typescript } = await prompts(
{
Expand Down
14 changes: 14 additions & 0 deletions packages/create-next-app/templates/app/js/app/layout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import './globals.css'

export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</head>
<body>{children}</body>
</html>
)
}
5 changes: 5 additions & 0 deletions packages/create-next-app/templates/app/js/pages/api/hello.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction}

export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' })
}
34 changes: 34 additions & 0 deletions packages/create-next-app/templates/app/ts/README-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.

The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
146 changes: 146 additions & 0 deletions packages/create-next-app/templates/app/ts/app/page.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
.container {
padding: 0 2rem;
}

.main {
min-height: 100vh;
padding: 4rem 0;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

.footer {
display: flex;
flex: 1;
padding: 2rem 0;
border-top: 1px solid #eaeaea;
justify-content: center;
align-items: center;
}

.footer a {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
}

.title {
margin: 0;
line-height: 1.15;
font-size: 4rem;
font-style: normal;
font-weight: 800;
letter-spacing: -0.025em;
}

.title a {
text-decoration: none;
color: #0070f3;
}

.title a:hover,
.title a:focus,
.title a:active {
text-decoration: underline;
}

.title,
.description {
text-align: center;
}

.description {
margin: 4rem 0;
line-height: 1.5;
font-size: 1.5rem;
}

.code {
background: #fafafa;
border-radius: 5px;
padding: 0.75rem;
font-size: 1.1rem;
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono,
Bitstream Vera Sans Mono, Courier New, monospace;
}

.grid {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
max-width: 1200px;
}

.card {
margin: 1rem;
padding: 1.5rem;
text-align: left;
color: inherit;
text-decoration: none;
border: 1px solid #eaeaea;
border-radius: 10px;
transition: color 0.15s ease, border-color 0.15s ease;
max-width: 300px;
}

.card:hover,
.card:focus,
.card:active {
color: #0070f3;
border-color: #0070f3;
}

.card h2 {
margin: 0 0 1rem 0;
font-size: 1.5rem;
}

.card p {
margin: 0;
font-size: 1.25rem;
line-height: 1.5;
}

.logo {
height: 1em;
margin-left: 0.5rem;
}

@media (max-width: 600px) {
.grid {
width: 100%;
flex-direction: column;
}
}

@media (prefers-color-scheme: dark) {
.title {
background: linear-gradient(180deg, #ffffff 0%, #aaaaaa 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-fill-color: transparent;
}
.title a {
background: linear-gradient(180deg, #0070f3 0%, #0153af 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
text-fill-color: transparent;
}
.card,
.footer {
border-color: #222;
}
.code {
background: #111;
}
.logo img {
filter: invert(1);
}
}
Loading