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:
parent
591321e882
commit
5a04e82ba9
1 changed files with 35 additions and 19 deletions
|
@ -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}`),
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue