Skip to content

Commit

Permalink
fix(cli): do not throw error when extracting examples in Node 18+ (#4…
Browse files Browse the repository at this point in the history
…0182)

`create-next-app` currently cannot extract examples/git repos in Node 18+, because of an issue with `node-tar` (isaacs/node-tar#321). The files are extracted, but an error is thrown that the stream has been prematurely closed. To prevent `create-next-app` from not being able to finish, ~for now, we can swallow this error, and hopefully `node-tar` will be patched soon.~
we can save the tar in the `tmp` folder and extract it from there as suggested: #40182 (review)

I cannot reproduce this on earlier Node.js versions. More context: #39321 (comment)

Fixes #39321



## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The examples guidelines are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing.md#adding-examples)
  • Loading branch information
balazsorban44 committed Sep 5, 2022
1 parent 591321e commit 5a04e82
Showing 1 changed file with 33 additions and 17 deletions.
50 changes: 33 additions & 17 deletions packages/create-next-app/helpers/examples.ts
Expand Up @@ -3,6 +3,9 @@ import got from 'got'
import tar from 'tar'
import { Stream } from 'stream'
import { promisify } from 'util'
import { join } from 'path'
import { tmpdir } from 'os'
import { createWriteStream } from 'fs'

const pipeline = promisify(Stream.pipeline)

Expand Down Expand Up @@ -79,31 +82,44 @@ export function existsInRepo(nameOrUrl: string): Promise<boolean> {
}
}

export function downloadAndExtractRepo(
async function downloadTar(url: string) {
const tempFile = join(tmpdir(), `next.js-cra-example.temp-${Date.now()}`)
await pipeline(got.stream(url), createWriteStream(tempFile))
return tempFile
}

export async function downloadAndExtractRepo(
root: string,
{ username, name, branch, filePath }: RepoInfo
): Promise<void> {
return pipeline(
got.stream(
`https://codeload.github.com/${username}/${name}/tar.gz/${branch}`
),
tar.extract(
{ cwd: root, strip: filePath ? filePath.split('/').length + 1 : 1 },
[`${name}-${branch.replace(/\//g, '-')}${filePath ? `/${filePath}` : ''}`]
)
) {
const tempFile = await downloadTar(
`https://codeload.github.com/${username}/${name}/tar.gz/${branch}`
)

await tar.x({
file: tempFile,
cwd: root,
strip: filePath ? filePath.split('/').length + 1 : 1,
filter: (p) =>
p.startsWith(
`${name}-${branch.replace(/\//g, '-')}${filePath ? `/${filePath}` : ''}`
),
})
}

export function downloadAndExtractExample(
root: string,
name: string
): Promise<void> {
export async function downloadAndExtractExample(root: string, name: string) {
if (name === '__internal-testing-retry') {
throw new Error('This is an internal example for testing the CLI.')
}

return pipeline(
got.stream('https://codeload.github.com/vercel/next.js/tar.gz/canary'),
tar.extract({ cwd: root, strip: 3 }, [`next.js-canary/examples/${name}`])
const tempFile = await downloadTar(
'https://codeload.github.com/vercel/next.js/tar.gz/canary'
)

await tar.x({
file: tempFile,
cwd: root,
strip: 3,
filter: (p) => p.includes(`next.js-canary/examples/${name}`),
})
}

0 comments on commit 5a04e82

Please sign in to comment.