{"id":18486362,"url":"https://github.com/maxgfr/github-change-json","last_synced_at":"2026-04-02T19:10:04.129Z","repository":{"id":40545685,"uuid":"469106320","full_name":"maxgfr/github-change-json","owner":"maxgfr","description":"Github action which lets you to change a value from a json file (e.g. package.json)","archived":false,"fork":false,"pushed_at":"2026-03-30T18:42:47.000Z","size":849,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-30T19:25:30.566Z","etag":null,"topics":["actions","github","github-actions","json","key","package-json","update","update-json","value","workflow"],"latest_commit_sha":null,"homepage":"https://github.com/marketplace/actions/github-change-json","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/maxgfr.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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-03-12T14:30:10.000Z","updated_at":"2026-03-30T18:42:47.000Z","dependencies_parsed_at":"2023-01-11T17:21:54.591Z","dependency_job_id":"9f0605a4-68d7-4f8f-b6a1-d2af21976693","html_url":"https://github.com/maxgfr/github-change-json","commit_stats":{"total_commits":61,"total_committers":4,"mean_commits":15.25,"dds":0.5245901639344263,"last_synced_commit":"03d7afaaf696e299cf50a87c8119bdecda56cf14"},"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"purl":"pkg:github/maxgfr/github-change-json","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fgithub-change-json","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fgithub-change-json/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fgithub-change-json/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fgithub-change-json/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/maxgfr","download_url":"https://codeload.github.com/maxgfr/github-change-json/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/maxgfr%2Fgithub-change-json/sbom","scorecard":{"id":629098,"data":{"date":"2025-08-11","repo":{"name":"github.com/maxgfr/github-change-json","commit":"573d7e6ba871a07fc23ebfef66e5faba78278863"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.5,"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":"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":"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":"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/check-dist.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/maxgfr/github-change-json/check-dist.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/check-dist.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/maxgfr/github-change-json/check-dist.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/check-dist.yml:49: update your workflow using https://app.stepsecurity.io/secureworkflow/maxgfr/github-change-json/check-dist.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tag.yaml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/maxgfr/github-change-json/tag.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/tag.yaml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/maxgfr/github-change-json/tag.yaml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/tag.yaml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/maxgfr/github-change-json/tag.yaml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test-action.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/maxgfr/github-change-json/test-action.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test-build.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/maxgfr/github-change-json/test-build.yml/main?enable=pin","Info:   0 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party 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":"Code-Review","score":0,"reason":"Found 0/18 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":"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/check-dist.yml:1","Warn: no topLevel permission defined: .github/workflows/tag.yaml:1","Warn: no topLevel permission defined: .github/workflows/test-action.yml:1","Warn: no topLevel permission defined: .github/workflows/test-build.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":"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 'main'"],"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":0,"reason":"11 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-7r3h-m5j6-3q42","Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","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-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7"],"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-21T07:20:01.545Z","repository_id":40545685,"created_at":"2025-08-21T07:20:01.545Z","updated_at":"2025-08-21T07:20:01.545Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31314035,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T12:59:32.332Z","status":"ssl_error","status_checked_at":"2026-04-02T12:54:48.875Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5: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":["actions","github","github-actions","json","key","package-json","update","update-json","value","workflow"],"created_at":"2024-11-06T12:49:12.300Z","updated_at":"2026-04-02T19:10:04.102Z","avatar_url":"https://github.com/maxgfr.png","language":"TypeScript","readme":"# github-change-json\n\n[![View Action](https://img.shields.io/badge/view-github%20action-yellow.svg)](https://github.com/marketplace/actions/github-change-json) [![Tests](https://img.shields.io/badge/tests-165%20passing-brightgreen)](https://github.com/maxgfr/github-change-json/actions/workflows/test-build.yml) [![Integration](https://img.shields.io/badge/integration-16%20jobs-blue)](https://github.com/maxgfr/github-change-json/actions/workflows/test-action.yml)\n\nA [GitHub Action](https://github.com/features/actions) to modify values in JSON and JSONC files during workflows. Supports nested keys, typed values, deep merge, array indices, schema validation, and more.\n\n## Why\n\nSometimes you need to update a `.json` file during a CI/CD workflow:\n\n- Publish the same package to GitHub Packages (`@myorg/pkg`) and npm (`pkg`) with different names\n- Bump a version number during a release\n- Update a `tsconfig.json` compiler option before deployment\n- Set the `homepage` field for GitHub Pages\n\nThis action handles all of these by modifying your JSON file in-place, preserving formatting and comments.\n\n## Quick Start\n\n```yaml\n- uses: maxgfr/github-change-json@main\n  with:\n    key: 'version'\n    value: '2.0.0'\n    path: package.json\n```\n\n## Full Workflow Example\n\n```yaml\nname: Release\non:\n  push:\n    branches: [main]\n\njobs:\n  release:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Set scoped name for GitHub Packages\n        uses: maxgfr/github-change-json@main\n        with:\n          key: 'name'\n          value: '@my-org/my-package'\n          path: package.json\n\n      - name: Bump version and add build metadata\n        uses: maxgfr/github-change-json@main\n        with:\n          path: package.json\n          changes: |\n            [\n              {\"key\": \"version\", \"value\": \"2.0.0\"},\n              {\"key\": \"private\", \"value\": \"false\", \"type\": \"boolean\"},\n              {\"key\": \"scripts\", \"value\": \"{\\\"prepublish\\\": \\\"tsc\\\"}\", \"merge\": true}\n            ]\n          schema: schemas/package.schema.json\n          commit: true\n```\n\n## Examples\n\n### Nested Keys (dot notation)\n\n```yaml\n- uses: maxgfr/github-change-json@main\n  with:\n    key: 'compilerOptions.target'\n    value: 'ES2020'\n    path: tsconfig.json\n```\n\nWorks with JSONC files (e.g. `tsconfig.json` with comments) -- comments are preserved.\n\n### Typed Values\n\nBy default values are strings. Use `type` for numbers, booleans, or JSON objects:\n\n```yaml\n- uses: maxgfr/github-change-json@main\n  with:\n    key: 'port'\n    value: '3000'\n    type: 'number'    # stored as 3000, not \"3000\"\n    path: config.json\n\n- uses: maxgfr/github-change-json@main\n  with:\n    key: 'compilerOptions.strict'\n    value: 'true'\n    type: 'boolean'   # stored as true, not \"true\"\n    path: tsconfig.json\n\n- uses: maxgfr/github-change-json@main\n  with:\n    key: 'scripts'\n    value: '{\"build\": \"tsc\", \"test\": \"jest\"}'\n    type: 'json'      # stored as an object, not a string\n    path: package.json\n```\n\n### Array Indices\n\nNumeric path segments are treated as array indices:\n\n```yaml\n- uses: maxgfr/github-change-json@main\n  with:\n    key: 'contributors.0.name'    # first element of the array\n    value: 'Alicia'\n    path: package.json\n```\n\n### Deep Merge\n\nMerge new keys into an existing object without overwriting untouched keys:\n\n```yaml\n- uses: maxgfr/github-change-json@main\n  with:\n    key: 'scripts'\n    value: '{\"start\": \"node .\", \"deploy\": \"fly deploy\"}'\n    merge: true\n    path: package.json\n# {\"build\":\"tsc\",\"test\":\"jest\"} + merge → {\"build\":\"tsc\",\"test\":\"jest\",\"start\":\"node .\",\"deploy\":\"fly deploy\"}\n```\n\nNested objects are recursively merged; arrays and primitives are replaced.\n\n### Delete a Key\n\n```yaml\n- uses: maxgfr/github-change-json@main\n  with:\n    key: 'devDependencies'\n    path: package.json\n    delete: true\n```\n\n### Multiple Changes at Once\n\n```yaml\n- uses: maxgfr/github-change-json@main\n  with:\n    path: package.json\n    changes: |\n      [\n        {\"key\": \"name\", \"value\": \"@my-org/my-package\"},\n        {\"key\": \"version\", \"value\": \"2.0.0\"},\n        {\"key\": \"private\", \"value\": \"true\", \"type\": \"boolean\"},\n        {\"key\": \"scripts\", \"value\": \"{\\\"deploy\\\": \\\"fly deploy\\\"}\", \"merge\": true},\n        {\"key\": \"devDependencies\", \"delete\": true}\n      ]\n```\n\n### Schema Validation\n\nValidate the result against a JSON Schema **before** writing. If validation fails, the file is not modified:\n\n```yaml\n- uses: maxgfr/github-change-json@main\n  with:\n    key: 'version'\n    value: '2.0.0'\n    path: package.json\n    schema: schemas/package.schema.json    # local file path\n    # or: schema: 'https://json.schemastore.org/package.json'\n```\n\n### Create File if Missing\n\nCreate the target file with `{}` if it doesn't exist yet (parent directories are created automatically):\n\n```yaml\n- uses: maxgfr/github-change-json@main\n  with:\n    key: 'database.host'\n    value: 'localhost'\n    path: config/settings.json\n    create-if-missing: true\n```\n\n### Dry Run\n\nPreview what would change without modifying the file:\n\n```yaml\n- uses: maxgfr/github-change-json@main\n  with:\n    key: 'name'\n    value: '@my-org/my-package'\n    path: package.json\n    dry-run: true\n```\n\n### Commit and Push\n\n```yaml\n- uses: maxgfr/github-change-json@main\n  with:\n    key: 'name'\n    value: '@my-org/my-package'\n    path: package.json\n    commit: true\n```\n\n### Commit with Sign-off (DCO)\n\nAdd a `Signed-off-by` trailer to the commit message for [DCO](https://developercertificate.org/) compliance:\n\n```yaml\n- uses: maxgfr/github-change-json@main\n  with:\n    key: 'version'\n    value: '2.0.0'\n    path: package.json\n    commit: true\n    signoff: true\n# Commit message will include:\n# Signed-off-by: \u003cGITHUB_ACTOR\u003e \u003c\u003cGITHUB_ACTOR\u003e@users.noreply.github.com\u003e\n```\n\n### Use Outputs\n\n```yaml\n- id: update\n  uses: maxgfr/github-change-json@main\n  with:\n    key: 'version'\n    value: '2.0.0'\n    path: package.json\n\n- run: |\n    echo \"Old: ${{ steps.update.outputs.old-value }}\"\n    echo \"New: ${{ steps.update.outputs.new-value }}\"\n\n- if: steps.update.outputs.modified == 'true'\n  run: echo \"File changed, deploying...\"\n```\n\n## Inputs\n\n| Name | Type | Required | Default | Description |\n|------|------|----------|---------|-------------|\n| `path` | string | **yes** | -- | Path to the JSON file (relative to repo root) |\n| `key` | string | no\\* | -- | Key to modify. Supports dot notation for nesting (`a.b.c`) and array indices (`items.0.name`). Escape literal dots with `\\\\` (`my\\\\.key`) |\n| `value` | string | no\\* | -- | Value to set (always passed as a string, converted via `type`) |\n| `type` | string | no | `string` | Value type: `string`, `number`, `boolean`, or `json` |\n| `commit` | boolean | no | `false` | Commit and push changes |\n| `signoff` | boolean | no | `false` | Add `Signed-off-by` trailer to the commit message (DCO) |\n| `delete` | boolean | no | `false` | Delete the key instead of setting a value |\n| `merge` | boolean | no | `false` | Deep merge a JSON object into the existing value |\n| `dry-run` | boolean | no | `false` | Preview changes without writing to disk |\n| `create-if-missing` | boolean | no | `false` | Create the file with `{}` if it doesn't exist |\n| `changes` | string | no | -- | JSON array of changes (overrides single-key inputs). Each item: `{\"key\", \"value\", \"type\", \"delete\", \"merge\"}` |\n| `schema` | string | no | -- | Path or URL to a JSON Schema to validate the result against |\n\n\\*Either `key` or `changes` is required. `value` is required unless `delete: true`.\n\n## Outputs\n\n| Name | Description |\n|------|-------------|\n| `old-value` | Previous value (string for single key, JSON object for multiple keys) |\n| `new-value` | New value after modification (same format as `old-value`) |\n| `modified` | `'true'` if the file content changed, `'false'` otherwise |\n\n## Behavior Details\n\n### JSONC Support\n\nFiles with line comments (`//`), block comments (`/* */`), and trailing commas are fully supported. Comments are preserved when modifying values.\n\n### Formatting Preservation\n\nThe action detects and preserves the original file's:\n- **Indentation** (2 spaces, 4 spaces, tabs)\n- **Line endings** (LF, CRLF)\n- **Trailing newline**\n\n### Schema Validation\n\n- Runs **before** writing -- the file is never left in an invalid state\n- Works in `dry-run` mode too (validates the would-be result)\n- Supports local file paths and `http://` / `https://` URLs (30s fetch timeout)\n- Uses JSON Schema draft-07 via [Ajv](https://ajv.js.org/)\n- `$ref` to external URLs within the schema is not supported\n\n### Commit Behavior\n\nWhen `commit: true`:\n- Git user name is set to `GITHUB_ACTOR` (fallback: `github-actions[bot]`)\n- Git user email is set to `\u003cGITHUB_ACTOR\u003e@users.noreply.github.com` (fallback: `github-actions@users.noreply.github.com`)\n- Commit message format:\n  - Single key: `chore: update \u003cpath\u003e (set \u003ckey\u003e=\u003cvalue\u003e)` / `(delete \u003ckey\u003e)` / `(merge \u003ckey\u003e=\u003cvalue\u003e)`\n  - Multiple changes: `chore: update \u003cpath\u003e with N changes`\n  - Long values are truncated to 50 characters in the commit message\n- Pushed to `GITHUB_HEAD_REF` (PR source branch) or `GITHUB_REF` (current ref) as fallback\n- Pre-commit hooks are bypassed (`--no-verify`)\n- When `signoff: true`, adds `Signed-off-by: Name \u003cemail\u003e` trailer via `--signoff`\n- Skipped in `dry-run` mode\n\n### Error Handling\n\nThe action fails with a clear message when:\n- File not found (and `create-if-missing` is `false`)\n- Invalid JSON/JSONC syntax in the target file\n- Invalid type conversion (`type: number` with `value: abc`, `NaN`, `Infinity`)\n- Invalid `type` value (anything other than `string`, `number`, `boolean`, `json`)\n- Conflicting flags (`delete` + `merge` both true)\n- Non-string `value` in `changes` array (e.g. `{\"value\": 42}` instead of `{\"value\": \"42\"}`)\n- Missing required fields (`key` or `value` when needed)\n- Invalid `changes` input (not valid JSON, not an array, missing `key`)\n- Merge with non-JSON or non-object value\n- Schema validation failure (with detailed per-field error messages)\n- Schema file not found, invalid JSON, or invalid schema structure\n- Schema URL fetch failure or timeout (30s)\n- Setting a nested path through a primitive (`name.sub` when `name` is a string)\n\n### Limitations\n\n- String key modifications require an object root (`{}`), not an array root (`[]`)\n- Purely numeric path segments are always array indices -- string keys like `\"0\"` are not supported\n- Merge requires a JSON object value (not arrays or primitives)\n- Schema `$ref` to external URLs is not resolved\n\n## Development\n\n```bash\npnpm install          # install dependencies\npnpm run build        # compile TypeScript\npnpm run package      # bundle with ncc\npnpm run lint         # run ESLint\npnpm run format       # format with Prettier\npnpm test             # run 165 tests\npnpm run all          # build + package + lint + test\n```\n\n## License\n\nMIT\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxgfr%2Fgithub-change-json","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmaxgfr%2Fgithub-change-json","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmaxgfr%2Fgithub-change-json/lists"}