{"_id":"@dudousxd/nestjs-authz-inertia","_rev":"4-8faaba6d77b9cd8b33fbae6482603647","name":"@dudousxd/nestjs-authz-inertia","dist-tags":{"latest":"0.1.3"},"versions":{"0.1.0":{"name":"@dudousxd/nestjs-authz-inertia","version":"0.1.0","keywords":["nestjs","authorization","authz","inertia","inertia.js","abilities","can"],"author":{"name":"Davi Carvalho","email":"davi@goflip.ai"},"license":"MIT","_id":"@dudousxd/nestjs-authz-inertia@0.1.0","maintainers":[{"name":"dudousxd","email":"davi_carvalho96@hotmail.com"}],"homepage":"https://github.com/DavideCarvalho/nestjs-authz#readme","bugs":{"url":"https://github.com/DavideCarvalho/nestjs-authz/issues"},"dist":{"shasum":"908a17d07137b15e4f4d99ce84b16f45632fcff3","tarball":"https://registry.npmjs.org/@dudousxd/nestjs-authz-inertia/-/nestjs-authz-inertia-0.1.0.tgz","fileCount":44,"integrity":"sha512-KKT4mjAo97I7IlqkQW/m+1vJSBgI7O6FEFGLHUgs3+nlSysUCWK4jhrjt/oVnRszYo21SbsAKquOV+CxpDE1oQ==","signatures":[{"sig":"MEUCID1tA8frgRmqHI3/Xg2gXmP//nZwFgsKXocYW3eVwWCkAiEA6Gjo4lkTVxUCetLhceWF6vLQF8xGcixEOn8LRlABH1A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dudousxd%2fnestjs-authz-inertia@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":62422},"main":"./dist/index.js","type":"module","_from":"file:dudousxd-nestjs-authz-inertia-0.1.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js","default":"./dist/client.js"}},"scripts":{"test":"vitest run --passWithNoTests","build":"tsc -p tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit","test:watch":"vitest"},"_npmUser":{"name":"dudousxd","email":"davi_carvalho96@hotmail.com"},"_resolved":"/tmp/b576e27d316eca6e8658c6d3cf929472/dudousxd-nestjs-authz-inertia-0.1.0.tgz","_integrity":"sha512-KKT4mjAo97I7IlqkQW/m+1vJSBgI7O6FEFGLHUgs3+nlSysUCWK4jhrjt/oVnRszYo21SbsAKquOV+CxpDE1oQ==","repository":{"url":"git+https://github.com/DavideCarvalho/nestjs-authz.git","type":"git","directory":"packages/inertia"},"_npmVersion":"10.8.2","description":"Inertia.js integration for @dudousxd/nestjs-authz — share a user's abilities as props so client `can()` checks need no network request.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@dudousxd/nestjs-authz-client":"^0.1.0"},"_hasShrinkwrap":false,"devDependencies":{"rxjs":"^7.8.1","vitest":"^3.0.0","typescript":"^5.4.0","@types/node":"^20.0.0","@nestjs/core":"^11.0.0","@nestjs/common":"^11.0.0","@nestjs/testing":"^11.0.0","reflect-metadata":"^0.2.2","@dudousxd/nestjs-authz":"^0.3.0","@dudousxd/nestjs-inertia":"^1.5.0"},"peerDependencies":{"@nestjs/core":">=10.0.0","@nestjs/common":">=10.0.0","reflect-metadata":">=0.1.13","@dudousxd/nestjs-authz":">=0.2.0","@dudousxd/nestjs-context":">=0.1.0","@dudousxd/nestjs-inertia":">=1.0.0"},"peerDependenciesMeta":{"@dudousxd/nestjs-context":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nestjs-authz-inertia_0.1.0_1781704713204_0.4444581869039037","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@dudousxd/nestjs-authz-inertia","version":"0.1.1","keywords":["nestjs","authorization","authz","inertia","inertia.js","abilities","can"],"author":{"name":"Davi Carvalho","email":"davi@goflip.ai"},"license":"MIT","_id":"@dudousxd/nestjs-authz-inertia@0.1.1","maintainers":[{"name":"dudousxd","email":"davi_carvalho96@hotmail.com"}],"homepage":"https://github.com/DavideCarvalho/nestjs-authz#readme","bugs":{"url":"https://github.com/DavideCarvalho/nestjs-authz/issues"},"dist":{"shasum":"636625541d64a6b3c19ff332fb07923e13106776","tarball":"https://registry.npmjs.org/@dudousxd/nestjs-authz-inertia/-/nestjs-authz-inertia-0.1.1.tgz","fileCount":44,"integrity":"sha512-MiUdbvRJDPnl49drS+jtnolcIfGwo4kLomoqkKvZMWMHI+MqcK5gyDPd7a8FzUwBAZ5mWvh73C2PutFyak+J9A==","signatures":[{"sig":"MEUCIGjZCemxhoqgeXv0augvuh81q6d4e1O8nBFL5mIkj0RZAiEAxiXrLee2K0EwcYMS5wQWp5slM0UsKSrpWSoBopqIJsI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dudousxd%2fnestjs-authz-inertia@0.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":63129},"main":"./dist/index.js","type":"module","_from":"file:dudousxd-nestjs-authz-inertia-0.1.1.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js","default":"./dist/client.js"}},"scripts":{"test":"vitest run --passWithNoTests","build":"tsc -p tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit","test:watch":"vitest"},"_npmUser":{"name":"dudousxd","email":"davi_carvalho96@hotmail.com"},"_resolved":"/tmp/3747a42435f7d2f5560f636edd1ebc4e/dudousxd-nestjs-authz-inertia-0.1.1.tgz","_integrity":"sha512-MiUdbvRJDPnl49drS+jtnolcIfGwo4kLomoqkKvZMWMHI+MqcK5gyDPd7a8FzUwBAZ5mWvh73C2PutFyak+J9A==","repository":{"url":"git+https://github.com/DavideCarvalho/nestjs-authz.git","type":"git","directory":"packages/inertia"},"_npmVersion":"10.8.2","description":"Inertia.js integration for @dudousxd/nestjs-authz — share a user's abilities as props so client `can()` checks need no network request.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@dudousxd/nestjs-authz-client":"^0.2.0"},"_hasShrinkwrap":false,"devDependencies":{"rxjs":"^7.8.1","vitest":"^3.0.0","typescript":"^5.4.0","@types/node":"^20.0.0","@nestjs/core":"^11.0.0","@nestjs/common":"^11.0.0","@nestjs/testing":"^11.0.0","reflect-metadata":"^0.2.2","@dudousxd/nestjs-authz":"^0.6.0","@dudousxd/nestjs-inertia":"^1.5.0"},"peerDependencies":{"@nestjs/core":">=10.0.0","@nestjs/common":">=10.0.0","reflect-metadata":">=0.1.13","@dudousxd/nestjs-authz":">=0.2.0","@dudousxd/nestjs-context":">=0.1.0","@dudousxd/nestjs-inertia":">=1.0.0"},"peerDependenciesMeta":{"@dudousxd/nestjs-context":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nestjs-authz-inertia_0.1.1_1781797247027_0.8402965171844325","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@dudousxd/nestjs-authz-inertia","version":"0.1.2","keywords":["nestjs","authorization","authz","inertia","inertia.js","abilities","can"],"author":{"name":"Davi Carvalho","email":"davi@goflip.ai"},"license":"MIT","_id":"@dudousxd/nestjs-authz-inertia@0.1.2","maintainers":[{"name":"dudousxd","email":"davi_carvalho96@hotmail.com"}],"homepage":"https://github.com/DavideCarvalho/nestjs-authz#readme","bugs":{"url":"https://github.com/DavideCarvalho/nestjs-authz/issues"},"dist":{"shasum":"1016e9543201323ef0dd428f328f5d850c3b66d8","tarball":"https://registry.npmjs.org/@dudousxd/nestjs-authz-inertia/-/nestjs-authz-inertia-0.1.2.tgz","fileCount":44,"integrity":"sha512-aqtavt0nzu6ZHe4jLafOVQ2kuV/uIKM71Ow9ylFfYZ3q2c86lVsoXs1ealESABv2ADByF5efcm4mcgXeizwFpw==","signatures":[{"sig":"MEQCIA6m986MbXGW0Cni3uePeWq3IoemhRAEKHRtdruPNCUKAiArGZHXoo9bhJ7jtXlBSOkAx5M0kHDxlsNAPZH7MQiExQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dudousxd%2fnestjs-authz-inertia@0.1.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":64092},"main":"./dist/index.js","type":"module","_from":"file:dudousxd-nestjs-authz-inertia-0.1.2.tgz","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js","default":"./dist/client.js"}},"scripts":{"test":"vitest run --passWithNoTests","build":"tsc -p tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit","test:watch":"vitest"},"_npmUser":{"name":"dudousxd","email":"davi_carvalho96@hotmail.com"},"_resolved":"/tmp/feb1d9beac23dbfe030468f43c8b3cb3/dudousxd-nestjs-authz-inertia-0.1.2.tgz","_integrity":"sha512-aqtavt0nzu6ZHe4jLafOVQ2kuV/uIKM71Ow9ylFfYZ3q2c86lVsoXs1ealESABv2ADByF5efcm4mcgXeizwFpw==","repository":{"url":"git+https://github.com/DavideCarvalho/nestjs-authz.git","type":"git","directory":"packages/inertia"},"_npmVersion":"10.8.2","description":"Inertia.js integration for @dudousxd/nestjs-authz — share a user's abilities as props so client `can()` checks need no network request.","directories":{},"_nodeVersion":"20.20.2","dependencies":{"@dudousxd/nestjs-authz-client":"^0.2.1"},"_hasShrinkwrap":false,"devDependencies":{"rxjs":"^7.8.1","vitest":"^3.0.0","typescript":"^5.4.0","@types/node":"^20.0.0","@nestjs/core":"^11.0.0","@nestjs/common":"^11.0.0","@nestjs/testing":"^11.0.0","reflect-metadata":"^0.2.2","@dudousxd/nestjs-authz":"^0.6.4","@dudousxd/nestjs-inertia":"^1.5.0"},"peerDependencies":{"@nestjs/core":">=10.0.0","@nestjs/common":">=10.0.0","reflect-metadata":">=0.1.13","@dudousxd/nestjs-authz":">=0.2.0","@dudousxd/nestjs-context":">=0.1.0","@dudousxd/nestjs-inertia":">=1.0.0"},"peerDependenciesMeta":{"@dudousxd/nestjs-context":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nestjs-authz-inertia_0.1.2_1782475187002_0.20492914961542041","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"@dudousxd/nestjs-authz-inertia","version":"0.1.3","description":"Inertia.js integration for @dudousxd/nestjs-authz — share a user's abilities as props so client `can()` checks need no network request.","license":"MIT","repository":{"type":"git","url":"git+https://github.com/DavideCarvalho/nestjs-authz.git","directory":"packages/inertia"},"author":{"name":"Davi Carvalho","email":"davi@goflip.ai"},"type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./client":{"types":"./dist/client.d.ts","import":"./dist/client.js","default":"./dist/client.js"}},"dependencies":{"@dudousxd/nestjs-authz-client":"^0.2.1"},"peerDependencies":{"@dudousxd/nestjs-authz":">=0.2.0","@dudousxd/nestjs-context":">=0.1.0","@dudousxd/nestjs-inertia":">=1.0.0","@nestjs/common":">=10.0.0","@nestjs/core":">=10.0.0","reflect-metadata":">=0.1.13"},"peerDependenciesMeta":{"@dudousxd/nestjs-context":{"optional":true}},"devDependencies":{"@dudousxd/nestjs-inertia":"^1.5.0","@nestjs/common":"^12.0.1","@nestjs/core":"^12.0.1","@nestjs/testing":"^12.0.1","@types/node":"^20.0.0","reflect-metadata":"^0.2.2","rxjs":"^7.8.1","typescript":"^5.4.0","vitest":"^3.0.0","@dudousxd/nestjs-authz":"^0.6.5"},"engines":{"node":">=20"},"keywords":["nestjs","authorization","authz","inertia","inertia.js","abilities","can"],"scripts":{"build":"tsc -p tsconfig.json","test":"vitest run --passWithNoTests","test:watch":"vitest","typecheck":"tsc -p tsconfig.json --noEmit"},"_id":"@dudousxd/nestjs-authz-inertia@0.1.3","bugs":{"url":"https://github.com/DavideCarvalho/nestjs-authz/issues"},"homepage":"https://github.com/DavideCarvalho/nestjs-authz#readme","_integrity":"sha512-oBWj50STfLYgh1K6LBmcvdL6RSjoSEx8fZG70iyOyL7cF5C/mJ1FY++2yx0OBQN/WfXrMAJDUWpba7RCMIhYSQ==","_resolved":"/tmp/3c01fd491c153436e034b6979c17d199/dudousxd-nestjs-authz-inertia-0.1.3.tgz","_from":"file:dudousxd-nestjs-authz-inertia-0.1.3.tgz","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-oBWj50STfLYgh1K6LBmcvdL6RSjoSEx8fZG70iyOyL7cF5C/mJ1FY++2yx0OBQN/WfXrMAJDUWpba7RCMIhYSQ==","shasum":"c48b45124f7b78c019c07668a335aab67e4ee404","tarball":"https://registry.npmjs.org/@dudousxd/nestjs-authz-inertia/-/nestjs-authz-inertia-0.1.3.tgz","fileCount":44,"unpackedSize":64557,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@dudousxd%2fnestjs-authz-inertia@0.1.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCdIv9n6kcOFyYZM44yvNlW5+9urwAv/6uhimEbeuXdjwIhAMHgsZQ0WUf9uEFABuSlhRZrDVyfvsabKuZZn8DJlc3V"}]},"_npmUser":{"name":"dudousxd","email":"davi_carvalho96@hotmail.com"},"directories":{},"maintainers":[{"name":"dudousxd","email":"davi_carvalho96@hotmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nestjs-authz-inertia_0.1.3_1788017600082_0.018291383977941056"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-17T13:58:33.052Z","modified":"2026-08-29T15:33:20.535Z","0.1.0":"2026-06-17T13:58:33.350Z","0.1.1":"2026-06-18T15:40:47.216Z","0.1.2":"2026-06-26T11:59:47.128Z","0.1.3":"2026-08-29T15:33:20.223Z"},"bugs":{"url":"https://github.com/DavideCarvalho/nestjs-authz/issues"},"author":{"name":"Davi Carvalho","email":"davi@goflip.ai"},"license":"MIT","homepage":"https://github.com/DavideCarvalho/nestjs-authz#readme","keywords":["nestjs","authorization","authz","inertia","inertia.js","abilities","can"],"repository":{"type":"git","url":"git+https://github.com/DavideCarvalho/nestjs-authz.git","directory":"packages/inertia"},"description":"Inertia.js integration for @dudousxd/nestjs-authz — share a user's abilities as props so client `can()` checks need no network request.","maintainers":[{"name":"dudousxd","email":"davi_carvalho96@hotmail.com"}],"readme":"# @dudousxd/nestjs-authz-inertia\n\nInertia.js integration for [`@dudousxd/nestjs-authz`](../core). It makes client-side\n`can(...)` checks resolve **without a network request** by sharing the current\nuser's abilities as Inertia props — the Laravel/Inertia model.\n\n```bash\npnpm add @dudousxd/nestjs-authz-inertia\n# peers: @dudousxd/nestjs-authz, @dudousxd/nestjs-inertia\n#        (optional) @dudousxd/nestjs-context\n```\n\n## The 3-tier model — prefer props → resource map → endpoint fallback\n\nAuthorization decisions reach the front end through three tiers. Prefer the earlier\n(no-request) tiers; the endpoint is a last resort.\n\n### Tier 1 — Shared props (no request)\n\nEvery Inertia render carries the current user's **class-level abilities** (all ad-hoc\ngates + class-level `@Policy` methods like `create`/`viewAny`) under `props.auth.can`:\n\n```jsonc\n{ \"auth\": { \"can\": { \"post.create\": true, \"access-admin\": false } } }\n```\n\nTwo equivalent ways to wire it:\n\n**A. Module (auto, via `req.inertia.share`)** — register `AuthzInertiaModule`; a global\ninterceptor shares the map on every Inertia request:\n\n```ts\n@Module({\n  imports: [\n    AuthzModule.forRoot({ policies: [PostPolicy] }),\n    InertiaModule.forRoot({ /* ... */ }),\n    AuthzInertiaModule.forRoot(), // shares props.auth.can automatically\n  ],\n})\nexport class AppModule {}\n```\n\n**B. Share factory (explicit, via inertia's own seam)** — drop a factory into\n`InertiaModule.forRoot({ share })`:\n\n```ts\nInertiaModule.forRoot({\n  share: createAuthzShare(gate, policyRegistry),\n})\n```\n\nBoth resolve abilities by direct in-process `gate.allows(...)` calls — no HTTP round-trip.\nThe ability name defaults to `\"<resourceLower>.<method>\"` (e.g. `post.create`); pass\n`abilityNamer: (_, m) => m` for bare method names, or a custom `propKey`.\n\n### Tier 2 — Per-resource `can` map (no request)\n\nFor instance-specific decisions (`update`/`delete` of *this* post), serialize a `can`\nmap onto the resource in your controller:\n\n```ts\nconst post = await this.posts.find(id);\nconst can = await authorizeResource(this.gate, post, ['update', 'delete']);\nreturn this.inertia.render('Post/Show', { post: { ...post, can } });\n// → { post: { id, title, can: { update: true, delete: false } } }\n```\n\nOn the client, hydrate it into the store keyed by `type#id` so `can('update', post)`\nanswers synchronously. (`authorizeResourceForUser` checks an explicit user.)\n\n### Tier 3 — Fallback endpoint (request, last resort)\n\nFor abilities not hydrated on the client, enable the opt-in endpoint in **core**:\n\n```ts\nAuthzModule.forRoot({ canEndpoint: true }) // POST /authz/can → { allowed }\n// or a custom path: canEndpoint: 'api/authz/can'\n```\n\nIt runs `gate.allows(ability, resource?)` for the current context user and returns\n`{ allowed }`. Off by default. This is the path the codegen-emitted `can()` targets.\n\n> **Class-level by default; per-instance with a loader.** Out of the box the endpoint resolves\n> **class-level abilities and ad-hoc gates** only — the `{ type, id }` shim it receives never\n> matches a `@Policy` by constructor, so a **resource-bound** ability that misses the cache and\n> falls through to `/authz/can` will **deny**. To make per-instance decisions resolve at tier 3,\n> register `resourceLoaders` keyed by the resource `type`:\n>\n> ```ts\n> AuthzModule.forRoot({\n>   canEndpoint: true,\n>   resourceLoaders: { Post: (id) => postRepo.findOneBy({ id: Number(id) }) },\n> })\n> ```\n>\n> The endpoint then loads the real entity before authorizing, so the instance `@Policy` matches\n> and decides correctly (a loader returning nullish → deny / not found). Prefer hydrating via\n> tiers 1-2 (shared props / `authorizeResource`) when you can; use `resourceLoaders` for the\n> abilities that genuinely need a tier-3 round-trip.\n\n## Client store (framework-neutral)\n\n`@dudousxd/nestjs-authz-inertia/client` is a tiny in-memory store + resolver with no\nframework dependency — `-react` and the codegen client reuse it.\n\n```ts\nimport { AbilityStore, hydrateFromInertiaProps, hydrateResource, createCan } from '@dudousxd/nestjs-authz-inertia/client';\n\nconst store = new AbilityStore();\nhydrateFromInertiaProps(store, page.props);              // tier 1: props.auth.can\nhydrateResource(store, { type: 'Post', id: post.id }, post.can); // tier 2\n\nconst can = createCan(store, { fallback: 'fetch', endpoint: '/authz/can' });\n\ncan('post.create');                       // → true   (sync, no request)\ncan('update', { type: 'Post', id: 7 });   // → false  (sync, from resource map)\ncan('mystery');                           // fallback: 'deny' → false; 'fetch' → Promise<boolean>\n```\n\n- **Cache hit** → returns a `boolean` synchronously, never touches the network.\n- **Cache miss** → `fallback: 'deny'` (default) returns `false`; `fallback: 'fetch'`\n  POSTs to the tier-3 endpoint and returns a `Promise<boolean>`. A **resource-bound**\n  miss under `'fetch'` resolves on the server only if the app registered a `resourceLoaders`\n  entry for that `type`; otherwise it denies (and `createCan` logs a one-time `console.warn`)\n  — hydrate per-instance decisions via tiers 1-2 or register a loader.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}