@unshared/fs 0.0.14 → 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. package/dist/createTemporaryDirectory.cjs +1 -1
  2. package/dist/createTemporaryDirectory.cjs.map +1 -1
  3. package/dist/createTemporaryDirectory.js +2 -2
  4. package/dist/createTemporaryDirectory.js.map +1 -1
  5. package/dist/createTemporaryFile.cjs +1 -1
  6. package/dist/createTemporaryFile.cjs.map +1 -1
  7. package/dist/createTemporaryFile.js +2 -2
  8. package/dist/createTemporaryFile.js.map +1 -1
  9. package/dist/findAncestor.cjs +1 -1
  10. package/dist/findAncestor.cjs.map +1 -1
  11. package/dist/findAncestor.js +2 -2
  12. package/dist/findAncestor.js.map +1 -1
  13. package/dist/findAncestors.cjs +1 -1
  14. package/dist/findAncestors.cjs.map +1 -1
  15. package/dist/findAncestors.js +3 -3
  16. package/dist/findAncestors.js.map +1 -1
  17. package/dist/glob.cjs +1 -1
  18. package/dist/glob.cjs.map +1 -1
  19. package/dist/glob.d.ts +2 -2
  20. package/dist/glob.js +4 -4
  21. package/dist/glob.js.map +1 -1
  22. package/dist/index.cjs +6 -6
  23. package/dist/index.d.ts +2 -2
  24. package/dist/index.js +6 -6
  25. package/dist/loadObject.cjs +1 -1
  26. package/dist/loadObject.cjs.map +1 -1
  27. package/dist/loadObject.d.ts +2 -2
  28. package/dist/loadObject.js +7 -7
  29. package/dist/loadObject.js.map +1 -1
  30. package/dist/touch.cjs +1 -1
  31. package/dist/touch.cjs.map +1 -1
  32. package/dist/touch.js +1 -1
  33. package/dist/touch.js.map +1 -1
  34. package/dist/updateFile.cjs.map +1 -1
  35. package/dist/updateFile.d.ts +1 -1
  36. package/dist/updateFile.js.map +1 -1
  37. package/dist/withTemporaryDirectories.cjs +2 -2
  38. package/dist/withTemporaryDirectories.cjs.map +1 -1
  39. package/dist/withTemporaryDirectories.js +2 -2
  40. package/dist/withTemporaryDirectories.js.map +1 -1
  41. package/dist/withTemporaryFiles.cjs +2 -2
  42. package/dist/withTemporaryFiles.cjs.map +1 -1
  43. package/dist/withTemporaryFiles.js +2 -2
  44. package/dist/withTemporaryFiles.js.map +1 -1
  45. package/package.json +6 -6
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- var node_path = require("node:path"), node_os = require("node:os"), promises = require("node:fs/promises");
2
+ var promises = require("node:fs/promises"), node_os = require("node:os"), node_path = require("node:path");
3
3
  async function createTemporaryDirectory(options = {}) {
4
4
  const {
5
5
  directory = node_os.tmpdir(),
@@ -1 +1 @@
1
- {"version":3,"file":"createTemporaryDirectory.cjs","sources":["../createTemporaryDirectory.ts"],"sourcesContent":["import { join } from 'node:path'\nimport { tmpdir } from 'node:os'\nimport { mkdir, rm } from 'node:fs/promises'\n\nexport interface CreateTemporaryDirectoryOptions {\n\n /**\n * The directory to create the temporary directory in.\n * Defaults to the system's temporary directory.\n *\n * @default tmpdir()\n */\n directory?: string\n\n /**\n * A function that generates a random string.\n *\n * @default () => Math.random().toString(36).slice(2)\n */\n random?: () => string\n}\n\n/**\n * Create a temporary directory with a random name and return\n * an object containing the directory path, and a function to\n * recursively remove the directory.\n *\n * @param options The options to create the temporary directory.\n * @returns A promise that resolves to the temporary directory object.\n * @example\n * // Create a temporary directory.\n * const [path, remove] = await createTemporaryDirectory()\n *\n * // Do something with the directory.\n * exec(`tar -czf ${path}.tar.gz ${path}`)\n *\n * // Remove the directory.\n * await remove()\n */\n\nexport async function createTemporaryDirectory(options: CreateTemporaryDirectoryOptions = {}) {\n const {\n directory = tmpdir(),\n random = () => Math.random().toString(36)\n .slice(2),\n } = options\n\n // --- Generate a random name.\n const name = random()\n const path = join(directory, name)\n\n // --- Create the directory.\n await mkdir(path, { recursive: true })\n\n // --- Return the path and a function to remove the directory.\n const remove = () => rm(path, { force: true, recursive: true })\n return [path, remove] as const\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n const { existsSync, statSync } = await import('node:fs')\n\n test('should create an empty temporary directory in \"/tmp/<random>\"', async() => {\n const [path] = await createTemporaryDirectory()\n const isDirectory = statSync(path).isDirectory()\n expect(path).toMatch(/^\\/tmp\\/[\\da-z]+$/)\n expect(isDirectory).toBe(true)\n })\n\n test('should create a temporary directory in the specified directory', async() => {\n const [path] = await createTemporaryDirectory({ directory: '/cache' })\n expect(path).toMatch(/^\\/cache\\/[\\da-z]+$/)\n })\n\n test('should recursively create the specified directory', async() => {\n const [path] = await createTemporaryDirectory({ directory: '/tmp/foo/bar' })\n expect(path).toMatch(/^\\/tmp\\/foo\\/bar\\/[\\da-z]+$/)\n })\n\n test('should create a temporary file with the given random function', async() => {\n const [path] = await createTemporaryDirectory({ random: () => 'foo' })\n expect(path).toMatch(/^\\/tmp\\/foo$/)\n })\n\n test('should remove the temporary file after calling the remove function', async() => {\n const [path, remove] = await createTemporaryDirectory()\n await remove()\n const exists = existsSync(path)\n expect(exists).toBe(false)\n })\n}\n"],"names":["tmpdir","join","mkdir","rm"],"mappings":";;AAwCsB,eAAA,yBAAyB,UAA2C,IAAI;AACtF,QAAA;AAAA,IACJ,YAAYA,QAAAA,OAAO;AAAA,IACnB,SAAS,MAAM,KAAK,SAAS,SAAS,EAAE,EACrC,MAAM,CAAC;AAAA,EAAA,IACR,SAGE,OAAO,UACP,OAAOC,eAAK,WAAW,IAAI;AAGjC,SAAA,MAAMC,eAAM,MAAM,EAAE,WAAW,GAAK,CAAC,GAI9B,CAAC,MADO,MAAMC,SAAAA,GAAG,MAAM,EAAE,OAAO,IAAM,WAAW,GAAM,CAAA,CAC1C;AACtB;;"}
1
+ {"version":3,"file":"createTemporaryDirectory.cjs","sources":["../createTemporaryDirectory.ts"],"sourcesContent":["import { mkdir, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\n\nexport interface CreateTemporaryDirectoryOptions {\n\n /**\n * The directory to create the temporary directory in.\n * Defaults to the system's temporary directory.\n *\n * @default tmpdir()\n */\n directory?: string\n\n /**\n * A function that generates a random string.\n *\n * @default () => Math.random().toString(36).slice(2)\n */\n random?: () => string\n}\n\n/**\n * Create a temporary directory with a random name and return\n * an object containing the directory path, and a function to\n * recursively remove the directory.\n *\n * @param options The options to create the temporary directory.\n * @returns A promise that resolves to the temporary directory object.\n * @example\n * // Create a temporary directory.\n * const [path, remove] = await createTemporaryDirectory()\n *\n * // Do something with the directory.\n * exec(`tar -czf ${path}.tar.gz ${path}`)\n *\n * // Remove the directory.\n * await remove()\n */\n\nexport async function createTemporaryDirectory(options: CreateTemporaryDirectoryOptions = {}) {\n const {\n directory = tmpdir(),\n random = () => Math.random().toString(36)\n .slice(2),\n } = options\n\n // --- Generate a random name.\n const name = random()\n const path = join(directory, name)\n\n // --- Create the directory.\n await mkdir(path, { recursive: true })\n\n // --- Return the path and a function to remove the directory.\n const remove = () => rm(path, { force: true, recursive: true })\n return [path, remove] as const\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n const { existsSync, statSync } = await import('node:fs')\n\n test('should create an empty temporary directory in \"/tmp/<random>\"', async() => {\n const [path] = await createTemporaryDirectory()\n const isDirectory = statSync(path).isDirectory()\n expect(path).toMatch(/^\\/tmp\\/[\\da-z]+$/)\n expect(isDirectory).toBe(true)\n })\n\n test('should create a temporary directory in the specified directory', async() => {\n const [path] = await createTemporaryDirectory({ directory: '/cache' })\n expect(path).toMatch(/^\\/cache\\/[\\da-z]+$/)\n })\n\n test('should recursively create the specified directory', async() => {\n const [path] = await createTemporaryDirectory({ directory: '/tmp/foo/bar' })\n expect(path).toMatch(/^\\/tmp\\/foo\\/bar\\/[\\da-z]+$/)\n })\n\n test('should create a temporary file with the given random function', async() => {\n const [path] = await createTemporaryDirectory({ random: () => 'foo' })\n expect(path).toMatch(/^\\/tmp\\/foo$/)\n })\n\n test('should remove the temporary file after calling the remove function', async() => {\n const [path, remove] = await createTemporaryDirectory()\n await remove()\n const exists = existsSync(path)\n expect(exists).toBe(false)\n })\n}\n"],"names":["tmpdir","join","mkdir","rm"],"mappings":";;AAwCsB,eAAA,yBAAyB,UAA2C,IAAI;AACtF,QAAA;AAAA,IACJ,YAAYA,QAAAA,OAAO;AAAA,IACnB,SAAS,MAAM,KAAK,SAAS,SAAS,EAAE,EACrC,MAAM,CAAC;AAAA,EAAA,IACR,SAGE,OAAO,UACP,OAAOC,eAAK,WAAW,IAAI;AAGjC,SAAA,MAAMC,eAAM,MAAM,EAAE,WAAW,GAAK,CAAC,GAI9B,CAAC,MADO,MAAMC,SAAAA,GAAG,MAAM,EAAE,OAAO,IAAM,WAAW,GAAM,CAAA,CAC1C;AACtB;;"}
@@ -1,6 +1,6 @@
1
- import { join } from "node:path";
2
- import { tmpdir } from "node:os";
3
1
  import { mkdir, rm } from "node:fs/promises";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
4
  async function createTemporaryDirectory(options = {}) {
5
5
  const {
6
6
  directory = tmpdir(),
@@ -1 +1 @@
1
- {"version":3,"file":"createTemporaryDirectory.js","sources":["../createTemporaryDirectory.ts"],"sourcesContent":["import { join } from 'node:path'\nimport { tmpdir } from 'node:os'\nimport { mkdir, rm } from 'node:fs/promises'\n\nexport interface CreateTemporaryDirectoryOptions {\n\n /**\n * The directory to create the temporary directory in.\n * Defaults to the system's temporary directory.\n *\n * @default tmpdir()\n */\n directory?: string\n\n /**\n * A function that generates a random string.\n *\n * @default () => Math.random().toString(36).slice(2)\n */\n random?: () => string\n}\n\n/**\n * Create a temporary directory with a random name and return\n * an object containing the directory path, and a function to\n * recursively remove the directory.\n *\n * @param options The options to create the temporary directory.\n * @returns A promise that resolves to the temporary directory object.\n * @example\n * // Create a temporary directory.\n * const [path, remove] = await createTemporaryDirectory()\n *\n * // Do something with the directory.\n * exec(`tar -czf ${path}.tar.gz ${path}`)\n *\n * // Remove the directory.\n * await remove()\n */\n\nexport async function createTemporaryDirectory(options: CreateTemporaryDirectoryOptions = {}) {\n const {\n directory = tmpdir(),\n random = () => Math.random().toString(36)\n .slice(2),\n } = options\n\n // --- Generate a random name.\n const name = random()\n const path = join(directory, name)\n\n // --- Create the directory.\n await mkdir(path, { recursive: true })\n\n // --- Return the path and a function to remove the directory.\n const remove = () => rm(path, { force: true, recursive: true })\n return [path, remove] as const\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n const { existsSync, statSync } = await import('node:fs')\n\n test('should create an empty temporary directory in \"/tmp/<random>\"', async() => {\n const [path] = await createTemporaryDirectory()\n const isDirectory = statSync(path).isDirectory()\n expect(path).toMatch(/^\\/tmp\\/[\\da-z]+$/)\n expect(isDirectory).toBe(true)\n })\n\n test('should create a temporary directory in the specified directory', async() => {\n const [path] = await createTemporaryDirectory({ directory: '/cache' })\n expect(path).toMatch(/^\\/cache\\/[\\da-z]+$/)\n })\n\n test('should recursively create the specified directory', async() => {\n const [path] = await createTemporaryDirectory({ directory: '/tmp/foo/bar' })\n expect(path).toMatch(/^\\/tmp\\/foo\\/bar\\/[\\da-z]+$/)\n })\n\n test('should create a temporary file with the given random function', async() => {\n const [path] = await createTemporaryDirectory({ random: () => 'foo' })\n expect(path).toMatch(/^\\/tmp\\/foo$/)\n })\n\n test('should remove the temporary file after calling the remove function', async() => {\n const [path, remove] = await createTemporaryDirectory()\n await remove()\n const exists = existsSync(path)\n expect(exists).toBe(false)\n })\n}\n"],"names":[],"mappings":";;;AAwCsB,eAAA,yBAAyB,UAA2C,IAAI;AACtF,QAAA;AAAA,IACJ,YAAY,OAAO;AAAA,IACnB,SAAS,MAAM,KAAK,SAAS,SAAS,EAAE,EACrC,MAAM,CAAC;AAAA,EAAA,IACR,SAGE,OAAO,UACP,OAAO,KAAK,WAAW,IAAI;AAGjC,SAAA,MAAM,MAAM,MAAM,EAAE,WAAW,GAAK,CAAC,GAI9B,CAAC,MADO,MAAM,GAAG,MAAM,EAAE,OAAO,IAAM,WAAW,GAAM,CAAA,CAC1C;AACtB;"}
1
+ {"version":3,"file":"createTemporaryDirectory.js","sources":["../createTemporaryDirectory.ts"],"sourcesContent":["import { mkdir, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\n\nexport interface CreateTemporaryDirectoryOptions {\n\n /**\n * The directory to create the temporary directory in.\n * Defaults to the system's temporary directory.\n *\n * @default tmpdir()\n */\n directory?: string\n\n /**\n * A function that generates a random string.\n *\n * @default () => Math.random().toString(36).slice(2)\n */\n random?: () => string\n}\n\n/**\n * Create a temporary directory with a random name and return\n * an object containing the directory path, and a function to\n * recursively remove the directory.\n *\n * @param options The options to create the temporary directory.\n * @returns A promise that resolves to the temporary directory object.\n * @example\n * // Create a temporary directory.\n * const [path, remove] = await createTemporaryDirectory()\n *\n * // Do something with the directory.\n * exec(`tar -czf ${path}.tar.gz ${path}`)\n *\n * // Remove the directory.\n * await remove()\n */\n\nexport async function createTemporaryDirectory(options: CreateTemporaryDirectoryOptions = {}) {\n const {\n directory = tmpdir(),\n random = () => Math.random().toString(36)\n .slice(2),\n } = options\n\n // --- Generate a random name.\n const name = random()\n const path = join(directory, name)\n\n // --- Create the directory.\n await mkdir(path, { recursive: true })\n\n // --- Return the path and a function to remove the directory.\n const remove = () => rm(path, { force: true, recursive: true })\n return [path, remove] as const\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n const { existsSync, statSync } = await import('node:fs')\n\n test('should create an empty temporary directory in \"/tmp/<random>\"', async() => {\n const [path] = await createTemporaryDirectory()\n const isDirectory = statSync(path).isDirectory()\n expect(path).toMatch(/^\\/tmp\\/[\\da-z]+$/)\n expect(isDirectory).toBe(true)\n })\n\n test('should create a temporary directory in the specified directory', async() => {\n const [path] = await createTemporaryDirectory({ directory: '/cache' })\n expect(path).toMatch(/^\\/cache\\/[\\da-z]+$/)\n })\n\n test('should recursively create the specified directory', async() => {\n const [path] = await createTemporaryDirectory({ directory: '/tmp/foo/bar' })\n expect(path).toMatch(/^\\/tmp\\/foo\\/bar\\/[\\da-z]+$/)\n })\n\n test('should create a temporary file with the given random function', async() => {\n const [path] = await createTemporaryDirectory({ random: () => 'foo' })\n expect(path).toMatch(/^\\/tmp\\/foo$/)\n })\n\n test('should remove the temporary file after calling the remove function', async() => {\n const [path, remove] = await createTemporaryDirectory()\n await remove()\n const exists = existsSync(path)\n expect(exists).toBe(false)\n })\n}\n"],"names":[],"mappings":";;;AAwCsB,eAAA,yBAAyB,UAA2C,IAAI;AACtF,QAAA;AAAA,IACJ,YAAY,OAAO;AAAA,IACnB,SAAS,MAAM,KAAK,SAAS,SAAS,EAAE,EACrC,MAAM,CAAC;AAAA,EAAA,IACR,SAGE,OAAO,UACP,OAAO,KAAK,WAAW,IAAI;AAGjC,SAAA,MAAM,MAAM,MAAM,EAAE,WAAW,GAAK,CAAC,GAI9B,CAAC,MADO,MAAM,GAAG,MAAM,EAAE,OAAO,IAAM,WAAW,GAAM,CAAA,CAC1C;AACtB;"}
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- var node_path = require("node:path"), node_os = require("node:os"), promises = require("node:fs/promises");
2
+ var promises = require("node:fs/promises"), node_os = require("node:os"), node_path = require("node:path");
3
3
  async function createTemporaryFile(content, options = {}) {
4
4
  const {
5
5
  directory = node_os.tmpdir(),
@@ -1 +1 @@
1
- {"version":3,"file":"createTemporaryFile.cjs","sources":["../createTemporaryFile.ts"],"sourcesContent":["import { join } from 'node:path'\nimport { tmpdir } from 'node:os'\nimport { mkdir, rm, writeFile } from 'node:fs/promises'\n\nexport interface CreateTemporaryFileOptions {\n\n /**\n * The directory to create the temporary file in.\n * Defaults to the system's temporary directory.\n *\n * @default tmpdir()\n */\n directory?: string\n\n /**\n * The file extension to use for the temporary file.\n *\n * @default ''\n */\n extension?: string\n\n /**\n * A function that generates a random string.\n *\n * @default () => Math.random().toString(36).slice(2)\n */\n random?: () => string\n}\n\n/**\n * Create a temporary file with a random name and return\n * an object containing the file path, and a function to\n * remove the file.\n *\n * @param content The content to write to the temporary file.\n * @param options The options to create the temporary file.\n * @returns A promise that resolves to the temporary file object.\n * @example\n * // Create a temporary file with the specified content.\n * const [path, remove] = await createTemporaryFile('Hello, world!')\n *\n * // Do something with the file.\n * exec(`openssl sha1 ${path}`)\n *\n * // Remove the file.\n * await remove()\n */\nexport async function createTemporaryFile(content?: Parameters<typeof writeFile>[1], options: CreateTemporaryFileOptions = {}) {\n const {\n directory = tmpdir(),\n extension,\n random = () => Math.random().toString(36)\n .slice(2),\n } = options\n\n // --- Generate a random name.\n const rand = random()\n const name = extension ? `${rand}.${extension}` : rand\n const path = join(directory, name)\n\n // --- Write the content to the file.\n await mkdir(directory, { recursive: true })\n await writeFile(path, content ?? '')\n\n // --- Return the path and a function to remove the file.\n const remove = () => rm(path, { force: true })\n return [path, remove] as const\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n const { existsSync, readFileSync, statSync } = await import('node:fs')\n\n test('should create an empty temporary file in \"/tmp/<random>\"', async() => {\n const [path] = await createTemporaryFile()\n const isFile = statSync(path).isFile()\n const content = readFileSync(path, 'utf8')\n expect(path).toMatch(/^\\/tmp\\/[\\da-z]+$/)\n expect(isFile).toBe(true)\n expect(content).toBe('')\n })\n\n test('should create a temporary file with the specified content', async() => {\n const [path] = await createTemporaryFile('Hello, world!')\n const content = readFileSync(path, 'utf8')\n expect(content).toBe('Hello, world!')\n })\n\n test('should create a temporary file in the specified directory', async() => {\n const [path] = await createTemporaryFile(undefined, { directory: '/cache' })\n expect(path).toMatch(/^\\/cache\\/[\\da-z]+$/)\n })\n\n test('should recursively create the specified directory', async() => {\n const [path] = await createTemporaryFile(undefined, { directory: '/tmp/foo/bar' })\n expect(path).toMatch(/^\\/tmp\\/foo\\/bar\\/[\\da-z]+$/)\n })\n\n test('should create a temporary file with the specified extension', async() => {\n const [path] = await createTemporaryFile(undefined, { extension: 'txt' })\n expect(path).toMatch(/^\\/tmp\\/[\\da-z]+\\.txt$/)\n })\n\n test('should create a temporary file with the given random function', async() => {\n const [path] = await createTemporaryFile(undefined, { random: () => 'foo' })\n expect(path).toMatch(/^\\/tmp\\/foo$/)\n })\n\n test('should remove the temporary file after calling the remove function', async() => {\n const [path, remove] = await createTemporaryFile()\n await remove()\n const exists = existsSync(path)\n expect(exists).toBe(false)\n })\n}\n"],"names":["tmpdir","join","mkdir","writeFile","rm"],"mappings":";;AA+CA,eAAsB,oBAAoB,SAA2C,UAAsC,IAAI;AACvH,QAAA;AAAA,IACJ,YAAYA,QAAAA,OAAO;AAAA,IACnB;AAAA,IACA,SAAS,MAAM,KAAK,SAAS,SAAS,EAAE,EACrC,MAAM,CAAC;AAAA,EAAA,IACR,SAGE,OAAO,OAAO,GACd,OAAO,YAAY,GAAG,IAAI,IAAI,SAAS,KAAK,MAC5C,OAAOC,UAAAA,KAAK,WAAW,IAAI;AAG3B,SAAA,MAAAC,SAAAA,MAAM,WAAW,EAAE,WAAW,IAAM,GAC1C,MAAMC,SAAA,UAAU,MAAM,WAAW,EAAE,GAI5B,CAAC,MADO,MAAMC,YAAG,MAAM,EAAE,OAAO,GAAM,CAAA,CACzB;AACtB;;"}
1
+ {"version":3,"file":"createTemporaryFile.cjs","sources":["../createTemporaryFile.ts"],"sourcesContent":["import { mkdir, rm, writeFile } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\n\nexport interface CreateTemporaryFileOptions {\n\n /**\n * The directory to create the temporary file in.\n * Defaults to the system's temporary directory.\n *\n * @default tmpdir()\n */\n directory?: string\n\n /**\n * The file extension to use for the temporary file.\n *\n * @default ''\n */\n extension?: string\n\n /**\n * A function that generates a random string.\n *\n * @default () => Math.random().toString(36).slice(2)\n */\n random?: () => string\n}\n\n/**\n * Create a temporary file with a random name and return\n * an object containing the file path, and a function to\n * remove the file.\n *\n * @param content The content to write to the temporary file.\n * @param options The options to create the temporary file.\n * @returns A promise that resolves to the temporary file object.\n * @example\n * // Create a temporary file with the specified content.\n * const [path, remove] = await createTemporaryFile('Hello, world!')\n *\n * // Do something with the file.\n * exec(`openssl sha1 ${path}`)\n *\n * // Remove the file.\n * await remove()\n */\nexport async function createTemporaryFile(content?: Parameters<typeof writeFile>[1], options: CreateTemporaryFileOptions = {}) {\n const {\n directory = tmpdir(),\n extension,\n random = () => Math.random().toString(36)\n .slice(2),\n } = options\n\n // --- Generate a random name.\n const rand = random()\n const name = extension ? `${rand}.${extension}` : rand\n const path = join(directory, name)\n\n // --- Write the content to the file.\n await mkdir(directory, { recursive: true })\n await writeFile(path, content ?? '')\n\n // --- Return the path and a function to remove the file.\n const remove = () => rm(path, { force: true })\n return [path, remove] as const\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n const { existsSync, readFileSync, statSync } = await import('node:fs')\n\n test('should create an empty temporary file in \"/tmp/<random>\"', async() => {\n const [path] = await createTemporaryFile()\n const isFile = statSync(path).isFile()\n const content = readFileSync(path, 'utf8')\n expect(path).toMatch(/^\\/tmp\\/[\\da-z]+$/)\n expect(isFile).toBe(true)\n expect(content).toBe('')\n })\n\n test('should create a temporary file with the specified content', async() => {\n const [path] = await createTemporaryFile('Hello, world!')\n const content = readFileSync(path, 'utf8')\n expect(content).toBe('Hello, world!')\n })\n\n test('should create a temporary file in the specified directory', async() => {\n const [path] = await createTemporaryFile(undefined, { directory: '/cache' })\n expect(path).toMatch(/^\\/cache\\/[\\da-z]+$/)\n })\n\n test('should recursively create the specified directory', async() => {\n const [path] = await createTemporaryFile(undefined, { directory: '/tmp/foo/bar' })\n expect(path).toMatch(/^\\/tmp\\/foo\\/bar\\/[\\da-z]+$/)\n })\n\n test('should create a temporary file with the specified extension', async() => {\n const [path] = await createTemporaryFile(undefined, { extension: 'txt' })\n expect(path).toMatch(/^\\/tmp\\/[\\da-z]+\\.txt$/)\n })\n\n test('should create a temporary file with the given random function', async() => {\n const [path] = await createTemporaryFile(undefined, { random: () => 'foo' })\n expect(path).toMatch(/^\\/tmp\\/foo$/)\n })\n\n test('should remove the temporary file after calling the remove function', async() => {\n const [path, remove] = await createTemporaryFile()\n await remove()\n const exists = existsSync(path)\n expect(exists).toBe(false)\n })\n}\n"],"names":["tmpdir","join","mkdir","writeFile","rm"],"mappings":";;AA+CA,eAAsB,oBAAoB,SAA2C,UAAsC,IAAI;AACvH,QAAA;AAAA,IACJ,YAAYA,QAAAA,OAAO;AAAA,IACnB;AAAA,IACA,SAAS,MAAM,KAAK,SAAS,SAAS,EAAE,EACrC,MAAM,CAAC;AAAA,EAAA,IACR,SAGE,OAAO,OAAO,GACd,OAAO,YAAY,GAAG,IAAI,IAAI,SAAS,KAAK,MAC5C,OAAOC,UAAAA,KAAK,WAAW,IAAI;AAG3B,SAAA,MAAAC,SAAAA,MAAM,WAAW,EAAE,WAAW,IAAM,GAC1C,MAAMC,SAAA,UAAU,MAAM,WAAW,EAAE,GAI5B,CAAC,MADO,MAAMC,YAAG,MAAM,EAAE,OAAO,GAAM,CAAA,CACzB;AACtB;;"}
@@ -1,6 +1,6 @@
1
- import { join } from "node:path";
2
- import { tmpdir } from "node:os";
3
1
  import { mkdir, writeFile, rm } from "node:fs/promises";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
4
  async function createTemporaryFile(content, options = {}) {
5
5
  const {
6
6
  directory = tmpdir(),
@@ -1 +1 @@
1
- {"version":3,"file":"createTemporaryFile.js","sources":["../createTemporaryFile.ts"],"sourcesContent":["import { join } from 'node:path'\nimport { tmpdir } from 'node:os'\nimport { mkdir, rm, writeFile } from 'node:fs/promises'\n\nexport interface CreateTemporaryFileOptions {\n\n /**\n * The directory to create the temporary file in.\n * Defaults to the system's temporary directory.\n *\n * @default tmpdir()\n */\n directory?: string\n\n /**\n * The file extension to use for the temporary file.\n *\n * @default ''\n */\n extension?: string\n\n /**\n * A function that generates a random string.\n *\n * @default () => Math.random().toString(36).slice(2)\n */\n random?: () => string\n}\n\n/**\n * Create a temporary file with a random name and return\n * an object containing the file path, and a function to\n * remove the file.\n *\n * @param content The content to write to the temporary file.\n * @param options The options to create the temporary file.\n * @returns A promise that resolves to the temporary file object.\n * @example\n * // Create a temporary file with the specified content.\n * const [path, remove] = await createTemporaryFile('Hello, world!')\n *\n * // Do something with the file.\n * exec(`openssl sha1 ${path}`)\n *\n * // Remove the file.\n * await remove()\n */\nexport async function createTemporaryFile(content?: Parameters<typeof writeFile>[1], options: CreateTemporaryFileOptions = {}) {\n const {\n directory = tmpdir(),\n extension,\n random = () => Math.random().toString(36)\n .slice(2),\n } = options\n\n // --- Generate a random name.\n const rand = random()\n const name = extension ? `${rand}.${extension}` : rand\n const path = join(directory, name)\n\n // --- Write the content to the file.\n await mkdir(directory, { recursive: true })\n await writeFile(path, content ?? '')\n\n // --- Return the path and a function to remove the file.\n const remove = () => rm(path, { force: true })\n return [path, remove] as const\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n const { existsSync, readFileSync, statSync } = await import('node:fs')\n\n test('should create an empty temporary file in \"/tmp/<random>\"', async() => {\n const [path] = await createTemporaryFile()\n const isFile = statSync(path).isFile()\n const content = readFileSync(path, 'utf8')\n expect(path).toMatch(/^\\/tmp\\/[\\da-z]+$/)\n expect(isFile).toBe(true)\n expect(content).toBe('')\n })\n\n test('should create a temporary file with the specified content', async() => {\n const [path] = await createTemporaryFile('Hello, world!')\n const content = readFileSync(path, 'utf8')\n expect(content).toBe('Hello, world!')\n })\n\n test('should create a temporary file in the specified directory', async() => {\n const [path] = await createTemporaryFile(undefined, { directory: '/cache' })\n expect(path).toMatch(/^\\/cache\\/[\\da-z]+$/)\n })\n\n test('should recursively create the specified directory', async() => {\n const [path] = await createTemporaryFile(undefined, { directory: '/tmp/foo/bar' })\n expect(path).toMatch(/^\\/tmp\\/foo\\/bar\\/[\\da-z]+$/)\n })\n\n test('should create a temporary file with the specified extension', async() => {\n const [path] = await createTemporaryFile(undefined, { extension: 'txt' })\n expect(path).toMatch(/^\\/tmp\\/[\\da-z]+\\.txt$/)\n })\n\n test('should create a temporary file with the given random function', async() => {\n const [path] = await createTemporaryFile(undefined, { random: () => 'foo' })\n expect(path).toMatch(/^\\/tmp\\/foo$/)\n })\n\n test('should remove the temporary file after calling the remove function', async() => {\n const [path, remove] = await createTemporaryFile()\n await remove()\n const exists = existsSync(path)\n expect(exists).toBe(false)\n })\n}\n"],"names":[],"mappings":";;;AA+CA,eAAsB,oBAAoB,SAA2C,UAAsC,IAAI;AACvH,QAAA;AAAA,IACJ,YAAY,OAAO;AAAA,IACnB;AAAA,IACA,SAAS,MAAM,KAAK,SAAS,SAAS,EAAE,EACrC,MAAM,CAAC;AAAA,EAAA,IACR,SAGE,OAAO,OAAO,GACd,OAAO,YAAY,GAAG,IAAI,IAAI,SAAS,KAAK,MAC5C,OAAO,KAAK,WAAW,IAAI;AAG3B,SAAA,MAAA,MAAM,WAAW,EAAE,WAAW,IAAM,GAC1C,MAAM,UAAU,MAAM,WAAW,EAAE,GAI5B,CAAC,MADO,MAAM,GAAG,MAAM,EAAE,OAAO,GAAM,CAAA,CACzB;AACtB;"}
1
+ {"version":3,"file":"createTemporaryFile.js","sources":["../createTemporaryFile.ts"],"sourcesContent":["import { mkdir, rm, writeFile } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\n\nexport interface CreateTemporaryFileOptions {\n\n /**\n * The directory to create the temporary file in.\n * Defaults to the system's temporary directory.\n *\n * @default tmpdir()\n */\n directory?: string\n\n /**\n * The file extension to use for the temporary file.\n *\n * @default ''\n */\n extension?: string\n\n /**\n * A function that generates a random string.\n *\n * @default () => Math.random().toString(36).slice(2)\n */\n random?: () => string\n}\n\n/**\n * Create a temporary file with a random name and return\n * an object containing the file path, and a function to\n * remove the file.\n *\n * @param content The content to write to the temporary file.\n * @param options The options to create the temporary file.\n * @returns A promise that resolves to the temporary file object.\n * @example\n * // Create a temporary file with the specified content.\n * const [path, remove] = await createTemporaryFile('Hello, world!')\n *\n * // Do something with the file.\n * exec(`openssl sha1 ${path}`)\n *\n * // Remove the file.\n * await remove()\n */\nexport async function createTemporaryFile(content?: Parameters<typeof writeFile>[1], options: CreateTemporaryFileOptions = {}) {\n const {\n directory = tmpdir(),\n extension,\n random = () => Math.random().toString(36)\n .slice(2),\n } = options\n\n // --- Generate a random name.\n const rand = random()\n const name = extension ? `${rand}.${extension}` : rand\n const path = join(directory, name)\n\n // --- Write the content to the file.\n await mkdir(directory, { recursive: true })\n await writeFile(path, content ?? '')\n\n // --- Return the path and a function to remove the file.\n const remove = () => rm(path, { force: true })\n return [path, remove] as const\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n const { existsSync, readFileSync, statSync } = await import('node:fs')\n\n test('should create an empty temporary file in \"/tmp/<random>\"', async() => {\n const [path] = await createTemporaryFile()\n const isFile = statSync(path).isFile()\n const content = readFileSync(path, 'utf8')\n expect(path).toMatch(/^\\/tmp\\/[\\da-z]+$/)\n expect(isFile).toBe(true)\n expect(content).toBe('')\n })\n\n test('should create a temporary file with the specified content', async() => {\n const [path] = await createTemporaryFile('Hello, world!')\n const content = readFileSync(path, 'utf8')\n expect(content).toBe('Hello, world!')\n })\n\n test('should create a temporary file in the specified directory', async() => {\n const [path] = await createTemporaryFile(undefined, { directory: '/cache' })\n expect(path).toMatch(/^\\/cache\\/[\\da-z]+$/)\n })\n\n test('should recursively create the specified directory', async() => {\n const [path] = await createTemporaryFile(undefined, { directory: '/tmp/foo/bar' })\n expect(path).toMatch(/^\\/tmp\\/foo\\/bar\\/[\\da-z]+$/)\n })\n\n test('should create a temporary file with the specified extension', async() => {\n const [path] = await createTemporaryFile(undefined, { extension: 'txt' })\n expect(path).toMatch(/^\\/tmp\\/[\\da-z]+\\.txt$/)\n })\n\n test('should create a temporary file with the given random function', async() => {\n const [path] = await createTemporaryFile(undefined, { random: () => 'foo' })\n expect(path).toMatch(/^\\/tmp\\/foo$/)\n })\n\n test('should remove the temporary file after calling the remove function', async() => {\n const [path, remove] = await createTemporaryFile()\n await remove()\n const exists = existsSync(path)\n expect(exists).toBe(false)\n })\n}\n"],"names":[],"mappings":";;;AA+CA,eAAsB,oBAAoB,SAA2C,UAAsC,IAAI;AACvH,QAAA;AAAA,IACJ,YAAY,OAAO;AAAA,IACnB;AAAA,IACA,SAAS,MAAM,KAAK,SAAS,SAAS,EAAE,EACrC,MAAM,CAAC;AAAA,EAAA,IACR,SAGE,OAAO,OAAO,GACd,OAAO,YAAY,GAAG,IAAI,IAAI,SAAS,KAAK,MAC5C,OAAO,KAAK,WAAW,IAAI;AAG3B,SAAA,MAAA,MAAM,WAAW,EAAE,WAAW,IAAM,GAC1C,MAAM,UAAU,MAAM,WAAW,EAAE,GAI5B,CAAC,MADO,MAAM,GAAG,MAAM,EAAE,OAAO,GAAM,CAAA,CACzB;AACtB;"}
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- var node_process = require("node:process"), node_path = require("node:path"), promises = require("node:fs/promises");
2
+ var promises = require("node:fs/promises"), node_path = require("node:path"), node_process = require("node:process");
3
3
  async function findAncestor(name, from = node_process.cwd()) {
4
4
  for (; from !== ""; ) {
5
5
  const absolutePath = node_path.resolve(from, name);
@@ -1 +1 @@
1
- {"version":3,"file":"findAncestor.cjs","sources":["../findAncestor.ts"],"sourcesContent":["import { cwd } from 'node:process'\nimport { dirname, resolve } from 'node:path'\nimport { access, constants } from 'node:fs/promises'\n\n/**\n * Find the first ancestor of a file from a given path. The search will start\n * from the given path and will continue until the root directory is reached.\n * If the file is not found, will throw an error.\n *\n * @param name The file name to find.\n * @param from The path to start from.\n * @returns The absolute path of the file found.\n * @example\n * // Create a file in the root directory.\n * await writeFile('/home/user/file.txt', 'Hello, world!')\n *\n * // Find the file from a subdirectory.\n * await findAncestor('file.txt', '/home/user/project') // '/home/user/file.txt'\n */\nexport async function findAncestor(name: string, from: string = cwd()): Promise<string | undefined> {\n while (from !== '') {\n const absolutePath = resolve(from, name)\n try {\n await access(absolutePath, constants.F_OK)\n return absolutePath\n }\n catch {\n\n /** Ignore error. */\n }\n if (from === '/') break\n from = dirname(from)\n }\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n const { vol } = await import('memfs')\n\n test('should resolve ancestor from current directory', async() => {\n vi.mock('node:process', () => ({ cwd: () => '/home/user/project' }))\n vol.fromJSON({ '/home/user/project/.npmrc': '' })\n const result = await findAncestor('.npmrc')\n expect(result).toBe('/home/user/project/.npmrc')\n })\n\n test('should resolve ancestor from given directory', async() => {\n vol.fromJSON({ '/home/user/.npmrc': '' })\n const result = await findAncestor('.npmrc', '/home/user/project')\n expect(result).toBe('/home/user/.npmrc')\n })\n\n test('should resolve ancestor at root directory', async() => {\n vol.fromJSON({ '/.npmrc': '' })\n const result = await findAncestor('.npmrc', '/home/user/project')\n expect(result).toBe('/.npmrc')\n })\n\n test('should resolve the first ancestor', async() => {\n vol.fromJSON({\n '/.npmrc': '',\n '/home/user/.npmrc': '',\n '/home/user/project/.npmrc': '',\n })\n const result = await findAncestor('.npmrc', '/home/user/project')\n expect(result).toBe('/home/user/project/.npmrc')\n })\n\n test('should return undefined if no ancestor was found', async() => {\n vol.fromJSON({})\n const result = await findAncestor('file', '/')\n expect(result).toBeUndefined()\n })\n}\n"],"names":["cwd","resolve","access","constants","dirname"],"mappings":";;AAmBA,eAAsB,aAAa,MAAc,OAAeA,aAAAA,OAAoC;AAClG,SAAO,SAAS,MAAI;AACZ,UAAA,eAAeC,UAAAA,QAAQ,MAAM,IAAI;AACnC,QAAA;AACF,aAAA,MAAMC,SAAO,OAAA,cAAcC,SAAU,UAAA,IAAI,GAClC;AAAA,IAAA,QAEH;AAAA,IAGN;AACA,QAAI,SAAS,IAAK;AAClB,WAAOC,UAAAA,QAAQ,IAAI;AAAA,EACrB;AACF;;"}
1
+ {"version":3,"file":"findAncestor.cjs","sources":["../findAncestor.ts"],"sourcesContent":["import { access, constants } from 'node:fs/promises'\nimport { dirname, resolve } from 'node:path'\nimport { cwd } from 'node:process'\n\n/**\n * Find the first ancestor of a file from a given path. The search will start\n * from the given path and will continue until the root directory is reached.\n * If the file is not found, will throw an error.\n *\n * @param name The file name to find.\n * @param from The path to start from.\n * @returns The absolute path of the file found.\n * @example\n * // Create a file in the root directory.\n * await writeFile('/home/user/file.txt', 'Hello, world!')\n *\n * // Find the file from a subdirectory.\n * await findAncestor('file.txt', '/home/user/project') // '/home/user/file.txt'\n */\nexport async function findAncestor(name: string, from: string = cwd()): Promise<string | undefined> {\n while (from !== '') {\n const absolutePath = resolve(from, name)\n try {\n await access(absolutePath, constants.F_OK)\n return absolutePath\n }\n catch {\n\n /** Ignore error. */\n }\n if (from === '/') break\n from = dirname(from)\n }\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n const { vol } = await import('memfs')\n\n test('should resolve ancestor from current directory', async() => {\n vi.mock('node:process', () => ({ cwd: () => '/home/user/project' }))\n vol.fromJSON({ '/home/user/project/.npmrc': '' })\n const result = await findAncestor('.npmrc')\n expect(result).toBe('/home/user/project/.npmrc')\n })\n\n test('should resolve ancestor from given directory', async() => {\n vol.fromJSON({ '/home/user/.npmrc': '' })\n const result = await findAncestor('.npmrc', '/home/user/project')\n expect(result).toBe('/home/user/.npmrc')\n })\n\n test('should resolve ancestor at root directory', async() => {\n vol.fromJSON({ '/.npmrc': '' })\n const result = await findAncestor('.npmrc', '/home/user/project')\n expect(result).toBe('/.npmrc')\n })\n\n test('should resolve the first ancestor', async() => {\n vol.fromJSON({\n '/.npmrc': '',\n '/home/user/.npmrc': '',\n '/home/user/project/.npmrc': '',\n })\n const result = await findAncestor('.npmrc', '/home/user/project')\n expect(result).toBe('/home/user/project/.npmrc')\n })\n\n test('should return undefined if no ancestor was found', async() => {\n vol.fromJSON({})\n const result = await findAncestor('file', '/')\n expect(result).toBeUndefined()\n })\n}\n"],"names":["cwd","resolve","access","constants","dirname"],"mappings":";;AAmBA,eAAsB,aAAa,MAAc,OAAeA,aAAAA,OAAoC;AAClG,SAAO,SAAS,MAAI;AACZ,UAAA,eAAeC,UAAAA,QAAQ,MAAM,IAAI;AACnC,QAAA;AACF,aAAA,MAAMC,SAAO,OAAA,cAAcC,SAAU,UAAA,IAAI,GAClC;AAAA,IAAA,QAEH;AAAA,IAGN;AACA,QAAI,SAAS,IAAK;AAClB,WAAOC,UAAAA,QAAQ,IAAI;AAAA,EACrB;AACF;;"}
@@ -1,6 +1,6 @@
1
- import { cwd } from "node:process";
2
- import { resolve, dirname } from "node:path";
3
1
  import { access, constants } from "node:fs/promises";
2
+ import { resolve, dirname } from "node:path";
3
+ import { cwd } from "node:process";
4
4
  async function findAncestor(name, from = cwd()) {
5
5
  for (; from !== ""; ) {
6
6
  const absolutePath = resolve(from, name);
@@ -1 +1 @@
1
- {"version":3,"file":"findAncestor.js","sources":["../findAncestor.ts"],"sourcesContent":["import { cwd } from 'node:process'\nimport { dirname, resolve } from 'node:path'\nimport { access, constants } from 'node:fs/promises'\n\n/**\n * Find the first ancestor of a file from a given path. The search will start\n * from the given path and will continue until the root directory is reached.\n * If the file is not found, will throw an error.\n *\n * @param name The file name to find.\n * @param from The path to start from.\n * @returns The absolute path of the file found.\n * @example\n * // Create a file in the root directory.\n * await writeFile('/home/user/file.txt', 'Hello, world!')\n *\n * // Find the file from a subdirectory.\n * await findAncestor('file.txt', '/home/user/project') // '/home/user/file.txt'\n */\nexport async function findAncestor(name: string, from: string = cwd()): Promise<string | undefined> {\n while (from !== '') {\n const absolutePath = resolve(from, name)\n try {\n await access(absolutePath, constants.F_OK)\n return absolutePath\n }\n catch {\n\n /** Ignore error. */\n }\n if (from === '/') break\n from = dirname(from)\n }\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n const { vol } = await import('memfs')\n\n test('should resolve ancestor from current directory', async() => {\n vi.mock('node:process', () => ({ cwd: () => '/home/user/project' }))\n vol.fromJSON({ '/home/user/project/.npmrc': '' })\n const result = await findAncestor('.npmrc')\n expect(result).toBe('/home/user/project/.npmrc')\n })\n\n test('should resolve ancestor from given directory', async() => {\n vol.fromJSON({ '/home/user/.npmrc': '' })\n const result = await findAncestor('.npmrc', '/home/user/project')\n expect(result).toBe('/home/user/.npmrc')\n })\n\n test('should resolve ancestor at root directory', async() => {\n vol.fromJSON({ '/.npmrc': '' })\n const result = await findAncestor('.npmrc', '/home/user/project')\n expect(result).toBe('/.npmrc')\n })\n\n test('should resolve the first ancestor', async() => {\n vol.fromJSON({\n '/.npmrc': '',\n '/home/user/.npmrc': '',\n '/home/user/project/.npmrc': '',\n })\n const result = await findAncestor('.npmrc', '/home/user/project')\n expect(result).toBe('/home/user/project/.npmrc')\n })\n\n test('should return undefined if no ancestor was found', async() => {\n vol.fromJSON({})\n const result = await findAncestor('file', '/')\n expect(result).toBeUndefined()\n })\n}\n"],"names":[],"mappings":";;;AAmBA,eAAsB,aAAa,MAAc,OAAe,OAAoC;AAClG,SAAO,SAAS,MAAI;AACZ,UAAA,eAAe,QAAQ,MAAM,IAAI;AACnC,QAAA;AACF,aAAA,MAAM,OAAO,cAAc,UAAU,IAAI,GAClC;AAAA,IAAA,QAEH;AAAA,IAGN;AACA,QAAI,SAAS,IAAK;AAClB,WAAO,QAAQ,IAAI;AAAA,EACrB;AACF;"}
1
+ {"version":3,"file":"findAncestor.js","sources":["../findAncestor.ts"],"sourcesContent":["import { access, constants } from 'node:fs/promises'\nimport { dirname, resolve } from 'node:path'\nimport { cwd } from 'node:process'\n\n/**\n * Find the first ancestor of a file from a given path. The search will start\n * from the given path and will continue until the root directory is reached.\n * If the file is not found, will throw an error.\n *\n * @param name The file name to find.\n * @param from The path to start from.\n * @returns The absolute path of the file found.\n * @example\n * // Create a file in the root directory.\n * await writeFile('/home/user/file.txt', 'Hello, world!')\n *\n * // Find the file from a subdirectory.\n * await findAncestor('file.txt', '/home/user/project') // '/home/user/file.txt'\n */\nexport async function findAncestor(name: string, from: string = cwd()): Promise<string | undefined> {\n while (from !== '') {\n const absolutePath = resolve(from, name)\n try {\n await access(absolutePath, constants.F_OK)\n return absolutePath\n }\n catch {\n\n /** Ignore error. */\n }\n if (from === '/') break\n from = dirname(from)\n }\n}\n\n/* v8 ignore start */\nif (import.meta.vitest) {\n const { vol } = await import('memfs')\n\n test('should resolve ancestor from current directory', async() => {\n vi.mock('node:process', () => ({ cwd: () => '/home/user/project' }))\n vol.fromJSON({ '/home/user/project/.npmrc': '' })\n const result = await findAncestor('.npmrc')\n expect(result).toBe('/home/user/project/.npmrc')\n })\n\n test('should resolve ancestor from given directory', async() => {\n vol.fromJSON({ '/home/user/.npmrc': '' })\n const result = await findAncestor('.npmrc', '/home/user/project')\n expect(result).toBe('/home/user/.npmrc')\n })\n\n test('should resolve ancestor at root directory', async() => {\n vol.fromJSON({ '/.npmrc': '' })\n const result = await findAncestor('.npmrc', '/home/user/project')\n expect(result).toBe('/.npmrc')\n })\n\n test('should resolve the first ancestor', async() => {\n vol.fromJSON({\n '/.npmrc': '',\n '/home/user/.npmrc': '',\n '/home/user/project/.npmrc': '',\n })\n const result = await findAncestor('.npmrc', '/home/user/project')\n expect(result).toBe('/home/user/project/.npmrc')\n })\n\n test('should return undefined if no ancestor was found', async() => {\n vol.fromJSON({})\n const result = await findAncestor('file', '/')\n expect(result).toBeUndefined()\n })\n}\n"],"names":[],"mappings":";;;AAmBA,eAAsB,aAAa,MAAc,OAAe,OAAoC;AAClG,SAAO,SAAS,MAAI;AACZ,UAAA,eAAe,QAAQ,MAAM,IAAI;AACnC,QAAA;AACF,aAAA,MAAM,OAAO,cAAc,UAAU,IAAI,GAClC;AAAA,IAAA,QAEH;AAAA,IAGN;AACA,QAAI,SAAS,IAAK;AAClB,WAAO,QAAQ,IAAI;AAAA,EACrB;AACF;"}
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- var node_process = require("node:process"), node_path = require("node:path"), promises = require("node:fs/promises"), awaitable = require("@unshared/functions/awaitable");
2
+ var awaitable = require("@unshared/functions/awaitable"), promises = require("node:fs/promises"), node_path = require("node:path"), node_process = require("node:process");
3
3
  function findAncestors(name, from = node_process.cwd()) {
4
4
  async function* createIterator() {
5
5
  for (; from !== ""; ) {
@@ -1 +1 @@
1
- {"version":3,"file":"findAncestors.cjs","sources":["../findAncestors.ts"],"sourcesContent":["import { cwd } from 'node:process'\nimport { dirname, resolve } from 'node:path'\nimport { access, constants } from 'node:fs/promises'\nimport { Awaitable, awaitable } from '@unshared/functions/awaitable'\n\n/**\n * Find all ancestors of a file from a given path. The search will start\n * from the given path and will continue until the root directory is reached.\n * If the file is not found, an empty array will be returned.\n *\n * @param name The file name to find.\n * @param from The path to start from.\n * @returns An awaitable iterator of the absolute paths of the files found.\n * @example\n * // Get all ancestors as an array.\n * const ancestors = await findAncestors('file', '/home/user/project')\n *\n * // Or, iterate over the ancestors one by one.\n * const ancestors = findAncestors('file', '/home/user/project')\n * for await (const ancestor of ancestors) console.log(ancestor)\n */\nexport function findAncestors(name: string, from: string = cwd()): Awaitable<AsyncIterable<string>, string[]> {\n async function * createIterator() {\n while (from !== '') {\n const absolutePath = resolve(from, name)\n try {\n await access(absolutePath, constants.F_OK)\n yield absolutePath\n }\n catch {\n\n /** Ignore error. */\n }\n if (from === '/') break\n from = dirname(from)\n }\n }\n\n // --- Instantiate the iterator and wrap it in an awaitable.\n const iterator = createIterator()\n return awaitable(iterator)\n}\n\n/** v8 ignore start */\nif (import.meta.vitest) {\n const { vol } = await import('memfs')\n\n test('should resolve ancestors from current directory', async() => {\n vi.mock('node:process', () => ({ cwd: () => '/home/user/project' }))\n vol.fromJSON({\n '/file': '',\n '/home/file': '',\n '/home/user/file': '',\n '/home/user/project/file': '',\n })\n const result = await findAncestors('file')\n expect(result).toStrictEqual([\n '/home/user/project/file',\n '/home/user/file',\n '/home/file',\n '/file',\n ])\n })\n\n test('should resolve ancestors at from given directory', async() => {\n vol.fromJSON({\n '/file': '',\n '/home/file': '',\n '/home/user/file': '',\n '/home/user/project/file': '',\n })\n const result = await findAncestors('file', '/home/user/project')\n expect(result).toStrictEqual([\n '/home/user/project/file',\n '/home/user/file',\n '/home/file',\n '/file',\n ])\n })\n\n test('should be iterable', async() => {\n vol.fromJSON({\n '/file': '',\n '/home/file': '',\n '/home/user/file': '',\n '/home/user/project/file': '',\n })\n const result = findAncestors('file', '/home/user/project')\n const items = []\n for await (const item of result) items.push(item)\n expect(items).toStrictEqual([\n '/home/user/project/file',\n '/home/user/file',\n '/home/file',\n '/file',\n ])\n })\n\n test('should return empty array if no ancestors were found', async() => {\n const result = await findAncestors('filename')\n expect(result).toStrictEqual([])\n })\n}\n"],"names":["cwd","resolve","access","constants","dirname","awaitable"],"mappings":";;AAqBO,SAAS,cAAc,MAAc,OAAeA,aAAAA,OAAmD;AAC5G,kBAAiB,iBAAiB;AAChC,WAAO,SAAS,MAAI;AACZ,YAAA,eAAeC,UAAAA,QAAQ,MAAM,IAAI;AACnC,UAAA;AACF,cAAMC,SAAAA,OAAO,cAAcC,SAAAA,UAAU,IAAI,GACzC,MAAM;AAAA,MAAA,QAEF;AAAA,MAGN;AACA,UAAI,SAAS,IAAK;AAClB,aAAOC,UAAAA,QAAQ,IAAI;AAAA,IACrB;AAAA,EACF;AAGA,QAAM,WAAW;AACjB,SAAOC,UAAAA,UAAU,QAAQ;AAC3B;;"}
1
+ {"version":3,"file":"findAncestors.cjs","sources":["../findAncestors.ts"],"sourcesContent":["import type { Awaitable } from '@unshared/functions/awaitable'\nimport { awaitable } from '@unshared/functions/awaitable'\nimport { access, constants } from 'node:fs/promises'\nimport { dirname, resolve } from 'node:path'\nimport { cwd } from 'node:process'\n\n/**\n * Find all ancestors of a file from a given path. The search will start\n * from the given path and will continue until the root directory is reached.\n * If the file is not found, an empty array will be returned.\n *\n * @param name The file name to find.\n * @param from The path to start from.\n * @returns An awaitable iterator of the absolute paths of the files found.\n * @example\n * // Get all ancestors as an array.\n * const ancestors = await findAncestors('file', '/home/user/project')\n *\n * // Or, iterate over the ancestors one by one.\n * const ancestors = findAncestors('file', '/home/user/project')\n * for await (const ancestor of ancestors) console.log(ancestor)\n */\nexport function findAncestors(name: string, from: string = cwd()): Awaitable<AsyncIterable<string>, string[]> {\n async function * createIterator() {\n while (from !== '') {\n const absolutePath = resolve(from, name)\n try {\n await access(absolutePath, constants.F_OK)\n yield absolutePath\n }\n catch {\n\n /** Ignore error. */\n }\n if (from === '/') break\n from = dirname(from)\n }\n }\n\n // --- Instantiate the iterator and wrap it in an awaitable.\n const iterator = createIterator()\n return awaitable(iterator)\n}\n\n/** v8 ignore start */\nif (import.meta.vitest) {\n const { vol } = await import('memfs')\n\n test('should resolve ancestors from current directory', async() => {\n vi.mock('node:process', () => ({ cwd: () => '/home/user/project' }))\n vol.fromJSON({\n '/file': '',\n '/home/file': '',\n '/home/user/file': '',\n '/home/user/project/file': '',\n })\n const result = await findAncestors('file')\n expect(result).toStrictEqual([\n '/home/user/project/file',\n '/home/user/file',\n '/home/file',\n '/file',\n ])\n })\n\n test('should resolve ancestors at from given directory', async() => {\n vol.fromJSON({\n '/file': '',\n '/home/file': '',\n '/home/user/file': '',\n '/home/user/project/file': '',\n })\n const result = await findAncestors('file', '/home/user/project')\n expect(result).toStrictEqual([\n '/home/user/project/file',\n '/home/user/file',\n '/home/file',\n '/file',\n ])\n })\n\n test('should be iterable', async() => {\n vol.fromJSON({\n '/file': '',\n '/home/file': '',\n '/home/user/file': '',\n '/home/user/project/file': '',\n })\n const result = findAncestors('file', '/home/user/project')\n const items = []\n for await (const item of result) items.push(item)\n expect(items).toStrictEqual([\n '/home/user/project/file',\n '/home/user/file',\n '/home/file',\n '/file',\n ])\n })\n\n test('should return empty array if no ancestors were found', async() => {\n const result = await findAncestors('filename')\n expect(result).toStrictEqual([])\n })\n}\n"],"names":["cwd","resolve","access","constants","dirname","awaitable"],"mappings":";;AAsBO,SAAS,cAAc,MAAc,OAAeA,aAAAA,OAAmD;AAC5G,kBAAiB,iBAAiB;AAChC,WAAO,SAAS,MAAI;AACZ,YAAA,eAAeC,UAAAA,QAAQ,MAAM,IAAI;AACnC,UAAA;AACF,cAAMC,SAAAA,OAAO,cAAcC,SAAAA,UAAU,IAAI,GACzC,MAAM;AAAA,MAAA,QAEF;AAAA,MAGN;AACA,UAAI,SAAS,IAAK;AAClB,aAAOC,UAAAA,QAAQ,IAAI;AAAA,IACrB;AAAA,EACF;AAGA,QAAM,WAAW;AACjB,SAAOC,UAAAA,UAAU,QAAQ;AAC3B;;"}
@@ -1,7 +1,7 @@
1
- import { cwd } from "node:process";
2
- import { resolve, dirname } from "node:path";
3
- import { access, constants } from "node:fs/promises";
4
1
  import { awaitable } from "@unshared/functions/awaitable";
2
+ import { access, constants } from "node:fs/promises";
3
+ import { resolve, dirname } from "node:path";
4
+ import { cwd } from "node:process";
5
5
  function findAncestors(name, from = cwd()) {
6
6
  async function* createIterator() {
7
7
  for (; from !== ""; ) {
@@ -1 +1 @@
1
- {"version":3,"file":"findAncestors.js","sources":["../findAncestors.ts"],"sourcesContent":["import { cwd } from 'node:process'\nimport { dirname, resolve } from 'node:path'\nimport { access, constants } from 'node:fs/promises'\nimport { Awaitable, awaitable } from '@unshared/functions/awaitable'\n\n/**\n * Find all ancestors of a file from a given path. The search will start\n * from the given path and will continue until the root directory is reached.\n * If the file is not found, an empty array will be returned.\n *\n * @param name The file name to find.\n * @param from The path to start from.\n * @returns An awaitable iterator of the absolute paths of the files found.\n * @example\n * // Get all ancestors as an array.\n * const ancestors = await findAncestors('file', '/home/user/project')\n *\n * // Or, iterate over the ancestors one by one.\n * const ancestors = findAncestors('file', '/home/user/project')\n * for await (const ancestor of ancestors) console.log(ancestor)\n */\nexport function findAncestors(name: string, from: string = cwd()): Awaitable<AsyncIterable<string>, string[]> {\n async function * createIterator() {\n while (from !== '') {\n const absolutePath = resolve(from, name)\n try {\n await access(absolutePath, constants.F_OK)\n yield absolutePath\n }\n catch {\n\n /** Ignore error. */\n }\n if (from === '/') break\n from = dirname(from)\n }\n }\n\n // --- Instantiate the iterator and wrap it in an awaitable.\n const iterator = createIterator()\n return awaitable(iterator)\n}\n\n/** v8 ignore start */\nif (import.meta.vitest) {\n const { vol } = await import('memfs')\n\n test('should resolve ancestors from current directory', async() => {\n vi.mock('node:process', () => ({ cwd: () => '/home/user/project' }))\n vol.fromJSON({\n '/file': '',\n '/home/file': '',\n '/home/user/file': '',\n '/home/user/project/file': '',\n })\n const result = await findAncestors('file')\n expect(result).toStrictEqual([\n '/home/user/project/file',\n '/home/user/file',\n '/home/file',\n '/file',\n ])\n })\n\n test('should resolve ancestors at from given directory', async() => {\n vol.fromJSON({\n '/file': '',\n '/home/file': '',\n '/home/user/file': '',\n '/home/user/project/file': '',\n })\n const result = await findAncestors('file', '/home/user/project')\n expect(result).toStrictEqual([\n '/home/user/project/file',\n '/home/user/file',\n '/home/file',\n '/file',\n ])\n })\n\n test('should be iterable', async() => {\n vol.fromJSON({\n '/file': '',\n '/home/file': '',\n '/home/user/file': '',\n '/home/user/project/file': '',\n })\n const result = findAncestors('file', '/home/user/project')\n const items = []\n for await (const item of result) items.push(item)\n expect(items).toStrictEqual([\n '/home/user/project/file',\n '/home/user/file',\n '/home/file',\n '/file',\n ])\n })\n\n test('should return empty array if no ancestors were found', async() => {\n const result = await findAncestors('filename')\n expect(result).toStrictEqual([])\n })\n}\n"],"names":[],"mappings":";;;;AAqBO,SAAS,cAAc,MAAc,OAAe,OAAmD;AAC5G,kBAAiB,iBAAiB;AAChC,WAAO,SAAS,MAAI;AACZ,YAAA,eAAe,QAAQ,MAAM,IAAI;AACnC,UAAA;AACF,cAAM,OAAO,cAAc,UAAU,IAAI,GACzC,MAAM;AAAA,MAAA,QAEF;AAAA,MAGN;AACA,UAAI,SAAS,IAAK;AAClB,aAAO,QAAQ,IAAI;AAAA,IACrB;AAAA,EACF;AAGA,QAAM,WAAW;AACjB,SAAO,UAAU,QAAQ;AAC3B;"}
1
+ {"version":3,"file":"findAncestors.js","sources":["../findAncestors.ts"],"sourcesContent":["import type { Awaitable } from '@unshared/functions/awaitable'\nimport { awaitable } from '@unshared/functions/awaitable'\nimport { access, constants } from 'node:fs/promises'\nimport { dirname, resolve } from 'node:path'\nimport { cwd } from 'node:process'\n\n/**\n * Find all ancestors of a file from a given path. The search will start\n * from the given path and will continue until the root directory is reached.\n * If the file is not found, an empty array will be returned.\n *\n * @param name The file name to find.\n * @param from The path to start from.\n * @returns An awaitable iterator of the absolute paths of the files found.\n * @example\n * // Get all ancestors as an array.\n * const ancestors = await findAncestors('file', '/home/user/project')\n *\n * // Or, iterate over the ancestors one by one.\n * const ancestors = findAncestors('file', '/home/user/project')\n * for await (const ancestor of ancestors) console.log(ancestor)\n */\nexport function findAncestors(name: string, from: string = cwd()): Awaitable<AsyncIterable<string>, string[]> {\n async function * createIterator() {\n while (from !== '') {\n const absolutePath = resolve(from, name)\n try {\n await access(absolutePath, constants.F_OK)\n yield absolutePath\n }\n catch {\n\n /** Ignore error. */\n }\n if (from === '/') break\n from = dirname(from)\n }\n }\n\n // --- Instantiate the iterator and wrap it in an awaitable.\n const iterator = createIterator()\n return awaitable(iterator)\n}\n\n/** v8 ignore start */\nif (import.meta.vitest) {\n const { vol } = await import('memfs')\n\n test('should resolve ancestors from current directory', async() => {\n vi.mock('node:process', () => ({ cwd: () => '/home/user/project' }))\n vol.fromJSON({\n '/file': '',\n '/home/file': '',\n '/home/user/file': '',\n '/home/user/project/file': '',\n })\n const result = await findAncestors('file')\n expect(result).toStrictEqual([\n '/home/user/project/file',\n '/home/user/file',\n '/home/file',\n '/file',\n ])\n })\n\n test('should resolve ancestors at from given directory', async() => {\n vol.fromJSON({\n '/file': '',\n '/home/file': '',\n '/home/user/file': '',\n '/home/user/project/file': '',\n })\n const result = await findAncestors('file', '/home/user/project')\n expect(result).toStrictEqual([\n '/home/user/project/file',\n '/home/user/file',\n '/home/file',\n '/file',\n ])\n })\n\n test('should be iterable', async() => {\n vol.fromJSON({\n '/file': '',\n '/home/file': '',\n '/home/user/file': '',\n '/home/user/project/file': '',\n })\n const result = findAncestors('file', '/home/user/project')\n const items = []\n for await (const item of result) items.push(item)\n expect(items).toStrictEqual([\n '/home/user/project/file',\n '/home/user/file',\n '/home/file',\n '/file',\n ])\n })\n\n test('should return empty array if no ancestors were found', async() => {\n const result = await findAncestors('filename')\n expect(result).toStrictEqual([])\n })\n}\n"],"names":[],"mappings":";;;;AAsBO,SAAS,cAAc,MAAc,OAAe,OAAmD;AAC5G,kBAAiB,iBAAiB;AAChC,WAAO,SAAS,MAAI;AACZ,YAAA,eAAe,QAAQ,MAAM,IAAI;AACnC,UAAA;AACF,cAAM,OAAO,cAAc,UAAU,IAAI,GACzC,MAAM;AAAA,MAAA,QAEF;AAAA,MAGN;AACA,UAAI,SAAS,IAAK;AAClB,aAAO,QAAQ,IAAI;AAAA,IACrB;AAAA,EACF;AAGA,QAAM,WAAW;AACjB,SAAO,UAAU,QAAQ;AAC3B;"}
package/dist/glob.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- var node_process = require("node:process"), node_path = require("node:path"), promises = require("node:fs/promises"), createPattern = require("@unshared/string/createPattern"), awaitable = require("@unshared/functions/awaitable");
2
+ var awaitable = require("@unshared/functions/awaitable"), createPattern = require("@unshared/string/createPattern"), promises = require("node:fs/promises"), node_path = require("node:path"), node_process = require("node:process");
3
3
  function glob(pattern, options = {}) {
4
4
  const {
5
5
  cwd = node_process.cwd(),
package/dist/glob.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"glob.cjs","sources":["../glob.ts"],"sourcesContent":["import { cwd as getCwd } from 'node:process'\nimport { join, relative } from 'node:path'\nimport { readdir, stat } from 'node:fs/promises'\nimport { Stats } from 'node:fs'\nimport { MaybeArray } from '@unshared/types'\nimport { createPattern } from '@unshared/string/createPattern'\nimport { Awaitable, awaitable } from '@unshared/functions/awaitable'\n\n/**\n * An entry in the glob result iterator or array.\n */\nexport type GlobEntry = Stats | string\n\n/**\n * The result of a glob operation. If `Stat` is `true` the result will be an\n * array of file stats. Otherwise the result will be an array of file paths.\n */\nexport type GlobResult<T extends boolean = boolean> = T extends true\n ? Awaitable<AsyncIterable<Stats>, Stats[]>\n : Awaitable<AsyncIterable<string>, string[]>\n\nexport interface GlobOptions<Stat extends boolean = boolean> {\n\n /**\n * The current working directory. Used to determine the base path for the glob\n * pattern.\n *\n * @default process.cwd()\n */\n cwd?: string\n\n /**\n * A list of patterns to exclude from the result.\n *\n * @default []\n */\n exclude?: MaybeArray<string>\n\n /**\n * Return the paths relative to the current working directory. Will be ignored\n * if `stats` is `true`.\n *\n * @default false\n */\n getRelative?: boolean\n\n /**\n * Return the file stats instead of the file path. Allowing you to filter-out\n * files based on their stats.\n *\n * @default false\n */\n getStats?: Stat\n\n /**\n * If `true` and the glob pattern will only match directories.\n *\n * @default false\n * @example glob('src/**', { onlyDirectories: true }) // ['src/foo', 'src/foo/bar']\n */\n onlyDirectories?: boolean\n\n /**\n * Only return entries that matches the path of a file.\n *\n * @default false\n * @example glob('src/**', { onlyFiles: true }) // ['src/foo.ts', 'src/foo/bar.ts']\n */\n onlyFiles?: boolean\n}\n\n/**\n * Find files matching a glob pattern.\n *\n * @param pattern The glob pattern.\n * @param options The glob options.\n * @returns An awaitable asyncronous iterator of file paths.\n * @example\n * const files = glob('src/*.ts')\n * for await (const file of files) { ... }\n */\nexport function glob(pattern: MaybeArray<string>, options?: GlobOptions<false>): GlobResult<false>\nexport function glob(pattern: MaybeArray<string>, options?: GlobOptions<true>): GlobResult<true>\nexport function glob<T extends boolean>(pattern: MaybeArray<string>, options?: GlobOptions<T>): GlobResult<T>\nexport function glob(pattern: MaybeArray<string>, options: GlobOptions = {}): GlobResult {\n const {\n cwd = getCwd(),\n exclude = [],\n getRelative = false,\n getStats = false,\n onlyDirectories = false,\n onlyFiles = false,\n } = options\n\n // --- Convert the pattern to an array of RegExp.\n const patternArray = Array.isArray(pattern) ? pattern : [pattern]\n const patterns = patternArray.map(createPattern)\n const exludeArray = Array.isArray(exclude) ? exclude : [exclude]\n const excludePatterns = exludeArray.map(createPattern)\n\n // --- Create an iterator that will yield the matching paths.\n const searchPool: string[] = [cwd]\n async function * createIterator() {\n while (searchPool.length > 0) {\n const directory = searchPool.pop()!\n const entities = await readdir(directory, { withFileTypes: true }).catch(() => [])\n\n for (const entity of entities) {\n const pathAbsolute = join(directory, entity.name)\n const pathRelative = relative(cwd, pathAbsolute)\n const isFile = entity.isFile()\n const isDirectory = entity.isDirectory()\n\n // --- Add the directory to the list of directories to check.\n if (isDirectory) searchPool.push(pathAbsolute)\n\n // --- Filter-out the non-matching entries.\n if (onlyFiles && !isFile) continue\n if (onlyDirectories && !isDirectory) continue\n\n // --- Check if the path matches the pattern(s).\n const isMatch = patterns.some(pattern => pattern.test(pathRelative))\n if (!isMatch) continue\n\n // --- Check if the path matches the exclude pattern(s).\n const isExcluded = excludePatterns.some(pattern => pattern.test(pathRelative))\n if (isExcluded) continue\n\n // --- Return the result.\n let result: GlobEntry = pathAbsolute\n if (getStats) result = await stat(pathAbsolute)\n if (getRelative) result = `./${pathRelative}`\n yield result\n }\n }\n }\n\n // --- Instantiate the iterator.\n const iterator = createIterator()\n\n // --- Return the iterator or the result as an array.\n return awaitable(iterator) as GlobResult\n}\n\n/* v8 ignore next */\nif (import.meta.vitest) {\n const { vol } = await import('memfs')\n\n beforeEach(() => {\n vol.fromJSON({\n '/project/bar.ts': '',\n '/project/baz.ts': '',\n '/project/dist/bar.js': '',\n '/project/dist/baz.js': '',\n '/project/dist/docs/CHANGELOG.md': '',\n '/project/dist/docs/README.md': '',\n '/project/dist/foo.js': '',\n '/project/foo.ts': '',\n '/project/README.md': '',\n })\n })\n\n test('should yield the paths matching a glob pattern', async() => {\n const files = glob('*.ts', { cwd: '/project' })\n const result = []\n for await (const file of files) result.push(file)\n expect(result).toStrictEqual([\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n ])\n })\n\n test('should find the absolute path matching a glob pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project' })\n expect(files).toStrictEqual([\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n ])\n })\n\n test('should find the relative path matching a glob pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project', getRelative: true })\n expect(files).toStrictEqual([\n './bar.ts',\n './baz.ts',\n './foo.ts',\n ])\n })\n\n test('should find the stats matching a glob pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project', getStats: true })\n const expected = [\n vol.statSync('/project/foo.ts'),\n vol.statSync('/project/bar.ts'),\n vol.statSync('/project/baz.ts'),\n ]\n expect(files.map(x => x.uid)).toStrictEqual(expected.map(x => x.uid))\n })\n\n test('should find the paths matching an exclude pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project', exclude: 'baz.ts' })\n const expected = [\n '/project/bar.ts',\n '/project/foo.ts',\n ]\n expect(files).toStrictEqual(expected)\n })\n\n test('should find nested and non-nested files', async() => {\n const files = await glob('**/*', { cwd: '/project', onlyFiles: true })\n expect(files).toStrictEqual([\n '/project/README.md',\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n '/project/dist/bar.js',\n '/project/dist/baz.js',\n '/project/dist/foo.js',\n '/project/dist/docs/CHANGELOG.md',\n '/project/dist/docs/README.md',\n ])\n })\n\n test('should find nested and non-nested directories', async() => {\n const files = await glob('**/*', { cwd: '/project', onlyDirectories: true })\n expect(files).toStrictEqual([\n '/project/dist',\n '/project/dist/docs',\n ])\n })\n\n test('should find files but exclude the dist directory', async() => {\n const files = await glob('*', { cwd: '/project', exclude: 'dist/**' })\n expect(files).toStrictEqual([\n '/project/README.md',\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n ])\n })\n\n test('should infer the return type as a collection of `Stats`', () => {\n const files = glob('*.ts', { cwd: '/project', getStats: true })\n expectTypeOf(files).toEqualTypeOf<Awaitable<AsyncIterable<Stats>, Stats[]>>()\n })\n\n test('should infer the return type as a collection of `string`', () => {\n const files = glob('*.ts', { cwd: '/project', getStats: false })\n expectTypeOf(files).toEqualTypeOf<Awaitable<AsyncIterable<string>, string[]>>()\n })\n\n test('should infer the return type as a collection of `Stats` or `string`', () => {\n const files = glob('*.ts', { cwd: '/project', getStats: true as boolean })\n expectTypeOf(files).toEqualTypeOf<Awaitable<AsyncIterable<Stats>, Stats[]> | Awaitable<AsyncIterable<string>, string[]>>()\n })\n}\n"],"names":["getCwd","createPattern","readdir","join","relative","pattern","stat","awaitable"],"mappings":";;AAoFO,SAAS,KAAK,SAA6B,UAAuB,IAAgB;AACjF,QAAA;AAAA,IACJ,MAAMA,aAAAA,IAAO;AAAA,IACb,UAAU,CAAC;AAAA,IACX,cAAc;AAAA,IACd,WAAW;AAAA,IACX,kBAAkB;AAAA,IAClB,YAAY;AAAA,EACV,IAAA,SAIE,YADe,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO,GAClC,IAAIC,cAAa,aAAA,GAEzC,mBADc,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO,GAC3B,IAAIA,cAAAA,aAAa,GAG/C,aAAuB,CAAC,GAAG;AACjC,kBAAiB,iBAAiB;AACzB,WAAA,WAAW,SAAS,KAAG;AAC5B,YAAM,YAAY,WAAW,IACvB,GAAA,WAAW,MAAMC,SAAAA,QAAQ,WAAW,EAAE,eAAe,GAAM,CAAA,EAAE,MAAM,MAAM,CAAE,CAAA;AAEjF,iBAAW,UAAU,UAAU;AAC7B,cAAM,eAAeC,UAAAA,KAAK,WAAW,OAAO,IAAI,GAC1C,eAAeC,mBAAS,KAAK,YAAY,GACzC,SAAS,OAAO,OAChB,GAAA,cAAc,OAAO;AAe3B,YAZI,eAAa,WAAW,KAAK,YAAY,GAGzC,aAAa,CAAC,UACd,mBAAmB,CAAC,eAIpB,CADY,SAAS,KAAK,CAAAC,aAAWA,SAAQ,KAAK,YAAY,CAAC,KAIhD,gBAAgB,KAAK,CAAAA,aAAWA,SAAQ,KAAK,YAAY,CAAC,EAC7D;AAGhB,YAAI,SAAoB;AACpB,qBAAU,SAAS,MAAMC,cAAK,YAAY,IAC1C,gBAAa,SAAS,KAAK,YAAY,KAC3C,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,QAAM,WAAW;AAGjB,SAAOC,UAAAA,UAAU,QAAQ;AAC3B;;"}
1
+ {"version":3,"file":"glob.cjs","sources":["../glob.ts"],"sourcesContent":["import type { Awaitable } from '@unshared/functions/awaitable'\nimport type { MaybeArray } from '@unshared/types'\nimport type { Stats } from 'node:fs'\nimport { awaitable } from '@unshared/functions/awaitable'\nimport { createPattern } from '@unshared/string/createPattern'\nimport { readdir, stat } from 'node:fs/promises'\nimport { join, relative } from 'node:path'\nimport { cwd as getCwd } from 'node:process'\n\n/**\n * An entry in the glob result iterator or array.\n */\nexport type GlobEntry = Stats | string\n\n/**\n * The result of a glob operation. If `Stat` is `true` the result will be an\n * array of file stats. Otherwise the result will be an array of file paths.\n */\nexport type GlobResult<T extends boolean = boolean> = T extends true\n ? Awaitable<AsyncIterable<Stats>, Stats[]>\n : Awaitable<AsyncIterable<string>, string[]>\n\nexport interface GlobOptions<Stat extends boolean = boolean> {\n\n /**\n * The current working directory. Used to determine the base path for the glob\n * pattern.\n *\n * @default process.cwd()\n */\n cwd?: string\n\n /**\n * A list of patterns to exclude from the result.\n *\n * @default []\n */\n exclude?: MaybeArray<string>\n\n /**\n * Return the paths relative to the current working directory. Will be ignored\n * if `stats` is `true`.\n *\n * @default false\n */\n getRelative?: boolean\n\n /**\n * Return the file stats instead of the file path. Allowing you to filter-out\n * files based on their stats.\n *\n * @default false\n */\n getStats?: Stat\n\n /**\n * If `true` and the glob pattern will only match directories.\n *\n * @default false\n * @example glob('src/**', { onlyDirectories: true }) // ['src/foo', 'src/foo/bar']\n */\n onlyDirectories?: boolean\n\n /**\n * Only return entries that matches the path of a file.\n *\n * @default false\n * @example glob('src/**', { onlyFiles: true }) // ['src/foo.ts', 'src/foo/bar.ts']\n */\n onlyFiles?: boolean\n}\n\n/**\n * Find files matching a glob pattern.\n *\n * @param pattern The glob pattern.\n * @param options The glob options.\n * @returns An awaitable asyncronous iterator of file paths.\n * @example\n * const files = glob('src/*.ts')\n * for await (const file of files) { ... }\n */\nexport function glob(pattern: MaybeArray<string>, options?: GlobOptions<false>): GlobResult<false>\nexport function glob(pattern: MaybeArray<string>, options?: GlobOptions<true>): GlobResult<true>\nexport function glob<T extends boolean>(pattern: MaybeArray<string>, options?: GlobOptions<T>): GlobResult<T>\nexport function glob(pattern: MaybeArray<string>, options: GlobOptions = {}): GlobResult {\n const {\n cwd = getCwd(),\n exclude = [],\n getRelative = false,\n getStats = false,\n onlyDirectories = false,\n onlyFiles = false,\n } = options\n\n // --- Convert the pattern to an array of RegExp.\n const patternArray = Array.isArray(pattern) ? pattern : [pattern]\n const patterns = patternArray.map(createPattern)\n const exludeArray = Array.isArray(exclude) ? exclude : [exclude]\n const excludePatterns = exludeArray.map(createPattern)\n\n // --- Create an iterator that will yield the matching paths.\n const searchPool: string[] = [cwd]\n async function * createIterator() {\n while (searchPool.length > 0) {\n const directory = searchPool.pop()!\n const entities = await readdir(directory, { withFileTypes: true }).catch(() => [])\n\n for (const entity of entities) {\n const pathAbsolute = join(directory, entity.name)\n const pathRelative = relative(cwd, pathAbsolute)\n const isFile = entity.isFile()\n const isDirectory = entity.isDirectory()\n\n // --- Add the directory to the list of directories to check.\n if (isDirectory) searchPool.push(pathAbsolute)\n\n // --- Filter-out the non-matching entries.\n if (onlyFiles && !isFile) continue\n if (onlyDirectories && !isDirectory) continue\n\n // --- Check if the path matches the pattern(s).\n const isMatch = patterns.some(pattern => pattern.test(pathRelative))\n if (!isMatch) continue\n\n // --- Check if the path matches the exclude pattern(s).\n const isExcluded = excludePatterns.some(pattern => pattern.test(pathRelative))\n if (isExcluded) continue\n\n // --- Return the result.\n let result: GlobEntry = pathAbsolute\n if (getStats) result = await stat(pathAbsolute)\n if (getRelative) result = `./${pathRelative}`\n yield result\n }\n }\n }\n\n // --- Instantiate the iterator.\n const iterator = createIterator()\n\n // --- Return the iterator or the result as an array.\n return awaitable(iterator) as GlobResult\n}\n\n/* v8 ignore next */\nif (import.meta.vitest) {\n const { vol } = await import('memfs')\n\n beforeEach(() => {\n vol.fromJSON({\n '/project/bar.ts': '',\n '/project/baz.ts': '',\n '/project/dist/bar.js': '',\n '/project/dist/baz.js': '',\n '/project/dist/docs/CHANGELOG.md': '',\n '/project/dist/docs/README.md': '',\n '/project/dist/foo.js': '',\n '/project/foo.ts': '',\n '/project/README.md': '',\n })\n })\n\n test('should yield the paths matching a glob pattern', async() => {\n const files = glob('*.ts', { cwd: '/project' })\n const result = []\n for await (const file of files) result.push(file)\n expect(result).toStrictEqual([\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n ])\n })\n\n test('should find the absolute path matching a glob pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project' })\n expect(files).toStrictEqual([\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n ])\n })\n\n test('should find the relative path matching a glob pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project', getRelative: true })\n expect(files).toStrictEqual([\n './bar.ts',\n './baz.ts',\n './foo.ts',\n ])\n })\n\n test('should find the stats matching a glob pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project', getStats: true })\n const expected = [\n vol.statSync('/project/foo.ts'),\n vol.statSync('/project/bar.ts'),\n vol.statSync('/project/baz.ts'),\n ]\n expect(files.map(x => x.uid)).toStrictEqual(expected.map(x => x.uid))\n })\n\n test('should find the paths matching an exclude pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project', exclude: 'baz.ts' })\n const expected = [\n '/project/bar.ts',\n '/project/foo.ts',\n ]\n expect(files).toStrictEqual(expected)\n })\n\n test('should find nested and non-nested files', async() => {\n const files = await glob('**/*', { cwd: '/project', onlyFiles: true })\n expect(files).toStrictEqual([\n '/project/README.md',\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n '/project/dist/bar.js',\n '/project/dist/baz.js',\n '/project/dist/foo.js',\n '/project/dist/docs/CHANGELOG.md',\n '/project/dist/docs/README.md',\n ])\n })\n\n test('should find nested and non-nested directories', async() => {\n const files = await glob('**/*', { cwd: '/project', onlyDirectories: true })\n expect(files).toStrictEqual([\n '/project/dist',\n '/project/dist/docs',\n ])\n })\n\n test('should find files but exclude the dist directory', async() => {\n const files = await glob('*', { cwd: '/project', exclude: 'dist/**' })\n expect(files).toStrictEqual([\n '/project/README.md',\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n ])\n })\n\n test('should infer the return type as a collection of `Stats`', () => {\n const files = glob('*.ts', { cwd: '/project', getStats: true })\n expectTypeOf(files).toEqualTypeOf<Awaitable<AsyncIterable<Stats>, Stats[]>>()\n })\n\n test('should infer the return type as a collection of `string`', () => {\n const files = glob('*.ts', { cwd: '/project', getStats: false })\n expectTypeOf(files).toEqualTypeOf<Awaitable<AsyncIterable<string>, string[]>>()\n })\n\n test('should infer the return type as a collection of `Stats` or `string`', () => {\n const files = glob('*.ts', { cwd: '/project', getStats: true as boolean })\n expectTypeOf(files).toEqualTypeOf<Awaitable<AsyncIterable<Stats>, Stats[]> | Awaitable<AsyncIterable<string>, string[]>>()\n })\n}\n"],"names":["getCwd","createPattern","readdir","join","relative","pattern","stat","awaitable"],"mappings":";;AAqFO,SAAS,KAAK,SAA6B,UAAuB,IAAgB;AACjF,QAAA;AAAA,IACJ,MAAMA,aAAAA,IAAO;AAAA,IACb,UAAU,CAAC;AAAA,IACX,cAAc;AAAA,IACd,WAAW;AAAA,IACX,kBAAkB;AAAA,IAClB,YAAY;AAAA,EACV,IAAA,SAIE,YADe,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO,GAClC,IAAIC,cAAa,aAAA,GAEzC,mBADc,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO,GAC3B,IAAIA,cAAAA,aAAa,GAG/C,aAAuB,CAAC,GAAG;AACjC,kBAAiB,iBAAiB;AACzB,WAAA,WAAW,SAAS,KAAG;AAC5B,YAAM,YAAY,WAAW,IACvB,GAAA,WAAW,MAAMC,SAAAA,QAAQ,WAAW,EAAE,eAAe,GAAM,CAAA,EAAE,MAAM,MAAM,CAAE,CAAA;AAEjF,iBAAW,UAAU,UAAU;AAC7B,cAAM,eAAeC,UAAAA,KAAK,WAAW,OAAO,IAAI,GAC1C,eAAeC,mBAAS,KAAK,YAAY,GACzC,SAAS,OAAO,OAChB,GAAA,cAAc,OAAO;AAe3B,YAZI,eAAa,WAAW,KAAK,YAAY,GAGzC,aAAa,CAAC,UACd,mBAAmB,CAAC,eAIpB,CADY,SAAS,KAAK,CAAAC,aAAWA,SAAQ,KAAK,YAAY,CAAC,KAIhD,gBAAgB,KAAK,CAAAA,aAAWA,SAAQ,KAAK,YAAY,CAAC,EAC7D;AAGhB,YAAI,SAAoB;AACpB,qBAAU,SAAS,MAAMC,cAAK,YAAY,IAC1C,gBAAa,SAAS,KAAK,YAAY,KAC3C,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,QAAM,WAAW;AAGjB,SAAOC,UAAAA,UAAU,QAAQ;AAC3B;;"}
package/dist/glob.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { Stats } from 'node:fs';
2
- import { MaybeArray } from '@unshared/types';
3
1
  import { Awaitable } from '@unshared/functions/awaitable';
2
+ import { MaybeArray } from '@unshared/types';
3
+ import { Stats } from 'node:fs';
4
4
 
5
5
  /**
6
6
  * An entry in the glob result iterator or array.
package/dist/glob.js CHANGED
@@ -1,8 +1,8 @@
1
- import { cwd } from "node:process";
2
- import { join, relative } from "node:path";
3
- import { readdir, stat } from "node:fs/promises";
4
- import { createPattern } from "@unshared/string/createPattern";
5
1
  import { awaitable } from "@unshared/functions/awaitable";
2
+ import { createPattern } from "@unshared/string/createPattern";
3
+ import { readdir, stat } from "node:fs/promises";
4
+ import { join, relative } from "node:path";
5
+ import { cwd } from "node:process";
6
6
  function glob(pattern, options = {}) {
7
7
  const {
8
8
  cwd: cwd$1 = cwd(),
package/dist/glob.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"glob.js","sources":["../glob.ts"],"sourcesContent":["import { cwd as getCwd } from 'node:process'\nimport { join, relative } from 'node:path'\nimport { readdir, stat } from 'node:fs/promises'\nimport { Stats } from 'node:fs'\nimport { MaybeArray } from '@unshared/types'\nimport { createPattern } from '@unshared/string/createPattern'\nimport { Awaitable, awaitable } from '@unshared/functions/awaitable'\n\n/**\n * An entry in the glob result iterator or array.\n */\nexport type GlobEntry = Stats | string\n\n/**\n * The result of a glob operation. If `Stat` is `true` the result will be an\n * array of file stats. Otherwise the result will be an array of file paths.\n */\nexport type GlobResult<T extends boolean = boolean> = T extends true\n ? Awaitable<AsyncIterable<Stats>, Stats[]>\n : Awaitable<AsyncIterable<string>, string[]>\n\nexport interface GlobOptions<Stat extends boolean = boolean> {\n\n /**\n * The current working directory. Used to determine the base path for the glob\n * pattern.\n *\n * @default process.cwd()\n */\n cwd?: string\n\n /**\n * A list of patterns to exclude from the result.\n *\n * @default []\n */\n exclude?: MaybeArray<string>\n\n /**\n * Return the paths relative to the current working directory. Will be ignored\n * if `stats` is `true`.\n *\n * @default false\n */\n getRelative?: boolean\n\n /**\n * Return the file stats instead of the file path. Allowing you to filter-out\n * files based on their stats.\n *\n * @default false\n */\n getStats?: Stat\n\n /**\n * If `true` and the glob pattern will only match directories.\n *\n * @default false\n * @example glob('src/**', { onlyDirectories: true }) // ['src/foo', 'src/foo/bar']\n */\n onlyDirectories?: boolean\n\n /**\n * Only return entries that matches the path of a file.\n *\n * @default false\n * @example glob('src/**', { onlyFiles: true }) // ['src/foo.ts', 'src/foo/bar.ts']\n */\n onlyFiles?: boolean\n}\n\n/**\n * Find files matching a glob pattern.\n *\n * @param pattern The glob pattern.\n * @param options The glob options.\n * @returns An awaitable asyncronous iterator of file paths.\n * @example\n * const files = glob('src/*.ts')\n * for await (const file of files) { ... }\n */\nexport function glob(pattern: MaybeArray<string>, options?: GlobOptions<false>): GlobResult<false>\nexport function glob(pattern: MaybeArray<string>, options?: GlobOptions<true>): GlobResult<true>\nexport function glob<T extends boolean>(pattern: MaybeArray<string>, options?: GlobOptions<T>): GlobResult<T>\nexport function glob(pattern: MaybeArray<string>, options: GlobOptions = {}): GlobResult {\n const {\n cwd = getCwd(),\n exclude = [],\n getRelative = false,\n getStats = false,\n onlyDirectories = false,\n onlyFiles = false,\n } = options\n\n // --- Convert the pattern to an array of RegExp.\n const patternArray = Array.isArray(pattern) ? pattern : [pattern]\n const patterns = patternArray.map(createPattern)\n const exludeArray = Array.isArray(exclude) ? exclude : [exclude]\n const excludePatterns = exludeArray.map(createPattern)\n\n // --- Create an iterator that will yield the matching paths.\n const searchPool: string[] = [cwd]\n async function * createIterator() {\n while (searchPool.length > 0) {\n const directory = searchPool.pop()!\n const entities = await readdir(directory, { withFileTypes: true }).catch(() => [])\n\n for (const entity of entities) {\n const pathAbsolute = join(directory, entity.name)\n const pathRelative = relative(cwd, pathAbsolute)\n const isFile = entity.isFile()\n const isDirectory = entity.isDirectory()\n\n // --- Add the directory to the list of directories to check.\n if (isDirectory) searchPool.push(pathAbsolute)\n\n // --- Filter-out the non-matching entries.\n if (onlyFiles && !isFile) continue\n if (onlyDirectories && !isDirectory) continue\n\n // --- Check if the path matches the pattern(s).\n const isMatch = patterns.some(pattern => pattern.test(pathRelative))\n if (!isMatch) continue\n\n // --- Check if the path matches the exclude pattern(s).\n const isExcluded = excludePatterns.some(pattern => pattern.test(pathRelative))\n if (isExcluded) continue\n\n // --- Return the result.\n let result: GlobEntry = pathAbsolute\n if (getStats) result = await stat(pathAbsolute)\n if (getRelative) result = `./${pathRelative}`\n yield result\n }\n }\n }\n\n // --- Instantiate the iterator.\n const iterator = createIterator()\n\n // --- Return the iterator or the result as an array.\n return awaitable(iterator) as GlobResult\n}\n\n/* v8 ignore next */\nif (import.meta.vitest) {\n const { vol } = await import('memfs')\n\n beforeEach(() => {\n vol.fromJSON({\n '/project/bar.ts': '',\n '/project/baz.ts': '',\n '/project/dist/bar.js': '',\n '/project/dist/baz.js': '',\n '/project/dist/docs/CHANGELOG.md': '',\n '/project/dist/docs/README.md': '',\n '/project/dist/foo.js': '',\n '/project/foo.ts': '',\n '/project/README.md': '',\n })\n })\n\n test('should yield the paths matching a glob pattern', async() => {\n const files = glob('*.ts', { cwd: '/project' })\n const result = []\n for await (const file of files) result.push(file)\n expect(result).toStrictEqual([\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n ])\n })\n\n test('should find the absolute path matching a glob pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project' })\n expect(files).toStrictEqual([\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n ])\n })\n\n test('should find the relative path matching a glob pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project', getRelative: true })\n expect(files).toStrictEqual([\n './bar.ts',\n './baz.ts',\n './foo.ts',\n ])\n })\n\n test('should find the stats matching a glob pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project', getStats: true })\n const expected = [\n vol.statSync('/project/foo.ts'),\n vol.statSync('/project/bar.ts'),\n vol.statSync('/project/baz.ts'),\n ]\n expect(files.map(x => x.uid)).toStrictEqual(expected.map(x => x.uid))\n })\n\n test('should find the paths matching an exclude pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project', exclude: 'baz.ts' })\n const expected = [\n '/project/bar.ts',\n '/project/foo.ts',\n ]\n expect(files).toStrictEqual(expected)\n })\n\n test('should find nested and non-nested files', async() => {\n const files = await glob('**/*', { cwd: '/project', onlyFiles: true })\n expect(files).toStrictEqual([\n '/project/README.md',\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n '/project/dist/bar.js',\n '/project/dist/baz.js',\n '/project/dist/foo.js',\n '/project/dist/docs/CHANGELOG.md',\n '/project/dist/docs/README.md',\n ])\n })\n\n test('should find nested and non-nested directories', async() => {\n const files = await glob('**/*', { cwd: '/project', onlyDirectories: true })\n expect(files).toStrictEqual([\n '/project/dist',\n '/project/dist/docs',\n ])\n })\n\n test('should find files but exclude the dist directory', async() => {\n const files = await glob('*', { cwd: '/project', exclude: 'dist/**' })\n expect(files).toStrictEqual([\n '/project/README.md',\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n ])\n })\n\n test('should infer the return type as a collection of `Stats`', () => {\n const files = glob('*.ts', { cwd: '/project', getStats: true })\n expectTypeOf(files).toEqualTypeOf<Awaitable<AsyncIterable<Stats>, Stats[]>>()\n })\n\n test('should infer the return type as a collection of `string`', () => {\n const files = glob('*.ts', { cwd: '/project', getStats: false })\n expectTypeOf(files).toEqualTypeOf<Awaitable<AsyncIterable<string>, string[]>>()\n })\n\n test('should infer the return type as a collection of `Stats` or `string`', () => {\n const files = glob('*.ts', { cwd: '/project', getStats: true as boolean })\n expectTypeOf(files).toEqualTypeOf<Awaitable<AsyncIterable<Stats>, Stats[]> | Awaitable<AsyncIterable<string>, string[]>>()\n })\n}\n"],"names":["cwd","getCwd","pattern"],"mappings":";;;;;AAoFO,SAAS,KAAK,SAA6B,UAAuB,IAAgB;AACjF,QAAA;AAAA,IACJA,KAAAA,QAAMC,IAAO;AAAA,IACb,UAAU,CAAC;AAAA,IACX,cAAc;AAAA,IACd,WAAW;AAAA,IACX,kBAAkB;AAAA,IAClB,YAAY;AAAA,EACV,IAAA,SAIE,YADe,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO,GAClC,IAAI,aAAa,GAEzC,mBADc,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO,GAC3B,IAAI,aAAa,GAG/C,aAAuB,CAACD,KAAG;AACjC,kBAAiB,iBAAiB;AACzB,WAAA,WAAW,SAAS,KAAG;AAC5B,YAAM,YAAY,WAAW,IACvB,GAAA,WAAW,MAAM,QAAQ,WAAW,EAAE,eAAe,GAAM,CAAA,EAAE,MAAM,MAAM,CAAE,CAAA;AAEjF,iBAAW,UAAU,UAAU;AAC7B,cAAM,eAAe,KAAK,WAAW,OAAO,IAAI,GAC1C,eAAe,SAASA,OAAK,YAAY,GACzC,SAAS,OAAO,OAChB,GAAA,cAAc,OAAO;AAe3B,YAZI,eAAa,WAAW,KAAK,YAAY,GAGzC,aAAa,CAAC,UACd,mBAAmB,CAAC,eAIpB,CADY,SAAS,KAAK,CAAAE,aAAWA,SAAQ,KAAK,YAAY,CAAC,KAIhD,gBAAgB,KAAK,CAAAA,aAAWA,SAAQ,KAAK,YAAY,CAAC,EAC7D;AAGhB,YAAI,SAAoB;AACpB,qBAAU,SAAS,MAAM,KAAK,YAAY,IAC1C,gBAAa,SAAS,KAAK,YAAY,KAC3C,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,QAAM,WAAW;AAGjB,SAAO,UAAU,QAAQ;AAC3B;"}
1
+ {"version":3,"file":"glob.js","sources":["../glob.ts"],"sourcesContent":["import type { Awaitable } from '@unshared/functions/awaitable'\nimport type { MaybeArray } from '@unshared/types'\nimport type { Stats } from 'node:fs'\nimport { awaitable } from '@unshared/functions/awaitable'\nimport { createPattern } from '@unshared/string/createPattern'\nimport { readdir, stat } from 'node:fs/promises'\nimport { join, relative } from 'node:path'\nimport { cwd as getCwd } from 'node:process'\n\n/**\n * An entry in the glob result iterator or array.\n */\nexport type GlobEntry = Stats | string\n\n/**\n * The result of a glob operation. If `Stat` is `true` the result will be an\n * array of file stats. Otherwise the result will be an array of file paths.\n */\nexport type GlobResult<T extends boolean = boolean> = T extends true\n ? Awaitable<AsyncIterable<Stats>, Stats[]>\n : Awaitable<AsyncIterable<string>, string[]>\n\nexport interface GlobOptions<Stat extends boolean = boolean> {\n\n /**\n * The current working directory. Used to determine the base path for the glob\n * pattern.\n *\n * @default process.cwd()\n */\n cwd?: string\n\n /**\n * A list of patterns to exclude from the result.\n *\n * @default []\n */\n exclude?: MaybeArray<string>\n\n /**\n * Return the paths relative to the current working directory. Will be ignored\n * if `stats` is `true`.\n *\n * @default false\n */\n getRelative?: boolean\n\n /**\n * Return the file stats instead of the file path. Allowing you to filter-out\n * files based on their stats.\n *\n * @default false\n */\n getStats?: Stat\n\n /**\n * If `true` and the glob pattern will only match directories.\n *\n * @default false\n * @example glob('src/**', { onlyDirectories: true }) // ['src/foo', 'src/foo/bar']\n */\n onlyDirectories?: boolean\n\n /**\n * Only return entries that matches the path of a file.\n *\n * @default false\n * @example glob('src/**', { onlyFiles: true }) // ['src/foo.ts', 'src/foo/bar.ts']\n */\n onlyFiles?: boolean\n}\n\n/**\n * Find files matching a glob pattern.\n *\n * @param pattern The glob pattern.\n * @param options The glob options.\n * @returns An awaitable asyncronous iterator of file paths.\n * @example\n * const files = glob('src/*.ts')\n * for await (const file of files) { ... }\n */\nexport function glob(pattern: MaybeArray<string>, options?: GlobOptions<false>): GlobResult<false>\nexport function glob(pattern: MaybeArray<string>, options?: GlobOptions<true>): GlobResult<true>\nexport function glob<T extends boolean>(pattern: MaybeArray<string>, options?: GlobOptions<T>): GlobResult<T>\nexport function glob(pattern: MaybeArray<string>, options: GlobOptions = {}): GlobResult {\n const {\n cwd = getCwd(),\n exclude = [],\n getRelative = false,\n getStats = false,\n onlyDirectories = false,\n onlyFiles = false,\n } = options\n\n // --- Convert the pattern to an array of RegExp.\n const patternArray = Array.isArray(pattern) ? pattern : [pattern]\n const patterns = patternArray.map(createPattern)\n const exludeArray = Array.isArray(exclude) ? exclude : [exclude]\n const excludePatterns = exludeArray.map(createPattern)\n\n // --- Create an iterator that will yield the matching paths.\n const searchPool: string[] = [cwd]\n async function * createIterator() {\n while (searchPool.length > 0) {\n const directory = searchPool.pop()!\n const entities = await readdir(directory, { withFileTypes: true }).catch(() => [])\n\n for (const entity of entities) {\n const pathAbsolute = join(directory, entity.name)\n const pathRelative = relative(cwd, pathAbsolute)\n const isFile = entity.isFile()\n const isDirectory = entity.isDirectory()\n\n // --- Add the directory to the list of directories to check.\n if (isDirectory) searchPool.push(pathAbsolute)\n\n // --- Filter-out the non-matching entries.\n if (onlyFiles && !isFile) continue\n if (onlyDirectories && !isDirectory) continue\n\n // --- Check if the path matches the pattern(s).\n const isMatch = patterns.some(pattern => pattern.test(pathRelative))\n if (!isMatch) continue\n\n // --- Check if the path matches the exclude pattern(s).\n const isExcluded = excludePatterns.some(pattern => pattern.test(pathRelative))\n if (isExcluded) continue\n\n // --- Return the result.\n let result: GlobEntry = pathAbsolute\n if (getStats) result = await stat(pathAbsolute)\n if (getRelative) result = `./${pathRelative}`\n yield result\n }\n }\n }\n\n // --- Instantiate the iterator.\n const iterator = createIterator()\n\n // --- Return the iterator or the result as an array.\n return awaitable(iterator) as GlobResult\n}\n\n/* v8 ignore next */\nif (import.meta.vitest) {\n const { vol } = await import('memfs')\n\n beforeEach(() => {\n vol.fromJSON({\n '/project/bar.ts': '',\n '/project/baz.ts': '',\n '/project/dist/bar.js': '',\n '/project/dist/baz.js': '',\n '/project/dist/docs/CHANGELOG.md': '',\n '/project/dist/docs/README.md': '',\n '/project/dist/foo.js': '',\n '/project/foo.ts': '',\n '/project/README.md': '',\n })\n })\n\n test('should yield the paths matching a glob pattern', async() => {\n const files = glob('*.ts', { cwd: '/project' })\n const result = []\n for await (const file of files) result.push(file)\n expect(result).toStrictEqual([\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n ])\n })\n\n test('should find the absolute path matching a glob pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project' })\n expect(files).toStrictEqual([\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n ])\n })\n\n test('should find the relative path matching a glob pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project', getRelative: true })\n expect(files).toStrictEqual([\n './bar.ts',\n './baz.ts',\n './foo.ts',\n ])\n })\n\n test('should find the stats matching a glob pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project', getStats: true })\n const expected = [\n vol.statSync('/project/foo.ts'),\n vol.statSync('/project/bar.ts'),\n vol.statSync('/project/baz.ts'),\n ]\n expect(files.map(x => x.uid)).toStrictEqual(expected.map(x => x.uid))\n })\n\n test('should find the paths matching an exclude pattern', async() => {\n const files = await glob('*.ts', { cwd: '/project', exclude: 'baz.ts' })\n const expected = [\n '/project/bar.ts',\n '/project/foo.ts',\n ]\n expect(files).toStrictEqual(expected)\n })\n\n test('should find nested and non-nested files', async() => {\n const files = await glob('**/*', { cwd: '/project', onlyFiles: true })\n expect(files).toStrictEqual([\n '/project/README.md',\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n '/project/dist/bar.js',\n '/project/dist/baz.js',\n '/project/dist/foo.js',\n '/project/dist/docs/CHANGELOG.md',\n '/project/dist/docs/README.md',\n ])\n })\n\n test('should find nested and non-nested directories', async() => {\n const files = await glob('**/*', { cwd: '/project', onlyDirectories: true })\n expect(files).toStrictEqual([\n '/project/dist',\n '/project/dist/docs',\n ])\n })\n\n test('should find files but exclude the dist directory', async() => {\n const files = await glob('*', { cwd: '/project', exclude: 'dist/**' })\n expect(files).toStrictEqual([\n '/project/README.md',\n '/project/bar.ts',\n '/project/baz.ts',\n '/project/foo.ts',\n ])\n })\n\n test('should infer the return type as a collection of `Stats`', () => {\n const files = glob('*.ts', { cwd: '/project', getStats: true })\n expectTypeOf(files).toEqualTypeOf<Awaitable<AsyncIterable<Stats>, Stats[]>>()\n })\n\n test('should infer the return type as a collection of `string`', () => {\n const files = glob('*.ts', { cwd: '/project', getStats: false })\n expectTypeOf(files).toEqualTypeOf<Awaitable<AsyncIterable<string>, string[]>>()\n })\n\n test('should infer the return type as a collection of `Stats` or `string`', () => {\n const files = glob('*.ts', { cwd: '/project', getStats: true as boolean })\n expectTypeOf(files).toEqualTypeOf<Awaitable<AsyncIterable<Stats>, Stats[]> | Awaitable<AsyncIterable<string>, string[]>>()\n })\n}\n"],"names":["cwd","getCwd","pattern"],"mappings":";;;;;AAqFO,SAAS,KAAK,SAA6B,UAAuB,IAAgB;AACjF,QAAA;AAAA,IACJA,KAAAA,QAAMC,IAAO;AAAA,IACb,UAAU,CAAC;AAAA,IACX,cAAc;AAAA,IACd,WAAW;AAAA,IACX,kBAAkB;AAAA,IAClB,YAAY;AAAA,EACV,IAAA,SAIE,YADe,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO,GAClC,IAAI,aAAa,GAEzC,mBADc,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO,GAC3B,IAAI,aAAa,GAG/C,aAAuB,CAACD,KAAG;AACjC,kBAAiB,iBAAiB;AACzB,WAAA,WAAW,SAAS,KAAG;AAC5B,YAAM,YAAY,WAAW,IACvB,GAAA,WAAW,MAAM,QAAQ,WAAW,EAAE,eAAe,GAAM,CAAA,EAAE,MAAM,MAAM,CAAE,CAAA;AAEjF,iBAAW,UAAU,UAAU;AAC7B,cAAM,eAAe,KAAK,WAAW,OAAO,IAAI,GAC1C,eAAe,SAASA,OAAK,YAAY,GACzC,SAAS,OAAO,OAChB,GAAA,cAAc,OAAO;AAe3B,YAZI,eAAa,WAAW,KAAK,YAAY,GAGzC,aAAa,CAAC,UACd,mBAAmB,CAAC,eAIpB,CADY,SAAS,KAAK,CAAAE,aAAWA,SAAQ,KAAK,YAAY,CAAC,KAIhD,gBAAgB,KAAK,CAAAA,aAAWA,SAAQ,KAAK,YAAY,CAAC,EAC7D;AAGhB,YAAI,SAAoB;AACpB,qBAAU,SAAS,MAAM,KAAK,YAAY,IAC1C,gBAAa,SAAS,KAAK,YAAY,KAC3C,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,QAAM,WAAW;AAGjB,SAAO,UAAU,QAAQ;AAC3B;"}
package/dist/index.cjs CHANGED
@@ -1,16 +1,16 @@
1
1
  "use strict";
2
2
  var createTemporaryDirectory = require("./createTemporaryDirectory.cjs"), createTemporaryFile = require("./createTemporaryFile.cjs"), findAncestor = require("./findAncestor.cjs"), findAncestors = require("./findAncestors.cjs"), glob = require("./glob.cjs"), loadObject = require("./loadObject.cjs"), touch = require("./touch.cjs"), updateFile = require("./updateFile.cjs"), withTemporaryDirectories = require("./withTemporaryDirectories.cjs"), withTemporaryFiles = require("./withTemporaryFiles.cjs");
3
- require("node:path");
4
- require("node:os");
5
3
  require("node:fs/promises");
4
+ require("node:os");
5
+ require("node:path");
6
6
  require("node:process");
7
7
  require("@unshared/functions/awaitable");
8
8
  require("@unshared/string/createPattern");
9
- require("node:fs");
10
- require("node:events");
11
- require("@unshared/reactivity/reactive");
12
- require("@unshared/functions/garbageCollected");
13
9
  require("@unshared/collection/overwrite");
10
+ require("@unshared/functions/garbageCollected");
11
+ require("@unshared/reactivity/reactive");
12
+ require("node:events");
13
+ require("node:fs");
14
14
  exports.createTemporaryDirectory = createTemporaryDirectory.createTemporaryDirectory;
15
15
  exports.createTemporaryFile = createTemporaryFile.createTemporaryFile;
16
16
  exports.findAncestor = findAncestor.findAncestor;
package/dist/index.d.ts CHANGED
@@ -10,7 +10,7 @@ export { withTemporaryDirectories } from './withTemporaryDirectories.js';
10
10
  export { withTemporaryFiles } from './withTemporaryFiles.js';
11
11
  import 'node:fs/promises';
12
12
  import '@unshared/functions/awaitable';
13
- import 'node:fs';
14
13
  import '@unshared/types';
15
- import 'node:events';
14
+ import 'node:fs';
16
15
  import '@unshared/reactivity/reactive';
16
+ import 'node:events';
package/dist/index.js CHANGED
@@ -8,17 +8,17 @@ import { touch } from "./touch.js";
8
8
  import { updateFile } from "./updateFile.js";
9
9
  import { withTemporaryDirectories } from "./withTemporaryDirectories.js";
10
10
  import { withTemporaryFiles } from "./withTemporaryFiles.js";
11
- import "node:path";
12
- import "node:os";
13
11
  import "node:fs/promises";
12
+ import "node:os";
13
+ import "node:path";
14
14
  import "node:process";
15
15
  import "@unshared/functions/awaitable";
16
16
  import "@unshared/string/createPattern";
17
- import "node:fs";
18
- import "node:events";
19
- import "@unshared/reactivity/reactive";
20
- import "@unshared/functions/garbageCollected";
21
17
  import "@unshared/collection/overwrite";
18
+ import "@unshared/functions/garbageCollected";
19
+ import "@unshared/reactivity/reactive";
20
+ import "node:events";
21
+ import "node:fs";
22
22
  export {
23
23
  FSObject,
24
24
  createTemporaryDirectory,
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- var node_path = require("node:path"), promises = require("node:fs/promises"), node_fs = require("node:fs"), node_events = require("node:events"), reactive = require("@unshared/reactivity/reactive"), garbageCollected = require("@unshared/functions/garbageCollected"), awaitable = require("@unshared/functions/awaitable"), overwrite = require("@unshared/collection/overwrite");
2
+ var overwrite = require("@unshared/collection/overwrite"), awaitable = require("@unshared/functions/awaitable"), garbageCollected = require("@unshared/functions/garbageCollected"), reactive = require("@unshared/reactivity/reactive"), node_events = require("node:events"), node_fs = require("node:fs"), promises = require("node:fs/promises"), node_path = require("node:path");
3
3
  class FSObject extends node_events.EventEmitter {
4
4
  /**
5
5
  * Load a JSON file and keep it synchronized with it's source file.