{"id":13998374,"url":"https://github.com/smikula/good-fences","last_synced_at":"2026-02-12T23:19:48.955Z","repository":{"id":26313198,"uuid":"108027351","full_name":"smikula/good-fences","owner":"smikula","description":"Code boundary management for TypeScript projects","archived":false,"fork":false,"pushed_at":"2023-11-30T18:58:09.000Z","size":461,"stargazers_count":190,"open_issues_count":23,"forks_count":18,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-19T06:51:06.002Z","etag":null,"topics":["hacktoberfest","typescript"],"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/smikula.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}},"created_at":"2017-10-23T19:09:17.000Z","updated_at":"2025-10-10T21:23:39.000Z","dependencies_parsed_at":"2023-11-30T19:49:20.892Z","dependency_job_id":null,"html_url":"https://github.com/smikula/good-fences","commit_stats":{"total_commits":131,"total_committers":13,"mean_commits":"10.076923076923077","dds":0.3587786259541985,"last_synced_commit":"07b3bda3a4ab3f0692d18149f0fc7852fd36dc12"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/smikula/good-fences","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smikula%2Fgood-fences","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smikula%2Fgood-fences/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smikula%2Fgood-fences/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smikula%2Fgood-fences/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smikula","download_url":"https://codeload.github.com/smikula/good-fences/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smikula%2Fgood-fences/sbom","scorecard":{"id":833391,"data":{"date":"2025-08-11","repo":{"name":"github.com/smikula/good-fences","commit":"76fe37ef42da874062bff7e5ecdc232014af640f"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"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":"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":"Code-Review","score":4,"reason":"Found 14/30 approved changesets -- score normalized to 4","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":"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":"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/ci.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/smikula/good-fences/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/smikula/good-fences/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/smikula/good-fences/publish.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/smikula/good-fences/publish.yml/master?enable=pin","Info:   0 out of   4 GitHub-owned GitHubAction 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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Warn: no topLevel permission defined: .github/workflows/publish.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":"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":"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":"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":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"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 30 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":0,"reason":"39 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-pfrx-2q88-qq97","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-rc47-6667-2j5j","Warn: Project is vulnerable to: GHSA-78xj-cgh5-2h22","Warn: Project is vulnerable to: GHSA-2p57-rm9w-gvfp","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-6c8f-qphg-qjgp","Warn: Project is vulnerable to: GHSA-p6mc-m468-83gw","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-5fw9-fq32-wv5p","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-44c6-4v22-4mhx","Warn: Project is vulnerable to: GHSA-4x5v-gmq8-25ch","Warn: Project is vulnerable to: GHSA-f5x3-32g6-xq36","Warn: Project is vulnerable to: GHSA-pq67-2wwv-3xjx","Warn: Project is vulnerable to: GHSA-8cj5-5rvv-wf4v","Warn: Project is vulnerable to: GHSA-jgrx-mgxx-jf9v","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-6fc8-4gx4-v693","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q","Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh"],"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-23T18:20:24.776Z","repository_id":26313198,"created_at":"2025-08-23T18:20:24.776Z","updated_at":"2025-08-23T18:20:24.776Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29386086,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T22:07:52.078Z","status":"ssl_error","status_checked_at":"2026-02-12T22:07:49.026Z","response_time":55,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["hacktoberfest","typescript"],"created_at":"2024-08-09T19:01:37.375Z","updated_at":"2026-02-12T23:19:48.939Z","avatar_url":"https://github.com/smikula.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# good-fences\r\n\r\n⚠ The JavaScript version of `good-fences` is no longer maintained.  Please see [`good-fences-rs`](https://github.com/Adjective-Object/good-fences-rs-core).\r\n\r\n## What is good-fences?\r\n\r\n\u003e \"Good fences make good neighbors.\"\r\n— Robert Frost, [*Mending Wall*](https://www.poetryfoundation.org/poems/44266/mending-wall)\r\n\r\nGood-fences is a tool that allows you to segment a TypeScript project into conceptual areas and manage dependencies between those areas.\r\n\r\nThis is mostly a concern for large projects with many people working on them, where it is impossible for every developer to have a wholistic understanding of the entire codebase.\r\nJavaScript's module system is a specialized form of anarchy because any file can import any other file, possibly allowing access to code that was really meant to be an internal implementation detail of some larger system.\r\nOther languages have concepts like DLL boundaries and the `internal` keyword to mitigate this.\r\nGood-fences provides a way to enforce similar boundaries in the TypeScript world.\r\n\r\n## Getting started\r\n\r\n1. Install:  `npm install -g good-fences`\r\n2. Configure with one or more fence.json files (see below).\r\n3. Run: `gf [options]`\r\n\r\n    Or run good-fences programmatically via the API:\r\n\r\n    ```typescript\r\n    import { run } from 'good-fences';\r\n    run(options);\r\n    ```\r\n\r\nAlso see the [sample project](./sample) which demonstrates how fences can be configured.\r\nTo run good-fences against the sample, just clone this repository and run `npm run sample`.\r\n\r\n## Configuring good-fences\r\n\r\nGood-fences is configured by creating **fence.json** files throughout your project's directory structure.\r\nThis configuration file defines a \"fence\" around that directory (and any subdirectories).\r\nWithin a fenced directory, modules may import each other without restriction—fences only control what passes in or out of them.\r\nFences may be nested, so that a given directory may have two or more configuration files that apply to it.\r\n\r\nA typical **fence.json** might look like the following.\r\n\r\n```\r\n{\r\n    \"tags\": [ \"tag1\", \"tag2\" ],\r\n    \"exports\": [\r\n        \"index\",\r\n        {\r\n            \"modules\": \"internals/*\",\r\n            \"accessibleTo\": \"tag3\"\r\n        }\r\n    ],\r\n    \"imports\": [\r\n        \"tag4\",\r\n        \"tag5\"\r\n    ],\r\n    \"dependencies\": [\r\n        \"dependency1\",\r\n        \"dependency2/lib/**\"\r\n    ]\r\n}\r\n```\r\n\r\n### Tags\r\n\r\nThe `tags` property can specify one or more tags to apply to all modules under this config's subdirectory.\r\nTags are a way of defining a class of files;\r\nfor example you might tag all your UI components with 'view', or you might have very granular tags for different areas within your application.\r\n(Or both!)\r\nTags are used by the other config options to scope which modules are accessible to other modules.\r\n\r\n### Exports\r\n\r\nThe `exports` property specifies what modules are accessible from the directory.\r\nIn other words, it allows you to keep private modules private.\r\nIf **fence.json** contains an `exports` definition, then in order for any module outside the directory to import a module under the directory, there must be a matching export rule.\r\nIf there is no `exports` definition, then *all* modules are considered exported.\r\n\r\nThe `exports` property is an array of rules.  A rule consists of:\r\n* The `modules` glob string which resolves to one or more modules within the directory.\r\n(An asterisk (`\"*\"`) indicates all modules under the directory.)\r\n* An optional `accessibleTo` property which is a tag (or array of tags) to which these modules are accessible.\r\n* If `accessibleTo` is not defined then there is no restriction on where these modules may be imported.\r\n(As a convenience, you can just provide a string as an export rule if you don't need to specify `accessibleTo`.)\r\n\r\nThis is best demonstrated with an example:\r\n\r\n```json\r\n\"exports\": [\r\n    \"index\",\r\n    {\r\n        \"modules\": \"views/**/*\",\r\n        \"accessibleTo\": \"view\"\r\n    },\r\n    {\r\n        \"modules\": \"data/store\",\r\n        \"accessibleTo\": [ \"data\", \"view\" ]\r\n    }\r\n]\r\n```\r\n\r\n* The `index` module is accessible to all modules.\r\n* Modules under the `/view` directory are accessible to any module tagged with 'view'.\r\n* The `data/store` module is accessible to any module tagged with 'data' or 'view'.\r\n\r\n### Imports\r\n\r\nThe `imports` property specifies what modules may be imported by modules in the directory.\r\nThis allows you to control your module graph by restricting unwanted dependencies.\r\n(Note that `imports` applies to your project code; for external dependencies see `dependencies` below.)\r\nIf **fence.json** contains an `imports` definition, then only imports with the given tags will be allowed.\r\nIf there is no `imports` definition, then *any* module is free to be imported.\r\n\r\nThe `imports` property is an array of tags:\r\n\r\n```json\r\n\"imports\": [\r\n    \"tag1\",\r\n    \"tag2\"\r\n]\r\n```\r\n\r\nIn this case, modules tagged with either 'tag1' or 'tag2' may be imported.\r\n\r\n### Dependencies\r\n\r\nThe `dependencies` property specifies what external dependencies (i.e. those installed under node_modules) may be imported by modules in the directory.\r\nIf **fence.json** contains an `dependencies` definition, then only matching dependencies are allowed.\r\n(If there is no `dependencies` definition, then *any* dependency is free to be imported.)\r\n\r\nThe `dependencies` property is an array of dependencies to allow.  Each element can be a simple glob string or an object that allows for more configuration.\r\n\r\n```json\r\n\"dependencies\": [\r\n    \"dependency1\",\r\n    \"dependency2/lib/**\",\r\n    {\r\n        \"dependency\": \"dependency3\",\r\n        \"accessibleTo\": \"tag3\"\r\n    }\r\n]\r\n```\r\n\r\n* The index of `dependency1` may be imported.\r\n* Anything under `dependency2/lib` may be imported.\r\n* The index of `dependency3` may be imported, but only by modules with the 'tag3' tag.\r\n\r\n## Options\r\n\r\n### Project\r\n\r\nSpecify the tsconfig file to use for your project.\r\n\r\nDefault           | CLI                                    | API\r\n------------------|----------------------------------------|----\r\n`./tsconfig.json` | `--project \u003cstring\u003e`\u003cbr/\u003e`-p \u003cstring\u003e` | `project: string`\r\n\r\n### Root Directory\r\n\r\nSpecify the project root directory or directories.\r\nThese are the folders that will be scanned for fences, and if running with\r\n`--looseRootFileDiscovery`, the directories that will be scanned for source files.\r\n\r\nDefault         | CLI                                    | API\r\n----------------|----------------------------------------|----\r\n`process.cwd()` | `--rootDir \u003cstring...\u003e`\u003cbr/\u003e`-r \u003cstring...\u003e` | `rootDir: string | string[]`\r\n\r\n\r\n### Ignore External Fences\r\n\r\nIgnore external fences (e.g. those in `node_modules`).\r\n\r\nDefault         | CLI                                    | API\r\n----------------|----------------------------------------|----\r\n`false`         | `--ignoreExternalFences`\u003cbr/\u003e`-i`      | `ignoreExternalFences: boolean`\r\n\r\n\r\n### Loose Root File Discovery\r\n\r\nDiscover sources from the root directories rather than discovering sources\r\nfrom the project file.\r\n\r\nDefault         | CLI                                    | API\r\n----------------|----------------------------------------|----\r\n`false`         | `--looseRootFileDiscovery`\u003cbr/\u003e`-x`    | `looseRootFileDiscovery: boolean`\r\n\r\n\r\n### Since Git Hash\r\n\r\nOnly run on files changed between the current git index and the given commit hash\r\nor reference name. If the git index is empty, good-fences will check against the\r\ncurrent HEAD instead.\r\n\r\nDefault         | CLI                                         | API\r\n----------------|---------------------------------------------|----\r\n`undefined`     | `--sinceGitHash \u003cstring\u003e`\u003cbr/\u003e`-g \u003cstring\u003e` | `sinceGitHash: string`\r\n\r\n\r\n### Partial Check Limit\r\n\r\nWhen running in a partial check (e.g. with `--sinceGitHash`), the maximum number\r\nof source files to check. If more than this number of files have changed in the\r\npartial check (including fences and source files), good-fences will exit with\r\ncode 0. This is intended for using good-fences as a pre-commit check.\r\n\r\nDefault         | CLI                                              | API\r\n----------------|--------------------------------------------------|----\r\n`undefined`     | `--partialCheckLimit \u003cnumber\u003e`\u003cbr/\u003e`-l \u003cnumber\u003e` | `partialCheckLimit: number`\r\n\r\n\r\n### Show Progress Bar\r\n\r\nWhether a progress bar should be displayed on the process stderr during fence\r\nchecking. Does not show while discovering files, only while actually running\r\nfences, so it may take several minutes to show on large projects not running\r\nwith `--looseRootFileDiscovery`.\r\n\r\nDefault         | CLI                                          | API\r\n----------------|----------------------------------------------|----\r\n`false`         | `--progressBar \u003cboolean\u003e`\u003cbr/\u003e`-p \u003cboolean\u003e` | `maxConcurrentFenceJobs: boolean`\r\n\r\n\r\n### Max Concurrent Fence Jobs\r\n\r\nThe maximum number of fence jobs to run at the same time. Should be set below MFILE on your machine, as otherwise good-fences will hit EMFILE and crash out.\r\n\r\nDefault         | CLI                                                   | API\r\n----------------|-------------------------------------------------------|----\r\n`6000`          | `--maxConcurrentFenceJobs \u003cnumber\u003e`\u003cbr/\u003e`-j \u003cnumber\u003e` | `maxConcurrentFenceJobs: number`\r\n\r\n\r\n### Exclude Files Patten\r\n\r\nSpecify a pattern for file names that should be excluded from good-fences validation. For example *.test.ts to exclude test files.\r\n\r\nDefault         | CLI                                                   | API\r\n----------------|-------------------------------------------------------|----\r\n`undefined`          | `--excludeFilesPattern \u003cstring\u003e`\u003cbr/\u003e`-p \u003cstring\u003e` | `excludeFilesPattern: string`\r\n\r\n\r\n## Return value\r\n\r\nWhen running good-fences via the API, the results are returned in a structure like the following:\r\n\r\n```json\r\n{\r\n    \"errors\": [\r\n        {\r\n            \"message\": \"The error message\",\r\n            \"sourceFile\": \"The source file where the error was encountered\",\r\n            \"rawImport\": \"The offending import\",\r\n            \"fencePath\": \"The fence whose rule was violated\",\r\n            \"detailedMessage\": \"A human-friendly message that includes all of the above\"\r\n        }\r\n    ],\r\n    \"warnings\": [\r\n        {\r\n            \"message\": \"The warning message\",\r\n            \"fencePath\": \"The fence which generated the warning\",\r\n            \"detailedMessage\": \"A human-friendly message that includes all of the above\"\r\n        }\r\n    ]\r\n}\r\n```\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmikula%2Fgood-fences","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmikula%2Fgood-fences","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmikula%2Fgood-fences/lists"}