{"_id":"@adaptive-ds/git-store","name":"@adaptive-ds/git-store","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@adaptive-ds/git-store","version":"0.1.0","scripts":{"build":"rm -rf ./dist && bun tsc -p ./tsconfig.lib.json","test":"bun test","test:w":"bun test --watch","release":"bash ./ops/release.sh","update":"bun update","update:commit":"bun update && git add package.json && bun run tsc && git commit -m \"chore(deps): update dependencies\" && git push","clean":"rm -rf ./dist","reset":"rm -rf ./node_modules","format":"biome format --write src package.json tsconfig.json tsconfig.lib.json biome.json"},"peerDependencies":{"@adaptive-ds/result":"^0.6.0","valibot":"^1.2.0"},"devDependencies":{"@adaptive-ds/result":"^0.6.0","@biomejs/biome":"^2.5.2","@types/bun":"^1.3.13","typescript":"^6.0.3","valibot":"^1.2.0"},"prettier":{"semi":false,"printWidth":120,"trailingComma":"all"},"type":"module","main":"dist/index.js","private":false,"license":"MIT","description":"Git-tracked JSON file storage: every create/edit/delete is committed and optionally pushed.","keywords":["typescript","git","json","storage","version-control"],"homepage":"https://github.com/david1gp/git-store","repository":{"type":"git","url":"git+https://github.com/david1gp/git-store.git"},"bugs":{"url":"https://github.com/david1gp/git-store/issues"},"types":"./dist/index.d.ts","imports":{"#result":"@adaptive-ds/result"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./*.js":{"types":"./dist/*.d.ts","import":"./dist/*.js"}},"_id":"@adaptive-ds/git-store@0.1.0","_nodeVersion":"26.5.1","_npmVersion":"11.17.0","dist":{"integrity":"sha512-5VW7BuRBjNYI/4cGceySen63G0dlHkxRwJBlcxEbJi5nNLRSQ0SGqTHfTmgcY7ErXRyt+R3ar/51+c7tc1H4Zg==","shasum":"8cef4f4efb730655e6a3ac6d703d469ac27d9656","tarball":"https://registry.npmjs.org/@adaptive-ds/git-store/-/git-store-0.1.0.tgz","fileCount":55,"unpackedSize":39968,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGm6EX6Uw5Ht3SL0Q8EGaY3db/1egkYpIp1bXz1v1qbDAiEAwnjg69CiwQxWCiuDTBkiovwhyTZvJWJ90SUMnD6gXLk="}]},"_npmUser":{"name":"david1gp","email":"david1gruppenplan@gmail.com"},"directories":{},"maintainers":[{"name":"david1gp","email":"david1gruppenplan@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/git-store_0.1.0_1785496861309_0.6350166848678205"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-31T11:21:01.098Z","0.1.0":"2026-07-31T11:21:01.474Z","modified":"2026-07-31T11:21:01.729Z"},"maintainers":[{"name":"david1gp","email":"david1gruppenplan@gmail.com"}],"description":"Git-tracked JSON file storage: every create/edit/delete is committed and optionally pushed.","homepage":"https://github.com/david1gp/git-store","keywords":["typescript","git","json","storage","version-control"],"repository":{"type":"git","url":"git+https://github.com/david1gp/git-store.git"},"bugs":{"url":"https://github.com/david1gp/git-store/issues"},"license":"MIT","readme":"# @adaptive-ds/git-store\n\nGit-tracked JSON file storage: every create/edit/delete is committed, and optionally pushed.\n\n## Why\n\nSometimes you want a small amount of structured data (config, project definitions, records) to be **auditable and revertible** without running a database. A git repo already gives you that: history, diffs, blame, revert, and a remote as an off-machine backup.\n\nThis library is the thin layer that makes a directory of JSON files behave like a store:\n\n- **Every write is a commit.** No separate \"save\" and \"commit\" step, so history can never drift from the files on disk.\n- **Validated reads.** Files are parsed and checked against a valibot schema, so corrupt or hand-edited data surfaces as an error instead of a runtime surprise.\n- **Path traversal is rejected.** Relative paths are checked before touching the filesystem, so a caller-supplied name like `../../outside.json` cannot escape the store.\n- **No shell injection.** Git runs via `Bun.spawn` with an argv array — never string interpolation into a shell.\n- **Never throws.** Every fallible function returns a `Result` from `@adaptive-ds/result`.\n\n## Install\n\n```bash\nbun add @adaptive-ds/git-store @adaptive-ds/result valibot\n```\n\n## Usage\n\n```ts\nimport * as a from \"valibot\"\nimport { gitStoreOpen, gitStoreWrite, gitStoreRead, gitStoreList, gitStoreHistory } from \"@adaptive-ds/git-store\"\n\nconst opened = await gitStoreOpen({\n  dir: \"/var/lib/my-store\",\n  autoPush: false,\n  branch: \"main\",\n  authorName: \"my-app\",\n  authorEmail: \"my-app@example.com\",\n})\nif (!opened.success) return opened\nconst store = opened.data\n\nawait gitStoreWrite(store, \"items/hello.json\", { hi: true }, \"add hello\")\n\nconst itemSchema = a.object({ hi: a.boolean() })\nconst read = await gitStoreRead(store, \"items/hello.json\", itemSchema)\nif (read.success) console.log(read.data.hi)\n\nconst files = await gitStoreList(store, \"items\")\nconst log = await gitStoreHistory(store, \"items/hello.json\", 10)\n```\n\n`gitStoreOpen` creates the directory and runs `git init` if the path is not a repo yet, so a fresh install needs no setup.\n\n## API\n\n| function | returns | notes |\n| --- | --- | --- |\n| `gitStoreOpen(options)` | `GitStore` | mkdir + `git init` if needed; sets local author config |\n| `gitStoreWrite(store, relPath, data, message)` | `string` | writes pretty JSON, `git add`, commit; returns sha |\n| `gitStoreRead(store, relPath, schema)` | `T` | reads, parses, validates with valibot |\n| `gitStoreDelete(store, relPath, message)` | `string` | `git rm` + commit; returns sha |\n| `gitStoreList(store, subDir?)` | `string[]` | recursive `.json` paths, sorted, `.git` excluded |\n| `gitStoreCommit(store, message)` | `string` | commits pending changes; `\"\"` if nothing to commit |\n| `gitStoreHistory(store, relPath?, limit?)` | `GitStoreCommitInfo[]` | `{ sha, date, author, message }` |\n| `gitStorePathIsSafe(relPath)` | `string` | rejects absolute paths, `..` segments, null bytes |\n| `gitStoreRun(store, args)` | `string` | escape hatch: run arbitrary git argv in the store |\n\nSet `autoPush: true` to `git push origin <branch>` after each commit; a failing push is returned as an error.\n\n## Result\n\nNothing throws. Fallible functions return `Result<T>` / `PromiseResult<T>`:\n\n```ts\nconst r = await gitStoreWrite(store, \"a.json\", data, \"msg\")\nif (!r.success) console.error(`${r.op}: ${r.errorMessage}`)\n```\n\n## Dev\n\n```bash\nbun test\n```\n","readmeFilename":"README.md","_rev":"1-e681ab12e84a96290836123348d3e48e"}