diff --git a/packages/create-next-app/create-app.ts b/packages/create-next-app/create-app.ts index f81d3538d9131..e56ec91283a38 100644 --- a/packages/create-next-app/create-app.ts +++ b/packages/create-next-app/create-app.ts @@ -11,7 +11,6 @@ import { existsInRepo, hasRepo, } from './helpers/examples' -import { makeDir } from './helpers/make-dir' import { tryGitInit } from './helpers/git' import { install } from './helpers/install' import { isFolderEmpty } from './helpers/is-folder-empty' @@ -133,7 +132,7 @@ export async function createApp({ const appName = path.basename(root) - await makeDir(root) + fs.mkdirSync(root, { recursive: true }) if (!isFolderEmpty(root, appName)) { process.exit(1) } diff --git a/packages/create-next-app/helpers/examples.ts b/packages/create-next-app/helpers/examples.ts index dad9895bd1e9c..54bcec0ba453d 100644 --- a/packages/create-next-app/helpers/examples.ts +++ b/packages/create-next-app/helpers/examples.ts @@ -1,13 +1,7 @@ /* eslint-disable import/no-extraneous-dependencies */ -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, promises as fs } from 'fs' - -const pipeline = promisify(Stream.pipeline) +import { Readable } from 'stream' +import { pipeline } from 'stream/promises' export type RepoInfo = { username: string @@ -17,8 +11,12 @@ export type RepoInfo = { } export async function isUrlOk(url: string): Promise { - const res = await got.head(url).catch((e) => e) - return res.statusCode === 200 + try { + const res = await fetch(url, { method: 'HEAD' }) + return res.status === 200 + } catch { + return false + } } export async function getRepoInfo( @@ -37,14 +35,19 @@ export async function getRepoInfo( // In this case "t" will be an empty string while the next part "_branch" will be undefined (t === '' && _branch === undefined) ) { - const infoResponse = await got( - `https://api.github.com/repos/${username}/${name}` - ).catch((e) => e) - if (infoResponse.statusCode !== 200) { + try { + const infoResponse = await fetch( + `https://api.github.com/repos/${username}/${name}` + ) + if (infoResponse.status !== 200) { + return + } + + const info = await infoResponse.json() + return { username, name, branch: info['default_branch'], filePath } + } catch { return } - const info = JSON.parse(infoResponse.body) - return { username, name, branch: info['default_branch'], filePath } } // If examplePath is available, the branch name takes the entire path @@ -82,33 +85,35 @@ export function existsInRepo(nameOrUrl: string): Promise { } } -async function downloadTar(url: string) { - const tempFile = join(tmpdir(), `next.js-cna-example.temp-${Date.now()}`) - await pipeline(got.stream(url), createWriteStream(tempFile)) - return tempFile +async function downloadTarStream(url: string) { + const res = await fetch(url) + + if (!res.body) { + throw new Error(`Failed to download: ${url}`) + } + + return Readable.fromWeb(res.body as import('stream/web').ReadableStream) } export async function downloadAndExtractRepo( root: string, { username, name, branch, filePath }: RepoInfo ) { - const tempFile = await downloadTar( - `https://codeload.github.com/${username}/${name}/tar.gz/${branch}` + await pipeline( + await downloadTarStream( + `https://codeload.github.com/${username}/${name}/tar.gz/${branch}` + ), + tar.x({ + cwd: root, + strip: filePath ? filePath.split('/').length + 1 : 1, + filter: (p) => + p.startsWith( + `${name}-${branch.replace(/\//g, '-')}${ + filePath ? `/${filePath}/` : '/' + }` + ), + }) ) - - await tar.x({ - file: tempFile, - cwd: root, - strip: filePath ? filePath.split('/').length + 1 : 1, - filter: (p) => - p.startsWith( - `${name}-${branch.replace(/\//g, '-')}${ - filePath ? `/${filePath}/` : '/' - }` - ), - }) - - await fs.unlink(tempFile) } export async function downloadAndExtractExample(root: string, name: string) { @@ -116,16 +121,14 @@ export async function downloadAndExtractExample(root: string, name: string) { throw new Error('This is an internal example for testing the CLI.') } - const tempFile = await downloadTar( - 'https://codeload.github.com/vercel/next.js/tar.gz/canary' + await pipeline( + await downloadTarStream( + 'https://codeload.github.com/vercel/next.js/tar.gz/canary' + ), + tar.x({ + cwd: root, + strip: 2 + name.split('/').length, + filter: (p) => p.includes(`next.js-canary/examples/${name}/`), + }) ) - - await tar.x({ - file: tempFile, - cwd: root, - strip: 2 + name.split('/').length, - filter: (p) => p.includes(`next.js-canary/examples/${name}/`), - }) - - await fs.unlink(tempFile) } diff --git a/packages/create-next-app/helpers/install.ts b/packages/create-next-app/helpers/install.ts index 911573b967b68..1f84892fbcf47 100644 --- a/packages/create-next-app/helpers/install.ts +++ b/packages/create-next-app/helpers/install.ts @@ -14,7 +14,7 @@ export async function install( /** Indicate whether there is an active Internet connection.*/ isOnline: boolean ): Promise { - let args: string[] = ['install'] + const args: string[] = ['install'] if (!isOnline) { console.log( yellow('You appear to be offline.\nFalling back to the local cache.') diff --git a/packages/create-next-app/helpers/is-folder-empty.ts b/packages/create-next-app/helpers/is-folder-empty.ts index ad89ec22fb3b7..09aa77258e07e 100644 --- a/packages/create-next-app/helpers/is-folder-empty.ts +++ b/packages/create-next-app/helpers/is-folder-empty.ts @@ -27,11 +27,12 @@ export function isFolderEmpty(root: string, name: string): boolean { '.yarn', ] - const conflicts = fs - .readdirSync(root) - .filter((file) => !validFiles.includes(file)) - // Support IntelliJ IDEA-based editors - .filter((file) => !/\.iml$/.test(file)) + const conflicts = fs.readdirSync(root).filter( + (file) => + !validFiles.includes(file) && + // Support IntelliJ IDEA-based editors + !/\.iml$/.test(file) + ) if (conflicts.length > 0) { console.log( diff --git a/packages/create-next-app/helpers/is-online.ts b/packages/create-next-app/helpers/is-online.ts index c2f3f83a93ce8..0b1cd31b8687a 100644 --- a/packages/create-next-app/helpers/is-online.ts +++ b/packages/create-next-app/helpers/is-online.ts @@ -1,5 +1,5 @@ import { execSync } from 'child_process' -import dns from 'dns' +import dns from 'dns/promises' import url from 'url' function getProxy(): string | undefined { @@ -15,26 +15,31 @@ function getProxy(): string | undefined { } } -export function getOnline(): Promise { - return new Promise((resolve) => { - dns.lookup('registry.yarnpkg.com', (registryErr) => { - if (!registryErr) { - return resolve(true) - } - - const proxy = getProxy() - if (!proxy) { - return resolve(false) - } +export async function getOnline(): Promise { + try { + await dns.lookup('registry.yarnpkg.com') + // If DNS lookup succeeds, we are online + return true + } catch { + // The DNS lookup failed, but we are still fine as long as a proxy has been set + const proxy = getProxy() + if (!proxy) { + return false + } - const { hostname } = url.parse(proxy) - if (!hostname) { - return resolve(false) - } + const { hostname } = url.parse(proxy) + if (!hostname) { + // Invalid proxy URL + return false + } - dns.lookup(hostname, (proxyErr) => { - resolve(proxyErr == null) - }) - }) - }) + try { + await dns.lookup(hostname) + // If DNS lookup succeeds for the proxy server, we are online + return true + } catch { + // The DNS lookup for the proxy server also failed, so we are offline + return false + } + } } diff --git a/packages/create-next-app/helpers/make-dir.ts b/packages/create-next-app/helpers/make-dir.ts deleted file mode 100644 index 5b12b996f03f6..0000000000000 --- a/packages/create-next-app/helpers/make-dir.ts +++ /dev/null @@ -1,8 +0,0 @@ -import fs from 'fs' - -export function makeDir( - root: string, - options = { recursive: true } -): Promise { - return fs.promises.mkdir(root, options) -} diff --git a/packages/create-next-app/helpers/validate-pkg.ts b/packages/create-next-app/helpers/validate-pkg.ts index cff613818f6e8..9be4f62a2bf09 100644 --- a/packages/create-next-app/helpers/validate-pkg.ts +++ b/packages/create-next-app/helpers/validate-pkg.ts @@ -1,10 +1,16 @@ // eslint-disable-next-line import/no-extraneous-dependencies import validateProjectName from 'validate-npm-package-name' -export function validateNpmName(name: string): { - valid: boolean - problems?: string[] -} { +type ValidateNpmNameResult = + | { + valid: true + } + | { + valid: false + problems: string[] + } + +export function validateNpmName(name: string): ValidateNpmNameResult { const nameValidation = validateProjectName(name) if (nameValidation.validForNewPackages) { return { valid: true } diff --git a/packages/create-next-app/index.ts b/packages/create-next-app/index.ts index fc24aa36370be..b922920ac75fe 100644 --- a/packages/create-next-app/index.ts +++ b/packages/create-next-app/index.ts @@ -184,7 +184,7 @@ async function run(): Promise { if (validation.valid) { return true } - return 'Invalid project name: ' + validation.problems![0] + return 'Invalid project name: ' + validation.problems[0] }, }) @@ -207,15 +207,17 @@ async function run(): Promise { const resolvedProjectPath = path.resolve(projectPath) const projectName = path.basename(resolvedProjectPath) - const { valid, problems } = validateNpmName(projectName) - if (!valid) { + const validation = validateNpmName(projectName) + if (!validation.valid) { console.error( `Could not create a project called ${red( `"${projectName}"` )} because of npm naming restrictions:` ) - problems!.forEach((p) => console.error(` ${red(bold('*'))} ${p}`)) + validation.problems.forEach((p) => + console.error(` ${red(bold('*'))} ${p}`) + ) process.exit(1) } diff --git a/packages/create-next-app/package.json b/packages/create-next-app/package.json index 24163270a9d8f..b8d2aac65b907 100644 --- a/packages/create-next-app/package.json +++ b/packages/create-next-app/package.json @@ -43,7 +43,6 @@ "conf": "10.2.0", "cross-spawn": "7.0.3", "fast-glob": "3.3.1", - "got": "10.7.0", "picocolors": "1.0.0", "prettier-plugin-tailwindcss": "0.3.0", "prompts": "2.4.2", diff --git a/packages/create-next-app/templates/index.ts b/packages/create-next-app/templates/index.ts index 166309f937e18..f484ecfd99efd 100644 --- a/packages/create-next-app/templates/index.ts +++ b/packages/create-next-app/templates/index.ts @@ -1,5 +1,4 @@ import { install } from '../helpers/install' -import { makeDir } from '../helpers/make-dir' import { copy } from '../helpers/copy' import { async as glob } from 'fast-glob' @@ -118,7 +117,7 @@ export const installTemplate = async ({ } if (srcDir) { - await makeDir(path.join(root, 'src')) + await fs.mkdir(path.join(root, 'src'), { recursive: true }) await Promise.all( SRC_DIR_NAMES.map(async (file) => { await fs diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 389888a853a66..df07c139b3474 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -725,9 +725,6 @@ importers: fast-glob: specifier: 3.3.1 version: 3.3.1 - got: - specifier: 10.7.0 - version: 10.7.0 picocolors: specifier: 1.0.0 version: 1.0.0 @@ -6261,11 +6258,6 @@ packages: engines: {node: '>=6'} dev: true - /@sindresorhus/is@2.1.0: - resolution: {integrity: sha512-lXKXfypKo644k4Da4yXkPCrwcvn6SlUW2X2zFbuflKHNjf0w9htru01bo26uMhleMXsDmnZ12eJLdrAZa9MANg==} - engines: {node: '>=10'} - dev: true - /@sinonjs/commons@1.8.6: resolution: {integrity: sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==} dependencies: @@ -6552,13 +6544,6 @@ packages: defer-to-connect: 1.1.3 dev: true - /@szmarczak/http-timer@4.0.5: - resolution: {integrity: sha512-PyRA9sm1Yayuj5OIoJ1hGt2YISX45w9WcFbh6ddT0Z/0yaFxOtGLInr4jUfU1EAFVs0Yfyfev4RNwBlUaHdlDQ==} - engines: {node: '>=10'} - dependencies: - defer-to-connect: 2.0.0 - dev: true - /@szmarczak/http-timer@5.0.1: resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} @@ -6755,15 +6740,6 @@ packages: resolution: {integrity: sha512-lOGyCnw+2JVPKU3wIV0srU0NyALwTBJlVSx5DfMQOFuuohA8y9S8orImpuIQikZ0uIQ8gehrRjxgQC1rLRi11w==} dev: true - /@types/cacheable-request@6.0.1: - resolution: {integrity: sha512-ykFq2zmBGOCbpIXtoVbz4SKY5QriWPh3AjyU4G74RYbtt5yOc5OfaY75ftjg7mikMOla1CTGpX3lLbuJh8DTrQ==} - dependencies: - '@types/http-cache-semantics': 4.0.0 - '@types/keyv': 3.1.1 - '@types/node': 20.2.5 - '@types/responselike': 1.0.0 - dev: true - /@types/cheerio@0.22.16: resolution: {integrity: sha512-bSbnU/D4yzFdzLpp3+rcDj0aQQMIRUBNJU7azPxdqMpnexjUSvGJyDuOBQBHeOZh1mMKgsJm6Dy+LLh80Ew4tQ==} dependencies: @@ -6902,10 +6878,6 @@ packages: '@types/node': 20.2.5 dev: true - /@types/http-cache-semantics@4.0.0: - resolution: {integrity: sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==} - dev: true - /@types/http-proxy@1.17.3: resolution: {integrity: sha512-wIPqXANye5BbORbuh74exbwNzj+UWCwWyeEFJzUQ7Fq3W2NSAy+7x7nX1fgbEypr2/TdKqpeuxLnXWgzN533/Q==} dependencies: @@ -9059,14 +9031,6 @@ packages: unset-value: 1.0.0 dev: false - /cacheable-lookup@2.0.1: - resolution: {integrity: sha512-EMMbsiOTcdngM/K6gV/OxF2x0t07+vMOWxZNSCRQMjO2MY2nhZQ6OYhOOpyQrbhqsgtvKGI7hcq6xjnA92USjg==} - engines: {node: '>=10'} - dependencies: - '@types/keyv': 3.1.1 - keyv: 4.0.0 - dev: true - /cacheable-request@6.1.0: resolution: {integrity: sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==} engines: {node: '>=8'} @@ -9080,19 +9044,6 @@ packages: responselike: 1.0.2 dev: true - /cacheable-request@7.0.1: - resolution: {integrity: sha512-lt0mJ6YAnsrBErpTMWeu5kl/tg9xMAWjavYTN6VQXM1A/teBITuNcccXsCxF0tDQQJf9DfAaX5O4e0zp0KlfZw==} - engines: {node: '>=8'} - dependencies: - clone-response: 1.0.2 - get-stream: 5.1.0 - http-cache-semantics: 4.1.0 - keyv: 4.0.0 - lowercase-keys: 2.0.0 - normalize-url: 4.5.0 - responselike: 2.0.0 - dev: true - /call-bind@1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: @@ -10782,13 +10733,6 @@ packages: mimic-response: 1.0.1 dev: true - /decompress-response@5.0.0: - resolution: {integrity: sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw==} - engines: {node: '>=10'} - dependencies: - mimic-response: 2.1.0 - dev: true - /dedent@0.7.0: resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} dev: true @@ -10843,11 +10787,6 @@ packages: resolution: {integrity: sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==} dev: true - /defer-to-connect@2.0.0: - resolution: {integrity: sha512-bYL2d05vOSf1JEZNx5vSAtPuBMkX8K9EUutg7zlKvTqKXHt7RhWJFbmd7qakVuf13i+IkGmp6FwSsONOf6VYIg==} - engines: {node: '>=10'} - dev: true - /defer-to-connect@2.0.1: resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} engines: {node: '>=10'} @@ -13460,29 +13399,6 @@ packages: dependencies: get-intrinsic: 1.2.1 - /got@10.7.0: - resolution: {integrity: sha512-aWTDeNw9g+XqEZNcTjMMZSy7B7yE9toWOFYip7ofFTLleJhvZwUxxTxkTpKvF+p1SAA4VHmuEy7PiHTHyq8tJg==} - engines: {node: '>=10'} - dependencies: - '@sindresorhus/is': 2.1.0 - '@szmarczak/http-timer': 4.0.5 - '@types/cacheable-request': 6.0.1 - '@types/keyv': 3.1.1 - '@types/responselike': 1.0.0 - cacheable-lookup: 2.0.1 - cacheable-request: 7.0.1 - decompress-response: 5.0.0 - duplexer3: 0.1.4 - get-stream: 5.1.0 - lowercase-keys: 2.0.0 - mimic-response: 2.1.0 - p-cancelable: 2.0.0 - p-event: 4.1.0 - responselike: 2.0.0 - to-readable-stream: 2.1.0 - type-fest: 0.10.0 - dev: true - /got@7.1.0: resolution: {integrity: sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw==} engines: {node: '>=4'} @@ -16118,10 +16034,6 @@ packages: resolution: {integrity: sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=} dev: true - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true - /json-merge-patch@1.0.2: resolution: {integrity: sha512-M6Vp2GN9L7cfuMXiWOmHj9bEFbeC250iVtcKQbqVgEsDVYnIsrNsbU+h/Y/PkbBQCtEa4Bez+Ebv0zfbC8ObLg==} dependencies: @@ -16287,12 +16199,6 @@ packages: json-buffer: 3.0.0 dev: true - /keyv@4.0.0: - resolution: {integrity: sha512-U7ioE8AimvRVLfw4LffyOIRhL2xVgmE8T22L6i0BucSnBUyv4w+I7VN/zVZwRKHOI6ZRUcdMdWHQ8KSUvGpEog==} - dependencies: - json-buffer: 3.0.1 - dev: true - /kind-of@3.2.2: resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} engines: {node: '>=0.10.0'} @@ -17792,11 +17698,6 @@ packages: engines: {node: '>=4'} dev: true - /mimic-response@2.1.0: - resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} - engines: {node: '>=8'} - dev: true - /min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -18859,18 +18760,6 @@ packages: engines: {node: '>=6'} dev: true - /p-cancelable@2.0.0: - resolution: {integrity: sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg==} - engines: {node: '>=8'} - dev: true - - /p-event@4.1.0: - resolution: {integrity: sha512-4vAd06GCsgflX4wHN1JqrMzBh/8QZ4j+rzp0cd2scXRwuBEv+QR3wrVA5aLhWDLw4y2WgDKvzWF3CCLmVM1UgA==} - engines: {node: '>=8'} - dependencies: - p-timeout: 2.0.1 - dev: true - /p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} engines: {node: '>=4'} @@ -18975,13 +18864,6 @@ packages: p-finally: 1.0.0 dev: true - /p-timeout@2.0.1: - resolution: {integrity: sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==} - engines: {node: '>=4'} - dependencies: - p-finally: 1.0.0 - dev: true - /p-timeout@3.2.0: resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} engines: {node: '>=8'} @@ -22026,12 +21908,6 @@ packages: lowercase-keys: 1.0.1 dev: true - /responselike@2.0.0: - resolution: {integrity: sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==} - dependencies: - lowercase-keys: 2.0.0 - dev: true - /restore-cursor@2.0.0: resolution: {integrity: sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==} engines: {node: '>=4'} @@ -23959,11 +23835,6 @@ packages: engines: {node: '>=6'} dev: true - /to-readable-stream@2.1.0: - resolution: {integrity: sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w==} - engines: {node: '>=8'} - dev: true - /to-regex-range@2.1.1: resolution: {integrity: sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==} engines: {node: '>=0.10.0'} @@ -24275,11 +24146,6 @@ packages: engines: {node: '>=4'} dev: true - /type-fest@0.10.0: - resolution: {integrity: sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw==} - engines: {node: '>=8'} - dev: true - /type-fest@0.13.1: resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} engines: {node: '>=10'}