{"_id":"@root/walk","_rev":"3-e6bcffa052ba06f27e1f5de711631a95","name":"@root/walk","dist-tags":{"latest":"1.1.0"},"versions":{"1.0.0":{"name":"@root/walk","version":"1.0.0","description":"fs.walk for node (as a port of Go's filepath.Walk)","homepage":"https://git.rootprojects.org/root/walk.js","main":"index.js","type":"module","scripts":{"test":"echo \"Error: no test specified\" && exit 1"},"repository":{"type":"git","url":"https://git.rootprojects.org/root/walk.js.git"},"keywords":["fs","walk","filepath","os"],"author":{"name":"AJ ONeal","email":"aj@therootcompany.com","url":"https://rootprojects.org/"},"license":"MPL-2.0","contributors":[{"name":"AJ ONeal","email":"coolaj86@gmail.com","url":"https://coolaj86.com"}],"gitHead":"7001b3e6150ed9216c2d62925f642e350eb93f2b","_id":"@root/walk@1.0.0","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","_npmUser":{"name":"coolaj86","email":"coolaj86@gmail.com"},"dist":{"integrity":"sha512-GU2po0STyHtjPSH5UpGeDe6WS59am9xjr3LL+zFhHqPrGuAfOemQheYtxQUpWffnLgw9LZ9qTZspFOvrAw98Lw==","shasum":"9fe464d34fdfdce3a8be8bf8ec56d61a049f9dc5","tarball":"https://registry.npmjs.org/@root/walk/-/walk-1.0.0.tgz","fileCount":5,"unpackedSize":21309,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf0LHcCRA9TVsSAnZWagAAxYQP/1aW7LtENTvJvI8skiNG\nZUjzcbgXxhkBEJWa2MrBTZna43JiUxKNywbyluL/5rgdqayMm7A0P/aef1Sx\nV60YTVOHuaxkH40HhUzxEIQZSxtCpltUbuGaSVVBAXTOajzTR7kgxIqZxd8E\nsIH2I7fWAEeWbnc4KYCKv9c3UiZsRPPOM767s7HIgK8JwYDzbM5lyolat6Sl\n1pkyHw5vM5gULX9ct0s3Q5E4R8oJROXvyh6Hi1Uoyz8z97SheB59/L59prR5\nZK3ZXFVp8HZN7k0hvSWoplX7ly5dbSNLM2ZL9I7CklBJzFZF7S2P5y5DQ0Z4\nvGZmfmmnb514VjHUM1KbE3zl1w9CQ0anFLrrWvoTtX/2Le6F2t0vHtPyAc/o\n+gynRpDC5Gy+gbD2+M9QwXD3azrnXntJ/P5qJqxQvi2Jx9JNDMb7C3iyeAUR\nsYVaA+RuLzzi73NkkM2BuFOxV3nW4/XMR4Q949hp52uJczPNUXp2YMRUNr0Y\niibE6JOesmIOVJrAnzdRHmc3AJu1jPhvuvsK1gpAXwVi05bUnUnmSdHOcM4y\ngO6vNflvK/sfYqzpgKf5+phIXgnL34lzURaCWa/OJxb01P9jMwRsa1J2wYEw\nn5Fa1pUhDVc/ospxfGKUEHAudlpi+wZOhiY1ZWG8hMV5ICwQqEgZN9VUeVKr\n98y5\r\n=7qSf\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIAKLj9sInGu8ccjjmEAbbYqZic415gkiWpYyQcDO/K6xAiBHz55oWpxiJOzIJQ5kWunC8M1LDL1FFsNP5XFu0BpMcw=="}]},"directories":{},"maintainers":[{"name":"turleybw","email":"turleybw@gmail.com"},{"name":"thejshaver","email":"john@jshaver.net"},{"name":"coolaj86","email":"coolaj86@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/walk_1.0.0_1607512539299_0.2060975037222179"},"_hasShrinkwrap":false},"1.1.0":{"name":"@root/walk","version":"1.1.0","description":"fs.walk for node (as a port of Go's filepath.Walk)","homepage":"https://git.rootprojects.org/root/walk.js","main":"index.js","scripts":{"prettier":"npx prettier --write '**/*.{md,js,mjs,cjs}'","test":"echo \"Error: no test specified\" && exit 1"},"repository":{"type":"git","url":"https://git.rootprojects.org/root/walk.js.git"},"keywords":["fs","walk","filepath","os"],"author":{"name":"AJ ONeal","email":"aj@therootcompany.com","url":"https://rootprojects.org/"},"license":"MPL-2.0","contributors":[{"name":"AJ ONeal","email":"coolaj86@gmail.com","url":"https://coolaj86.com"}],"gitHead":"22e686a414744358658618928b3a537420ff80d0","_id":"@root/walk@1.1.0","_nodeVersion":"14.15.1","_npmVersion":"6.14.8","_npmUser":{"name":"coolaj86","email":"coolaj86@gmail.com"},"dist":{"integrity":"sha512-FfXPAta9u2dBuaXhPRawBcijNC9rmKVApmbi6lIZyg36VR/7L02ytxoY5K/14PJlHqiBUoYII73cTlekdKTUOw==","shasum":"784d81e8b8d3fb3bedbb0e18952e4ea577e3796a","tarball":"https://registry.npmjs.org/@root/walk/-/walk-1.1.0.tgz","fileCount":6,"unpackedSize":26337,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf0WF6CRA9TVsSAnZWagAAZHoP/RL3XMow/BQ900exDn5r\newLsyprpnUfjiSxOdy300mwiWAL/uIFArwa58I7alXIqjc8apFcl8iNdK0Er\n/0/FKTv5iUa4/7cgut0WTKeniRjxM6NmhjTtLGGWGxqiK+CCO/qy1wJfiJRd\njmFIEjJsar+PI7PEG7i4nwzdjFRKZMSf0FoUR5MAdTGTuhbWeawVo/0cwpCA\nRMxu4mMdC3zDr3+jeCtET6aQgx3MPMpdfOIsTbIfhIktHu25u6E8EOZdO2jp\n0a77HcANeCNj5Uxo/WrOJCsiHpVhMXEHnOy0iRfAlWLyWMXCb/9ANr/79uzT\nJhcPpmWhJcn2CKx2dVzS0jqD0JQasJwgwb5cm7T3fnDVDnGU14oeJTLU2uMa\nbaFzavyVXuUpz1B89yjsoeafMDAoS1ExlFhi3xxLDvdskSHAGKeQDOsSSmQQ\nDAYyWcRvHVLeex4flMe1qTzJPkuADdkj6cpA5g4+2bai7LBiVdcJxR1k+aNy\nPiNI244BHlncBOU5Q62X5LnmmFKlmxuDI7jQVNxcOtxIlkpsZ/2K7oOFyns+\nhB9hlFXWWy84j3EAaIf96Ml5fEtGmzlFb49ek0DYduov3FkbQGFW+qNGBy90\nrR6Y1+QlCKLOihTXjhd7teB24YZbn9ZgatpMcAxGRgmR5xDT4MsCKdmjWC9+\nOU72\r\n=icNS\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIG4LL4WH8hzbhPn36tNzDGQSLpbmVx5RPaCbamZpZV7DAiEArg3trXl+tIxtrttWe1mDFCmfQvBw0Pl+XMsgSTZ2jJM="}]},"directories":{},"maintainers":[{"name":"coolaj86","email":"coolaj86@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/walk_1.1.0_1607557498377_0.0031562556114677065"},"_hasShrinkwrap":false}},"time":{"created":"2020-12-09T11:15:38.885Z","1.0.0":"2020-12-09T11:15:39.525Z","modified":"2022-04-06T20:39:46.653Z","1.1.0":"2020-12-09T23:44:58.530Z"},"maintainers":[{"name":"coolaj86","email":"coolaj86@gmail.com"}],"description":"fs.walk for node (as a port of Go's filepath.Walk)","homepage":"https://git.rootprojects.org/root/walk.js","keywords":["fs","walk","filepath","os"],"repository":{"type":"git","url":"https://git.rootprojects.org/root/walk.js.git"},"contributors":[{"name":"AJ ONeal","email":"coolaj86@gmail.com","url":"https://coolaj86.com"}],"author":{"name":"AJ ONeal","email":"aj@therootcompany.com","url":"https://rootprojects.org/"},"license":"MPL-2.0","readme":"# Walk.js (@root/walk)\n\nWalk a directory recursively and handle each entity (files, directories, symlnks, etc).\n\n(a port of Go's [`filepath.Walk`](https://golang.org/pkg/path/filepath/#Walk)\nusing Node.js v10+'s `fs.readdir`'s `withFileTypes` and ES 2021)\n\n```js\nawait Walk.walk(pathname, walkFunc);\n\nasync function walkFunc(err, pathname, dirent) {\n  // err is failure to lstat a file or directory\n  // pathname is relative path, including the file or folder name\n  // dirent = { name, isDirectory(), isFile(), isSymbolicLink(), ... }\n\n  if (err) {\n    return false;\n  }\n  console.log(pathname);\n}\n```\n\n# Table of Contents\n\n- Install\n- Usage\n  - CommonJS\n  - ES Modules\n- API\n  - Walk.walk\n    - walkFunc\n    - Example: filter dotfiles\n  - Walk.create\n    - withFileStats\n    - sort (and filter)\n- [Node walk in <50 Lines of Code](https://therootcompany.com/blog/fs-walk-for-node-js/)\n- License (MPL-2.0)\n\n# Install\n\n```bash\nnpm install --save @root/walk\n```\n\n# Usage\n\nYou can use this with Node v12+ using Vanilla JS (CommonJS) or ES2021 (ES Modules).\n\n## CommonJS (Vanilla JS / ES5)\n\n```js\nvar Walk = require(\"@root/walk\");\nvar path = require(\"path\");\n\nWalk.walk(\"./\", walkFunc).then(function () {\n  console.log(\"Done\");\n});\n\n// walkFunc must be async, or return a Promise\nfunction walkFunc(err, pathname, dirent) {\n  if (err) {\n    // throw an error to stop walking\n    // (or return to ignore and keep going)\n    console.warn(\"fs stat error for %s: %s\", pathname, err.message);\n    return Promise.resolve();\n  }\n\n  // return false to skip a directory\n  // (ex: skipping \"dot file\" directories)\n  if (dirent.isDirectory() && dirent.name.startsWith(\".\")) {\n    return Promise.resolve(false);\n  }\n\n  // fs.Dirent is a slimmed-down, faster version of fs.Stats\n  console.log(\"name:\", dirent.name, \"in\", path.dirname(pathname));\n  // (only one of these will be true)\n  console.log(\"is file?\", dirent.isFile());\n  console.log(\"is link?\", dirent.isSymbolicLink());\n\n  return Promise.resolve();\n}\n```\n\n## ECMAScript 2021 (ES Modules)\n\n`@root/walk` can be used with async/await or Promises.\n\n```js\nimport { walk } from \"@root/walk\";\nimport path from \"path\";\n\nconst walkFunc = async (err, pathname, dirent) => {\n  if (err) {\n    throw err;\n  }\n\n  if (dirent.isDirectory() && dirent.name.startsWith(\".\")) {\n    return false;\n  }\n\n  console.log(\"name:\", dirent.name, \"in\", path.dirname(pathname));\n};\n\nawait walk(\"./\", walkFunc);\n\nconsole.log(\"Done\");\n```\n\n# API Documentation\n\n## Walk.walk(pathname, walkFunc)\n\n`Walk.walk` walks `pathname` (inclusive) and calls `walkFunc` for each file system entity.\n\nIt can be used with Promises:\n\n```js\nWalk.walk(pathname, promiseWalker).then(doMore);\n```\n\nOr with async / await:\n\n```js\nawait Walk.walk(pathname, asyncWalker);\n```\n\nThe behavior should exactly match Go's\n[`filepath.Walk`](https://golang.org/pkg/path/filepath/#Walk) with a few exceptions:\n\n- uses JavaScript Promises/async/await\n- receives `dirent` rather than `lstat` (for performance, see `withFileStats`)\n- optional parameters to change stat behavior and sort order\n\n### walkFunc\n\nHandles each directory entry\n\n```js\nasync function walkFunc(err, pathname, dirent) {\n  // `err` is a file system stat error\n  // `pathname` is the full pathname, including the file name\n  // `dirent` is an fs.Dirent with a `name`, `isDirectory`, `isFile`, etc\n  return null;\n}\n```\n\n## Walk.create(options)\n\nCreate a custom walker with these options:\n\n- `withFileStats: true` walkFunc will receive fs.Stats[] from fs.lstat instead of fs.Dirent[]\n- `sort: (entities) => entities.sort()` sort and/or filter entities before walking them\n\n```js\nconst walk = Walk.create({\n  withFileStats: true,\n  sort: (entities) => entities.sort()),\n});\n```\n\n## withFileStats\n\nBy default `walk` will use `fs.readdir(pathname, { withFileTypes: true })` which returns `fs.Dirent[]`,\nwhich only has name and file type info, but is much faster when you don't need the complete `fs.Stats`.\n\nEnable `withFileStats` to use get full `fs.Stats`. This will use `fs.readdir(pathname)` (returning `String[]`)\nand then call `fs.lstat(pathname)` - including `mtime`, `birthtime`, `uid`, etc - right after.\n\n```js\nconst walk = Walk.create({\n  withFileStats: true,\n});\n\nwalk(\".\", async function (err, pathname, stat) {\n  console.log(stat.name, stat.uid, stat.birthtime, stat.isDirectory());\n});\n```\n\n## sort (and filter)\n\nSometimes you want to give priority to walking certain directories first.\n\nThe `sort` option allows you to specify a funciton that modifies the `fs.Dirent[]` entities (default) or `String[]` filenames (`withFileStats: true`).\n\nSince you must return the sorted array, you can also filter here if you'd prefer.\n\n```js\nconst byNameWithoutDotFiles = (entities) => {\n  // sort by name\n  // filter dot files\n  return entities\n    .sort((a, b) => {\n      if (a.name > b.name) {\n        return 1;\n      }\n      if (a.name < b.name) {\n        return -1;\n      }\n      return 0;\n    })\n    .filter((ent) => !ent.name.startsWith(\".\"));\n};\n\nconst walk = Walk.create({ sort: byNameWithoutDotFiles });\n\nwalk(\".\", async function (err, pathname, stat) {\n  // each directories contents will be listed alphabetically\n  console.log(pathname);\n});\n```\n\nNote: this gets the result of `fs.readdir()`. If `withFileStats` is `true` you will get a `String[]` of filenames - because this hapens BEFORE `fs.lstat()` is called - otherwise you will get `fs.Dirent[]`.\n\n# node walk in 50 lines of code\n\nIf you're like me and you hate dependencies,\nhere's the bare minimum node fs walk function:\n\nSee [snippet.js](/snippet.js) or <https://therootcompany.com/blog/fs-walk-for-node-js/>.\n\n# License\n\nThe main module, as published to NPM, is licensed the MPL-2.0.\n\nThe ~50 line snippet is licensed CC0-1.0 (Public Domain).\n","readmeFilename":"README.md"}