{"_id":"@1moby/just-auth","_rev":"8-e1fb097c2aa1ed99cad439d228b628b4","name":"@1moby/just-auth","dist-tags":{"latest":"0.4.3"},"versions":{"0.1.0":{"name":"@1moby/just-auth","version":"0.1.0","keywords":["auth","authentication","oauth","react","session","edge","cloudflare","workers","d1","sqlite","postgres","mysql","rbac","zero-dependency"],"author":{"name":"1moby"},"license":"MIT","_id":"@1moby/just-auth@0.1.0","maintainers":[{"name":"mynameisanu","email":"anu@anusoft.biz"}],"homepage":"https://github.com/1moby/just-auth#readme","bugs":{"url":"https://github.com/1moby/just-auth/issues"},"dist":{"shasum":"1f1824434cadb24528130b9aae4496c8de6b522b","tarball":"https://registry.npmjs.org/@1moby/just-auth/-/just-auth-0.1.0.tgz","fileCount":144,"integrity":"sha512-mxUpVzhTQL/7z48bsRne/PTuCUiU5aSdHPDCm2Hjgwa3UCjBvTB5drhhth5qRUlXHQaBuRBd3Wh7wqMbsxwIfw==","signatures":[{"sig":"MEUCIQDvo7EVnfujlF2zocTeYEHCTVzHYPt2kG7Nn7TKJ/Fk+QIgOOfLYwnq0WYtmvmrYTYeH2DtrlFa1T4PqZbIvjlBcVQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":251251},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./src/index.ts"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./src/client/index.ts"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./src/server/index.ts"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.js","default":"./src/middleware/index.ts"},"./adapters/d1":{"types":"./dist/adapters/d1.d.ts","import":"./dist/adapters/d1.js","default":"./src/adapters/d1.ts"},"./adapters/pg":{"types":"./dist/adapters/pg.d.ts","import":"./dist/adapters/pg.js","default":"./src/adapters/pg.ts"},"./adapters/mysql":{"types":"./dist/adapters/mysql.d.ts","import":"./dist/adapters/mysql.js","default":"./src/adapters/mysql.ts"},"./adapters/bun-sql":{"types":"./dist/adapters/bun-sql.d.ts","import":"./dist/adapters/bun-sql.js","default":"./src/adapters/bun-sql.ts"},"./adapters/bun-sqlite":{"types":"./dist/adapters/bun-sqlite.d.ts","import":"./dist/adapters/bun-sqlite.js","default":"./src/adapters/bun-sqlite.ts"}},"gitHead":"aec880b349019fcf509feabf9e0d3ec2349ed566","scripts":{"test":"bun test","build":"bun scripts/build.ts","prepare":"bun scripts/build.ts","prepublishOnly":"bun run build"},"_npmUser":{"name":"mynameisanu","email":"anu@anusoft.biz"},"repository":{"url":"git+https://github.com/1moby/just-auth.git","type":"git"},"_npmVersion":"10.9.4","description":"Lightweight zero-dependency edge-native auth library for React","directories":{},"sideEffects":false,"_nodeVersion":"22.22.0","_hasShrinkwrap":false,"devDependencies":{"react":"^19.2.4","@types/bun":"latest","typescript":"^5","@types/react":"^19.2.14"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/just-auth_0.1.0_1774339694882_0.7017645654820801","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@1moby/just-auth","version":"0.1.1","keywords":["auth","authentication","oauth","react","session","edge","cloudflare","workers","d1","sqlite","postgres","mysql","rbac","zero-dependency"],"author":{"name":"1moby"},"license":"MIT","_id":"@1moby/just-auth@0.1.1","maintainers":[{"name":"mynameisanu","email":"anu@anusoft.biz"}],"homepage":"https://github.com/1moby/just-auth#readme","bugs":{"url":"https://github.com/1moby/just-auth/issues"},"dist":{"shasum":"85efc2a18b72c7faf9b74ecb6b83259e5cd0d460","tarball":"https://registry.npmjs.org/@1moby/just-auth/-/just-auth-0.1.1.tgz","fileCount":144,"integrity":"sha512-lCxeCrTC/riQEdp8lTM/kzxxnMs6XlXyrc6/jtieRLsMXz7m/y+yjTAMO9RcqcSOIJ2h9rDvM79ZUhPzOvjf9w==","signatures":[{"sig":"MEYCIQCewk4YbHhByHMFhuvWqIRvEf45TDSuFmxOnfQSfUg6EAIhANM65NCVoo4zsvc97vciCJKxMp2RcnaAPvdJoxh1nQE5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":267747},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./src/index.ts"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./src/client/index.ts"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./src/server/index.ts"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.js","default":"./src/middleware/index.ts"},"./adapters/d1":{"types":"./dist/adapters/d1.d.ts","import":"./dist/adapters/d1.js","default":"./src/adapters/d1.ts"},"./adapters/pg":{"types":"./dist/adapters/pg.d.ts","import":"./dist/adapters/pg.js","default":"./src/adapters/pg.ts"},"./adapters/mysql":{"types":"./dist/adapters/mysql.d.ts","import":"./dist/adapters/mysql.js","default":"./src/adapters/mysql.ts"},"./adapters/bun-sql":{"types":"./dist/adapters/bun-sql.d.ts","import":"./dist/adapters/bun-sql.js","default":"./src/adapters/bun-sql.ts"},"./adapters/bun-sqlite":{"types":"./dist/adapters/bun-sqlite.d.ts","import":"./dist/adapters/bun-sqlite.js","default":"./src/adapters/bun-sqlite.ts"}},"gitHead":"4c98a3af65af850fa50cf26d732d75c046aa2d31","scripts":{"test":"bun test","build":"bun scripts/build.ts","prepare":"bun scripts/build.ts","prepublishOnly":"bun run build"},"_npmUser":{"name":"mynameisanu","email":"anu@anusoft.biz"},"repository":{"url":"git+https://github.com/1moby/just-auth.git","type":"git"},"_npmVersion":"10.9.4","description":"Lightweight zero-dependency edge-native auth library for React","directories":{},"sideEffects":false,"_nodeVersion":"22.22.0","_hasShrinkwrap":false,"devDependencies":{"react":"^19.2.4","@types/bun":"latest","typescript":"^5","@types/react":"^19.2.14"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/just-auth_0.1.1_1774944101542_0.1280731748852144","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@1moby/just-auth","version":"0.1.2","keywords":["auth","authentication","oauth","react","session","edge","cloudflare","workers","d1","sqlite","postgres","mysql","rbac","zero-dependency"],"author":{"name":"1moby"},"license":"MIT","_id":"@1moby/just-auth@0.1.2","maintainers":[{"name":"mynameisanu","email":"anu@anusoft.biz"}],"homepage":"https://github.com/1moby/just-auth#readme","bugs":{"url":"https://github.com/1moby/just-auth/issues"},"dist":{"shasum":"df0f079ea07c56842f183f6eb8e7dfa4e93c0e5f","tarball":"https://registry.npmjs.org/@1moby/just-auth/-/just-auth-0.1.2.tgz","fileCount":144,"integrity":"sha512-YMMVVr1CQvdygW9TbyabIhtPKbYaS+K1CLgb56vH5t/NViNLJiJPXhYkwkzwLi0xAuzo236p/RSsIOtOXk8x4w==","signatures":[{"sig":"MEUCICk3+z48424Oi6KGXck1rc2nb+asWxMXtGeI2FV2po1sAiEA+dIQwKF+8vUkYDFrYcHOGf2SWWEaY6MW3N3I0bxX4sw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":277546},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./src/index.ts"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./src/client/index.ts"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./src/server/index.ts"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.js","default":"./src/middleware/index.ts"},"./adapters/d1":{"types":"./dist/adapters/d1.d.ts","import":"./dist/adapters/d1.js","default":"./src/adapters/d1.ts"},"./adapters/pg":{"types":"./dist/adapters/pg.d.ts","import":"./dist/adapters/pg.js","default":"./src/adapters/pg.ts"},"./adapters/mysql":{"types":"./dist/adapters/mysql.d.ts","import":"./dist/adapters/mysql.js","default":"./src/adapters/mysql.ts"},"./adapters/bun-sql":{"types":"./dist/adapters/bun-sql.d.ts","import":"./dist/adapters/bun-sql.js","default":"./src/adapters/bun-sql.ts"},"./adapters/bun-sqlite":{"types":"./dist/adapters/bun-sqlite.d.ts","import":"./dist/adapters/bun-sqlite.js","default":"./src/adapters/bun-sqlite.ts"}},"gitHead":"c047f8feb1369bac971ce460433f04b2f5adb3c5","scripts":{"test":"bun test","build":"bun scripts/build.ts","prepare":"bun scripts/build.ts","prepublishOnly":"bun run build"},"_npmUser":{"name":"mynameisanu","email":"anu@anusoft.biz"},"repository":{"url":"git+https://github.com/1moby/just-auth.git","type":"git"},"_npmVersion":"10.9.4","description":"Lightweight zero-dependency edge-native auth library for React","directories":{},"sideEffects":false,"_nodeVersion":"22.22.0","_hasShrinkwrap":false,"devDependencies":{"react":"^19.2.4","@types/bun":"latest","typescript":"^5","@types/react":"^19.2.14"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/just-auth_0.1.2_1775123689216_0.8268793627038058","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@1moby/just-auth","version":"0.2.1","keywords":["auth","authentication","oauth","react","session","edge","cloudflare","workers","d1","sqlite","postgres","mysql","rbac","zero-dependency"],"author":{"name":"1moby"},"license":"MIT","_id":"@1moby/just-auth@0.2.1","maintainers":[{"name":"mynameisanu","email":"anu@anusoft.biz"}],"homepage":"https://github.com/1moby/just-auth#readme","bugs":{"url":"https://github.com/1moby/just-auth/issues"},"dist":{"shasum":"0aff60383d9fc2d85b34caaf926573b34e521d00","tarball":"https://registry.npmjs.org/@1moby/just-auth/-/just-auth-0.2.1.tgz","fileCount":144,"integrity":"sha512-VgyNJWDDI88quc/o7m60TByGCBqQRtiGPUkYMLFKUOj9wH58Qw+CrUOVomEtHNwX4sxQPdGkJK8sHhX1n5GUsA==","signatures":[{"sig":"MEUCIQDAtJjd/+DPmSB2IDXie/TSnCjcL2WNbHCz+YWdGoJ9YwIgeFCU9Zjewcu+pRtZYT15qFSovKfMyd5eoJi4m+B7GsQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":296427},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./src/index.ts"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./src/client/index.ts"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./src/server/index.ts"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.js","default":"./src/middleware/index.ts"},"./adapters/d1":{"types":"./dist/adapters/d1.d.ts","import":"./dist/adapters/d1.js","default":"./src/adapters/d1.ts"},"./adapters/pg":{"types":"./dist/adapters/pg.d.ts","import":"./dist/adapters/pg.js","default":"./src/adapters/pg.ts"},"./adapters/mysql":{"types":"./dist/adapters/mysql.d.ts","import":"./dist/adapters/mysql.js","default":"./src/adapters/mysql.ts"},"./adapters/bun-sql":{"types":"./dist/adapters/bun-sql.d.ts","import":"./dist/adapters/bun-sql.js","default":"./src/adapters/bun-sql.ts"},"./adapters/bun-sqlite":{"types":"./dist/adapters/bun-sqlite.d.ts","import":"./dist/adapters/bun-sqlite.js","default":"./src/adapters/bun-sqlite.ts"}},"gitHead":"310d55eeb3bd6349f156caf09490c7a18070337a","scripts":{"test":"bun test","build":"bun scripts/build.ts","prepare":"bun scripts/build.ts","prepublishOnly":"bun run build"},"_npmUser":{"name":"mynameisanu","email":"anu@anusoft.biz"},"repository":{"url":"git+https://github.com/1moby/just-auth.git","type":"git"},"_npmVersion":"10.9.4","description":"Lightweight zero-dependency edge-native auth library for React","directories":{},"sideEffects":false,"_nodeVersion":"22.22.0","_hasShrinkwrap":false,"devDependencies":{"react":"^19.2.4","@types/bun":"latest","typescript":"^5","@types/react":"^19.2.14"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/just-auth_0.2.1_1776433990106_0.7443651459171168","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@1moby/just-auth","version":"0.3.0","keywords":["auth","authentication","oauth","react","session","edge","cloudflare","workers","d1","sqlite","postgres","mysql","rbac","zero-dependency"],"author":{"name":"1moby"},"license":"MIT","_id":"@1moby/just-auth@0.3.0","maintainers":[{"name":"mynameisanu","email":"anu@anusoft.biz"}],"homepage":"https://github.com/1moby/just-auth#readme","bugs":{"url":"https://github.com/1moby/just-auth/issues"},"dist":{"shasum":"fdff25cba21106cf9bc209c28dffd82a73bbe0d0","tarball":"https://registry.npmjs.org/@1moby/just-auth/-/just-auth-0.3.0.tgz","fileCount":144,"integrity":"sha512-BWczG7sNFkpAvJEuxctVWemSZp3hMMUcu/5+T/Yi2xaOZIpazKASkCqwylLpvvIgfK1nnHgFX/Pa325dLcTarg==","signatures":[{"sig":"MEUCIAJOvOfHDNwkFvDtPqwDDOSkWxn+UmDIAX4WD0iGQCUDAiEA7vc15azKZDQF9U/bknfGLj/rZAH9EejH5nv6cN800GM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":299818},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./src/index.ts"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./src/client/index.ts"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./src/server/index.ts"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.js","default":"./src/middleware/index.ts"},"./adapters/d1":{"types":"./dist/adapters/d1.d.ts","import":"./dist/adapters/d1.js","default":"./src/adapters/d1.ts"},"./adapters/pg":{"types":"./dist/adapters/pg.d.ts","import":"./dist/adapters/pg.js","default":"./src/adapters/pg.ts"},"./adapters/mysql":{"types":"./dist/adapters/mysql.d.ts","import":"./dist/adapters/mysql.js","default":"./src/adapters/mysql.ts"},"./adapters/bun-sql":{"types":"./dist/adapters/bun-sql.d.ts","import":"./dist/adapters/bun-sql.js","default":"./src/adapters/bun-sql.ts"},"./adapters/bun-sqlite":{"types":"./dist/adapters/bun-sqlite.d.ts","import":"./dist/adapters/bun-sqlite.js","default":"./src/adapters/bun-sqlite.ts"}},"gitHead":"9dda694154d05262499592967c152286215d1345","scripts":{"test":"bun test","build":"bun scripts/build.ts","prepare":"bun scripts/build.ts","prepublishOnly":"bun run build"},"_npmUser":{"name":"mynameisanu","email":"anu@anusoft.biz"},"repository":{"url":"git+https://github.com/1moby/just-auth.git","type":"git"},"_npmVersion":"10.9.4","description":"Lightweight zero-dependency edge-native auth library for React","directories":{},"sideEffects":false,"_nodeVersion":"22.22.0","_hasShrinkwrap":false,"devDependencies":{"react":"^19.2.4","@types/bun":"latest","typescript":"^5","@types/react":"^19.2.14"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/just-auth_0.3.0_1776492892173_0.2272135184148376","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@1moby/just-auth","version":"0.4.1","keywords":["auth","authentication","oauth","react","session","edge","cloudflare","workers","d1","sqlite","postgres","mysql","rbac","clickhouse","approvals","zero-dependency"],"author":{"name":"1moby"},"license":"MIT","_id":"@1moby/just-auth@0.4.1","maintainers":[{"name":"mynameisanu","email":"anu@anusoft.biz"}],"homepage":"https://github.com/1moby/just-auth#readme","bugs":{"url":"https://github.com/1moby/just-auth/issues"},"dist":{"shasum":"40d2c25448edfb9309cc8defd4030454795e4a53","tarball":"https://registry.npmjs.org/@1moby/just-auth/-/just-auth-0.4.1.tgz","fileCount":194,"integrity":"sha512-W/tgpLPxxnDop5hYmWGPNJLLtDEwhCCqJCDRYY4GZL4pmvAJbp3ReiZUFWPCntp5NzIsio3cgBYJKqQS+qr2FA==","signatures":[{"sig":"MEUCIAWaykm3w1i+WcfG9OFFEh0vhe7QyxHGDgDvzOf3cVgJAiEAhqkyrXgubYz4ODk+0aXI2LE5sJ8GpzMj8eNOBAibAfY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":492864},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./src/index.ts"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./src/client/index.ts"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./src/server/index.ts"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.js","default":"./src/middleware/index.ts"},"./adapters/d1":{"types":"./dist/adapters/d1.d.ts","import":"./dist/adapters/d1.js","default":"./src/adapters/d1.ts"},"./adapters/pg":{"types":"./dist/adapters/pg.d.ts","import":"./dist/adapters/pg.js","default":"./src/adapters/pg.ts"},"./adapters/mysql":{"types":"./dist/adapters/mysql.d.ts","import":"./dist/adapters/mysql.js","default":"./src/adapters/mysql.ts"},"./adapters/bun-sql":{"types":"./dist/adapters/bun-sql.d.ts","import":"./dist/adapters/bun-sql.js","default":"./src/adapters/bun-sql.ts"},"./adapters/bun-sqlite":{"types":"./dist/adapters/bun-sqlite.d.ts","import":"./dist/adapters/bun-sqlite.js","default":"./src/adapters/bun-sqlite.ts"},"./adapters/clickhouse":{"types":"./dist/adapters/clickhouse/index.d.ts","import":"./dist/adapters/clickhouse/index.js","default":"./src/adapters/clickhouse/index.ts"}},"gitHead":"5beba6dce63d34a2c26e5909a91e348fa5537a7c","scripts":{"test":"bun test","build":"bun scripts/build.ts","prepare":"bun scripts/build.ts","prepublishOnly":"bun run build"},"_npmUser":{"name":"mynameisanu","email":"anu@anusoft.biz"},"repository":{"url":"git+https://github.com/1moby/just-auth.git","type":"git"},"_npmVersion":"10.9.4","description":"Lightweight zero-dependency edge-native auth library for React","directories":{},"sideEffects":false,"_nodeVersion":"22.22.0","_hasShrinkwrap":false,"devDependencies":{"react":"^19.2.4","@types/bun":"latest","typescript":"^5","@types/react":"^19.2.14","@clickhouse/client":"^1.13.3"},"peerDependencies":{"react":">=18","@clickhouse/client":">=1.0.0"},"peerDependenciesMeta":{"@clickhouse/client":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/just-auth_0.4.1_1777276142798_0.5329317263863003","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"name":"@1moby/just-auth","version":"0.4.2","keywords":["auth","authentication","oauth","react","session","edge","cloudflare","workers","d1","sqlite","postgres","mysql","rbac","clickhouse","approvals","zero-dependency"],"author":{"name":"1moby"},"license":"MIT","_id":"@1moby/just-auth@0.4.2","maintainers":[{"name":"mynameisanu","email":"anu@anusoft.biz"}],"homepage":"https://github.com/1moby/just-auth#readme","bugs":{"url":"https://github.com/1moby/just-auth/issues"},"dist":{"shasum":"18a776bcecacccb430604dca7a5e987e0c1db3b0","tarball":"https://registry.npmjs.org/@1moby/just-auth/-/just-auth-0.4.2.tgz","fileCount":194,"integrity":"sha512-MIVYwUSFg5McFCU0sZkW32n/1t/7rGxhvOQanWtEgnoEwkFfXqWZHIaiHgZD2aodBy1L1nglVXLkDSaMq6qPBg==","signatures":[{"sig":"MEUCIF7ppuD+5gYynuhn40OthEdyNAPUuVmHAm9asbAXOzAQAiEA2g/IiL3y5L40komQju1pc8erLXS+FfAljJJ1xTY+D/4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":494596},"type":"module","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./src/index.ts"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./src/client/index.ts"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./src/server/index.ts"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.js","default":"./src/middleware/index.ts"},"./adapters/d1":{"types":"./dist/adapters/d1.d.ts","import":"./dist/adapters/d1.js","default":"./src/adapters/d1.ts"},"./adapters/pg":{"types":"./dist/adapters/pg.d.ts","import":"./dist/adapters/pg.js","default":"./src/adapters/pg.ts"},"./adapters/mysql":{"types":"./dist/adapters/mysql.d.ts","import":"./dist/adapters/mysql.js","default":"./src/adapters/mysql.ts"},"./adapters/bun-sql":{"types":"./dist/adapters/bun-sql.d.ts","import":"./dist/adapters/bun-sql.js","default":"./src/adapters/bun-sql.ts"},"./adapters/bun-sqlite":{"types":"./dist/adapters/bun-sqlite.d.ts","import":"./dist/adapters/bun-sqlite.js","default":"./src/adapters/bun-sqlite.ts"},"./adapters/clickhouse":{"types":"./dist/adapters/clickhouse/index.d.ts","import":"./dist/adapters/clickhouse/index.js","default":"./src/adapters/clickhouse/index.ts"}},"gitHead":"2359e27a9f4c7ad4a8b786d2d15c9707766b3784","scripts":{"test":"bun test","build":"bun scripts/build.ts","prepare":"bun scripts/build.ts","prepublishOnly":"bun run build"},"_npmUser":{"name":"mynameisanu","email":"anu@anusoft.biz"},"repository":{"url":"git+https://github.com/1moby/just-auth.git","type":"git"},"_npmVersion":"10.9.4","description":"Lightweight zero-dependency edge-native auth library for React","directories":{},"sideEffects":false,"_nodeVersion":"22.22.0","_hasShrinkwrap":false,"devDependencies":{"react":"^19.2.4","@types/bun":"latest","typescript":"^5","@types/react":"^19.2.14","@clickhouse/client":"^1.13.3"},"peerDependencies":{"react":">=18","@clickhouse/client":">=1.0.0"},"peerDependenciesMeta":{"@clickhouse/client":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/just-auth_0.4.2_1777280398098_0.15976025288335371","host":"s3://npm-registry-packages-npm-production"}},"0.4.3":{"name":"@1moby/just-auth","version":"0.4.3","description":"Lightweight zero-dependency edge-native auth library for React","type":"module","sideEffects":false,"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./src/index.ts"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.js","default":"./src/client/index.ts"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.js","default":"./src/server/index.ts"},"./middleware":{"types":"./dist/middleware/index.d.ts","import":"./dist/middleware/index.js","default":"./src/middleware/index.ts"},"./adapters/d1":{"types":"./dist/adapters/d1.d.ts","import":"./dist/adapters/d1.js","default":"./src/adapters/d1.ts"},"./adapters/bun-sqlite":{"types":"./dist/adapters/bun-sqlite.d.ts","import":"./dist/adapters/bun-sqlite.js","default":"./src/adapters/bun-sqlite.ts"},"./adapters/pg":{"types":"./dist/adapters/pg.d.ts","import":"./dist/adapters/pg.js","default":"./src/adapters/pg.ts"},"./adapters/mysql":{"types":"./dist/adapters/mysql.d.ts","import":"./dist/adapters/mysql.js","default":"./src/adapters/mysql.ts"},"./adapters/bun-sql":{"types":"./dist/adapters/bun-sql.d.ts","import":"./dist/adapters/bun-sql.js","default":"./src/adapters/bun-sql.ts"},"./adapters/clickhouse":{"types":"./dist/adapters/clickhouse/index.d.ts","import":"./dist/adapters/clickhouse/index.js","default":"./src/adapters/clickhouse/index.ts"}},"scripts":{"build":"bun scripts/build.ts","prepare":"bun scripts/build.ts","test":"bun test","prepublishOnly":"bun run build"},"keywords":["auth","authentication","oauth","react","session","edge","cloudflare","workers","d1","sqlite","postgres","mysql","rbac","clickhouse","approvals","zero-dependency"],"author":{"name":"1moby"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/1moby/just-auth.git"},"homepage":"https://github.com/1moby/just-auth#readme","bugs":{"url":"https://github.com/1moby/just-auth/issues"},"peerDependencies":{"@clickhouse/client":">=1.0.0","react":">=18"},"peerDependenciesMeta":{"@clickhouse/client":{"optional":true}},"devDependencies":{"@clickhouse/client":"^1.13.3","@types/bun":"latest","@types/react":"^19.2.14","react":"^19.2.4","typescript":"^5"},"_id":"@1moby/just-auth@0.4.3","gitHead":"0bde54d319de096b84cc13471ba503f081c854b9","_nodeVersion":"22.22.0","_npmVersion":"10.9.4","dist":{"integrity":"sha512-3ymWTxhkPMjOeagaxAEWPSsSa2HdC1F92/9LIEoHijCWOvXAqKS1elr8P4AXn9yLPXseEiic7C/CsvpD5adE9g==","shasum":"0997ba58709706a3582b276937be471c453e89d0","tarball":"https://registry.npmjs.org/@1moby/just-auth/-/just-auth-0.4.3.tgz","fileCount":194,"unpackedSize":585370,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCcTsmXu9/uZ5sYWndDlAHHz8q5Z9MTgrcB8JnoMd9HkgIgXv5ACPkVPZT+1rZ8SwT5BqHww0ecXTltTgEGQD5rRWw="}]},"_npmUser":{"name":"mynameisanu","email":"anu@anusoft.biz"},"directories":{},"maintainers":[{"name":"mynameisanu","email":"anu@anusoft.biz"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/just-auth_0.4.3_1777299311632_0.9509342825192744"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-24T08:08:14.832Z","modified":"2026-04-27T14:15:12.103Z","0.1.0":"2026-03-24T08:08:15.015Z","0.1.1":"2026-03-31T08:01:41.702Z","0.1.2":"2026-04-02T09:54:49.407Z","0.2.1":"2026-04-17T13:53:10.247Z","0.3.0":"2026-04-18T06:14:52.309Z","0.4.1":"2026-04-27T07:49:02.956Z","0.4.2":"2026-04-27T08:59:58.238Z","0.4.3":"2026-04-27T14:15:11.974Z"},"bugs":{"url":"https://github.com/1moby/just-auth/issues"},"author":{"name":"1moby"},"license":"MIT","homepage":"https://github.com/1moby/just-auth#readme","keywords":["auth","authentication","oauth","react","session","edge","cloudflare","workers","d1","sqlite","postgres","mysql","rbac","clickhouse","approvals","zero-dependency"],"repository":{"type":"git","url":"git+https://github.com/1moby/just-auth.git"},"description":"Lightweight zero-dependency edge-native auth library for React","maintainers":[{"name":"mynameisanu","email":"anu@anusoft.biz"}],"readme":"# @1moby/just-auth\n\nLightweight, zero-dependency, edge-native auth library for React.\n\nOAuth 2.0 + PKCE, email/password, session management, RBAC, route-level middleware, and (with the ClickHouse adapter) a multi-org permission graph + approval-flow primitives — all built on Web Crypto API and raw SQL. Works with Cloudflare Workers, Bun, Deno, Next.js, and any runtime that supports standard `Request`/`Response`.\n\n## Features\n\n- **Zero runtime dependencies** — only React as a peer dep (`@clickhouse/client` is an optional peer for the CH adapter)\n- **OAuth 2.0 + PKCE** — built-in providers for Google, GitHub, LINE\n- **Email/password auth** — PBKDF2-SHA256 (600k iterations), timing-safe comparison\n- **Account linking** — multiple providers share one user account via email matching (`allowEmailAccountLinking`)\n- **Lifecycle callbacks** — `signIn` to gate OAuth sign-in + inject extra user columns; `session` to customize the `/api/auth/session` response body\n- **Session management** — sliding window (30-day sessions, auto-extend at 15 days), SHA-256 hashed tokens\n- **RBAC** — optional role-based access control with code-defined permissions; multi-role per user, role inheritance, deny rules\n- **Email/domain restriction** — `allowedEmails` config to restrict by domain or custom function\n- **Route permission middleware** — `createAuthMiddleware` for path-based permission gating\n- **Database adapters** — D1, bun:sqlite, pg, mysql2, Bun.sql, ClickHouse — bring your own driver\n- **ClickHouse extras (experimental)** — multi-org / department / supervisor permission graph (`adapter.rbac`) + approval-flow state machine (`adapter.approvals`); integration-tested against CH 24.8 / 25.3 / 25.10\n- **Table prefix** — `tablePrefix: \"myapp_\"` for shared databases\n- **Non-destructive migrations** — validates existing schema, never ALTER or DROP\n- **Security hardened** — open redirect protection, password length limits, POST-only logout\n- **Edge-native** — standard `Request`/`Response`, no Node.js-specific APIs\n\n## Install\n\n```bash\nbun add @1moby/just-auth\n# or\nnpm install @1moby/just-auth\n```\n\n## Quick Start\n\n### 1. Choose a Database Adapter\n\n```ts\n// Cloudflare D1\nimport { createD1Adapter } from \"@1moby/just-auth/adapters/d1\";\nconst db = createD1Adapter(env.DB);\n\n// bun:sqlite\nimport { createBunSQLiteAdapter } from \"@1moby/just-auth/adapters/bun-sqlite\";\nconst db = createBunSQLiteAdapter(new Database(\"auth.db\"));\n\n// PostgreSQL (pg)\nimport { createPgAdapter } from \"@1moby/just-auth/adapters/pg\";\nconst db = createPgAdapter(new Pool({ connectionString: env.DATABASE_URL }));\n\n// MySQL (mysql2)\nimport { createMySQLAdapter } from \"@1moby/just-auth/adapters/mysql\";\nconst db = createMySQLAdapter(pool);\n\n// Bun.sql (Postgres or MySQL)\nimport { createBunSQLAdapter } from \"@1moby/just-auth/adapters/bun-sql\";\nconst db = createBunSQLAdapter(Bun.sql);\nconst db = createBunSQLAdapter(Bun.sql, { dialect: \"mysql\" });\n```\n\nOnly the adapter you import gets bundled. Drivers are peer dependencies — install what you need.\n\n### 2. Run Migrations\n\n```ts\nimport { migrate } from \"@1moby/just-auth\";\n\nawait migrate(db);\n// With table prefix:\nawait migrate(db, { tablePrefix: \"myapp_\" });\n```\n\nMigrations are non-destructive: creates tables if missing, validates existing schema, never alters or drops existing tables.\n\n### 3. Server Setup\n\n```ts\nimport {\n  createReactAuth,\n  createGoogleProvider,\n  createGitHubProvider,\n} from \"@1moby/just-auth\";\n\nconst auth = createReactAuth({\n  providers: [\n    createGoogleProvider({\n      clientId: env.GOOGLE_CLIENT_ID,\n      clientSecret: env.GOOGLE_CLIENT_SECRET,\n      redirectURI: \"https://example.com/api/auth/callback/google\",\n    }),\n    createGitHubProvider({\n      clientId: env.GITHUB_CLIENT_ID,\n      clientSecret: env.GITHUB_CLIENT_SECRET,\n      redirectURI: \"https://example.com/api/auth/callback/github\",\n    }),\n  ],\n  database: db,\n  credentials: true,\n  oauthAutoCreateAccount: true,\n  allowEmailAccountLinking: true,\n});\n\n// Handle auth routes\nconst response = await auth.handleRequest(request);\nif (response) return response;\n```\n\n### 4. Protect Server Routes\n\n```ts\nconst session = await auth.auth(request);\nif (!session) {\n  return new Response(\"Unauthorized\", { status: 401 });\n}\n// session.user = { id, email, name, avatarUrl, role }\n```\n\n### 5. React Client\n\n```tsx\nimport { SessionProvider, useSession, signIn, signOut } from \"@1moby/just-auth/client\";\n\nfunction App() {\n  return (\n    <SessionProvider>\n      <Profile />\n    </SessionProvider>\n  );\n}\n\nfunction Profile() {\n  const { data, status } = useSession();\n\n  if (status === \"loading\") return <p>Loading...</p>;\n  if (status === \"unauthenticated\") return <button onClick={() => signIn(\"google\")}>Sign In</button>;\n\n  return (\n    <div>\n      <p>Hello, {data.user.name}</p>\n      <button onClick={() => signOut()}>Sign Out</button>\n    </div>\n  );\n}\n```\n\n### 6. Email/Password\n\n```tsx\nimport { signIn, signUp } from \"@1moby/just-auth/client\";\n\n// Register\nconst res = await signUp({ email: \"user@example.com\", password: \"secret123\" });\n\n// Login\nconst res = await signIn(\"credentials\", { email: \"user@example.com\", password: \"secret123\" });\n```\n\n## Configuration\n\n```ts\ncreateReactAuth({\n  providers: [...],\n  database: db,\n\n  // Auth options\n  basePath: \"/api/auth\",               // default: \"/api/auth\"\n  credentials: true,                   // enable email/password auth\n  allowRegistration: true,             // allow self-registration (default: true when credentials enabled)\n  oauthAutoCreateAccount: true,        // auto-create users on OAuth login (default: false)\n  allowEmailAccountLinking: true,      // link accounts by verified email match (default: false)\n  passwordMinLength: 8,               // default: 8, max: 128\n\n  // Email restriction\n  allowedEmails: [\"@1moby.com\"],       // domain allowlist\n  // or: allowedEmails: (email) => email.endsWith(\"@1moby.com\"),\n\n  // Table prefix for shared databases\n  tablePrefix: \"myapp_\",              // → myapp_users, myapp_accounts, myapp_sessions\n\n  // Cookie options\n  cookie: {\n    name: \"auth_session\",             // default: \"auth_session\"\n    secure: true,                     // default: true\n    sameSite: \"lax\",                  // default: \"lax\"\n    domain: \".example.com\",           // for subdomain sharing\n    path: \"/\",                        // default: \"/\"\n  },\n\n  // Session options\n  session: {\n    maxAge: 30 * 86400,               // 30 days (seconds)\n    refreshThreshold: 15 * 86400,     // extend when < 15 days remaining\n  },\n\n  // RBAC (see full RBAC section below)\n  rbac: {\n    statements: {\n      post: [\"create\", \"read\", \"update\", \"delete\"],\n      user: [\"list\", \"ban\", \"set-role\"],\n    },\n    roles: {\n      user: { post: [\"read\"] },\n      admin: \"*\",  // wildcard = all permissions\n    },\n    defaultRole: \"user\",\n  },\n\n  // Custom error redirect target (used by signIn callback rejections)\n  pages: { error: \"/auth/error\" },\n\n  // Lifecycle callbacks (see \"Hooks\" section)\n  callbacks: {\n    signIn: async (ctx) => ({ allow: true }),\n    session: async ({ user, session }) => ({ user, session }),\n  },\n});\n```\n\n## Email-based account linking\n\nWhen a user signs in via OAuth and their `(provider_id, provider_user_id)` has no matching row in `accounts`, but their profile email matches an existing user, the default behavior is to reject with `OAuthAccountNotLinked` (HTTP 403). Set `allowEmailAccountLinking: true` to instead link the incoming OAuth account to the existing user.\n\n```ts\ncreateReactAuth({\n  // ...\n  allowEmailAccountLinking: true,\n});\n```\n\n**Trust implication.** Linking by email is safe only when you trust the identity provider to verify the email (e.g. Google Workspace with a hosted-domain restriction, or a corporate IdP). If a provider lets users sign up with unverified emails, a malicious user could claim ownership of another user's email and get their account linked.\n\nWhen a link occurs, the `signIn` callback (if set) is invoked with `ctx.emailLinked === true` and `ctx.existingUserId` set to the linked user's id — useful for audit logs:\n\n```ts\ncallbacks: {\n  signIn: async (ctx) => {\n    if (ctx.emailLinked) {\n      await auditLog.record({ event: \"oauth_account_linked\", userId: ctx.existingUserId, provider: ctx.provider });\n    }\n    return { allow: true };\n  },\n}\n```\n\nThe older `allowDangerousEmailAccountLinking` flag still works as an alias for backward compatibility but is deprecated; prefer `allowEmailAccountLinking` in new code.\n\n## Hooks\n\nTwo optional lifecycle callbacks let consumers intercept sign-in and customize the session response without forking the library. Both are plain async functions on `AuthConfig.callbacks`.\n\n### `signIn` — gate OAuth sign-in, inject extra columns\n\nFires inside the OAuth callback handler, **after** token exchange and user lookup but **before** any user or account row is written. Return `{ allow: false, reason }` to abort (the user is redirected to `pages.error ?? \"/\"` with `?error=REASON`). Return `{ allow: true, userOverrides }` to continue; `userOverrides` is merged into the `users` INSERT as extra columns — only applied when a new user is being created. The base identity columns (`id`, `email`, `name`, `avatar_url`) cannot be overridden. The `role` column IS overridable — you can assign an initial role to the new user via `userOverrides: { role: \"admin\" }`. Use with care; the library does not validate role names.\n\n```ts\nimport type { AuthConfig } from \"@1moby/just-auth\";\n\nexport const authConfig: AuthConfig = {\n  // ... providers, database, etc.\n  pages: { error: \"/auth/error\" },\n  callbacks: {\n    signIn: async (ctx) => {\n      if (!ctx.profile.email?.endsWith(\"@1moby.com\")) {\n        return { allow: false, reason: \"DOMAIN_BLOCKED\" };\n      }\n      // Optional: look up invitation, attach org_id\n      return {\n        allow: true,\n        userOverrides: { org_id: \"the-org-uuid\" },\n      };\n    },\n  },\n};\n```\n\nExtra columns must already exist on the `users` table — the library never ALTERs existing tables. Column names are validated against `/^[a-zA-Z_][a-zA-Z0-9_]*$/` before being interpolated into the INSERT; values use parameter binding.\n\n### `session` — customize the `/api/auth/session` response\n\nFires on every `GET /api/auth/session` call, after the session + user are loaded. Whatever you return becomes the response body verbatim (the default `{ user, session, accounts, permissions }` shape is bypassed entirely — include what you need).\n\n```ts\ncallbacks: {\n  session: async ({ user, session }) => {\n    const roles = await fetchRolesFor(user.id);\n    return { user, roles, sessionExpiresAt: session.expiresAt };\n  },\n}\n```\n\nWith no `callbacks.session` set, the default response shape is unchanged from 0.1.x.\n\n## RBAC\n\nSupports multi-role per user, role inheritance, and deny rules — all backward-compatible with single-role setups.\n\n### Basic (single role)\n\n```ts\nrbac: {\n  statements: {\n    post: [\"create\", \"read\", \"update\", \"delete\"],\n    user: [\"list\", \"ban\", \"set-role\"],\n  },\n  roles: {\n    viewer: { post: [\"read\"] },\n    admin: \"*\",  // all permissions\n  },\n  defaultRole: \"viewer\",\n}\n```\n\n### Multi-role\n\nMultiple roles stored as comma-separated string in the same `role` column (`\"user,editor\"`):\n\n```ts\n// Assign multiple roles\nPOST /api/auth/role\n{ userId: \"u1\", roles: [\"user\", \"editor\"] }\n\n// Add a role incrementally\n{ userId: \"u1\", addRole: \"editor\" }\n\n// Remove a role\n{ userId: \"u1\", removeRole: \"admin\" }\n```\n\n### Role Inheritance\n\n```ts\nroles: {\n  viewer: { post: [\"read\"] },\n  editor: {\n    allow: { post: [\"create\", \"read\", \"update\"] },\n    inherits: [\"viewer\"],  // gets all viewer permissions\n  },\n  moderator: {\n    allow: { user: [\"list\", \"ban\"] },\n    inherits: [\"editor\"],  // editor → viewer chain\n  },\n}\n```\n\n### Deny Rules (deny always wins)\n\n```ts\nroles: {\n  moderator: {\n    allow: { user: [\"list\", \"ban\", \"set-role\"] },\n    deny: { user: [\"set-role\"] },  // can ban but can't change roles\n  },\n  admin: {\n    allow: \"*\",\n    deny: { billing: [\"manage\"] },  // can view but not manage billing\n  },\n  superadmin: \"*\",  // unrestricted\n}\n```\n\n### Server API\n\n```ts\nconst canEdit = await auth.hasPermission(request, \"post:update\");\nconst isAdmin = await auth.hasRole(request, \"admin\");     // multi-role aware\nconst roles = await auth.getRoles(request);                // [\"user\", \"editor\"]\n```\n\n### Client API\n\n```tsx\nimport { usePermission, useRole } from \"@1moby/just-auth/client\";\n\nconst canEdit = usePermission(\"post:update\");\nconst isAdmin = useRole(\"admin\");  // works with \"user,admin\" multi-role\n```\n\n## Route Permission Middleware\n\n```ts\nimport { createAuthMiddleware } from \"@1moby/just-auth/middleware\";\n\nconst { handle } = createAuthMiddleware(auth, {\n  publicPaths: [\"/login\", \"/public/*\"],\n  loginRedirect: \"/login\",\n  routePermissions: {\n    \"/admin/*\": \"admin:access\",\n    \"/api/admin/*\": \"admin:access\",\n  },\n  onForbidden: (req) => new Response(\"Forbidden\", { status: 403 }),\n});\n\n// In your server:\nconst blocked = await handle(request);\nif (blocked) return blocked;\n// ...proceed with normal routing\n```\n\nAuto-skips static files (`.js`, `.css`, `.png`, etc.). Supports exact paths and glob patterns.\n\n## Auth Routes\n\nDefault `basePath: \"/api/auth\"`:\n\n| Route | Method | Description |\n|-------|--------|-------------|\n| `/api/auth/login/:provider` | GET | Redirect to OAuth provider |\n| `/api/auth/callback/:provider` | GET | Handle OAuth callback, create session |\n| `/api/auth/register` | POST | Register with email/password |\n| `/api/auth/callback/credentials` | POST | Login with email/password |\n| `/api/auth/session` | GET | Return session JSON + linked accounts + permissions |\n| `/api/auth/role` | POST | Set user role (requires `user:set-role` permission) |\n| `/api/auth/logout` | POST | Invalidate session, return `{ ok: true }` |\n\n## Database Adapters\n\nBring your own driver — only the adapter you import gets bundled:\n\n```ts\nimport { createD1Adapter } from \"@1moby/just-auth/adapters/d1\";\nimport { createBunSQLiteAdapter } from \"@1moby/just-auth/adapters/bun-sqlite\";\nimport { createPgAdapter } from \"@1moby/just-auth/adapters/pg\";\nimport { createMySQLAdapter } from \"@1moby/just-auth/adapters/mysql\";\nimport { createBunSQLAdapter } from \"@1moby/just-auth/adapters/bun-sql\";\n```\n\nThe Pg and Bun.sql adapters auto-translate `?` placeholders to `$1, $2, ...`. Schema uses portable types (`VARCHAR(255)`, `BIGINT`, `TEXT`) that work across SQLite, Postgres, and MySQL.\n\nYou can also implement the `DatabaseAdapter` interface directly for any custom driver.\n\n## ClickHouse adapter (experimental)\n\n`@1moby/just-auth/adapters/clickhouse` is a drop-in replacement for the SQL adapters that backs auth state on ClickHouse `ReplacingMergeTree` tables, plus exposes two extra APIs on the same adapter object:\n\n- `adapter.rbac` — a multi-org / department / supervisor permission graph.\n- `adapter.approvals` — an approval-flow state machine (open / decide / delegate / expire).\n- `adapter.migrate()` — idempotent DDL setup, cluster-aware.\n\n```ts\nimport { createClient } from \"@clickhouse/client\";\nimport { createClickhouseAdapter } from \"@1moby/just-auth/adapters/clickhouse\";\nimport { createReactAuth } from \"@1moby/just-auth\";\n\nconst ch = createClient({ url: env.CH_URL, username: env.CH_USER, password: env.CH_PASS });\nconst adapter = createClickhouseAdapter({ client: ch });\nawait adapter.migrate();\n\nconst auth = createReactAuth({\n  database: adapter,\n  providers: [/* ... */],\n});\n\n// RBAC\nawait adapter.rbac.createOrganization({ id: \"org1\", name: \"Acme\" });\nawait adapter.rbac.defineRole({ id: \"editor\", scope: \"org\", permissions: [\"dashboard.edit\"] });\nawait adapter.rbac.grantUserRole({ userId: \"u1\", roleId: \"editor\", orgId: \"org1\", grantedBy: \"system\" });\n\nconst decision = await adapter.rbac.resolvePermission({\n  userId: \"u1\",\n  permission: \"dashboard.edit\",\n  resource: { orgId: \"org1\" },\n});\n// decision.allowed === true; decision.via === \"role\"\n\n// Approvals\nconst req = await adapter.approvals.open({\n  requesterUserId: \"u1\",\n  action: \"dashboard.publish\",\n  resource: { orgId: \"org1\" },\n  payload: { title: \"Q4\" },\n  chainStrategy: \"supervisor_chain\",\n});\nawait adapter.approvals.decide({\n  requestId: req.id,\n  approverUserId: \"boss\",\n  decision: \"approved\",\n});\n```\n\n### Verified versions\n\nThe adapter is integration-tested against three live ClickHouse servers. All 13 spec scenarios pass on each:\n\n| Server | Image tag | Status |\n| --- | --- | --- |\n| 24.x LTS | `clickhouse/clickhouse-server:24.8` | ✓ 13/13 |\n| 25.x LTS | `clickhouse/clickhouse-server:25.3` | ✓ 13/13 |\n| 25.10+ | `clickhouse/clickhouse-server:25.10` | ✓ 13/13 |\n\nTo reproduce locally:\n\n```bash\ndocker compose -f examples/clickhouse/docker-compose.yml up -d\nbun tests/integration/clickhouse/run.ts        # all three\nbun tests/integration/clickhouse/run.ts 24     # one version\ndocker compose -f examples/clickhouse/docker-compose.yml down -v\n```\n\n### OLAP-on-OLTP trade-offs (read these before adopting)\n\n- **Hot reads use `FINAL`** on `ReplacingMergeTree` to collapse to the latest version per key. This is more expensive than a typical SQL row read; budget for it.\n- **`sessions_dict`** Dictionary fronts the session lookup hot path. Default `LIFETIME(MIN 5 MAX 15)` — *up to 15s* of staleness on revoked sessions. Either accept the window, force `SYSTEM RELOAD DICTIONARY sessions_dict` on revoke, or disable the dict via `useSessionDict: false`.\n- **Email uniqueness is best-effort.** ClickHouse has no transactional unique constraint. Two parallel `createUser` calls with the same email both succeed; the consumer must check via `FINAL ... LIMIT 1` before insert. Even then, a residual race window remains.\n- **Cascade deletes are app-level.** Deleting a user emits tombstone rows across `users`, `accounts`, `sessions`, and `user_role_grants` *sequentially*. There is a small window where the user is gone but related rows are not.\n- **No multi-table transactions.** The approval state machine writes a tombstone row + a fresh row for each transition. A crash between the audit-log append and the request-row update can leave the audit slightly ahead of state.\n- **Cluster mode.** Pass `cluster: 'name'` to wrap every DDL with `ON CLUSTER '<name>'` and every engine with `Replicated*`. Keeper paths follow `/clickhouse/tables/{installation}/{shard}/<table>` (uses CH macros).\n\nThe pre-existing `RbacConfig`-style RBAC continues to work on every adapter (including ClickHouse) — the graph RBAC API is *additive*, you can use either or both.\n\nSee `examples/clickhouse/` for a runnable docker-compose setup.\n\n## Exports\n\n```ts\n// Main\nimport { createReactAuth, migrate } from \"@1moby/just-auth\";\nimport { createGoogleProvider, createGitHubProvider, createLineProvider } from \"@1moby/just-auth\";\nimport { hashPassword, verifyPassword, resolvePermissions, parseRoles } from \"@1moby/just-auth\";\nimport { createQueries, resolveTableNames } from \"@1moby/just-auth\";\n\n// Client\nimport { SessionProvider, useSession, signIn, signUp, signOut } from \"@1moby/just-auth/client\";\nimport { usePermission, useRole } from \"@1moby/just-auth/client\";\n\n// Middleware\nimport { createAuthMiddleware } from \"@1moby/just-auth/middleware\";\n\n// Database Adapters\nimport { createD1Adapter } from \"@1moby/just-auth/adapters/d1\";\nimport { createBunSQLiteAdapter } from \"@1moby/just-auth/adapters/bun-sqlite\";\nimport { createPgAdapter } from \"@1moby/just-auth/adapters/pg\";\nimport { createMySQLAdapter } from \"@1moby/just-auth/adapters/mysql\";\nimport { createBunSQLAdapter } from \"@1moby/just-auth/adapters/bun-sql\";\nimport { createClickhouseAdapter } from \"@1moby/just-auth/adapters/clickhouse\";\n\n// Types\nimport type {\n  AuthConfig, AuthInstance, User, Session, Account,\n  DatabaseAdapter, OAuthProvider, SessionManager,\n  RbacConfig, RoleDefinition, SessionContextValue, SessionStatus,\n  Queries, TableNames, MigrateOptions,\n  // 0.2.x callbacks\n  AuthCallbacks, SignInCallbackContext, SignInCallbackResult,\n  SessionCallbackContext, PagesConfig,\n} from \"@1moby/just-auth\";\n\n// ClickHouse adapter types (when using @1moby/just-auth/adapters/clickhouse)\nimport type {\n  Organization, Department, EffectiveRole, PermissionDecision,\n  PermissionVia, RoleScope, RoleDefinition as CHRoleDefinition,\n  RoleGrant, ApprovalRequest, ApprovalStatus, ApprovalDecision,\n  RbacApi, ApprovalsApi, CHClient, CHTableNames,\n} from \"@1moby/just-auth/adapters/clickhouse\";\n```\n\n## Testing\n\n```bash\nbun test                                          # unit suite (331 tests across 20 files)\n\n# ClickHouse integration matrix (requires Docker)\ndocker compose -f examples/clickhouse/docker-compose.yml up -d\nbun tests/integration/clickhouse/run.ts           # all 13 scenarios x CH 24.8 / 25.3 / 25.10\ndocker compose -f examples/clickhouse/docker-compose.yml down -v\n```\n\n## Security\n\nWhat the library protects against, and what your application still has to handle.\n\n### What's enforced by the library\n\n- **Session tokens** — 256-bit random, SHA-256-hashed in storage, sliding window with 30-day TTL. Raw tokens never touch the database.\n- **OAuth state** — 256-bit random per flow, timing-safe equality, **per-provider cookie names** (`oauth_state_<id>`, `code_verifier_<id>`) so concurrent flows don't cross-contaminate. Cleared on every callback exit path (success and every error).\n- **PKCE** — S256 code verifier on Google and LINE; GitHub passes the challenge but its OAuth-App tokens endpoint may not enforce it.\n- **Cookie prefixes** — default cookie name is `__Host-auth_session`. If you set `cookie.domain` or a non-`/` `cookie.path`, the library auto-downgrades to `__Secure-…` (a `__Host-` cookie with Domain set is silently rejected by browsers).\n- **Email-based account linking** — gated on `profile.emailVerified === true` *and* `allowEmailAccountLinking: true`. Set `allowUnverifiedEmailLinking: true` to opt out (don't, unless you trust the IdP). Returns `EmailNotVerified` when the provider didn't verify the email.\n- **`signIn` callback `userOverrides`** — `id`, `email`, `name`, `avatar_url`, `password_hash`, and `role` are reserved and cannot be injected. Other column names pass through but are validated against `/^[a-zA-Z_][a-zA-Z0-9_]*$/` before being interpolated.\n- **`POST /role`** — requires the `user:set-role` permission. Cannot be used to change your own role. Cannot grant a role whose permissions aren't a subset of yours (no privilege escalation in a single call).\n- **Email enumeration on registration** — `hashPassword` runs unconditionally before checking if the email exists, so taken/available paths take comparable wall time.\n- **Email enumeration on credentials login** — `verifyPassword` always runs against either the user's hash or a dummy hash of the same shape.\n- **CSRF (defense in depth)** — `Origin` / `Referer` check on every POST, alongside `SameSite=Lax` cookies.\n- **Open redirect** — `onAuthSuccess` and `pages.error` are validated against `isSafeRedirect` (same-origin only).\n- **HTML attribute escaping** — `&`, `\"`, `'`, `` ` ``, `<`, `>` are all escaped in the OAuth-redirect HTML.\n- **Email case** — normalized to lowercase + trimmed at every ingestion point (registration, OAuth callback, `allowedEmails` check) so `Alice@x.com` and `alice@x.com` collapse to one identity.\n- **ClickHouse table names** — every consumer-provided table name is validated against the SQL identifier regex at adapter construction time.\n- **`createReactAuth` provider IDs** — must match `[a-zA-Z0-9_-]+` (cookie-name safety).\n\n### What you still need to do\n\n- **Rate limit `POST /register` and `POST /callback/credentials`.** The library enforces a `passwordMinLength` (default 8 — bump to 12+ for new apps) and a 128-char max to prevent PBKDF2 DoS, but it does not rate-limit. Add Cloudflare Rate Limiting rules, an upstream WAF, or a middleware in front of the auth routes.\n- **Force-sign-out all sessions on password change.** The library exposes `queries.deleteUserSessions(userId)` if you wire it; the framework doesn't auto-revoke other sessions when a single password is changed.\n- **Audit your `signIn` callback.** Anything you put in `userOverrides` is written to the `users` row. Reserved keys (`id`, `email`, `name`, `avatar_url`, `password_hash`, `role`) are rejected, but if your callback echoes user-controlled data into `userOverrides` for any *other* column, the user controls that column.\n- **Trust your `X-Forwarded-Host` / `X-Forwarded-Proto` source.** The library uses these headers to build absolute redirect URLs in the OAuth flow. Only trust them when the auth server is firewalled behind a known reverse proxy.\n- **Provide a password-reset / magic-link flow.** The library doesn't ship one. The `verification_tokens` table is reserved for that purpose (in the CH adapter); SQL adapters don't migrate it by default.\n- **Consider GitHub PKCE limitations.** GitHub's OAuth Apps don't enforce the `code_verifier` you send. The library still sends one for forward compatibility but don't rely on it for security against authorization-code interception.\n\n### Reporting\n\nOpen a GitHub security advisory (preferred) or email the maintainer if you find a vulnerability.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}