{"_id":"@deijose/nix-js-auth","_rev":"9-2f050f22df2d07eaefb663f375326d34","name":"@deijose/nix-js-auth","dist-tags":{"latest":"1.2.2"},"versions":{"0.1.0":{"name":"@deijose/nix-js-auth","version":"0.1.0","keywords":["nix-js","auth","authentication","authorization","rbac","abac","signals","reactive","typescript"],"author":{"name":"Deiver Vasquez"},"license":"MIT","_id":"@deijose/nix-js-auth@0.1.0","maintainers":[{"name":"deijose","email":"estudiandovazmore@gmail.com"}],"homepage":"https://github.com/DeijoseDevelop/nix-js-auth","bugs":{"url":"https://github.com/DeijoseDevelop/nix-js-auth/issues"},"dist":{"shasum":"e3d87323a7725972b7c88282507b43b3518ef9e1","tarball":"https://registry.npmjs.org/@deijose/nix-js-auth/-/nix-js-auth-0.1.0.tgz","fileCount":24,"integrity":"sha512-0gQkOD7QplI7kU3rm46dLLVVWIBgfeHUrM29vy4l4oUDltxc+ZWEJk1kBGfGnVSEADtQ8xSvGgWRsK2gjIBaTA==","signatures":[{"sig":"MEUCIFz41gPfr/yocdjfSPINcOGroKjoCwQYmrlPqlEjXJwGAiEArBDSlLtbqoU3Ltwf9l6B+oxjp87rPBC4+RBEuvOcM7Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":118811},"main":"./dist/lib/nix-js-auth.cjs","type":"module","types":"./dist/lib/index.d.ts","module":"./dist/lib/nix-js-auth.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/lib/index.d.ts","import":"./dist/lib/nix-js-auth.js","require":"./dist/lib/nix-js-auth.cjs"}},"gitHead":"8abb38a06a9090a0651db1c5056fbbcf62c3f850","scripts":{"dev":"vite","test":"vitest run","build":"tsc && vite build","prepack":"npm run clean:lib && npm run build:lib","preview":"vite preview","build:lib":"vite build --config vite.lib.config.ts && tsc --project tsconfig.lib.json && terser dist/lib/nix-js-auth.js -c -m -o dist/lib/nix-js-auth.js && terser dist/lib/nix-js-auth.cjs -c -m -o dist/lib/nix-js-auth.cjs","clean:lib":"rm -rf dist/lib","typecheck":"tsc --noEmit"},"_npmUser":{"name":"deijose","email":"estudiandovazmore@gmail.com"},"repository":{"url":"git+https://github.com/DeijoseDevelop/nix-js-auth.git","type":"git"},"_npmVersion":"11.13.0","description":"Authentication and authorization library for Nix.js — drivers, policies, and router guards built on signals.","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.0","terser":"^5.46.0","vitest":"^4.0.18","happy-dom":"^20.8.3","typescript":"~5.9.3","@deijose/nix-js":"^2.5.3"},"peerDependencies":{"@deijose/nix-js":"^2.5.3"},"_npmOperationalInternal":{"tmp":"tmp/nix-js-auth_0.1.0_1782256849786_0.12934271083925553","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@deijose/nix-js-auth","version":"0.2.0","keywords":["nix-js","auth","authentication","authorization","rbac","abac","signals","reactive","typescript"],"author":{"name":"Deiver Vasquez"},"license":"MIT","_id":"@deijose/nix-js-auth@0.2.0","maintainers":[{"name":"deijose","email":"estudiandovazmore@gmail.com"}],"homepage":"https://github.com/DeijoseDevelop/nix-js-auth","bugs":{"url":"https://github.com/DeijoseDevelop/nix-js-auth/issues"},"dist":{"shasum":"b5fe298166c1fced21867a6e0f40358083f9b3ef","tarball":"https://registry.npmjs.org/@deijose/nix-js-auth/-/nix-js-auth-0.2.0.tgz","fileCount":32,"integrity":"sha512-5pcUL3LZ/QJ5JN01iIjKjOJTHG6iSz+uC8Buyu8+tCk/a+6hPZy2URK39IdR5Xt6jY4PMosxqryMYjU71HdHDQ==","signatures":[{"sig":"MEUCIQCEtf0f0gqM2577iXN6Y4V4+KZ1GpQu0Dmh8SZx9tQ+hgIgc+02CwnNqBysfmNKy3Z0J6fnlvumoflkrQPe0BWBcpo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":162196},"main":"./dist/lib/nix-js-auth.cjs","type":"module","types":"./dist/lib/index.d.ts","module":"./dist/lib/nix-js-auth.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/lib/index.d.ts","import":"./dist/lib/nix-js-auth.js","require":"./dist/lib/nix-js-auth.cjs"},"./command":{"types":"./dist/lib/command.d.ts","import":"./dist/lib/command.js","require":"./dist/lib/command.cjs"}},"gitHead":"120cb192f9f5ec14ea13e1a7694c70817802a69e","scripts":{"dev":"vite","test":"vitest run","build":"tsc && vite build","prepack":"npm run clean:lib && npm run build:lib","preview":"vite preview","build:lib":"vite build --config vite.lib.config.ts && tsc --project tsconfig.lib.json && terser dist/lib/nix-js-auth.js -c -m -o dist/lib/nix-js-auth.js && terser dist/lib/nix-js-auth.cjs -c -m -o dist/lib/nix-js-auth.cjs && terser dist/lib/command.js -c -m -o dist/lib/command.js && terser dist/lib/command.cjs -c -m -o dist/lib/command.cjs","clean:lib":"rm -rf dist/lib","typecheck":"tsc --noEmit"},"_npmUser":{"name":"deijose","email":"estudiandovazmore@gmail.com"},"repository":{"url":"git+https://github.com/DeijoseDevelop/nix-js-auth.git","type":"git"},"_npmVersion":"11.13.0","description":"Authentication and authorization library for Nix.js — drivers, policies, and router guards built on signals.","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.0","terser":"^5.46.0","vitest":"^4.0.18","happy-dom":"^20.8.3","typescript":"~5.9.3","@deijose/nix-js":"^2.5.3","@deijose/nix-query":"^1.3.7"},"peerDependencies":{"@deijose/nix-js":"^2.5.3","@deijose/nix-query":"^1.3.7"},"peerDependenciesMeta":{"@deijose/nix-query":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nix-js-auth_0.2.0_1782257835714_0.7662854222969631","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@deijose/nix-js-auth","version":"1.0.0","keywords":["nix-js","auth","authentication","authorization","rbac","abac","signals","reactive","typescript"],"author":{"name":"Deiver Vasquez"},"license":"MIT","_id":"@deijose/nix-js-auth@1.0.0","maintainers":[{"name":"deijose","email":"estudiandovazmore@gmail.com"}],"homepage":"https://github.com/DeijoseDevelop/nix-js-auth","bugs":{"url":"https://github.com/DeijoseDevelop/nix-js-auth/issues"},"dist":{"shasum":"bcd2da6428083400980a0faa426cc926326a123a","tarball":"https://registry.npmjs.org/@deijose/nix-js-auth/-/nix-js-auth-1.0.0.tgz","fileCount":34,"integrity":"sha512-7jXl+diuvnkujaX0kt5nwOiQhnm2OQkunmLRlGskikaieThhUBkgVu/cFjny8YUeeyT9COKU3JHF90MOF3toFw==","signatures":[{"sig":"MEYCIQDYjU/YlGaEAlMQqsRRn70SRCVClwGMRE8Oz4DA0anA0wIhAN1Y5usU0gE/aCaTr2IR8ZDFdzIB1QMdviHyNsg9e6ng","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":198516},"main":"./dist/lib/nix-js-auth.cjs","type":"module","types":"./dist/lib/index.d.ts","module":"./dist/lib/nix-js-auth.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/lib/index.d.ts","import":"./dist/lib/nix-js-auth.js","require":"./dist/lib/nix-js-auth.cjs"},"./command":{"types":"./dist/lib/command.d.ts","import":"./dist/lib/command.js","require":"./dist/lib/command.cjs"}},"gitHead":"0778e6d491b423acae082360a8ed413725decb31","scripts":{"dev":"vite","test":"vitest run","build":"tsc && vite build","prepack":"npm run clean:lib && npm run build:lib","preview":"vite preview","build:lib":"vite build --config vite.lib.config.ts && tsc --project tsconfig.lib.json && terser dist/lib/nix-js-auth.js -c -m -o dist/lib/nix-js-auth.js && terser dist/lib/nix-js-auth.cjs -c -m -o dist/lib/nix-js-auth.cjs && terser dist/lib/command.js -c -m -o dist/lib/command.js && terser dist/lib/command.cjs -c -m -o dist/lib/command.cjs","clean:lib":"rm -rf dist/lib","typecheck":"tsc --noEmit"},"_npmUser":{"name":"deijose","email":"estudiandovazmore@gmail.com"},"repository":{"url":"git+https://github.com/DeijoseDevelop/nix-js-auth.git","type":"git"},"_npmVersion":"11.13.0","description":"Authentication and authorization library for Nix.js — drivers, policies, and router guards built on signals.","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.0","terser":"^5.46.0","vitest":"^4.0.18","happy-dom":"^20.8.3","typescript":"~5.9.3","@deijose/nix-js":"^2.5.3","@deijose/nix-query":"^1.3.7"},"peerDependencies":{"@deijose/nix-js":"^2.5.3","@deijose/nix-query":"^1.3.7"},"peerDependenciesMeta":{"@deijose/nix-query":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nix-js-auth_1.0.0_1782258364020_0.33912224243796985","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@deijose/nix-js-auth","version":"1.0.1","keywords":["nix-js","auth","authentication","authorization","rbac","abac","signals","reactive","typescript"],"author":{"name":"Deiver Vasquez"},"license":"MIT","_id":"@deijose/nix-js-auth@1.0.1","maintainers":[{"name":"deijose","email":"estudiandovazmore@gmail.com"}],"homepage":"https://github.com/DeijoseDevelop/nix-js-auth","bugs":{"url":"https://github.com/DeijoseDevelop/nix-js-auth/issues"},"dist":{"shasum":"6e1c7c5b1545de24bb44ceb4df0ac8e3763dcfed","tarball":"https://registry.npmjs.org/@deijose/nix-js-auth/-/nix-js-auth-1.0.1.tgz","fileCount":34,"integrity":"sha512-+zOLuBZwCkiNczrWh9vsE/u/3lqvGgpksEBTP9wbQCv56ShKefS0TT3safEtfcvAdF9RKEaLBhvCgjLG1HbK0w==","signatures":[{"sig":"MEUCIQCWZHRMUYhhZ+DcOHo83Pm/ugKU0LnhHpuwHJSX+QOk+AIgFSyH/DAD1+OkdqJHv2A9arLd3m/1fxmaA4J/LIFqS3I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":200392},"main":"./dist/lib/nix-js-auth.cjs","type":"module","types":"./dist/lib/index.d.ts","module":"./dist/lib/nix-js-auth.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/lib/index.d.ts","import":"./dist/lib/nix-js-auth.js","require":"./dist/lib/nix-js-auth.cjs"},"./command":{"types":"./dist/lib/command.d.ts","import":"./dist/lib/command.js","require":"./dist/lib/command.cjs"}},"gitHead":"75e50897556c80981241a0522f700a6dca1471ba","scripts":{"dev":"vite","test":"vitest run","build":"tsc && vite build","prepack":"npm run clean:lib && npm run build:lib","preview":"vite preview","build:lib":"vite build --config vite.lib.config.ts && tsc --project tsconfig.lib.json && terser dist/lib/nix-js-auth.js -c -m -o dist/lib/nix-js-auth.js && terser dist/lib/nix-js-auth.cjs -c -m -o dist/lib/nix-js-auth.cjs && terser dist/lib/command.js -c -m -o dist/lib/command.js && terser dist/lib/command.cjs -c -m -o dist/lib/command.cjs","clean:lib":"rm -rf dist/lib","typecheck":"tsc --noEmit"},"_npmUser":{"name":"deijose","email":"estudiandovazmore@gmail.com"},"repository":{"url":"git+https://github.com/DeijoseDevelop/nix-js-auth.git","type":"git"},"_npmVersion":"11.13.0","description":"Authentication and authorization library for Nix.js — drivers, policies, and router guards built on signals.","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.0","terser":"^5.46.0","vitest":"^4.0.18","happy-dom":"^20.8.3","typescript":"~5.9.3","@deijose/nix-js":"^2.5.3","@deijose/nix-query":"^1.3.7"},"peerDependencies":{"@deijose/nix-js":"^2.5.3","@deijose/nix-query":"^1.3.7"},"peerDependenciesMeta":{"@deijose/nix-query":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nix-js-auth_1.0.1_1782258583166_0.662924421922239","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@deijose/nix-js-auth","version":"1.1.0","keywords":["nix-js","auth","authentication","authorization","rbac","abac","signals","reactive","typescript"],"author":{"name":"Deiver Vasquez"},"license":"MIT","_id":"@deijose/nix-js-auth@1.1.0","maintainers":[{"name":"deijose","email":"estudiandovazmore@gmail.com"}],"homepage":"https://github.com/DeijoseDevelop/nix-js-auth","bugs":{"url":"https://github.com/DeijoseDevelop/nix-js-auth/issues"},"dist":{"shasum":"fb6abed954b557bde1d859c8dc9455954a69b132","tarball":"https://registry.npmjs.org/@deijose/nix-js-auth/-/nix-js-auth-1.1.0.tgz","fileCount":34,"integrity":"sha512-lLf4SXO8rjqXh1qFih/Sq7DkRABG/YV8QvSX28Pko+snAr6+2hWY+FS8x02ujBFzpGNjkRn4jSRVyarXTj7YKw==","signatures":[{"sig":"MEUCIQC/B6iX2D25Td8ov31RQmZW+r97pDyA21+9lGFMJ/HL2wIgeWvcy39J7RhRbFBmHFx2+/OpD0ZOh4LItkJCMrglGjU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":206454},"main":"./dist/lib/nix-js-auth.cjs","type":"module","types":"./dist/lib/index.d.ts","module":"./dist/lib/nix-js-auth.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/lib/index.d.ts","import":"./dist/lib/nix-js-auth.js","require":"./dist/lib/nix-js-auth.cjs"},"./command":{"types":"./dist/lib/command.d.ts","import":"./dist/lib/command.js","require":"./dist/lib/command.cjs"}},"gitHead":"7b6d2fa5278f1e562f5cd0d49bf246b7f5377e5e","scripts":{"dev":"vite","test":"vitest run","build":"tsc && vite build","prepack":"npm run clean:lib && npm run build:lib","preview":"vite preview","build:lib":"vite build --config vite.lib.config.ts && tsc --project tsconfig.lib.json && terser dist/lib/nix-js-auth.js -c -m -o dist/lib/nix-js-auth.js && terser dist/lib/nix-js-auth.cjs -c -m -o dist/lib/nix-js-auth.cjs && terser dist/lib/command.js -c -m -o dist/lib/command.js && terser dist/lib/command.cjs -c -m -o dist/lib/command.cjs","clean:lib":"rm -rf dist/lib","typecheck":"tsc --noEmit"},"_npmUser":{"name":"deijose","email":"estudiandovazmore@gmail.com"},"repository":{"url":"git+https://github.com/DeijoseDevelop/nix-js-auth.git","type":"git"},"_npmVersion":"11.13.0","description":"Authentication and authorization library for Nix.js — drivers, policies, and router guards built on signals.","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.0","terser":"^5.46.0","vitest":"^4.0.18","happy-dom":"^20.8.3","typescript":"~5.9.3","@deijose/nix-js":"^2.5.3","@deijose/nix-query":"^1.3.7"},"peerDependencies":{"@deijose/nix-js":"^2.5.3","@deijose/nix-query":"^1.3.7"},"peerDependenciesMeta":{"@deijose/nix-query":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nix-js-auth_1.1.0_1782917914998_0.19755986708686746","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@deijose/nix-js-auth","version":"1.1.1","keywords":["nix-js","auth","authentication","authorization","rbac","abac","signals","reactive","typescript"],"author":{"name":"Deiver Vasquez"},"license":"MIT","_id":"@deijose/nix-js-auth@1.1.1","maintainers":[{"name":"deijose","email":"estudiandovazmore@gmail.com"}],"homepage":"https://github.com/DeijoseDevelop/nix-js-auth","bugs":{"url":"https://github.com/DeijoseDevelop/nix-js-auth/issues"},"dist":{"shasum":"6ddf7373284feaebb7b2c4ec337ca1b6414c2830","tarball":"https://registry.npmjs.org/@deijose/nix-js-auth/-/nix-js-auth-1.1.1.tgz","fileCount":34,"integrity":"sha512-pP8UZh2E/hLDAeulMcP1/xCt0jTQAdlaDHxTtxOrVMIyCwnw1oOz+lAA4t70u4tsD5YHrLDci4EDu69d8i3xyQ==","signatures":[{"sig":"MEUCIQDJBmkLzjzlAH6nWlWfx6emxyapVausjACndCDxCoW2FwIgGHzYHO/BrEQ47YHLIRB7Z8Wdy2Ldvz3b/2r5yPBo7+o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":206464},"main":"./dist/lib/nix-js-auth.cjs","type":"module","types":"./dist/lib/index.d.ts","module":"./dist/lib/nix-js-auth.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/lib/index.d.ts","import":"./dist/lib/nix-js-auth.js","require":"./dist/lib/nix-js-auth.cjs"},"./command":{"types":"./dist/lib/command.d.ts","import":"./dist/lib/command.js","require":"./dist/lib/command.cjs"}},"gitHead":"7b6d2fa5278f1e562f5cd0d49bf246b7f5377e5e","scripts":{"dev":"vite","test":"vitest run","build":"tsc && vite build","prepack":"npm run clean:lib && npm run build:lib","preview":"vite preview","build:lib":"vite build --config vite.lib.config.ts && tsc --project tsconfig.lib.json && terser dist/lib/nix-js-auth.js -c -m -o dist/lib/nix-js-auth.js && terser dist/lib/nix-js-auth.cjs -c -m -o dist/lib/nix-js-auth.cjs && terser dist/lib/command.js -c -m -o dist/lib/command.js && terser dist/lib/command.cjs -c -m -o dist/lib/command.cjs","clean:lib":"rm -rf dist/lib","typecheck":"tsc --noEmit"},"_npmUser":{"name":"deijose","email":"estudiandovazmore@gmail.com"},"repository":{"url":"git+https://github.com/DeijoseDevelop/nix-js-auth.git","type":"git"},"_npmVersion":"10.9.9","description":"Authentication and authorization library for Nix.js — drivers, policies, and router guards built on signals.","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.0","terser":"^5.46.0","vitest":"^4.0.18","happy-dom":"^20.8.3","typescript":"~5.9.3","@deijose/nix-js":"3.0.3","@deijose/nix-query":"^1.3.7"},"peerDependencies":{"@deijose/nix-js":"^2.5.3 || ^3.0.0","@deijose/nix-query":"^1.3.7"},"peerDependenciesMeta":{"@deijose/nix-query":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nix-js-auth_1.1.1_1787279787199_0.12239425173744167","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@deijose/nix-js-auth","version":"1.2.0","keywords":["nix-js","auth","authentication","authorization","rbac","abac","signals","reactive","typescript"],"author":{"name":"Deiver Vasquez"},"license":"MIT","_id":"@deijose/nix-js-auth@1.2.0","maintainers":[{"name":"deijose","email":"estudiandovazmore@gmail.com"}],"homepage":"https://github.com/DeijoseDevelop/nix-js-auth","bugs":{"url":"https://github.com/DeijoseDevelop/nix-js-auth/issues"},"dist":{"shasum":"2526dee3b72d21873e7adcbae6a1410793415eb0","tarball":"https://registry.npmjs.org/@deijose/nix-js-auth/-/nix-js-auth-1.2.0.tgz","fileCount":34,"integrity":"sha512-VF9+Expath3VZdyatudbbyVyz0aRVLE4b1p1a4S6gvgtfd9pofMmZGoNAxD7Y33CckLpROgkavre7RxpIwG+Xw==","signatures":[{"sig":"MEUCIEC8nSM6ehDK4OMwmmy+DuBwMPwU4F59QIYMADJnB1zqAiEAk/2RxPCD5vh2x4Iz33cC67RtIM3sT1fgg5FVAGpAO4s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":249296},"main":"./dist/lib/nix-js-auth.cjs","type":"module","types":"./dist/lib/index.d.ts","module":"./dist/lib/nix-js-auth.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/lib/index.d.ts","import":"./dist/lib/nix-js-auth.js","require":"./dist/lib/nix-js-auth.cjs"},"./command":{"types":"./dist/lib/command.d.ts","import":"./dist/lib/command.js","require":"./dist/lib/command.cjs"}},"gitHead":"0e1b62eb675e85a760a2d4e69c63e5793137a940","scripts":{"dev":"vite","test":"vitest run","build":"tsc && vite build","prepack":"npm run clean:lib && npm run build:lib","preview":"vite preview","build:lib":"vite build --config vite.lib.config.ts && tsc --project tsconfig.lib.json && terser dist/lib/nix-js-auth.js -c -m -o dist/lib/nix-js-auth.js && terser dist/lib/nix-js-auth.cjs -c -m -o dist/lib/nix-js-auth.cjs && terser dist/lib/command.js -c -m -o dist/lib/command.js && terser dist/lib/command.cjs -c -m -o dist/lib/command.cjs","clean:lib":"rm -rf dist/lib","typecheck":"tsc --noEmit"},"_npmUser":{"name":"deijose","email":"estudiandovazmore@gmail.com"},"repository":{"url":"git+https://github.com/DeijoseDevelop/nix-js-auth.git","type":"git"},"_npmVersion":"10.9.9","description":"Authentication and authorization library for Nix.js — drivers, policies, and router guards built on signals.","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.0","terser":"^5.46.0","vitest":"^4.0.18","happy-dom":"^20.8.3","typescript":"~5.9.3","@deijose/nix-js":"3.0.3","@deijose/nix-query":"^1.3.7"},"peerDependencies":{"@deijose/nix-js":"^2.5.3 || ^3.0.0","@deijose/nix-query":"^1.3.7"},"peerDependenciesMeta":{"@deijose/nix-query":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nix-js-auth_1.2.0_1787354654977_0.36943767656623105","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@deijose/nix-js-auth","version":"1.2.1","keywords":["nix-js","auth","authentication","authorization","rbac","abac","signals","reactive","typescript"],"author":{"name":"Deiver Vasquez"},"license":"MIT","_id":"@deijose/nix-js-auth@1.2.1","maintainers":[{"name":"deijose","email":"estudiandovazmore@gmail.com"}],"homepage":"https://github.com/DeijoseDevelop/nix-js-auth","bugs":{"url":"https://github.com/DeijoseDevelop/nix-js-auth/issues"},"dist":{"shasum":"c4519db1687ad7ec951d8724172f6a14c15dec37","tarball":"https://registry.npmjs.org/@deijose/nix-js-auth/-/nix-js-auth-1.2.1.tgz","fileCount":34,"integrity":"sha512-Bv9LFFm7M2OjVz+qHETBxuhdHa2qF2FAeGzZbv3pLjt/XpNKF1rTu4QJGQAXdMO6hsvYOh23gfa0yr+gTrRJsQ==","signatures":[{"sig":"MEQCIHQ+KyZ1tJoLYIueEnPUO6Nm57c5moia7TzvqLwKMXFHAiAUb2DSGeZg5m2JC1zpvMlPtKrQut6FYVfd/GGmE3xuNw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":249221},"main":"./dist/lib/nix-js-auth.cjs","type":"module","types":"./dist/lib/index.d.ts","module":"./dist/lib/nix-js-auth.js","engines":{"node":">=18.0.0"},"exports":{".":{"types":"./dist/lib/index.d.ts","import":"./dist/lib/nix-js-auth.js","require":"./dist/lib/nix-js-auth.cjs"},"./command":{"types":"./dist/lib/command.d.ts","import":"./dist/lib/command.js","require":"./dist/lib/command.cjs"}},"gitHead":"d8afab8a54b4cc21c1c631e26d32fc090f951bd8","scripts":{"dev":"vite","test":"vitest run","build":"tsc && vite build","prepack":"npm run clean:lib && npm run build:lib","preview":"vite preview","build:lib":"vite build --config vite.lib.config.ts && tsc --project tsconfig.lib.json && terser dist/lib/nix-js-auth.js -c -m -o dist/lib/nix-js-auth.js && terser dist/lib/nix-js-auth.cjs -c -m -o dist/lib/nix-js-auth.cjs && terser dist/lib/command.js -c -m -o dist/lib/command.js && terser dist/lib/command.cjs -c -m -o dist/lib/command.cjs","clean:lib":"rm -rf dist/lib","typecheck":"tsc --noEmit"},"_npmUser":{"name":"deijose","email":"estudiandovazmore@gmail.com"},"repository":{"url":"git+https://github.com/DeijoseDevelop/nix-js-auth.git","type":"git"},"_npmVersion":"10.9.9","description":"Authentication and authorization library for Nix.js — drivers, policies, and router guards built on signals.","directories":{},"sideEffects":false,"_nodeVersion":"22.14.0","_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.0","terser":"^5.46.0","vitest":"^4.0.18","happy-dom":"^20.8.3","typescript":"~5.9.3","@deijose/nix-js":"3.0.3","@deijose/nix-query":"^1.3.7"},"peerDependencies":{"@deijose/nix-js":"^2.5.3 || ^3.0.0","@deijose/nix-query":"^1.3.7"},"peerDependenciesMeta":{"@deijose/nix-query":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/nix-js-auth_1.2.1_1787445878348_0.46434526725780145","host":"s3://npm-registry-packages-npm-production"}},"1.2.2":{"name":"@deijose/nix-js-auth","version":"1.2.2","description":"Authentication and authorization library for Nix.js — drivers, policies, and router guards built on signals.","license":"MIT","author":{"name":"Deiver Vasquez"},"type":"module","homepage":"https://github.com/DeijoseDevelop/nix-js-auth","repository":{"type":"git","url":"git+https://github.com/DeijoseDevelop/nix-js-auth.git"},"main":"./dist/lib/nix-js-auth.cjs","module":"./dist/lib/nix-js-auth.js","types":"./dist/lib/index.d.ts","exports":{".":{"import":"./dist/lib/nix-js-auth.js","require":"./dist/lib/nix-js-auth.cjs","types":"./dist/lib/index.d.ts"},"./command":{"import":"./dist/lib/command.js","require":"./dist/lib/command.cjs","types":"./dist/lib/command.d.ts"}},"keywords":["nix-js","auth","authentication","authorization","rbac","abac","signals","reactive","typescript"],"sideEffects":false,"engines":{"node":">=18.0.0"},"scripts":{"dev":"vite","build":"tsc && vite build","preview":"vite preview","clean:lib":"rm -rf dist/lib","build:lib":"vite build --config vite.lib.config.ts && tsc --project tsconfig.lib.json && terser dist/lib/nix-js-auth.js -c -m -o dist/lib/nix-js-auth.js && terser dist/lib/nix-js-auth.cjs -c -m -o dist/lib/nix-js-auth.cjs && terser dist/lib/command.js -c -m -o dist/lib/command.js && terser dist/lib/command.cjs -c -m -o dist/lib/command.cjs","prepack":"npm run clean:lib && npm run build:lib","typecheck":"tsc --noEmit","test":"vitest run"},"peerDependencies":{"@deijose/nix-js":"^2.5.3 || ^3.0.0","@deijose/nix-query":"^1.3.7"},"peerDependenciesMeta":{"@deijose/nix-query":{"optional":true}},"devDependencies":{"@deijose/nix-js":"3.0.3","@deijose/nix-query":"^1.3.7","happy-dom":"^20.8.3","terser":"^5.46.0","typescript":"~5.9.3","vite":"^8.0.0","vitest":"^4.0.18"},"_id":"@deijose/nix-js-auth@1.2.2","gitHead":"eeadd5f023fd9803b8eba1b20105bbe7ff8b2583","bugs":{"url":"https://github.com/DeijoseDevelop/nix-js-auth/issues"},"_nodeVersion":"22.14.0","_npmVersion":"10.9.9","dist":{"integrity":"sha512-X/pqSrzSz0G5rl16GcFsvNcfUqIQssrF6Zqak7gVwesCW+Ju1vV6Xw57hgYyJcsr05QuiEP+vK2FnGA0JfXTLQ==","shasum":"aef77ca97e978c48337bc8f359f225a56fba6c16","tarball":"https://registry.npmjs.org/@deijose/nix-js-auth/-/nix-js-auth-1.2.2.tgz","fileCount":34,"unpackedSize":249221,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHx54pbvYvjyP6v2p1CR04bll8SOOCM5T/Fkacmo9PZTAiBkXkvrjpsnEkO/yQ2hRH0MR9ewv+D0bbH2lSMcWtT+nw=="}]},"_npmUser":{"name":"deijose","email":"estudiandovazmore@gmail.com"},"directories":{},"maintainers":[{"name":"deijose","email":"estudiandovazmore@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/nix-js-auth_1.2.2_1787445977188_0.8408712802171681"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-23T23:20:49.552Z","modified":"2026-08-23T00:46:17.466Z","0.1.0":"2026-06-23T23:20:49.914Z","0.2.0":"2026-06-23T23:37:15.863Z","1.0.0":"2026-06-23T23:46:04.183Z","1.0.1":"2026-06-23T23:49:43.292Z","1.1.0":"2026-07-01T14:58:35.144Z","1.1.1":"2026-08-21T02:36:27.348Z","1.2.0":"2026-08-21T23:24:15.150Z","1.2.1":"2026-08-23T00:44:38.488Z","1.2.2":"2026-08-23T00:46:17.308Z"},"bugs":{"url":"https://github.com/DeijoseDevelop/nix-js-auth/issues"},"author":{"name":"Deiver Vasquez"},"license":"MIT","homepage":"https://github.com/DeijoseDevelop/nix-js-auth","keywords":["nix-js","auth","authentication","authorization","rbac","abac","signals","reactive","typescript"],"repository":{"type":"git","url":"git+https://github.com/DeijoseDevelop/nix-js-auth.git"},"description":"Authentication and authorization library for Nix.js — drivers, policies, and router guards built on signals.","maintainers":[{"name":"deijose","email":"estudiandovazmore@gmail.com"}],"readme":"# @deijose/nix-js-auth\n\n[![npm version](https://img.shields.io/npm/v/@deijose/nix-js-auth.svg)](https://www.npmjs.com/package/@deijose/nix-js-auth)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n\nAuthentication and authorization library for [Nix.js](https://nix-js.dev) built entirely on reactive signals.\n\n**Agnostic by design.** Bring your own driver, your own user model, and your own authorization rules. The library only orchestrates state and exposes it as signals that the router, templates, and components can read reactively.\n\n## Table of contents\n\n- [Features](#features)\n- [Installation](#installation)\n- [Core concepts](#core-concepts)\n- [Quick start](#quick-start)\n- [Core API](#core-api)\n- [Drivers](#drivers)\n- [Providers](#providers)\n- [Storage adapters](#storage-adapters)\n- [Auth manager](#auth-manager)\n- [SSR seeds](#ssr-seeds)\n- [Policy engine](#policy-engine)\n- [Router integration](#router-integration)\n- [Optional provide/inject](#optional-provideinject)\n- [Multi-provider](#multi-provider)\n- [Auto-refresh](#auto-refresh)\n- [Optional `nix-query` integration](#optional-nix-query-integration)\n- [Testing](#testing)\n- [Best practices](#best-practices)\n- [TypeScript](#typescript)\n- [API overview](#api-overview)\n- [FAQ](#faq)\n- [License](#license)\n\n## Features\n\n- **Signal-based state**: `auth.user`, `auth.isAuthenticated`, `auth.can(...)` are reactive signals.\n- **Driver-based core**: connect JWT, session cookies, API keys, OIDC, or any custom backend.\n- **Custom user model**: no forced `roles` or `permissions` fields; use identity mapping or custom policies.\n- **Policy engine**: compose authorization rules with `createPolicy`, `rbacPolicy` (with tenant support), and helpers.\n- **Router integration**: declarative `meta.auth` DSL and standalone guards.\n- **Optional `provide/inject`**: use `auth` directly or inject it via `useAuth()`.\n- **Multiple providers**: support email/password, API keys, OIDC, and other strategies in the same app.\n- **Auto-refresh**: automatically refresh tokens before expiry; custom schedules supported.\n- **Storage adapters**: localStorage, sessionStorage, cookies, and memory.\n- **Auth manager**: `createAuthManager` for multi-context or multi-tenant apps.\n- **SSR seeds**: `seed` option for server-side rendering.\n- **Optional `nix-query` integration**: auth-aware commands via `@deijose/nix-js-auth/command`.\n- **TypeScript-first**: full generic support for `Session`, `User`, and `Credentials`.\n\n## Installation\n\n```bash\nnpm install @deijose/nix-js @deijose/nix-js-auth\n```\n\n`@deijose/nix-js` is a peer dependency.\n\n## Core concepts\n\n### Auth instance\n\nAn `AuthInstance` is the central object. It holds signals for the current session and user, and exposes methods to log in, log out, refresh, and evaluate policies.\n\n```ts\nconst auth = createAuth({ driver, storage });\n```\n\n### Driver\n\nA driver knows how to talk to your backend. It is the only place where HTTP calls, OAuth redirects, or biometric flows live. The core does not assume any transport.\n\n### Policy\n\nA policy is a pure function that decides whether a user can perform an action. Policies are attached to the auth instance and evaluated by `auth.can()`.\n\n### Router guard\n\n`authRouterPlugin` reads the `meta.auth` field of each route and decides whether to allow navigation, redirect to login, or redirect to an unauthorized page.\n\n## Quick start\n\n```ts\nimport { createAuth, jwtDriver, localStorageAdapter, createPolicy } from \"@deijose/nix-js-auth\";\n\nconst auth = createAuth({\n  driver: jwtDriver({\n    loginUrl: \"/api/login\",\n    refreshUrl: \"/api/refresh\",\n  }),\n  storage: localStorageAdapter({ key: \"app:session\" }),\n  identity: {\n    roles: \"roles\",\n    permissions: \"permissions\",\n  },\n});\n\nauth.attachPolicy(\n  createPolicy((user, action, context) => {\n    if (!user) return false;\n    if (action === \"post:edit\") {\n      return user.permissions?.includes(\"post:edit\") || user.id === context.authorId;\n    }\n    return false;\n  }),\n);\n\nawait auth.login({ email: \"deiver@example.com\", password: \"secret\" });\n\nconsole.log(auth.isAuthenticated.value); // true\nconsole.log(auth.can(\"post:edit\", { authorId: \"42\" }).value); // true | false\n```\n\n## Core API\n\n### `createAuth(options)`\n\nCreates a reactive auth instance.\n\n```ts\ninterface CreateAuthOptions<Session, User, Credentials> {\n  driver?: AuthDriver<Session, User, Credentials>;\n  providers?: Record<string, AuthDriver<Session, User, Credentials>>;\n  defaultProvider?: string;\n  storage?: AuthStorage<Session>;\n  autoRefresh?: boolean | AutoRefreshOptions<Session>;\n  seed?: Session | (() => Session | null);\n  identity?: AuthIdentity<User>;\n  onChange?: (session: Session | null) => void;\n  onError?: (error: unknown, event: AuthEvent) => void;\n  name?: string;\n  refreshOptions?: RefreshOptions;\n  multiTabSync?: MultiTabSyncOptions;\n}\n\ninterface AutoRefreshOptions<Session> {\n  beforeExpirySeconds?: number;\n  schedule?: (session: Session, refresh: () => Promise<void>) => (() => void);\n}\n\ninterface RefreshOptions {\n  maxRetries?: number; // default: 3\n  retryDelay?: number | ((failureCount: number) => number); // default: exponential\n  isTransientError?: (error: unknown) => boolean; // default: 5xx, 429, TypeError\n}\n\ninterface MultiTabSyncOptions {\n  enabled?: boolean; // default: false\n  channelName?: string; // default: \"nix-auth:<name>\"\n}\n```\n\n### Signals\n\n| Signal | Type | Description |\n| --- | --- | --- |\n| `auth.session` | `Signal<Session \\| null>` | Raw session data returned by the driver. |\n| `auth.user` | `Signal<User \\| null>` | User object derived from the session via `driver.toUser`. |\n| `auth.token` | `Signal<string \\| null>` | Token extracted from the session. |\n| `auth.isAuthenticated` | `Signal<boolean>` | `true` when `user` is not null. |\n| `auth.isAnonymous` | `Signal<boolean>` | `true` when `user` is null. |\n| `auth.isReady` | `Signal<boolean>` | `true` after the initial storage hydration completes. |\n| `auth.isLoading` | `Signal<boolean>` | `true` during login, logout, or refresh. |\n| `auth.error` | `Signal<unknown>` | Last error encountered. |\n| `auth.activeProvider` | `Signal<string \\| null>` | Current provider name when providers are used. |\n\n### Methods\n\n```ts\n// Authentication\nawait auth.login(credentials);\nawait auth.logout();\nawait auth.refresh();\nawait auth.ready();\n\n// Manual session control\nauth.setSession(session);\nauth.clearSession();\n\n// Policies\nauth.attachPolicy(policy);\nauth.detachPolicy(policy);\n\n// Authorization checks\nconst allowed = auth.can(\"post:edit\", { id: \"42\" }).value;\nconst decision = auth.authorize(\"post:edit\", { id: \"42\" }).value; // { allow, redirect? }\n\n// Identity helpers\nauth.hasRole(\"admin\").value;\nauth.hasPermission(\"post:edit\").value;\nauth.hasScope(\"read\").value;\nauth.hasAnyRole([\"admin\", \"editor\"]).value;\nauth.hasAllPermissions([\"post:edit\", \"post:publish\"]).value;\n```\n\n### Identity mapping\n\nThe `identity` option maps the helpers to your user fields:\n\n```ts\nconst auth = createAuth({\n  driver,\n  identity: {\n    roles: \"myRoles\",\n    permissions: (user) => user.claims,\n    scopes: (user) => user.oauthScopes,\n  },\n});\n```\n\nIf no mapping is provided, the helpers fall back to `user.roles`, `user.permissions`, and `user.scopes`.\n\n## Drivers\n\nA driver implements the `AuthDriver` interface:\n\n```ts\ninterface AuthDriver<Session, User, Credentials> {\n  name: string;\n  login(credentials: Credentials): Promise<Session>;\n  logout(session: Session): Promise<void>;\n  hydrate?(raw: unknown): Promise<Session | null>;\n  refresh?(session: Session): Promise<Session>;\n  getExpiry?(session: Session): number | undefined;\n  toUser?(session: Session): User;\n  getToken?(session: Session): string | null;\n  isValid?(session: Session): boolean;\n}\n```\n\n### `jwtDriver(options)`\n\n```ts\nimport { jwtDriver } from \"@deijose/nix-js-auth\";\n\nconst auth = createAuth({\n  driver: jwtDriver({\n    loginUrl: \"/api/login\",\n    logoutUrl: \"/api/logout\",\n    refreshUrl: \"/api/refresh\",\n    headers: { \"x-api-version\": \"v2\" },\n  }),\n});\n```\n\nExpected session shape:\n\n```ts\ninterface JwtSession<User> {\n  user: User;\n  token: string;\n  refreshToken?: string;\n  expiresAt?: number;\n}\n```\n\n### `sessionCookieDriver(options)`\n\nFor backends that use `httpOnly` session cookies. The browser sends the cookie automatically with `credentials: \"include\"`.\n\n```ts\nimport { sessionCookieDriver } from \"@deijose/nix-js-auth\";\n\nconst auth = createAuth({\n  driver: sessionCookieDriver({\n    loginUrl: \"/api/login\",\n    logoutUrl: \"/api/logout\",\n    sessionUrl: \"/api/session\",\n  }),\n  storage: cookieAdapter({ key: \"app:session\" }),\n});\n```\n\nThe driver will call `sessionUrl` during hydration to recover the current user from the server. If the session is expired, the server should return `401` and the driver will return `null`.\n\n### `mockDriver(options)`\n\nUseful for tests and prototypes.\n\n```ts\nimport { mockDriver } from \"@deijose/nix-js-auth\";\n\nconst auth = createAuth({\n  driver: mockDriver({\n    name: \"fake\",\n    login: async (creds) => ({ user: { id: \"1\", roles: [\"admin\"] }, token: \"abc\" }),\n    toUser: (session) => session.user,\n    getToken: (session) => session.token,\n  }),\n});\n```\n\n### Custom driver\n\n```ts\nconst legacyDriver = {\n  name: \"legacy\",\n  async login(credentials) {\n    const res = await fetch(\"/legacy/auth\", {\n      method: \"POST\",\n      body: JSON.stringify(credentials),\n    });\n    return res.json();\n  },\n  async logout(session) {\n    await fetch(\"/legacy/auth\", {\n      headers: { \"X-Legacy-Token\": session.token },\n    });\n  },\n  toUser(session) {\n    return session.employee;\n  },\n  getToken(session) {\n    return session.token;\n  },\n  getExpiry(session) {\n    return session.expiresAt;\n  },\n};\n\nconst auth = createAuth({ driver: legacyDriver });\n```\n\n### Hydration\n\nIf a driver implements `hydrate`, it can validate or re-fetch the session when loading from storage:\n\n```ts\nconst driver = {\n  // ...\n  async hydrate(raw) {\n    const res = await fetch(\"/api/session/validate\", {\n      headers: { Authorization: `Bearer ${(raw as any).token}` },\n    });\n    return res.ok ? (raw as Session) : null;\n  },\n};\n```\n\n### Refresh error handling (v1.2)\n\nBy default, `refresh()` retries transient errors (5xx, 429, network failures)\nup to 3 times with exponential backoff, keeping the session alive. Only\n401/403 errors trigger logout.\n\n```ts\nconst auth = createAuth({\n  driver,\n  autoRefresh: true,\n  refreshOptions: {\n    maxRetries: 5,\n    retryDelay: (failureCount) => Math.min(1000 * 2 ** failureCount, 10000),\n    isTransientError: (err) => {\n      // Custom predicate — return true to retry, false to logout\n      const status = (err as { status?: number }).status;\n      return status === undefined || status >= 500 || status === 429;\n    },\n  },\n});\n```\n\n### Multi-tab synchronization (v1.2)\n\nEnable `multiTabSync` to broadcast login/logout events across browser tabs\nvia `BroadcastChannel`:\n\n```ts\nconst auth = createAuth({\n  driver,\n  storage: localStorageAdapter({ key: \"app:session\" }),\n  multiTabSync: { enabled: true },\n});\n```\n\nWhen the user logs in on Tab A, Tab B receives the session automatically.\nWhen the user logs out on any tab, all tabs clear the session.\n\n## Providers\n\nA provider is a named driver. This is useful when an app supports multiple authentication mechanisms.\n\n```ts\nimport { credentialsProvider, mockDriver } from \"@deijose/nix-js-auth\";\n\nconst auth = createAuth({\n  providers: {\n    credentials: credentialsProvider({\n      login: async (creds) => {\n        const res = await fetch(\"/api/login\", {\n          method: \"POST\",\n          body: JSON.stringify(creds),\n        });\n        return res.json();\n      },\n    }),\n    apiKey: mockDriver({\n      name: \"apiKey\",\n      login: async (creds) => ({ user: { id: \"2\" }, token: creds.key }),\n    }),\n  },\n  defaultProvider: \"credentials\",\n});\n\nawait auth.login(\"credentials\", { email, password });\nawait auth.login(\"apiKey\", { key: \"secret\" });\n\nconsole.log(auth.activeProvider.value); // \"apiKey\"\n```\n\n### `apiKeyProvider(options)`\n\nProvider for API-key authentication.\n\n```ts\nimport { apiKeyProvider } from \"@deijose/nix-js-auth\";\n\nconst auth = createAuth({\n  providers: {\n    apiKey: apiKeyProvider({\n      validate: async (key) => {\n        const res = await fetch(\"/api/validate-key\", {\n          headers: { \"x-api-key\": key },\n        });\n        return res.json();\n      },\n    }),\n  },\n  defaultProvider: \"apiKey\",\n});\n\nawait auth.login(\"apiKey\", { key: \"secret\" });\n```\n\n### `oidcProvider(options)`\n\nBasic OIDC provider with PKCE. The provider discovers endpoints from the issuer's `/.well-known/openid-configuration`.\n\n```ts\nimport { oidcProvider } from \"@deijose/nix-js-auth\";\n\nconst provider = oidcProvider({\n  authority: \"https://idp.example.com\",\n  clientId: \"client-id\",\n  redirectUri: \"https://app.example.com/callback\",\n  postLogoutRedirectUri: \"https://app.example.com\",\n  scope: \"openid profile email\",\n});\n\nconst auth = createAuth({ driver: provider });\n\n// 1. Start login\nconst loginUrl = await provider.buildLoginUrl();\nwindow.location.href = loginUrl.url;\n// Save loginUrl.state, loginUrl.codeVerifier and loginUrl.nonce\n\n// 2. After callback, complete login\nconst params = new URLSearchParams(window.location.search);\nconst session = await auth.login({\n  code: params.get(\"code\")!,\n  codeVerifier: savedCodeVerifier,\n  state: params.get(\"state\")!,\n  nonce: savedNonce,\n});\n\n// 3. Logout — performLogout builds the URL and redirects automatically\nawait provider.performLogout(session, { mode: \"redirect\" });\n// Or use a background fetch for back-channel logout:\n// await provider.performLogout(session, { mode: \"fetch\" });\n```\n\n`performLogout(session, options)` (v1.2) builds the end_session URL and\nexecutes the redirect (or background fetch) automatically. Supports a custom\n`redirect` function for testing or non-browser environments.\n\n## Storage adapters\n\nStorage adapters are responsible for persisting the session between reloads.\n\n```ts\nimport { localStorageAdapter, sessionStorageAdapter, cookieAdapter, memoryAdapter } from \"@deijose/nix-js-auth\";\n\nconst auth = createAuth({\n  driver,\n  storage: localStorageAdapter({ key: \"app:session\" }),\n});\n```\n\n### `localStorageAdapter({ key })`\n\nPersists to `localStorage`. Falls back to in-memory if storage is unavailable.\n\n### `sessionStorageAdapter({ key })`\n\nPersists to `sessionStorage`.\n\n### `cookieAdapter({ key })`\n\nPersists to `document.cookie`. Useful for non-`httpOnly` session data or for\nsharing small state with the server.\n\n> ⚠️ **Security warning**: Cookies set via `document.cookie` are accessible\n> from JavaScript and vulnerable to XSS attacks. **Do NOT store JWTs or\n> access tokens here.** Use `sessionCookieDriver` (httpOnly) or\n> `localStorageAdapter` instead. The adapter emits a `console.warn` by\n> default; set `suppressSecurityWarning: true` to silence it.\n\n```ts\nconst auth = createAuth({\n  driver,\n  storage: cookieAdapter({\n    key: \"app:session\",\n    days: 7,\n    sameSite: \"lax\",\n    suppressSecurityWarning: true, // only if storing non-sensitive data\n  }),\n});\n```\n\n### `memoryAdapter()`\n\nIn-memory only. Useful for tests and server-side rendering seeds.\n\n## Auth manager\n\nFor apps that need multiple auth instances (multi-context, multi-tenant, or admin + customer portals):\n\n```ts\nimport { createAuthManager, jwtDriver, localStorageAdapter } from \"@deijose/nix-js-auth\";\n\nconst manager = createAuthManager();\n\nconst customer = manager.create(\"customer\", {\n  driver: jwtDriver({ loginUrl: \"/api/customer/login\" }),\n  storage: localStorageAdapter({ key: \"customer:session\" }),\n});\n\nconst admin = manager.create(\"admin\", {\n  driver: jwtDriver({ loginUrl: \"/api/admin/login\" }),\n  storage: localStorageAdapter({ key: \"admin:session\" }),\n});\n\nconsole.log(manager.list()); // [\"customer\", \"admin\"]\nconsole.log(manager.get(\"admin\")); // AuthInstance\n\nmanager.remove(\"customer\");\n```\n\n## SSR seeds\n\nWhen rendering on the server, pass the initial session so the first client render is hydrated immediately:\n\n```ts\nconst auth = createAuth({\n  driver,\n  seed: serverSession,\n});\n```\n\nYou can also pass a function that returns the seed:\n\n```ts\nconst auth = createAuth({\n  driver,\n  seed: () => readSessionFromRequest(request),\n});\n```\n\n## Policy engine\n\nPolicies are pure functions that receive the user, the action, the context, and the session.\n\n```ts\nimport { createPolicy } from \"@deijose/nix-js-auth\";\n\nauth.attachPolicy(\n  createPolicy((user, action, context, session) => {\n    if (!user) return false;\n\n    if (action === \"admin:dashboard\") {\n      return user.isAdmin === true;\n    }\n\n    if (action === \"post:edit\") {\n      return user.permissions?.includes(\"post:edit\") || user.id === context.authorId;\n    }\n\n    return false;\n  }),\n);\n```\n\n`auth.can(action, context?)` returns a reactive signal that re-evaluates when the user or the attached policies change.\n\n### Policy helpers\n\n```ts\nimport { hasRole, hasPermission, hasScope, isOwner, all, any, not } from \"@deijose/nix-js-auth\";\n\nauth.attachPolicy(\n  createPolicy((user, action, context) => {\n    if (!user) return false;\n\n    if (action === \"admin:dashboard\") {\n      return hasRole(\"admin\")(user, context);\n    }\n\n    if (action === \"post:edit\") {\n      return any(\n        hasPermission(\"post:edit\"),\n        isOwner(\"post\", context.id),\n      )(user, context);\n    }\n\n    if (action === \"post:delete\") {\n      return all(\n        hasRole(\"admin\"),\n        not(isOwner(\"post\", context.id)),\n      )(user, context);\n    }\n\n    return false;\n  }),\n);\n```\n\n### `rbacPolicy`\n\nConvenience policy for role-based and permission-based access control.\n\n```ts\nimport { rbacPolicy } from \"@deijose/nix-js-auth\";\n\nauth.attachPolicy(\n  rbacPolicy({\n    resolveRoles: (user) => user.roles,\n    resolvePermissions: (user) => user.permissions,\n  }),\n);\n\nauth.can(\"role:admin\").value;\nauth.can(\"permission:post:edit\").value;\n```\n\n#### Tenant support\n\nFor multi-tenant apps, pass `tenant` in the context and resolve roles/permissions per tenant:\n\n```ts\nauth.attachPolicy(\n  rbacPolicy({\n    resolveRoles: (user, tenant) => (tenant ? user.rolesByTenant[tenant] : user.roles),\n    resolvePermissions: (user, tenant) => (tenant ? user.permissionsByTenant[tenant] : user.permissions),\n  }),\n);\n\nauth.can(\"role:admin\", { tenant: \"acme\" }).value;\nauth.can(\"permission:post:edit\", { tenant: \"globex\" }).value;\n```\n\n## Router integration\n\n```ts\nimport { createRouter } from \"@deijose/nix-js\";\nimport { authRouterPlugin, requireAuth } from \"@deijose/nix-js-auth\";\n\nconst router = createRouter([\n  { path: \"/login\", component: LoginPage, meta: { auth: \"public\" } },\n  { path: \"/admin\", component: AdminPage, meta: { auth: { can: \"admin:dashboard\" } } },\n  { path: \"/post/:id/edit\", component: EditPost, meta: { auth: { can: \"post:edit\" } } },\n  { path: \"/public\", component: PublicPage, meta: { auth: false } },\n  { path: \"/profile\", component: ProfilePage, meta: { auth: \"optional\" } },\n]);\n\nrouter.beforeEach(\n  authRouterPlugin(auth, router, {\n    public: [\"/login\", \"/register\"],\n    defaultRedirect: \"/login\",\n    fallbackRedirect: \"/unauthorized\",\n  }),\n);\n```\n\n### `meta.auth` DSL\n\nThe `meta.auth` field accepts:\n\n- `\"public\"` or `false` — allow anyone.\n- `\"optional\"` — allow the route, but auth is optional.\n- `string` — action passed to `auth.can(action)`.\n- `string[]` — any of the actions must be allowed.\n- object:\n  - `can` — action passed to `auth.can(action, context)`.\n  - `context` — static context or a function returning context.\n  - `role` — required role.\n  - `roles` — any of the roles.\n  - `permission` — required permission.\n  - `permissions` — all of the permissions.\n  - `provider` — required active provider.\n  - `redirect` — custom redirect path.\n  - `allow` — boolean or a guard function `(to, from, auth) => boolean \\| string \\| Promise<...>`.\n- function — full custom guard `(to, from, auth) => NavigationGuardResult`.\n\n### Dynamic context in routes\n\n```ts\nconst router = createRouter([\n  {\n    path: \"/post/:id/edit\",\n    component: EditPost,\n    meta: {\n      auth: {\n        can: \"post:edit\",\n        context: () => ({ id: router.params.value.id }),\n      },\n    },\n  },\n]);\n```\n\n### Standalone guards\n\n```ts\nimport { requireAuth, requireRole, requirePermission, requireProvider, requirePolicy } from \"@deijose/nix-js-auth\";\n\nrouter.beforeEach(requireAuth(auth, \"/login\"));\nrouter.beforeEach(requireRole(auth, \"admin\", \"/unauthorized\"));\nrouter.beforeEach(requirePermission(auth, \"post:edit\", \"/unauthorized\"));\nrouter.beforeEach(requireProvider(auth, \"apiKey\", \"/login\"));\nrouter.beforeEach(requirePolicy(auth, (to, from) => auth.can(\"custom:action\", { path: to }).value));\n```\n\n### Custom meta interpreter\n\nFor advanced use cases, you can replace the default meta interpreter:\n\n```ts\nrouter.beforeEach(\n  authRouterPlugin(auth, router, {\n    interpretMeta(meta, auth, to, from) {\n      if (!meta) return undefined;\n      if (meta === \"public\") return undefined;\n      if (typeof meta === \"string\") {\n        return auth.can(meta).value ? undefined : \"/unauthorized\";\n      }\n      return undefined;\n    },\n  }),\n);\n```\n\n## Optional provide/inject\n\n```ts\nimport { provide } from \"@deijose/nix-js\";\nimport { AuthKey, useAuth, setActiveAuth } from \"@deijose/nix-js-auth\";\n\nprovide(AuthKey, auth);\n\n// Or set globally for multi-tenant reactive switching:\nsetActiveAuth(auth);\n\n// In a descendant component — useAuth() returns a reactive Signal:\nconst authSignal = useAuth();\n// authSignal.value is the AuthInstance | undefined\nif (authSignal.value) {\n  console.log(authSignal.value.isAuthenticated.value);\n}\n\n// Non-reactive access (for guards, plugins):\nimport { getAuth } from \"@deijose/nix-js-auth\";\nconst auth = getAuth();\n```\n\n`useAuth()` returns a `Signal<AuthInstance | undefined>` that tracks the\nactive auth instance. When you call `setActiveAuth(newAuth)`, all components\nusing `useAuth()` re-render with the new instance — useful for multi-tenant\ndynamic switching.\n\nThe library is fully usable without `provide/inject` if you prefer to export\nthe instance directly.\n\n## Multi-provider\n\n```ts\nimport { createAuth, credentialsProvider, mockDriver } from \"@deijose/nix-js-auth\";\n\nconst auth = createAuth({\n  providers: {\n    credentials: credentialsProvider({\n      login: async (creds) => {\n        const res = await fetch(\"/api/login\", {\n          method: \"POST\",\n          body: JSON.stringify(creds),\n        });\n        return res.json();\n      },\n    }),\n    apiKey: mockDriver({\n      name: \"apiKey\",\n      login: async (creds) => ({ user: { id: \"2\" }, token: creds.key }),\n    }),\n  },\n  defaultProvider: \"credentials\",\n  storage: localStorageAdapter({ key: \"app:session\" }),\n});\n\nawait auth.login(\"credentials\", { email, password });\nawait auth.login(\"apiKey\", { key: \"secret\" });\n\nconsole.log(auth.activeProvider.value); // \"apiKey\"\n```\n\n## Auto-refresh\n\nWhen a driver provides `getExpiry`, the library can refresh the session before it expires.\n\n```ts\nconst auth = createAuth({\n  driver: jwtDriver({\n    loginUrl: \"/api/login\",\n    refreshUrl: \"/api/refresh\",\n  }),\n  autoRefresh: true, // default: 60 seconds before expiry\n});\n```\n\n### Custom refresh schedule\n\nFor advanced control, provide a custom scheduler:\n\n```ts\nconst auth = createAuth({\n  driver,\n  autoRefresh: {\n    beforeExpirySeconds: 120,\n    schedule(session, refresh) {\n      const d = driver.getExpiry?.(session);\n      if (!d) return () => {};\n      const delay = Math.max(0, d - Date.now() - 120_000);\n      const timer = setTimeout(() => void refresh(), delay);\n      return () => clearTimeout(timer);\n    },\n  },\n});\n```\n\n## Optional `nix-query` integration\n\n`@deijose/nix-query` is an **optional** peer dependency. If you already use it, you can wrap auth-aware commands from the `./command` subpath.\n\n```bash\nnpm install @deijose/nix-query\n```\n\n```ts\nimport { authCommand, createLoginCommand, createLogoutCommand, authHeaders } from \"@deijose/nix-js-auth/command\";\n\n// Inject the current token into any command\nconst savePost = authCommand(auth, \"post/save\", async (payload, ctx) => {\n  const res = await fetch(\"/api/posts\", {\n    method: \"POST\",\n    headers: {\n      ...authHeaders(auth),\n      \"content-type\": \"application/json\",\n    },\n    body: JSON.stringify(payload),\n    signal: ctx.signal,\n  });\n  return res.json();\n});\n\n// Or expose login/logout as commands\nconst login = createLoginCommand(auth, \"auth/login\");\nconst logout = createLogoutCommand(auth, \"auth/logout\");\n```\n\n## Testing\n\n`mockDriver` makes the library easy to test without a real backend.\n\n```ts\nimport { describe, it, expect } from \"vitest\";\nimport { createAuth, mockDriver } from \"@deijose/nix-js-auth\";\n\ndescribe(\"auth\", () => {\n  it(\"logs in\", async () => {\n    const auth = createAuth({\n      driver: mockDriver({\n        login: () => Promise.resolve({ user: { id: \"1\", roles: [\"admin\"] }, token: \"abc\" }),\n        toUser: (s) => s.user,\n        getToken: (s) => s.token,\n      }),\n    });\n\n    await auth.login({ email: \"test@example.com\", password: \"secret\" });\n\n    expect(auth.isAuthenticated.value).toBe(true);\n    expect(auth.user.value).toEqual({ id: \"1\", roles: [\"admin\"] });\n    expect(auth.token.value).toBe(\"abc\");\n  });\n});\n```\n\n## Best practices\n\n- **Keep the core unopinionated**: do not put backend-specific logic outside the driver.\n- **Use `toUser`**: always implement `toUser` if your session object wraps the user.\n- **Prefer `can()` in templates**: `auth.can(\"post:edit\").value` is reactive and efficient.\n- **Separate policies**: split domain-specific rules into multiple policies instead of one giant function.\n- **Custom redirect**: use `redirect` in `meta.auth` or a custom `interpretMeta` for route-specific behavior.\n- **Do not store tokens in plain localStorage for production**: use `httpOnly` cookies when possible. Provide a `sessionCookieDriver` or custom driver that reads the cookie.\n- **Never store JWTs in `cookieAdapter`**: cookies set via `document.cookie` are JS-accessible and XSS-vulnerable. Use `sessionCookieDriver` (httpOnly) instead.\n- **Hydrate safely**: implement `hydrate` in the driver to validate the stored session on startup.\n- **Enable multi-tab sync**: use `multiTabSync: { enabled: true }` so login/logout propagates across tabs.\n- **Use `refreshOptions`**: configure retry behavior to avoid logging users out on transient network errors.\n\n## TypeScript\n\n`createAuth` accepts generics for `Session`, `User`, and `Credentials`:\n\n```ts\ninterface MySession {\n  user: MyUser;\n  token: string;\n  expiresAt: number;\n}\n\ninterface MyUser {\n  id: string;\n  roles: string[];\n  permissions: string[];\n}\n\ninterface MyCredentials {\n  email: string;\n  password: string;\n}\n\nconst auth = createAuth<MySession, MyUser, MyCredentials>({\n  driver: myDriver,\n});\n```\n\nThe returned `AuthInstance` is typed accordingly.\n\n## API overview\n\n### Core\n\n- `createAuth(options)` — reactive auth instance.\n- `createAuthManager()` — manage multiple named auth instances.\n- `auth.login(credentials)` / `auth.login(\"provider\", credentials)`\n- `auth.logout()` / `auth.refresh()` / `auth.ready()`\n- `auth.session`, `auth.user`, `auth.token`, `auth.isAuthenticated`, `auth.isReady`, `auth.isLoading`, `auth.error`\n- `auth.setSession(session)`, `auth.clearSession()`\n- `auth.attachPolicy(policy)`, `auth.detachPolicy(policy)`\n- `auth.can(action, context?)`, `auth.authorize(action, context?)`\n- `auth.hasRole(role)`, `auth.hasPermission(permission)`, `auth.hasScope(scope)`\n- `auth.hasAnyRole(roles)`, `auth.hasAllPermissions(permissions)`\n\n### Drivers\n\n- `jwtDriver(options)` — JWT / Bearer token flow.\n- `sessionCookieDriver(options)` — `httpOnly` session cookie flow.\n- `mockDriver(options)` — testing and prototyping.\n- Custom driver via `AuthDriver` interface.\n\n### Providers\n\n- `credentialsProvider(options)` — email/password or custom credentials.\n- `apiKeyProvider(options)` — API-key authentication.\n- `oidcProvider(options)` — OIDC with PKCE.\n\n### Storage adapters\n\n- `localStorageAdapter({ key })`, `sessionStorageAdapter({ key })`, `cookieAdapter({ key })`, `memoryAdapter()`.\n\n### Policy engine\n\n- `createPolicy(evaluator)`\n- `rbacPolicy(options)` — supports tenant-aware resolvers.\n- `hasRole`, `hasPermission`, `hasScope`, `isOwner`, `all`, `any`, `not`.\n\n### Router\n\n- `authRouterPlugin(auth, router, options)`\n- `requireAuth`, `requireRole`, `requirePermission`, `requireProvider`, `requirePolicy`.\n\n### Optional command integration\n\nFrom `@deijose/nix-js-auth/command`:\n\n- `authCommand(auth, commandKey, executeFn, options?)`\n- `createLoginCommand(auth, commandKey, options?)`\n- `createLogoutCommand(auth, commandKey, options?)`\n- `authHeaders(auth)`\n\n## FAQ\n\n### Does the library work without a router?\n\nYes. Use `auth.isAuthenticated` and `auth.can()` directly in your components.\n\n### Can I use multiple auth instances in the same app?\n\nYes. Use `createAuthManager` for named instances or call `createAuth` multiple times directly.\n\n### What happens if the session expires while the user is using the app?\n\nIf the driver implements `refresh` and `getExpiry`, and `autoRefresh` is enabled, the library will refresh the token automatically before expiry.\n\n### How do I handle OAuth / OIDC?\n\nUse the built-in `oidcProvider` for a basic PKCE flow, or write a custom driver that handles the redirect and callback.\n\n### How do I integrate with `nix-query`?\n\nImport `@deijose/nix-js-auth/command` and use `authCommand`, `createLoginCommand`, or `createLogoutCommand`.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}