fix(cli): do not throw error when extracting examples in Node 18+ (#40182)

`create-next-app` currently cannot extract examples/git repos in Node 18+, because of an issue with `node-tar` (https://github.com/npm/node-tar/issues/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: https://github.com/vercel/next.js/pull/40182#pullrequestreview-1095216714

I cannot reproduce this on earlier Node.js versions. More context: https://github.com/vercel/next.js/issues/39321#issuecomment-1235642058

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)
This commit is contained in:
Balázs Orbán 2022-09-05 18:11:12 +02:00 committed by GitHub
parent 591321e882
commit 5a04e82ba9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -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)
@ -79,31 +82,44 @@ export function existsInRepo(nameOrUrl: string): Promise<boolean> {
}
}
export 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}` : ''}`]
)
)
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 function downloadAndExtractExample(
export async function downloadAndExtractRepo(
root: string,
name: string
): Promise<void> {
{ username, name, branch, filePath }: RepoInfo
) {
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 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}`),
})
}