{
  "content": "# @nan0web/db-browser\n\nBrowser Database client as extension of @nan0web/db\n\n> 🇬🇧 [English](./README.md) | 🇺🇦 [Українська](./docs/uk/README.md)\n\n<!-- %PACKAGE_STATUS% -->\n\n## Description\n\nThe `@nan0web/db-browser` package provides a database interface for browser environments,\nextending the base `@nan0web/db` functionality with HTTP-based document operations.\nCore class:\n\n- `DBBrowser` — extends DB with browser-specific features like remote fetching and saving\n  via standard HTTP methods (GET, POST, PUT, DELETE).\n\n**v1.1.0** — UDA 2.0 Integration: fallback chain, change events, proactive `.json` extension.\n\nThis package is ideal for building browser-based applications that require remote data\nfetching with support for inheritance, references, and directory indexing.\n\n## Installation\nPrerequsites: `npm install @nan0web/db-browser`\n\nHow to install with npm?\n```bash\nnpm install @nan0web/db-browser\n```\n\nHow to install with pnpm?\n```bash\npnpm add @nan0web/db-browser\n```\n\nHow to install with yarn?\n```bash\nyarn add @nan0web/db-browser\n```\n\n### Fetching Documents\n\nDBBrowser supports fetching documents from remote servers with full URI resolution.\n\nHow to fetch a document?\n```js\nimport DBBrowser from \"@nan0web/db-browser\"\nconst db = new DBBrowser({\n\thost: 'https://api.example.com',\n\troot: '/data/',\n})\nconst users = await db.fetch('users.json')\nconsole.info(users)\n// [\n//   {\"email\":\"alice@example.com\",\"id\":1,\"name\":\"Alice\"},\n//   {\"email\":\"bob@example.com\",\"id\":2,\"name\":\"Bob\"},\n// ]\n```\n### Saving Documents\n\nUse POST requests to save new documents.\nThe server side must provide such API.\n\nHow to save a new document?\n```js\nimport DBBrowser from \"@nan0web/db-browser\"\nconst db = new DBBrowser({\n\thost: 'https://api.example.com',\n\troot: '/data/',\n})\nconst result = await db.saveDocument('new-file.json', { test: 'value' })\nconsole.info('Save result:', result) // ← Save result: true\n```\n### Writing Documents\n\nUse PUT requests to update or overwrite existing documents.\n\nHow to write (update) a document?\n```js\nimport DBBrowser from \"@nan0web/db-browser\"\nconst db = new DBBrowser({\n\thost: 'https://api.example.com',\n\troot: '/data/',\n})\nconst data = [\n\t{ id: 1, name: 'Alice Cooper', email: 'alice@example.com' },\n\t{ id: 2, name: 'Bob Marley', email: 'bob@example.com' },\n\t{ id: 3, name: 'Charlie Brown', email: 'charlie@example.com' },\n]\nconst result = await db.writeDocument('users.json', data)\nconsole.info('Write result:', result) // ← Write result: { written: true }\n```\n### Dropping Documents\n\nUse DELETE requests to remove documents.\n\nHow to drop a document?\n```js\nimport DBBrowser from \"@nan0web/db-browser\"\nconst db = new DBBrowser({\n\thost: 'https://api.example.com',\n\troot: '/data/',\n})\nconst result = await db.dropDocument('new-file.json')\nconsole.info('Drop result:', result) // ← Drop result: true\n```\n### Directory Reading\n\nDBBrowser supports reading directories and resolving relative paths.\n\nHow to read directory contents?\n```js\nimport DBBrowser from \"@nan0web/db-browser\"\nconst db = new DBBrowser({\n\thost: 'https://api.example.com',\n\troot: '/data/',\n})\nconst entries = []\nfor await (const entry of db.readDir('.')) {\n\tentries.push(entry.name)\n}\nconsole.info('Directory entries:', entries)\n// Directory entries: [\"users.json\", \"posts/first.json\"]\n```\n### Search Documents\n\nSupports glob-style searching within remote structures.\n\nHow to search for documents?\n```js\nimport DBBrowser from \"@nan0web/db-browser\"\nconst db = new DBBrowser({\n\thost: 'https://api.example.com',\n\troot: '/data/',\n})\nconst entries = []\nfor await (const uri of db.find((uri) => uri.endsWith('.json'))) {\n\tentries.push(uri)\n}\nconsole.info('Found JSON files:', entries)\n// Found JSON files: [\"/data/users.json\", \"/data/posts/first.json\"]\n```\n### Extract Subset\n\nCreate a new DBBrowser instance rooted at a specific subdirectory.\n\nHow to extract a subset of the database?\n```js\nimport DBBrowser from \"@nan0web/db-browser\"\nconst db = new DBBrowser({\n\thost: 'https://api.example.com',\n\troot: '/data/',\n})\nconst subDB = db.extract('posts/')\nconsole.info('Subset cwd:', subDB.cwd) // ← Subset root: data/posts/\nconsole.info('Subset root:', subDB.root) // ← Subset root: data/posts/\nconsole.info('Subset instanceof DBBrowser:', subDB instanceof DBBrowser)\n// Subset instanceof DBBrowser: true\n```\n### Fallback Chain (UDA 2.0)\n\nAttach a secondary database as a fallback source.\nWhen a document is not found in the primary DB, the fallback is queried automatically.\n\nHow to use fallback chain?\n```js\nimport DBBrowser from \"@nan0web/db-browser\"\nconst primary = new DBBrowser({\n\thost: 'https://api.example.com',\n\troot: '/data/',\n})\nconst fallback = new DBBrowser({\n\thost: 'https://api.example.com',\n\troot: '/data/',\n})\nprimary.attach(fallback)\nconst users = await primary.fetch('users.json')\nconsole.info('Fetched via chain:', users)\n// Fetched via chain: [{...}, {...}]\n```\n### Change Events (UDA 2.0)\n\nListen for document changes on save and drop operations.\n\nHow to listen for change events?\n```js\nimport DBBrowser from \"@nan0web/db-browser\"\nconst db = new DBBrowser({\n\thost: 'https://api.example.com',\n\troot: '/data/',\n})\nconst events = []\ndb.on('change', (event) => events.push(event))\nawait db.saveDocument('new-file.json', { test: 'value' })\nawait db.dropDocument('new-file.json')\nconsole.info('Events:', events.length) // ← Events: 2\n```\n## API\n\n### DBBrowser\n\nExtends `@nan0web/db`.\n\n* **Static Properties**\n  * `FetchFn` – Static fetch function used globally unless overridden.\n\n* **Instance Properties**\n  * `host` – Base URL host.\n  * `timeout` – Default timeout for requests (ms).\n  * `fetchFn` – Per-instance fetch handler.\n\n* **Methods**\n  * `ensureAccess(uri, level)` – Validates access mode for a URI.\n  * `fetchRemote(uri, requestInit)` – Performs remote fetch with timeout handling.\n  * `_fetchPrimary(uri)` – Primary fetch logic (v1.1.0: renamed from `fetch()`).\n  * `load()` – Loads the root index.\n  * `statDocument(uri)` – Fetches metadata via HEAD request.\n  * `loadDocument(uri, defaultValue)` – Fetches and parses a document (JSON + text).\n  * `saveDocument(uri, document)` – Saves a new file using POST. Emits `change` event.\n  * `writeDocument(uri, document)` – Updates/overwrites file using PUT.\n  * `dropDocument(uri)` – Deletes a file using DELETE. Emits `change` event.\n  * `extract(uri)` – Creates a new DB subset rooted at the URI.\n  * `readDir(uri)` – Reads directory contents with index loading support.\n  * `attach(db)` – Attaches a fallback database (UDA 2.0).\n  * `on('change', fn)` – Subscribes to document change events (UDA 2.0).\n  * `static from(input)` – Instantiates or returns existing DBBrowser instance.\n\nAll exported classes should pass basic test to ensure API examples work\n\n## Java•Script\n\nUses `d.ts` files for autocompletion\n\n## CLI Playground\n\nHow to run DBBrowser demo?\n```bash\ngit clone https://github.com/nan0web/db-browser.git\ncd db-browser\nnpm install\nnpm run play\n```\n\n## Contributing\n\nHow to contribute? - [check here](./CONTRIBUTING.md)\n\n## License\n\nHow to check license ISC? - [check here](./LICENSE)\n"
}