{"_id":"@aginix/vulcan-data-provider","_rev":"2-736de09292861529dc2518268fb6e133","name":"@aginix/vulcan-data-provider","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@aginix/vulcan-data-provider","version":"0.1.0","keywords":["react-admin","data-provider","adonisjs","adonis","vulcan","postgrest","rest","api"],"author":{"name":"n3n"},"license":"UNLICENSED","_id":"@aginix/vulcan-data-provider@0.1.0","maintainers":[{"name":"n3n","email":"nonpawit.tee@gmail.com"}],"c8":{"exclude":["tests/**"],"reporter":["text","html"]},"dist":{"shasum":"3eaacab8ca7339f98791ab6789a439a954e38d34","tarball":"https://registry.npmjs.org/@aginix/vulcan-data-provider/-/vulcan-data-provider-0.1.0.tgz","fileCount":10,"integrity":"sha512-cP+ppGoWPtNS90IExWpvXXXWug88c1sqfpfnHYZzb5RuwivPFSGhsm77gXeSnAT1I/jaZ93zv32V2baOVq4QnQ==","signatures":[{"sig":"MEUCIEx9+AalgwwVM2BIpfBPu8vNOpE74pbvMcR9wEcPqVpmAiEAsgPqgWojyuGoGJZDBfuhe6M4oDrV7is0OVzpgvEJuCs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":34481},"main":"build/index.js","type":"module","types":"build/index.d.ts","tsdown":{"dts":false,"clean":true,"entry":["./index.ts","./src/types.ts","./src/url_builder.ts","./src/data_provider.ts"],"format":"esm","minify":"dce-only","outDir":"./build","target":"esnext","external":["ra-core","react-admin","qs","dequal"],"treeshake":false,"sourcemaps":false,"fixedExtension":false},"engines":{"node":">=24.0.0"},"exports":{".":{"types":"./build/index.d.ts","default":"./build/index.js"},"./types":{"types":"./build/src/types.d.ts","default":"./build/src/types.js"},"./url_builder":{"types":"./build/src/url_builder.d.ts","default":"./build/src/url_builder.js"}},"scripts":{"lint":"eslint .","test":"c8 npm run quick:test","build":"npm run compile","format":"prettier --write .","compile":"tsdown && tsc --emitDeclarationOnly --declaration","pretest":"npm run lint","release":"release-it","version":"npm run build","typecheck":"tsc --noEmit","precompile":"npm run lint","quick:test":"node --import=@poppinss/ts-exec --enable-source-maps bin/test.ts","prepublishOnly":"npm run build"},"_npmUser":{"name":"n3n","email":"nonpawit.tee@gmail.com"},"prettier":"@adonisjs/prettier-config","release-it":{"git":{"push":true,"tagName":"vulcan-data-provider-v${version}","commitMessage":"chore(vulcan-data-provider): release ${version}","tagAnnotation":"vulcan-data-provider-v${version}","requireUpstream":true,"requireCleanWorkingDir":true},"npm":{"publish":true,"skipChecks":true},"github":{"release":true,"releaseName":"@aginix/vulcan-data-provider ${version}"},"plugins":{"@release-it/conventional-changelog":{"preset":{"name":"angular"}}}},"_npmVersion":"11.8.0","description":"React Admin data provider for APIs built with @aginix/adonis-vulcan","directories":{},"_nodeVersion":"24.13.1","dependencies":{"qs":"^6.14.0","dequal":"^2.0.3"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"c8":"^11.0.0","eslint":"^10.0.3","tsdown":"^0.21.0","ra-core":"^5.0.0","prettier":"^3.8.1","@types/qs":"^6.9.18","release-it":"^19.2.4","typescript":"^5.9.3","@types/node":"^25.3.5","react-admin":"^5.0.0","@japa/assert":"^4.2.0","@japa/runner":"^5.3.0","@poppinss/ts-exec":"^1.4.4","@adonisjs/tsconfig":"^2.0.0","@adonisjs/eslint-config":"^3.0.0","@adonisjs/prettier-config":"^1.4.5","@release-it/conventional-changelog":"^10.0.5"},"peerDependencies":{"ra-core":"^5.0.0","react-admin":"^5.0.0"},"peerDependenciesMeta":{"react-admin":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/vulcan-data-provider_0.1.0_1778438086307_0.7523623216847175","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@aginix/vulcan-data-provider","description":"React Admin data provider for APIs built with @aginix/adonis-vulcan","version":"0.1.1","engines":{"node":">=24.0.0"},"type":"module","main":"build/index.js","types":"build/index.d.ts","exports":{".":{"types":"./build/index.d.ts","default":"./build/index.js"},"./url_builder":{"types":"./build/src/url_builder.d.ts","default":"./build/src/url_builder.js"},"./types":{"types":"./build/src/types.d.ts","default":"./build/src/types.js"}},"scripts":{"typecheck":"tsc --noEmit","lint":"eslint .","format":"prettier --write .","quick:test":"node --import=@poppinss/ts-exec --enable-source-maps bin/test.ts","pretest":"npm run lint","test":"c8 npm run quick:test","precompile":"npm run lint","compile":"tsdown && tsc --emitDeclarationOnly --declaration","build":"npm run compile","release":"release-it","version":"npm run build","prepublishOnly":"npm run build"},"keywords":["react-admin","data-provider","adonisjs","adonis","vulcan","postgrest","rest","api"],"author":{"name":"n3n"},"license":"UNLICENSED","dependencies":{"dequal":"^2.0.3"},"devDependencies":{"@adonisjs/eslint-config":"^3.0.0","@adonisjs/prettier-config":"^1.4.5","@adonisjs/tsconfig":"^2.0.0","@japa/assert":"^4.2.0","@japa/runner":"^5.3.0","@poppinss/ts-exec":"^1.4.4","@release-it/conventional-changelog":"^10.0.5","@types/node":"^25.3.5","c8":"^11.0.0","eslint":"^10.0.3","prettier":"^3.8.1","ra-core":"^5.0.0","react-admin":"^5.0.0","release-it":"^19.2.4","tsdown":"^0.21.0","typescript":"^5.9.3"},"peerDependencies":{"ra-core":"^5.0.0","react-admin":"^5.0.0"},"peerDependenciesMeta":{"react-admin":{"optional":true}},"publishConfig":{"access":"public"},"tsdown":{"entry":["./index.ts","./src/types.ts","./src/url_builder.ts","./src/data_provider.ts"],"outDir":"./build","clean":true,"format":"esm","minify":"dce-only","fixedExtension":false,"dts":false,"treeshake":false,"sourcemaps":false,"target":"esnext","external":["ra-core","react-admin","dequal"]},"release-it":{"git":{"requireCleanWorkingDir":true,"requireUpstream":true,"commitMessage":"chore(vulcan-data-provider): release ${version}","tagAnnotation":"vulcan-data-provider-v${version}","push":true,"tagName":"vulcan-data-provider-v${version}"},"github":{"release":true,"releaseName":"@aginix/vulcan-data-provider ${version}"},"npm":{"publish":true,"skipChecks":true},"plugins":{"@release-it/conventional-changelog":{"preset":{"name":"angular"}}}},"c8":{"reporter":["text","html"],"exclude":["tests/**"]},"prettier":"@adonisjs/prettier-config","gitHead":"67596b7341ef3e0a9eb009880138802e30e77365","_id":"@aginix/vulcan-data-provider@0.1.1","_nodeVersion":"24.13.1","_npmVersion":"11.8.0","dist":{"integrity":"sha512-iu1/fGELoxqW+6dQ7ZjYj9cuS3UafxtTMtsIKUJXJwtyUlB44tT/SFSXaCsBeyRhpbAU9ttqR7RqperLWzyZkA==","shasum":"b4b6981ad1c2540ecb6863b69a0094d625f69ca3","tarball":"https://registry.npmjs.org/@aginix/vulcan-data-provider/-/vulcan-data-provider-0.1.1.tgz","fileCount":10,"unpackedSize":36904,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAw/lWTim+/Dmsr0myMkTQ8Pq5CCGSuZ/6VkrkFDbSl5AiBeXzZlAF6LDmQ8ov+KI3D3IXaXqJNaWmVEPKuGhOZsOw=="}]},"_npmUser":{"name":"n3n","email":"nonpawit.tee@gmail.com"},"directories":{},"maintainers":[{"name":"n3n","email":"nonpawit.tee@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/vulcan-data-provider_0.1.1_1783406452321_0.20662947862757708"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-10T18:34:46.247Z","modified":"2026-07-07T06:40:52.584Z","0.1.0":"2026-05-10T18:34:46.450Z","0.1.1":"2026-07-07T06:40:52.454Z"},"author":{"name":"n3n"},"license":"UNLICENSED","keywords":["react-admin","data-provider","adonisjs","adonis","vulcan","postgrest","rest","api"],"description":"React Admin data provider for APIs built with @aginix/adonis-vulcan","maintainers":[{"name":"n3n","email":"nonpawit.tee@gmail.com"}],"readme":"# @aginix/vulcan-data-provider\n\n[React Admin](https://marmelab.com/react-admin/) data provider for APIs built\nwith [`@aginix/adonis-vulcan`](../adonis-vulcan)'s `BaseResourceController`.\n\nIt speaks the same PostgREST-style filter grammar that `BaseResourceController`\nparses on the server side (`?status=eq.active&age=gte.18`), so any controller\nthat `extends BaseResourceController` is wired up automatically.\n\n## Install\n\n```sh\npnpm add @aginix/vulcan-data-provider react-admin\n```\n\n`react-admin` (or `ra-core`) is a peer dependency.\n\n## Usage\n\n```tsx\nimport { Admin, Resource, fetchUtils } from 'react-admin'\nimport { vulcanDataProvider } from '@aginix/vulcan-data-provider'\n\nimport { PostList, PostEdit, PostCreate } from './posts'\n\nconst dataProvider = vulcanDataProvider({\n  apiUrl: '/api',\n  httpClient: fetchUtils.fetchJson,\n})\n\nexport const App = () => (\n  <Admin dataProvider={dataProvider}>\n    <Resource name=\"posts\" list={PostList} edit={PostEdit} create={PostCreate} />\n  </Admin>\n)\n```\n\n## How it maps to the API\n\n| react-admin call    | HTTP method + URL                                   |\n| ------------------- | --------------------------------------------------- |\n| `getList`           | `GET /<resource>?page=&perPage=&order=&<filters>`   |\n| `getOne`            | `GET /<resource>/<id>`                              |\n| `getMany`           | `GET /<resource>?id=in.(...)&page=1&perPage=<n>`    |\n| `getManyReference`  | `GET /<resource>?<target>=eq.<id>&...`              |\n| `create`            | `POST /<resource>`                                  |\n| `update`            | `PUT /<resource>/<id>` (only changed fields)        |\n| `updateMany`        | `PUT /<resource>/<id>` looped (no batch endpoint)   |\n| `delete`            | `DELETE /<resource>/<id>`                           |\n| `deleteMany`        | `DELETE /<resource>/<id>` looped                    |\n\nResponse envelope (matches `ResourceSerializer` / Lucid pagination):\n\n```jsonc\n// list\n{ \"data\": [...], \"metadata\": { \"total\": 99, \"perPage\": 25, \"currentPage\": 1, ... } }\n\n// single\n{ \"data\": { ... } }\n\n// destroy → 204 No Content\n```\n\n## Filter grammar\n\nThe data provider reads react-admin's `filter` object and emits\nPostgREST-flavored query strings that `@aginix/adonis-vulcan`'s `FilterParser`\nunderstands.\n\n| Filter shape                                      | URL fragment                              |\n| ------------------------------------------------- | ----------------------------------------- |\n| `{ status: 'active' }`                            | `status=eq.active`                        |\n| `{ 'age@gt': 18 }`                                | `age=gt.18`                               |\n| `{ 'name@like': 'foo bar' }`                      | `name=like.*foo*&name=like.*bar*`         |\n| `{ tags: ['admin', 'user'] }`                     | `tags=in.(admin,user)`                    |\n| `{ q: 'search' }`                                 | `q=search` (no operator)                  |\n| `{ faculty: { name: 'CS' } }`                     | `faculty.name=eq.CS` (embedded filter)    |\n| `{ 'curriculums.exists': 'true' }`                | `curriculums.exists=true` (special key)   |\n\nSet `defaultListOp` on the config to change the implicit operator from `eq` to\nsomething else (e.g. `'ilike'` for free-text fields).\n\n## Compound primary keys\n\nFor resources whose primary key is more than one column, register the column\nlist when constructing the provider:\n\n```ts\nimport { vulcanDataProvider, defaultPrimaryKeys } from '@aginix/vulcan-data-provider'\n\ndefaultPrimaryKeys.set('enrollments', ['student_id', 'course_id'])\n\nconst dataProvider = vulcanDataProvider({\n  apiUrl: '/api',\n  httpClient: fetchUtils.fetchJson,\n  primaryKeys: defaultPrimaryKeys,\n})\n```\n\nThe provider then synthesizes a virtual `id` (a JSON-encoded array of the key\nparts) so react-admin's record-by-id flow keeps working transparently.\n\n## Configuration\n\n```ts\ntype VulcanDataProviderConfig = {\n  apiUrl: string\n  httpClient: (url: string, options?: any) => Promise<{ status, headers, body, json }>\n  defaultListOp?: VulcanOperator           // default: 'eq'\n  sortOrder?: VulcanSortOrder              // default: ASC nullsLast / DESC nullsFirst\n  primaryKeys?: Map<string, readonly string[]>  // default: ['id'] for every resource\n  pageParam?: string                       // default: 'page'\n  perPageParam?: string                    // default: 'perPage'\n}\n```\n","readmeFilename":"README.md"}