diff --git a/package-lock.json b/package-lock.json index 359298fd8a..cddc7cd85e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21829,12 +21829,11 @@ }, "node_modules/tinyglobby": { "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", - "dev": true, + "resolved": "https://pkg.pr.new/tinyglobby@131", + "integrity": "sha512-uuM7nc+5QFgns974lHg2z8bFC/IIqR0TgfCKTXx683InNJ3TlYcTyzF7trowUGEGbBfcWvIo2E3AYwUPKVdgmg==", "license": "MIT", "dependencies": { - "fdir": "^6.4.4", + "fdir": "^6.4.6", "picomatch": "^4.0.2" }, "engines": { @@ -24876,9 +24875,9 @@ "devDependencies": { "cpy": "^11.0.0", "cpy-cli": "^5.0.0", - "fast-glob": "^3.2.12", "npm-run-all2": "^6.0.0", "rollup-plugin-node-polyfills": "^0.2.1", + "tinyglobby": "^0.2.13", "tmp-promise": "^3.0.2", "typescript": "^5.0.0", "vite": "^6.0.0", @@ -25649,7 +25648,6 @@ "es-module-lexer": "^1.0.0", "esbuild": "0.25.5", "execa": "^8.0.0", - "fast-glob": "^3.3.3", "filter-obj": "^6.0.0", "find-up": "^7.0.0", "is-builtin-module": "^3.1.0", @@ -25665,6 +25663,7 @@ "require-package-name": "^2.0.1", "resolve": "^2.0.0-next.1", "semver": "^7.3.8", + "tinyglobby": "https://pkg.pr.new/tinyglobby@131", "tmp-promise": "^3.0.2", "toml": "^3.0.0", "unixify": "^1.0.0", diff --git a/packages/zip-it-and-ship-it/package.json b/packages/zip-it-and-ship-it/package.json index dceba9dc17..7e05bca770 100644 --- a/packages/zip-it-and-ship-it/package.json +++ b/packages/zip-it-and-ship-it/package.json @@ -52,7 +52,6 @@ "es-module-lexer": "^1.0.0", "esbuild": "0.25.5", "execa": "^8.0.0", - "fast-glob": "^3.3.3", "filter-obj": "^6.0.0", "find-up": "^7.0.0", "is-builtin-module": "^3.1.0", @@ -68,6 +67,7 @@ "require-package-name": "^2.0.1", "resolve": "^2.0.0-next.1", "semver": "^7.3.8", + "tinyglobby": "https://pkg.pr.new/tinyglobby@131", "tmp-promise": "^3.0.2", "toml": "^3.0.0", "unixify": "^1.0.0", diff --git a/packages/zip-it-and-ship-it/src/runtimes/node/utils/included_files.ts b/packages/zip-it-and-ship-it/src/runtimes/node/utils/included_files.ts index 2fe32ba394..686f7fe765 100644 --- a/packages/zip-it-and-ship-it/src/runtimes/node/utils/included_files.ts +++ b/packages/zip-it-and-ship-it/src/runtimes/node/utils/included_files.ts @@ -1,6 +1,7 @@ import { normalize, resolve } from 'path' +import { lstatSync } from 'fs' -import glob from 'fast-glob' +import { glob } from 'tinyglobby' import { minimatch } from '../../../utils/matching.js' @@ -54,14 +55,21 @@ export const getPathsOfIncludedFiles = async ( dot: true, ignore: excludePatterns, onlyFiles: false, - // get directories as well to get symlinked directories, - // to filter the regular non symlinked directories out mark them with a slash at the end to filter them out. - markDirectories: true, followSymbolicLinks: false, + expandDirectories: false, }) - const paths = pathGroups.filter((path) => !path.endsWith('/')).map(normalize) + const paths = pathGroups.filter(pathFilter).map(normalize) // now filter the non symlinked directories out that got marked with a trailing slash return { excludePatterns, paths } } + +function pathFilter(path: string) { + try { + const stats = lstatSync(path) + return !stats.isDirectory() || stats.isSymbolicLink() + } catch (_err) { + return false + } +} diff --git a/packages/zip-it-and-ship-it/src/utils/matching.ts b/packages/zip-it-and-ship-it/src/utils/matching.ts index 08665faf3e..8a6208d6c2 100644 --- a/packages/zip-it-and-ship-it/src/utils/matching.ts +++ b/packages/zip-it-and-ship-it/src/utils/matching.ts @@ -1,15 +1,16 @@ -import originalGlob from 'fast-glob' import { minimatch as minimatchFunction, type MinimatchOptions } from 'minimatch' import normalizePath from 'normalize-path' +import { glob as originalGlob, type GlobOptions } from 'tinyglobby' /** * Both glob and minimatch only support unix style slashes in patterns * For this reason we wrap them and ensure all patterns are always unixified * We use `normalize-path` here instead of `unixify` because we do not want to remove drive letters */ -export const glob = function (pattern: string, options: originalGlob.Options): Promise { - const normalizedIgnore = options.ignore?.map((expression) => normalizePath(expression)) - return originalGlob(normalizePath(pattern), { ...options, ignore: normalizedIgnore }) +export const glob = function (pattern: string, options: GlobOptions): Promise { + const ignore = Array.isArray(options.ignore) ? options.ignore : options.ignore ? [options.ignore] : [] + const normalizedIgnore = ignore.map((expression) => normalizePath(expression)) + return originalGlob(normalizePath(pattern), { ...options, ignore: normalizedIgnore, expandDirectories: false }) } export const minimatch = function (target: string, pattern: string, options?: MinimatchOptions): boolean { diff --git a/packages/zip-it-and-ship-it/tests/main.test.ts b/packages/zip-it-and-ship-it/tests/main.test.ts index 66ecbe8c50..7bdaa0c5f4 100644 --- a/packages/zip-it-and-ship-it/tests/main.test.ts +++ b/packages/zip-it-and-ship-it/tests/main.test.ts @@ -6,10 +6,10 @@ import cpy from 'cpy' import decompress from 'decompress' import merge from 'deepmerge' import { execa, execaNode } from 'execa' -import glob from 'fast-glob' import isCI from 'is-ci' import { pathExists } from 'path-exists' import semver from 'semver' +import { glob } from 'tinyglobby' import { dir as getTmpDir, tmpName } from 'tmp-promise' import unixify from 'unixify' import { afterAll, afterEach, beforeAll, describe, expect, test, vi } from 'vitest' @@ -2840,7 +2840,7 @@ describe('zip-it-and-ship-it', () => { await decompress(files[0].path, unzipPath) - const fileNames: string[] = await glob('**', { dot: true, cwd: unzipPath }) + const fileNames: string[] = await glob('**', { dot: true, cwd: unzipPath, expandDirectories: false }) const duplicates = fileNames.filter((item, index) => fileNames.indexOf(item) !== index) expect(duplicates).toHaveLength(0) }) diff --git a/packages/zip-it-and-ship-it/tests/telemetry.test.ts b/packages/zip-it-and-ship-it/tests/telemetry.test.ts index cb76676740..68e718a382 100644 --- a/packages/zip-it-and-ship-it/tests/telemetry.test.ts +++ b/packages/zip-it-and-ship-it/tests/telemetry.test.ts @@ -1,7 +1,7 @@ import { join } from 'path' import decompress from 'decompress' -import glob from 'fast-glob' +import { glob } from 'tinyglobby' import { dir as getTmpDir } from 'tmp-promise' import { expect, test } from 'vitest' @@ -32,7 +32,7 @@ test('The telemetry file should be added by default to the function bundle', asy await decompress(result!.path, unzippedPath) - const files = await glob('**/*', { cwd: unzippedPath }) + const files = await glob('**/*', { cwd: unzippedPath, expandDirectories: false }) expect(files.sort()).toEqual([ '___netlify-bootstrap.mjs', '___netlify-entry-point.mjs', diff --git a/packages/zip-it-and-ship-it/tests/v2api.test.ts b/packages/zip-it-and-ship-it/tests/v2api.test.ts index 1c15df6b90..0182d1bf89 100644 --- a/packages/zip-it-and-ship-it/tests/v2api.test.ts +++ b/packages/zip-it-and-ship-it/tests/v2api.test.ts @@ -4,8 +4,8 @@ import { platform } from 'process' import { getPath as getBootstrapPath } from '@netlify/serverless-functions-api' import merge from 'deepmerge' -import glob from 'fast-glob' import { pathExists } from 'path-exists' +import { glob } from 'tinyglobby' import { dir as getTmpDir } from 'tmp-promise' import { afterEach, describe, expect, test, vi } from 'vitest' @@ -128,7 +128,7 @@ describe('V2 functions API', () => { const [{ name: archive, entryFilename, path }] = files - const untranspiledFiles = await glob(`${path}/**/*.ts`) + const untranspiledFiles = await glob(`${path}/**/*.ts`, { expandDirectories: false }) expect(untranspiledFiles).toEqual([]) const func = await importFunctionFile(`${tmpDir}/${archive}/${entryFilename}`)