diff --git a/package-lock.json b/package-lock.json index ddfcbfbe0fa..b5bdfc7e7fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -52,9 +52,7 @@ "fastest-levenshtein": "1.0.16", "fastify": "4.29.0", "find-up": "7.0.0", - "flush-write-stream": "2.0.0", "folder-walker": "3.2.0", - "from2-array": "0.0.4", "fuzzy": "0.1.3", "get-port": "5.1.1", "gh-release-fetch": "4.0.3", @@ -100,8 +98,6 @@ "strip-ansi-control-characters": "2.0.0", "tempy": "3.1.0", "terminal-link": "4.0.0", - "through2-filter": "4.0.0", - "through2-map": "4.0.0", "toml": "3.0.0", "tomlify-j0.4": "3.0.0", "ulid": "2.3.0", @@ -129,7 +125,6 @@ "@types/envinfo": "7.8.4", "@types/eslint-config-prettier": "^6.11.3", "@types/etag": "1.8.3", - "@types/flush-write-stream": "1.0.2", "@types/folder-walker": "3.2.4", "@types/gitconfiglocal": "2.0.3", "@types/inquirer": "9.0.7", @@ -147,7 +142,6 @@ "@types/semver": "7.7.0", "@types/serialize-javascript": "^5.0.4", "@types/source-map-support": "0.5.10", - "@types/through2-map": "3.0.4", "@types/write-file-atomic": "4.0.3", "@types/ws": "8.18.1", "@vitest/coverage-v8": "3.1.1", @@ -5281,15 +5275,6 @@ "@types/range-parser": "*" } }, - "node_modules/@types/flush-write-stream": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/flush-write-stream/-/flush-write-stream-1.0.2.tgz", - "integrity": "sha512-oCYNbTboisCucq8YBdP97XCmAbI3+Mfpt1XYsedBuZRxWSXsX6LEud8aaACauX3t822XmkdftFCbS+8RvylLWA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/folder-walker": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/@types/folder-walker/-/folder-walker-3.2.4.tgz", @@ -5529,25 +5514,6 @@ "@types/node": "*" } }, - "node_modules/@types/through2": { - "version": "2.0.41", - "resolved": "https://registry.npmjs.org/@types/through2/-/through2-2.0.41.tgz", - "integrity": "sha512-ryQ0tidWkb1O1JuYvWKyMLYEtOWDqF5mHerJzKz/gQpoAaJq2l/dsMPBF0B5BNVT34rbARYJ5/tsZwLfUi2kwQ==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/through2-map": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/through2-map/-/through2-map-3.0.4.tgz", - "integrity": "sha512-021N9/i2YhF8oln0JUrYXkfKt9WO6/FqhmsuiolycRGX+u28VUHyFOWh0E5ZuoqS25d99gg71bTmzTA4TbxPiA==", - "dev": true, - "dependencies": { - "@types/node": "*", - "@types/through2": "*" - } - }, "node_modules/@types/write-file-atomic": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/@types/write-file-atomic/-/write-file-atomic-4.0.3.tgz", @@ -11132,15 +11098,6 @@ "dev": true, "license": "ISC" }, - "node_modules/flush-write-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-2.0.0.tgz", - "integrity": "sha512-uXClqPxT4xW0lcdSBheb2ObVU+kuqUk3Jk64EwieirEXZx9XUrVwp/JuBfKAWaM4T5Td/VL7QLDWPXp/MvGm/g==", - "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - } - }, "node_modules/fn.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", @@ -11268,14 +11225,6 @@ "readable-stream": "^2.0.0" } }, - "node_modules/from2-array": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/from2-array/-/from2-array-0.0.4.tgz", - "integrity": "sha512-0G0cAp7sYLobH7ALsr835x98PU/YeVF7wlwxdWbCUaea7wsa7lJfKZUAo6p2YZGZ8F94luCuqHZS3JtFER6uPg==", - "dependencies": { - "from2": "^2.0.3" - } - }, "node_modules/from2/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -17810,36 +17759,6 @@ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, - "node_modules/through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "dependencies": { - "readable-stream": "3" - } - }, - "node_modules/through2-filter": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-4.0.0.tgz", - "integrity": "sha512-P8IpQL19bSdXqGLvLdbidYRxERXgHEXGcQofPxbLpPkqS1ieOrUrocdYRTNv8YwSukaDJWr71s6F2kZ3bvgEhA==", - "dependencies": { - "through2": "^4.0.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/through2-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/through2-map/-/through2-map-4.0.0.tgz", - "integrity": "sha512-+rpmDB5yckiBGEuqJSsWYWMs9e1zdksypDKvByysEyN+knhsPXV9Z6O2mA9meczIa6AON7bi2G3xWk5T8UG4zQ==", - "dependencies": { - "through2": "^4.0.2" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -22868,15 +22787,6 @@ "@types/range-parser": "*" } }, - "@types/flush-write-stream": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/flush-write-stream/-/flush-write-stream-1.0.2.tgz", - "integrity": "sha512-oCYNbTboisCucq8YBdP97XCmAbI3+Mfpt1XYsedBuZRxWSXsX6LEud8aaACauX3t822XmkdftFCbS+8RvylLWA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, "@types/folder-walker": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/@types/folder-walker/-/folder-walker-3.2.4.tgz", @@ -23111,25 +23021,6 @@ "@types/node": "*" } }, - "@types/through2": { - "version": "2.0.41", - "resolved": "https://registry.npmjs.org/@types/through2/-/through2-2.0.41.tgz", - "integrity": "sha512-ryQ0tidWkb1O1JuYvWKyMLYEtOWDqF5mHerJzKz/gQpoAaJq2l/dsMPBF0B5BNVT34rbARYJ5/tsZwLfUi2kwQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/through2-map": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/through2-map/-/through2-map-3.0.4.tgz", - "integrity": "sha512-021N9/i2YhF8oln0JUrYXkfKt9WO6/FqhmsuiolycRGX+u28VUHyFOWh0E5ZuoqS25d99gg71bTmzTA4TbxPiA==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/through2": "*" - } - }, "@types/write-file-atomic": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/@types/write-file-atomic/-/write-file-atomic-4.0.3.tgz", @@ -26976,15 +26867,6 @@ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", "dev": true }, - "flush-write-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-2.0.0.tgz", - "integrity": "sha512-uXClqPxT4xW0lcdSBheb2ObVU+kuqUk3Jk64EwieirEXZx9XUrVwp/JuBfKAWaM4T5Td/VL7QLDWPXp/MvGm/g==", - "requires": { - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - } - }, "fn.name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", @@ -27085,14 +26967,6 @@ } } }, - "from2-array": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/from2-array/-/from2-array-0.0.4.tgz", - "integrity": "sha512-0G0cAp7sYLobH7ALsr835x98PU/YeVF7wlwxdWbCUaea7wsa7lJfKZUAo6p2YZGZ8F94luCuqHZS3JtFER6uPg==", - "requires": { - "from2": "^2.0.3" - } - }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -31717,30 +31591,6 @@ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" }, - "through2": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", - "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", - "requires": { - "readable-stream": "3" - } - }, - "through2-filter": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-4.0.0.tgz", - "integrity": "sha512-P8IpQL19bSdXqGLvLdbidYRxERXgHEXGcQofPxbLpPkqS1ieOrUrocdYRTNv8YwSukaDJWr71s6F2kZ3bvgEhA==", - "requires": { - "through2": "^4.0.2" - } - }, - "through2-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/through2-map/-/through2-map-4.0.0.tgz", - "integrity": "sha512-+rpmDB5yckiBGEuqJSsWYWMs9e1zdksypDKvByysEyN+knhsPXV9Z6O2mA9meczIa6AON7bi2G3xWk5T8UG4zQ==", - "requires": { - "through2": "^4.0.2" - } - }, "tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", diff --git a/package.json b/package.json index f195a0ce327..e1166c7fd64 100644 --- a/package.json +++ b/package.json @@ -100,9 +100,7 @@ "fastest-levenshtein": "1.0.16", "fastify": "4.29.0", "find-up": "7.0.0", - "flush-write-stream": "2.0.0", "folder-walker": "3.2.0", - "from2-array": "0.0.4", "fuzzy": "0.1.3", "get-port": "5.1.1", "gh-release-fetch": "4.0.3", @@ -148,8 +146,6 @@ "strip-ansi-control-characters": "2.0.0", "tempy": "3.1.0", "terminal-link": "4.0.0", - "through2-filter": "4.0.0", - "through2-map": "4.0.0", "toml": "3.0.0", "tomlify-j0.4": "3.0.0", "ulid": "2.3.0", @@ -173,7 +169,6 @@ "@types/envinfo": "7.8.4", "@types/eslint-config-prettier": "^6.11.3", "@types/etag": "1.8.3", - "@types/flush-write-stream": "1.0.2", "@types/folder-walker": "3.2.4", "@types/gitconfiglocal": "2.0.3", "@types/inquirer": "9.0.7", @@ -191,7 +186,6 @@ "@types/semver": "7.7.0", "@types/serialize-javascript": "^5.0.4", "@types/source-map-support": "0.5.10", - "@types/through2-map": "3.0.4", "@types/write-file-atomic": "4.0.3", "@types/ws": "8.18.1", "@vitest/coverage-v8": "3.1.1", diff --git a/src/utils/deploy/deploy-site.ts b/src/utils/deploy/deploy-site.ts index 014f1d822fc..1244ffa6a99 100644 --- a/src/utils/deploy/deploy-site.ts +++ b/src/utils/deploy/deploy-site.ts @@ -20,6 +20,9 @@ import hashFiles from './hash-files.js' 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' + +export type { DeployEvent } const buildStatsString = (possibleParts: (string | false | undefined)[]) => { const parts = possibleParts.filter(Boolean) @@ -28,13 +31,6 @@ const buildStatsString = (possibleParts: (string | false | undefined)[]) => { return parts.length > 1 ? `${message} and ${parts[parts.length - 1]}` : message } -// TODO(serhalp): This is alternatingly called "event", "status", and "progress". Standardize. -export interface DeployEvent { - type: string - msg: string - phase: 'start' | 'progress' | 'error' | 'stop' -} - export const deploySite = async ( command: BaseCommand, api: $TSFixMe, @@ -115,7 +111,6 @@ export const deploySite = async ( concurrentHash, hashAlgorithm, statusCb, - assetType, manifestPath, skipFunctionsCache, rootDir: siteRoot, diff --git a/src/utils/deploy/hash-files.ts b/src/utils/deploy/hash-files.ts index e6b5a5cab02..e6785b0858c 100644 --- a/src/utils/deploy/hash-files.ts +++ b/src/utils/deploy/hash-files.ts @@ -30,7 +30,7 @@ const hashFiles = async ({ const files = {} // hash: [fileObj, fileObj, fileObj] const filesShaMap = {} - const manifestCollector = manifestCollectorCtor(files, filesShaMap, { statusCb, assetType }) + const manifestCollector = manifestCollectorCtor(files, filesShaMap, { statusCb }) await pipeline([fileStream, fileFilter, hasher, fileNormalizer, manifestCollector]) diff --git a/src/utils/deploy/hash-fns.ts b/src/utils/deploy/hash-fns.ts index 2e1ea08ee6c..f1c5cc56459 100644 --- a/src/utils/deploy/hash-fns.ts +++ b/src/utils/deploy/hash-fns.ts @@ -1,10 +1,9 @@ import { readFile } from 'fs/promises' import path from 'path' import { pipeline } from 'stream/promises' +import { Readable } from 'stream' import { zipFunctions, type FunctionResult, type TrafficRules } from '@netlify/zip-it-and-ship-it' -// @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'from... Remove this comment to see the full error message -import fromArray from 'from2-array' import BaseCommand from '../../commands/base-command.js' import { $TSFixMe } from '../../commands/types.js' @@ -109,8 +108,6 @@ const hashFns = async ( command: BaseCommand, directories: string[], config: { - /** @default 'function' */ - assetType?: string concurrentHash?: number functionsConfig: $TSFixMe /** @default 'sha256' */ @@ -123,7 +120,6 @@ const hashFns = async ( }, ): Promise<$TSFixMe> => { const { - assetType = 'function', concurrentHash, functionsConfig, hashAlgorithm = 'sha256', @@ -211,7 +207,7 @@ const hashFns = async ( ({ nativeNodeModules }) => nativeNodeModules !== undefined && Object.keys(nativeNodeModules).length !== 0, ) - const functionStream = fromArray.obj(fileObjs) + const functionStream = Readable.from(fileObjs) const hasher = hasherCtor({ concurrentHash, hashAlgorithm }) @@ -220,7 +216,7 @@ const hashFns = async ( const functions = {} // hash: [fileObj, fileObj, fileObj] const fnShaMap = {} - const manifestCollector = manifestCollectorCtor(functions, fnShaMap, { statusCb, assetType }) + const manifestCollector = manifestCollectorCtor(functions, fnShaMap, { statusCb }) await pipeline([functionStream, hasher, manifestCollector]) return { functionSchedules, functions, functionsWithNativeModules, fnShaMap, fnConfig } diff --git a/src/utils/deploy/hasher-segments.ts b/src/utils/deploy/hasher-segments.ts index 9a461333db0..31886282485 100644 --- a/src/utils/deploy/hasher-segments.ts +++ b/src/utils/deploy/hasher-segments.ts @@ -1,14 +1,12 @@ import { createHash } from 'node:crypto' import { createReadStream } from 'node:fs' +import { Transform, Writable } from 'node:stream' import { pipeline } from 'node:stream/promises' -import flushWriteStream from 'flush-write-stream' import transform from 'parallel-transform' -// @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'thro... Remove this comment to see the full error message -import { objCtor as objFilterCtor } from 'through2-filter' -import { obj as map } from 'through2-map' import { normalizePath } from './util.js' +import type { StatusCallback } from './status-cb.js' const hashFile = async (filePath: string, algorithm: string) => { const hasher = createHash(algorithm) @@ -36,42 +34,63 @@ export const hasherCtor = ({ concurrentHash, hashAlgorithm }) => { } // Inject normalized file names into normalizedPath and assetType -// @ts-expect-error TS(7031) FIXME: Binding element 'assetType' implicitly has an 'any... Remove this comment to see the full error message -export const fileNormalizerCtor = ({ assetType, normalizer: normalizeFunction }) => - map((fileObj) => { - const normalizedFile = { ...fileObj, assetType, normalizedPath: normalizePath(fileObj.relname) } +export const fileNormalizerCtor = ({ + assetType, + normalizer: normalizeFunction, +}: { + assetType: string + normalizer?: (file: unknown) => unknown +}) => { + return new Transform({ + objectMode: true, + transform(fileObj, _, callback) { + const normalizedFile = { ...fileObj, assetType, normalizedPath: normalizePath(fileObj.relname) } - if (normalizeFunction !== undefined) { - return normalizeFunction(normalizedFile) - } + const result = normalizeFunction !== undefined ? normalizeFunction(normalizedFile) : normalizedFile + + this.push(result) - return normalizedFile + callback() + }, }) +} // A writable stream segment ctor that normalizes file paths, and writes shaMap's -// @ts-expect-error TS(7006) FIXME: Parameter 'filesObj' implicitly has an 'any' type. -export const manifestCollectorCtor = (filesObj, shaMap, { assetType, statusCb }) => { - if (!statusCb || !assetType) throw new Error('Missing required options') - return flushWriteStream.obj((fileObj, _, cb) => { - filesObj[fileObj.normalizedPath] = fileObj.hash +export const manifestCollectorCtor = ( + filesObj: Record, + shaMap: Record, + { statusCb }: { statusCb: StatusCallback }, +) => { + return new Writable({ + objectMode: true, + write(fileObj, _encoding, callback) { + filesObj[fileObj.normalizedPath] = fileObj.hash - // We map a hash to multiple fileObj's because the same file - // might live in two different locations + // Maintain hash to fileObj mapping + if (Array.isArray(shaMap[fileObj.hash])) { + shaMap[fileObj.hash].push(fileObj) + } else { + shaMap[fileObj.hash] = [fileObj] + } - if (Array.isArray(shaMap[fileObj.hash])) { - shaMap[fileObj.hash].push(fileObj) - } else { - shaMap[fileObj.hash] = [fileObj] - } - statusCb({ - type: 'hashing', - msg: `Hashing ${fileObj.relname}`, - phase: 'progress', - }) - cb() + statusCb({ + type: 'hashing', + msg: `Hashing ${fileObj.relname}`, + phase: 'progress', + }) + + callback() + }, }) } -// transform stream ctor that filters folder-walker results for only files -// @ts-expect-error TS(7006) FIXME: Parameter 'fileObj' implicitly has an 'any' type. -export const fileFilterCtor = objFilterCtor((fileObj) => fileObj.type === 'file') +export const fileFilterCtor = () => + new Transform({ + objectMode: true, + transform(fileObj, _, callback) { + if (fileObj.type === 'file') { + this.push(fileObj) + } + callback() + }, + }) diff --git a/src/utils/deploy/status-cb.ts b/src/utils/deploy/status-cb.ts new file mode 100644 index 00000000000..11c887ec00f --- /dev/null +++ b/src/utils/deploy/status-cb.ts @@ -0,0 +1,8 @@ +// TODO(serhalp): This is alternatingly called "event", "status", and "progress". Standardize. +export interface DeployEvent { + type: string + msg: string + phase: 'start' | 'progress' | 'error' | 'stop' +} + +export type StatusCallback = (status: DeployEvent) => void