From fd738086649573eeccf6201037cc4ea49b1eec48 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Thu, 17 Apr 2025 19:37:26 +0300 Subject: [PATCH 1/4] fix(deps): remove tempy --- package-lock.json | 113 +----------------- package.json | 1 - src/lib/functions/runtimes/go/index.ts | 2 +- src/utils/deploy/deploy-site.ts | 2 +- src/utils/temporary-file.ts | 27 +++++ .../integration/commands/blobs/blobs.test.ts | 2 +- .../completion/completion-install.test.ts | 2 +- .../dev/dev-forms-and-redirects.test.ts | 3 +- tests/integration/utils/fixture.ts | 2 +- tests/integration/utils/mock-execa.ts | 2 +- tests/unit/utils/deploy/hash-fns.test.ts | 2 +- 11 files changed, 38 insertions(+), 120 deletions(-) create mode 100644 src/utils/temporary-file.ts diff --git a/package-lock.json b/package-lock.json index 41d323a89d2..f5930729766 100644 --- a/package-lock.json +++ b/package-lock.json @@ -95,7 +95,6 @@ "readdirp": "4.1.2", "semver": "7.7.1", "source-map-support": "0.5.21", - "tempy": "3.1.0", "terminal-link": "4.0.0", "toml": "3.0.0", "tomlify-j0.4": "3.0.0", @@ -8955,31 +8954,6 @@ } } }, - "node_modules/crypto-random-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", - "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", - "dependencies": { - "type-fest": "^1.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/crypto-random-string/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/css-select": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", @@ -17625,38 +17599,11 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true, "engines": { "node": ">=14.16" } }, - "node_modules/tempy": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", - "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", - "dependencies": { - "is-stream": "^3.0.0", - "temp-dir": "^3.0.0", - "type-fest": "^2.12.2", - "unique-string": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/tempy/node_modules/is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/terminal-link": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-4.0.0.tgz", @@ -18206,20 +18153,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/unique-string": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", - "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", - "dependencies": { - "crypto-random-string": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/universal-user-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", @@ -25403,21 +25336,6 @@ "integrity": "sha512-uZwy53h6ITBxXdzsw7UcGQZ1QSyjBSkAknu70Zb7+JWmJ1LstE1hVFEgt34RVoCQJn8kstSOnNmRjK93SG1LBg==", "requires": {} }, - "crypto-random-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-4.0.0.tgz", - "integrity": "sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==", - "requires": { - "type-fest": "^1.0.1" - }, - "dependencies": { - "type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==" - } - } - }, "css-select": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", @@ -31516,25 +31434,8 @@ "temp-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", - "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==" - }, - "tempy": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/tempy/-/tempy-3.1.0.tgz", - "integrity": "sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==", - "requires": { - "is-stream": "^3.0.0", - "temp-dir": "^3.0.0", - "type-fest": "^2.12.2", - "unique-string": "^3.0.0" - }, - "dependencies": { - "is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==" - } - } + "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", + "dev": true }, "terminal-link": { "version": "4.0.0", @@ -31917,14 +31818,6 @@ "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==" }, - "unique-string": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-3.0.0.tgz", - "integrity": "sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==", - "requires": { - "crypto-random-string": "^4.0.0" - } - }, "universal-user-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.2.tgz", diff --git a/package.json b/package.json index c57510822ce..1b645b88853 100644 --- a/package.json +++ b/package.json @@ -143,7 +143,6 @@ "readdirp": "4.1.2", "semver": "7.7.1", "source-map-support": "0.5.21", - "tempy": "3.1.0", "terminal-link": "4.0.0", "toml": "3.0.0", "tomlify-j0.4": "3.0.0", diff --git a/src/lib/functions/runtimes/go/index.ts b/src/lib/functions/runtimes/go/index.ts index 4d2ef48ba19..5cbcb2c7717 100644 --- a/src/lib/functions/runtimes/go/index.ts +++ b/src/lib/functions/runtimes/go/index.ts @@ -2,7 +2,6 @@ import { dirname, extname } from 'path' import { platform } from 'process' import type { LambdaEvent } from 'lambda-local' -import { temporaryFile } from 'tempy' import type { BaseBuildResult, @@ -13,6 +12,7 @@ import type { } from '../index.js' import execa from '../../../../utils/execa.js' import { runFunctionsProxy } from '../../local-proxy.js' +import { temporaryFile } from '../../../../utils/temporary-file.js' const isWindows = platform === 'win32' diff --git a/src/utils/deploy/deploy-site.ts b/src/utils/deploy/deploy-site.ts index 1244ffa6a99..9b1b5e8afc7 100644 --- a/src/utils/deploy/deploy-site.ts +++ b/src/utils/deploy/deploy-site.ts @@ -1,7 +1,6 @@ import { rm } from 'fs/promises' import cleanDeep from 'clean-deep' -import { temporaryDirectory } from 'tempy' import BaseCommand from '../../commands/base-command.js' import { type $TSFixMe } from '../../commands/types.js' @@ -21,6 +20,7 @@ import hashFns from './hash-fns.js' import uploadFiles from './upload-files.js' import { getUploadList, waitForDeploy, waitForDiff } from './util.js' import type { DeployEvent } from './status-cb.js' +import { temporaryDirectory } from '../temporary-file.js' export type { DeployEvent } diff --git a/src/utils/temporary-file.ts b/src/utils/temporary-file.ts new file mode 100644 index 00000000000..a4b46be629b --- /dev/null +++ b/src/utils/temporary-file.ts @@ -0,0 +1,27 @@ +import * as path from 'node:path' +import * as os from 'node:os' +import * as crypto from 'node:crypto' +import * as fs from 'node:fs' + +const uniqueString = () => crypto.randomBytes(8).toString('hex') + +const tempDir = os.tmpdir() + +export function temporaryFile({ name, extension }: { name?: string; extension?: string } = {}): string { + if (name) { + if (extension !== undefined && extension !== null) { + throw new Error('The `name` and `extension` options are mutually exclusive') + } + return path.join(tempDir, name) + } + + const baseName = uniqueString() + const ext = extension ? '.' + extension.replace(/^\./, '') : '' + return path.join(tempDir, baseName + ext) +} + +export function temporaryDirectory({ prefix = '' } = {}): string { + const directory = path.join(tempDir, prefix + uniqueString()) + fs.mkdirSync(directory) + return directory +} diff --git a/tests/integration/commands/blobs/blobs.test.ts b/tests/integration/commands/blobs/blobs.test.ts index 493a01c8f01..5843c470a20 100644 --- a/tests/integration/commands/blobs/blobs.test.ts +++ b/tests/integration/commands/blobs/blobs.test.ts @@ -5,11 +5,11 @@ import { env } from 'process' import { ListResultBlob } from '@netlify/blobs' import { BlobsServer } from '@netlify/blobs/server' import httpProxy from 'http-proxy' -import { temporaryDirectory } from 'tempy' import { afterAll, beforeAll, describe, expect, test } from 'vitest' import { FixtureTestContext, setupFixtureTests } from '../../utils/fixture.js' import { Route } from '../../utils/mock-api-vitest.js' +import { temporaryDirectory } from '../../../../src/utils/temporary-file.js' const blobsProxy = httpProxy.createProxyServer({}) diff --git a/tests/integration/commands/completion/completion-install.test.ts b/tests/integration/commands/completion/completion-install.test.ts index 800b47a891e..00572999ea9 100644 --- a/tests/integration/commands/completion/completion-install.test.ts +++ b/tests/integration/commands/completion/completion-install.test.ts @@ -1,12 +1,12 @@ import { describe, test, beforeAll, afterAll } from 'vitest' import fs from 'fs' import { rm } from 'fs/promises' -import { temporaryDirectory } from 'tempy' import { handleQuestions, CONFIRM, DOWN, NO, answerWithValue } from '../../utils/handle-questions.js' import execa from 'execa' import { cliPath } from '../../utils/cli-path.js' import { join } from 'path' import { TABTAB_CONFIG_LINE, AUTOLOAD_COMPINIT } from '../../../../src/utils/command-helpers.js' +import { temporaryDirectory } from '../../../../src/utils/temporary-file.js' describe('completion:install command', () => { let tempDir: string diff --git a/tests/integration/commands/dev/dev-forms-and-redirects.test.ts b/tests/integration/commands/dev/dev-forms-and-redirects.test.ts index b16d8696a3c..12e6d0726ac 100644 --- a/tests/integration/commands/dev/dev-forms-and-redirects.test.ts +++ b/tests/integration/commands/dev/dev-forms-and-redirects.test.ts @@ -11,6 +11,7 @@ import { describe, test } from 'vitest' import { withDevServer } from '../../utils/dev-server.js' import { withSiteBuilder } from '../../utils/site-builder.js' +import { temporaryDirectory } from '../../../../src/utils/temporary-file.js' describe.concurrent('commands/dev-forms-and-redirects', () => { test('should return 404 when redirecting to a non existing function', async (t) => { @@ -427,7 +428,6 @@ describe.concurrent('commands/dev-forms-and-redirects', () => { }; ` - const { temporaryDirectory } = await import('tempy') const pluginDirectory = temporaryDirectory() await fs.writeFile(path.join(pluginDirectory, 'manifest.yml'), pluginManifest) @@ -486,7 +486,6 @@ describe.concurrent('commands/dev-forms-and-redirects', () => { }; ` - const { temporaryDirectory } = await import('tempy') const pluginDirectory = temporaryDirectory() await fs.writeFile(path.join(pluginDirectory, 'manifest.yml'), pluginManifest) diff --git a/tests/integration/utils/fixture.ts b/tests/integration/utils/fixture.ts index 56e99656336..74f0aa0be63 100644 --- a/tests/integration/utils/fixture.ts +++ b/tests/integration/utils/fixture.ts @@ -3,13 +3,13 @@ import { join } from 'path' import { fileURLToPath } from 'url' import type { NodeOptions } from 'execa' -import { temporaryDirectory } from 'tempy' import { afterAll, afterEach, beforeAll, beforeEach, describe } from 'vitest' import { callCli } from './call-cli.js' import { DevServer, startDevServer } from './dev-server.js' import { MockApi, Route, getCLIOptions, startMockApi } from './mock-api-vitest.js' import { SiteBuilder } from './site-builder.js' +import { temporaryDirectory } from '../../../src/utils/temporary-file.js' const FIXTURES_DIRECTORY = fileURLToPath(new URL('../__fixtures__/', import.meta.url)) diff --git a/tests/integration/utils/mock-execa.ts b/tests/integration/utils/mock-execa.ts index 6efaf9e1d05..fa1c4447b1a 100644 --- a/tests/integration/utils/mock-execa.ts +++ b/tests/integration/utils/mock-execa.ts @@ -1,12 +1,12 @@ import { rm, writeFile } from 'fs/promises' import { pathToFileURL } from 'url' +import { temporaryFile } from '../../../src/utils/temporary-file' // Saves to disk a JavaScript file with the contents provided and returns // an environment variable that replaces the `execa` module implementation. // A cleanup method is also returned, allowing the consumer to remove the // mock file. export const createMock = async (contents: string) => { - const { temporaryFile } = await import('tempy') const path = temporaryFile({ extension: 'js' }) await writeFile(path, contents) diff --git a/tests/unit/utils/deploy/hash-fns.test.ts b/tests/unit/utils/deploy/hash-fns.test.ts index 16a4669588a..d58a5bea0e3 100644 --- a/tests/unit/utils/deploy/hash-fns.test.ts +++ b/tests/unit/utils/deploy/hash-fns.test.ts @@ -1,12 +1,12 @@ import path from 'node:path' -import { temporaryDirectory } from 'tempy' import { expect, test } from 'vitest' import BaseCommand from '../../../../src/commands/base-command.js' import { DEFAULT_CONCURRENT_HASH } from '../../../../src/utils/deploy/constants.js' import hashFns from '../../../../src/utils/deploy/hash-fns.js' import { withSiteBuilder } from '../../../integration/utils/site-builder.js' +import { temporaryDirectory } from '../../../../src/utils/temporary-file.js' test('Hashes files in a folder', async (t) => { await withSiteBuilder(t, async (builder) => { From 4f4c2680cb9dfc0bfb808400904401db8c2eebf3 Mon Sep 17 00:00:00 2001 From: v1rtl Date: Fri, 18 Apr 2025 11:14:41 +0300 Subject: [PATCH 2/4] fix: lint errors --- src/utils/temporary-file.ts | 2 +- tests/integration/utils/mock-execa.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/temporary-file.ts b/src/utils/temporary-file.ts index a4b46be629b..1466fe7806a 100644 --- a/src/utils/temporary-file.ts +++ b/src/utils/temporary-file.ts @@ -9,7 +9,7 @@ const tempDir = os.tmpdir() export function temporaryFile({ name, extension }: { name?: string; extension?: string } = {}): string { if (name) { - if (extension !== undefined && extension !== null) { + if (typeof extension === 'string') { throw new Error('The `name` and `extension` options are mutually exclusive') } return path.join(tempDir, name) diff --git a/tests/integration/utils/mock-execa.ts b/tests/integration/utils/mock-execa.ts index fa1c4447b1a..8f3d8bc5901 100644 --- a/tests/integration/utils/mock-execa.ts +++ b/tests/integration/utils/mock-execa.ts @@ -1,6 +1,6 @@ import { rm, writeFile } from 'fs/promises' import { pathToFileURL } from 'url' -import { temporaryFile } from '../../../src/utils/temporary-file' +import { temporaryFile } from '../../../src/utils/temporary-file.js' // Saves to disk a JavaScript file with the contents provided and returns // an environment variable that replaces the `execa` module implementation. From cd9aa86550455d161aaabdd624e34d4aa240288e Mon Sep 17 00:00:00 2001 From: v1rtl Date: Fri, 18 Apr 2025 11:20:09 +0300 Subject: [PATCH 3/4] fix: fmt --- src/utils/temporary-file.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/temporary-file.ts b/src/utils/temporary-file.ts index 1466fe7806a..fd038f37aae 100644 --- a/src/utils/temporary-file.ts +++ b/src/utils/temporary-file.ts @@ -9,7 +9,7 @@ const tempDir = os.tmpdir() export function temporaryFile({ name, extension }: { name?: string; extension?: string } = {}): string { if (name) { - if (typeof extension === 'string') { + if (typeof extension === 'string') { throw new Error('The `name` and `extension` options are mutually exclusive') } return path.join(tempDir, name) From 93bc7e2494c1ae047a0e41bec43f20f7fe51f98a Mon Sep 17 00:00:00 2001 From: v1rtl Date: Sat, 19 Apr 2025 13:58:22 +0300 Subject: [PATCH 4/4] fix: remove unecessary code for handling `name` --- src/utils/temporary-file.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/utils/temporary-file.ts b/src/utils/temporary-file.ts index fd038f37aae..947b8b8cbb6 100644 --- a/src/utils/temporary-file.ts +++ b/src/utils/temporary-file.ts @@ -7,21 +7,13 @@ const uniqueString = () => crypto.randomBytes(8).toString('hex') const tempDir = os.tmpdir() -export function temporaryFile({ name, extension }: { name?: string; extension?: string } = {}): string { - if (name) { - if (typeof extension === 'string') { - throw new Error('The `name` and `extension` options are mutually exclusive') - } - return path.join(tempDir, name) - } - +export function temporaryFile({ extension }: { extension?: string } = {}): string { const baseName = uniqueString() const ext = extension ? '.' + extension.replace(/^\./, '') : '' return path.join(tempDir, baseName + ext) } export function temporaryDirectory({ prefix = '' } = {}): string { - const directory = path.join(tempDir, prefix + uniqueString()) - fs.mkdirSync(directory) + const directory = fs.mkdtempSync(`${tempDir}${path.sep}${prefix}`) return directory }