{"id":43472967,"url":"https://github.com/goerwin/directory-validator","last_synced_at":"2026-02-03T07:18:58.123Z","repository":{"id":42481870,"uuid":"96841678","full_name":"goerwin/directory-validator","owner":"goerwin","description":"Tool to validate directory structures","archived":false,"fork":false,"pushed_at":"2025-07-30T18:08:24.000Z","size":1034,"stargazers_count":17,"open_issues_count":3,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-21T16:09:57.581Z","etag":null,"topics":["directory","directory-analyzer","directory-utilities","directory-validator","folder","folder-validator","validation","validator"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/goerwin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-07-11T02:28:11.000Z","updated_at":"2025-07-06T13:46:55.000Z","dependencies_parsed_at":"2025-08-18T15:51:29.072Z","dependency_job_id":"ac57e283-b7df-4ce4-8ff7-6066dcc886f6","html_url":"https://github.com/goerwin/directory-validator","commit_stats":{"total_commits":109,"total_committers":3,"mean_commits":"36.333333333333336","dds":0.06422018348623848,"last_synced_commit":"b92aef6af5bcc4fa9df3ecfc189cc39da2c65131"},"previous_names":["erwingo/directory-validator"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/goerwin/directory-validator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goerwin%2Fdirectory-validator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goerwin%2Fdirectory-validator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goerwin%2Fdirectory-validator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goerwin%2Fdirectory-validator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/goerwin","download_url":"https://codeload.github.com/goerwin/directory-validator/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/goerwin%2Fdirectory-validator/sbom","scorecard":{"id":382990,"data":{"date":"2025-08-11","repo":{"name":"github.com/goerwin/directory-validator","commit":"b4090edeab692ba546f3b21a1e5da0bad1dd8a8c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.1,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 1/19 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-to-npm.yml:7: update your workflow using https://app.stepsecurity.io/secureworkflow/goerwin/directory-validator/publish-to-npm.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-to-npm.yml:8: update your workflow using https://app.stepsecurity.io/secureworkflow/goerwin/directory-validator/publish-to-npm.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish-to-npm.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/goerwin/directory-validator/publish-to-npm.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/publish-to-npm.yml:12","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   0 out of   1 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/publish-to-npm.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 12 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":6,"reason":"4 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T15:54:40.694Z","repository_id":42481870,"created_at":"2025-08-18T15:54:40.694Z","updated_at":"2025-08-18T15:54:40.694Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29037156,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T06:39:36.383Z","status":"ssl_error","status_checked_at":"2026-02-03T06:39:32.787Z","response_time":96,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["directory","directory-analyzer","directory-utilities","directory-validator","folder","folder-validator","validation","validator"],"created_at":"2026-02-03T07:18:56.727Z","updated_at":"2026-02-03T07:18:58.117Z","avatar_url":"https://github.com/goerwin.png","language":"TypeScript","readme":"# directory-validator\n\n[![Package Version](https://img.shields.io/npm/v/directory-validator.svg)](https://www.npmjs.com/package/directory-validator)\n\nCLI Tool to validate directory structures.\nIf you want to have control over what files/dirs a directory can have then this can be useful.\n\n## Installation\n\n```\n$ npm install directory-validator\n```\n\n## Usage\n\nGenerate a configuration file `.directoryvalidator.json` to start with:\n\n```\n$ directory-validator --init\n```\n\nRun the validator on the current directory:\n\n```\n$ directory-validator .\n```\n\nThe tool will evaluate the rules provided by the configuration file against the current directory and output errors if any.\n\n## Configuration File\n\n```jsonc\n{\n  \"ignoreFiles\": [\".gitignore\"],\n  \"ignoreDirs\": [\"node_modules\", \".git\"],\n  \"commonRules\": {\n    \"rule_indexfile\": {\n      \"type\": \"file\",\n      \"name\": \"index.js\"\n    }\n  },\n  \"rules\": [\n    {\n      \"type\": \"file\",\n      \"name\": \"package.json\"\n    },\n    {\n      \"type\": \"common\",\n      \"key\": \"rule_indexfile\"\n    },\n    {\n      \"type\": \"directory\",\n      \"name\": \"src\",\n      \"isOptional\": true,\n      \"rules\": [\n        {\n          \"type\": \"common\",\n          \"key\": \"rule_indexfile\"\n        }\n      ]\n    }\n  ]\n}\n```\n\nIn this example:\n\n- We ignore the file `.gitignore` and both `.node_modules` and `.git` directories from being analized\n- We want to have one file name `package.json` and one file named `index.js`\n- We want one directory `src` to have one file named `index.js`. Since it's optional,\n  if the directory does not exist we ignore the rule, but if it does then it must only\n  have one file `index.js`\n\n### ignoreFiles:\n\nA string or glob pattern. For example:\n\n```jsonc\n[\n  \"package.json\",\n  \"**/*.test.js\",\n  \".*\" // files starting with \".\"\n]\n```\n\n### ignoreDirs:\n\nA string or glob pattern. For example:\n\n```jsonc\n[\n  \"node_modules\",\n  \"src/**/tests\",\n  \".*\" // dirs starting with \".\"\n]\n```\n\n### commonRules:\n\nDefine File, Directory and Common rules that can be reused in `rules`\n\n```jsonc\n{\n  // key must start with \"rule_\"\n  // Examples:\n  \"rule_indexfile\": {\n    \"type\": \"file\",\n    \"name\": \"index.js\"\n  },\n  \"rule_anotherrule\": {\n    \"type\": \"directory\",\n    \"name\": \"images\",\n    \"rules\": [\n      {\n        \"type\": \"file\",\n        \"name\": \"logo.png\"\n      }\n    ]\n  }\n}\n```\n\n### rules:\n\nCan contain File, Directory and Common Rules\n\n#### File Rule\n\n```jsonc\n{\n  // Required\n  \"type\": \"file\",\n\n  // Required\n  // can be string or RegExp\n  // if RegExp then it has to start and end with /\n  // if string then it can contain one\n  // special case: [camelCase], [UPPERCASE], [dash-case], [snake_case], *\n  // Examples:\n  \"name\": \"package.json\",\n  \"name\": \"[snake_case]\",\n  \"name\": \"[camelCase].js\",\n  \"name\": \".[UPPERCASE]\",\n  \"name\": \".[dash-case].jpg\",\n  \"name\": \"*.png\",\n  \"name\": \"/index.(js|ts)/\",\n\n  // Optional\n  // default: null\n  // can be string or RegExp (do not include the dot)\n  // if RegExp then it has to start and end with /\n  // Examples:\n  \"extension\": \"js\",\n  \"extension\": \"png\",\n  \"extension\": \"/(png|jpg|gif)/\",\n\n  // Optional\n  // default: false\n  // Whether the file can be included\n  \"isOptional\": false\n}\n```\n\n#### Directory Rule\n\n```jsonc\n{\n  // Required\n  \"type\": \"directory\",\n\n  // Required\n  // Same options as file names\n  // Examples:\n  \"name\": \"src\",\n  \"name\": \"important-[dash-case]\",\n\n  // Optional\n  // default: false\n  // Whether the directory can be included\n  \"isOptional\": false,\n\n  // Optional\n  // default: false\n  // Whether the directory can be recursive\n  // Adds the ability to check directory rules recursively\n  \"isRecursive\": false,\n\n  // Optional\n  // An array containing file and directory rules\n  // If empty or omitted then we don't validate dir content\n  \"rules\": []\n}\n```\n\n#### Common Rule\n\n```jsonc\n{\n  // Required\n  \"type\": \"common\",\n\n  // Required\n  // must match a key property inside \"commonRules\"\n  // examples:\n  \"key\": \"rule_indexfile\",\n  \"key\": \"rule_test2\",\n  \"key\": \"rule_whatever\",\n\n  // Optional\n  // default: false\n  // Whether the directory can be included\n  \"isOptional\": false\n}\n```\n\n## Notes\n\n- When you run `$ directory-validator ./` it will look for a `.directoryvalidator.json` file in the current directory, if it doesn't find one, it will try to look for one in the upper directory and so on until the home directory is reached. If no file is found then no rules are applied.\n\n- Rules are inclusive, meaning that if multiple rules match the same files/dirs, they pass.\n  - For example, the rules `{ \"name\": \"index.js\", \"type\": \"file\" }` and `{ \"name\": \"[camelCase].js\", \"type\": \"file\" }`, will match a file `index.js` so they both pass.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoerwin%2Fdirectory-validator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgoerwin%2Fdirectory-validator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgoerwin%2Fdirectory-validator/lists"}