{"_id":"@ajay.inpis/multitenant-search","_rev":"9-f7703f86d4f9b3f325a51e51027e96c5","name":"@ajay.inpis/multitenant-search","dist-tags":{"latest":"1.0.8"},"versions":{"1.0.0":{"name":"@ajay.inpis/multitenant-search","version":"1.0.0","keywords":["search","multi-tenant","apim","api-management","elasticsearch","typesense","cache","performance"],"author":{"name":"Ajay Singh"},"license":"MIT","_id":"@ajay.inpis/multitenant-search@1.0.0","maintainers":[{"name":"ajay.inpis","email":"ajay@inichepro.com"}],"homepage":"https://github.com/ajaysingh452/multitenant-search#readme","bugs":{"url":"https://github.com/ajaysingh452/multitenant-search/issues"},"dist":{"shasum":"2f855bbb4a8bad11f49fa3420c37f62c6c2308de","tarball":"https://registry.npmjs.org/@ajay.inpis/multitenant-search/-/multitenant-search-1.0.0.tgz","fileCount":30,"integrity":"sha512-cVod68cNhNHRcpd23AcfLuL0vaOjN0wHakZFP/FBmW3DEbhO885r366mVJfsIMO2qoEOM3debhWg9GYOSr4KUw==","signatures":[{"sig":"MEQCIA2X8mUg6u/79zm3Jf0RTnxfYYAkblyw4ULRu/2zXW36AiAo8FxFOZ5p8p/9xTIG9qJHYi0Yu6qGD+l5YxHFpQBxBQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":98628},"main":"lib/package-index.js","types":"lib/package-index.d.ts","engines":{"npm":">=8.0.0","node":">=16.0.0"},"gitHead":"9ac58076dbb49ededfa93db0389dda1b6e267faa","scripts":{"dev":"tsc -p tsconfig.package.json --watch","demo":"node demo.js","test":"jest","build":"tsc -p tsconfig.package.json","start":"node lib/search-platform.js","build:full":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"ajay.inpis","email":"ajay@inichepro.com"},"repository":{"url":"git+https://github.com/ajaysingh452/multitenant-search.git","type":"git"},"_npmVersion":"10.5.0","description":"Production-grade multi-tenant search platform.","directories":{},"_nodeVersion":"20.12.2","dependencies":{"joi":"^17.9.2","cors":"^2.8.5","pino":"^8.14.1","uuid":"^9.0.0","helmet":"^7.0.0","morgan":"^1.10.0","express":"^4.18.2","node-cache":"^5.1.2","compression":"^1.7.4","pino-pretty":"^10.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","ts-jest":"^29.1.0","typescript":"^5.1.3","@types/cors":"^2.8.13","@types/jest":"^29.5.2","@types/node":"^20.0.0","@types/uuid":"^9.0.2","@types/morgan":"^1.9.4","@types/express":"^4.17.17","@types/compression":"^1.7.2"},"peerDependencies":{"redis":"^4.0.0","typesense":"^1.7.0","@opensearch-project/opensearch":"^2.0.0"},"peerDependenciesMeta":{"redis":{"optional":true},"typesense":{"optional":true},"@opensearch-project/opensearch":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/multitenant-search_1.0.0_1759759616476_0.5409528748048944","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@ajay.inpis/multitenant-search","version":"1.0.1","keywords":["search","multi-tenant","apim","api-management","elasticsearch","typesense","cache","performance"],"author":{"name":"Ajay Singh"},"license":"MIT","_id":"@ajay.inpis/multitenant-search@1.0.1","maintainers":[{"name":"ajay.inpis","email":"ajay@inichepro.com"}],"homepage":"https://github.com/ajaysingh452/multitenant-search#readme","bugs":{"url":"https://github.com/ajaysingh452/multitenant-search/issues"},"dist":{"shasum":"b3d19afcff1a42fc2334b04a1d938070e2da458c","tarball":"https://registry.npmjs.org/@ajay.inpis/multitenant-search/-/multitenant-search-1.0.1.tgz","fileCount":30,"integrity":"sha512-FX0xhnx8XeOfJ7ckseAApi8c8ai4/7ZQ1pAriqgkfLl0vbFiNp4flylKTcrkWwXwIVcgnGjfmuZJnALYiC62yg==","signatures":[{"sig":"MEUCIFPX4PyI4TUagd+w+Ez40wQbuWTdZd7PPCfEYUbAVT2xAiEAiILvg24amqrU1nES39KKIQeq3saJo6Tn4SSk2ft3YEM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":98610},"main":"lib/package-index.js","types":"lib/package-index.d.ts","engines":{"npm":">=8.0.0","node":">=16.0.0"},"gitHead":"9ac58076dbb49ededfa93db0389dda1b6e267faa","scripts":{"dev":"tsc -p tsconfig.package.json --watch","demo":"node demo.js","test":"jest","build":"tsc -p tsconfig.package.json","start":"node lib/search-platform.js","build:full":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"ajay.inpis","email":"ajay@inichepro.com"},"repository":{"url":"git+https://github.com/ajaysingh452/multitenant-search.git","type":"git"},"_npmVersion":"10.5.0","description":"Production-grade multi-tenant search platform.","directories":{},"_nodeVersion":"20.12.2","dependencies":{"joi":"^17.9.2","cors":"^2.8.5","pino":"^8.14.1","uuid":"^9.0.0","helmet":"^7.0.0","morgan":"^1.10.0","express":"^4.18.2","node-cache":"^5.1.2","compression":"^1.7.4","pino-pretty":"^10.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","ts-jest":"^29.1.0","typescript":"^5.1.3","@types/cors":"^2.8.13","@types/jest":"^29.5.2","@types/node":"^20.0.0","@types/uuid":"^9.0.2","@types/morgan":"^1.9.4","@types/express":"^4.17.17","@types/compression":"^1.7.2"},"peerDependencies":{"redis":"^4.0.0","typesense":"^1.7.0","@opensearch-project/opensearch":"^2.0.0"},"peerDependenciesMeta":{"redis":{"optional":true},"typesense":{"optional":true},"@opensearch-project/opensearch":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/multitenant-search_1.0.1_1759767003697_0.6113962450948827","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@ajay.inpis/multitenant-search","version":"1.0.2","keywords":["search","multi-tenant","apim","api-management","elasticsearch","typesense","cache","performance"],"author":{"name":"Ajay Singh"},"license":"MIT","_id":"@ajay.inpis/multitenant-search@1.0.2","maintainers":[{"name":"ajay.inpis","email":"ajay@inichepro.com"}],"homepage":"https://github.com/ajaysingh452/multitenant-search#readme","bugs":{"url":"https://github.com/ajaysingh452/multitenant-search/issues"},"dist":{"shasum":"fcb8dde1bab092c3bb8b0cb5e60baf99317c225f","tarball":"https://registry.npmjs.org/@ajay.inpis/multitenant-search/-/multitenant-search-1.0.2.tgz","fileCount":30,"integrity":"sha512-jcja1ESsIIod+Vcr4vm88DuPLscd/psq140s6by5cQYFgyjUA/jjmBxaVb7RiM/dL4+WpPRbh5ncLkibVyH0YA==","signatures":[{"sig":"MEQCICH5bo+j7bC8aCM8MwZhOlaQRSjXh2Zg0nc27A98U7YVAiAa89QD1L2xi3sQaLC6ygO2Giw6NtvRHWugV73lc/CoCg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":98622},"main":"lib/package-index.js","types":"lib/package-index.d.ts","engines":{"npm":">=8.0.0","node":">=16.0.0"},"gitHead":"9ac58076dbb49ededfa93db0389dda1b6e267faa","scripts":{"dev":"tsc -p tsconfig.package.json --watch","demo":"node demo.js","test":"jest","build":"tsc -p tsconfig.package.json","start":"node lib/search-platform.js","build:full":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"ajay.inpis","email":"ajay@inichepro.com"},"repository":{"url":"git+https://github.com/ajaysingh452/multitenant-search.git","type":"git"},"_npmVersion":"10.5.0","description":"Production-grade multi-tenant search platform.","directories":{},"_nodeVersion":"20.12.2","dependencies":{"joi":"^17.9.2","cors":"^2.8.5","pino":"^8.14.1","uuid":"^9.0.0","helmet":"^7.0.0","morgan":"^1.10.0","express":"^4.18.2","node-cache":"^5.1.2","compression":"^1.7.4","pino-pretty":"^10.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","ts-jest":"^29.1.0","typescript":"^5.1.3","@types/cors":"^2.8.13","@types/jest":"^29.5.2","@types/node":"^20.0.0","@types/uuid":"^9.0.2","@types/morgan":"^1.9.4","@types/express":"^4.17.17","@types/compression":"^1.7.2"},"peerDependencies":{"redis":"^4.0.0","typesense":"^1.7.0","@opensearch-project/opensearch":"^2.0.0"},"peerDependenciesMeta":{"redis":{"optional":true},"typesense":{"optional":true},"@opensearch-project/opensearch":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/multitenant-search_1.0.2_1759767405960_0.9013141877277582","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@ajay.inpis/multitenant-search","version":"1.0.3","keywords":["search","multi-tenant","apim","api-management","elasticsearch","typesense","cache","performance"],"author":{"name":"Ajay Singh"},"license":"MIT","_id":"@ajay.inpis/multitenant-search@1.0.3","maintainers":[{"name":"ajay.inpis","email":"ajay@inichepro.com"}],"homepage":"https://github.com/ajaysingh452/multitenant-search#readme","bugs":{"url":"https://github.com/ajaysingh452/multitenant-search/issues"},"dist":{"shasum":"1eebb8684dbf1f63c55090e9c4ee34fed602f377","tarball":"https://registry.npmjs.org/@ajay.inpis/multitenant-search/-/multitenant-search-1.0.3.tgz","fileCount":30,"integrity":"sha512-CBfDwPL4FWcUwJZJo8+4yKjDJ2PQzfL97gF4l8fLOhFzY1r439uzLqjqL2CkDJYB5eJ77/uQADTw3MdquHxIuQ==","signatures":[{"sig":"MEQCIFXAs57mPH5U92Jav80KHE54Rre+rsY3v+lyBHgt+nBAAiBpgMP1Mwzrf0aGtZLiPDhbKcgfYPvFxaidoY2ZfX5fBw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":98594},"main":"lib/package-index.js","types":"lib/package-index.d.ts","engines":{"npm":">=8.0.0","node":">=16.0.0"},"gitHead":"9ac58076dbb49ededfa93db0389dda1b6e267faa","scripts":{"dev":"tsc -p tsconfig.package.json --watch","demo":"node demo.js","test":"jest","build":"tsc -p tsconfig.package.json","start":"node lib/search-platform.js","build:full":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"ajay.inpis","email":"ajay@inichepro.com"},"repository":{"url":"git+https://github.com/ajaysingh452/multitenant-search.git","type":"git"},"_npmVersion":"10.5.0","description":"Production-grade multi-tenant search platform.","directories":{},"_nodeVersion":"20.12.2","dependencies":{"joi":"^17.9.2","cors":"^2.8.5","pino":"^8.14.1","uuid":"^9.0.0","helmet":"^7.0.0","morgan":"^1.10.0","express":"^4.18.2","node-cache":"^5.1.2","compression":"^1.7.4","pino-pretty":"^10.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","ts-jest":"^29.1.0","typescript":"^5.1.3","@types/cors":"^2.8.13","@types/jest":"^29.5.2","@types/node":"^20.0.0","@types/uuid":"^9.0.2","@types/morgan":"^1.9.4","@types/express":"^4.17.17","@types/compression":"^1.7.2"},"peerDependencies":{"redis":"^4.0.0","typesense":"^1.7.0","@opensearch-project/opensearch":"^2.0.0"},"peerDependenciesMeta":{"redis":{"optional":true},"typesense":{"optional":true},"@opensearch-project/opensearch":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/multitenant-search_1.0.3_1759767720881_0.7718361316605695","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@ajay.inpis/multitenant-search","version":"1.0.4","keywords":["search","multi-tenant","apim","api-management","elasticsearch","typesense","cache","performance"],"author":{"name":"Ajay Singh"},"license":"MIT","_id":"@ajay.inpis/multitenant-search@1.0.4","maintainers":[{"name":"ajay.inpis","email":"ajay@inichepro.com"}],"homepage":"https://github.com/ajaysingh452/multitenant-search#readme","bugs":{"url":"https://github.com/ajaysingh452/multitenant-search/issues"},"dist":{"shasum":"055ec4bdb5445406f389506c1c21b862eef00ce4","tarball":"https://registry.npmjs.org/@ajay.inpis/multitenant-search/-/multitenant-search-1.0.4.tgz","fileCount":30,"integrity":"sha512-IPtx/UI405ErJMmwmkMGTz4Bxnz5MWgRcr/YeKhoOLYBcfxtV403VE/sZSAkLfWYQlG29BPPEvAYvaK7PU8QgQ==","signatures":[{"sig":"MEUCIC3NyqLiC+4pBIQsFDHeE6o3tungMXTIHu3w2FgXQ8v7AiEA7U9c5hmfh/tdrNivMpRyMBO90NBLrwa67k1uyJ/jIfA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":98658},"main":"lib/package-index.js","types":"lib/package-index.d.ts","engines":{"npm":">=8.0.0","node":">=16.0.0"},"gitHead":"51ac8c7b2ef009ff7f9a89ea8efe2d30a0d1511f","scripts":{"dev":"tsc -p tsconfig.package.json --watch","demo":"node demo.js","test":"jest","build":"tsc -p tsconfig.package.json","start":"node lib/search-platform.js","build:full":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"ajay.inpis","email":"ajay@inichepro.com"},"repository":{"url":"git+https://github.com/ajaysingh452/multitenant-search.git","type":"git"},"_npmVersion":"10.5.0","description":"Production-grade multi-tenant search platform.","directories":{},"_nodeVersion":"20.12.2","dependencies":{"joi":"^17.9.2","cors":"^2.8.5","pino":"^8.14.1","uuid":"^9.0.0","helmet":"^7.0.0","morgan":"^1.10.0","express":"^4.18.2","node-cache":"^5.1.2","compression":"^1.7.4","pino-pretty":"^10.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","ts-jest":"^29.1.0","typescript":"^5.1.3","@types/cors":"^2.8.13","@types/jest":"^29.5.2","@types/node":"^20.0.0","@types/uuid":"^9.0.2","@types/morgan":"^1.9.4","@types/express":"^4.17.17","@types/compression":"^1.7.2"},"peerDependencies":{"redis":"^4.0.0","typesense":"^1.7.0","@opensearch-project/opensearch":"^2.0.0"},"peerDependenciesMeta":{"redis":{"optional":true},"typesense":{"optional":true},"@opensearch-project/opensearch":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/multitenant-search_1.0.4_1759998771022_0.8280734223114952","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"@ajay.inpis/multitenant-search","version":"1.0.5","keywords":["search","multi-tenant","apim","api-management","elasticsearch","typesense","cache","performance"],"author":{"name":"Ajay Singh"},"license":"MIT","_id":"@ajay.inpis/multitenant-search@1.0.5","maintainers":[{"name":"ajay.inpis","email":"ajay@inichepro.com"}],"homepage":"https://github.com/ajaysingh452/multitenant-search#readme","bugs":{"url":"https://github.com/ajaysingh452/multitenant-search/issues"},"dist":{"shasum":"5c55d0d88a677a7483305a89cc6ffd6d72a2a13a","tarball":"https://registry.npmjs.org/@ajay.inpis/multitenant-search/-/multitenant-search-1.0.5.tgz","fileCount":30,"integrity":"sha512-7aEykMbC6fcyR5A3ntAvAfq6FfjWXvI0o6tTWDLzmglRlDSad9gdqkKigGh+VTQrtFS+J6cDNfUbZ9ZIbQ3wWA==","signatures":[{"sig":"MEUCIQDJpjoMXZeEk6fPbuATu/jmVoHHN4JYE/ADu/YH2n50fQIgAq2djKRQnLwSrWumc3oAbLdk4/p9LH0+AkaHcxI3mQs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":98656},"main":"lib/package-index.js","types":"lib/package-index.d.ts","engines":{"npm":">=8.0.0","node":">=16.0.0"},"gitHead":"51ac8c7b2ef009ff7f9a89ea8efe2d30a0d1511f","scripts":{"dev":"tsc -p tsconfig.package.json --watch","demo":"node demo.js","test":"jest","build":"tsc -p tsconfig.package.json","start":"node lib/search-platform.js","build:full":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"ajay.inpis","email":"ajay@inichepro.com"},"repository":{"url":"git+https://github.com/ajaysingh452/multitenant-search.git","type":"git"},"_npmVersion":"10.5.0","description":"Production-grade multi-tenant search platform.","directories":{},"_nodeVersion":"20.12.2","dependencies":{"joi":"^17.9.2","cors":"^2.8.5","pino":"^8.14.1","uuid":"^9.0.0","helmet":"^7.0.0","morgan":"^1.10.0","express":"^4.18.2","node-cache":"^5.1.2","compression":"^1.7.4","pino-pretty":"^10.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","ts-jest":"^29.1.0","typescript":"^5.1.3","@types/cors":"^2.8.13","@types/jest":"^29.5.2","@types/node":"^20.0.0","@types/uuid":"^9.0.2","@types/morgan":"^1.9.4","@types/express":"^4.17.17","@types/compression":"^1.7.2"},"peerDependencies":{"redis":"^4.0.0","typesense":"^1.7.0","@opensearch-project/opensearch":"^2.0.0"},"peerDependenciesMeta":{"redis":{"optional":true},"typesense":{"optional":true},"@opensearch-project/opensearch":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/multitenant-search_1.0.5_1759998941068_0.3479750708703455","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"@ajay.inpis/multitenant-search","version":"1.0.6","keywords":["search","multi-tenant","apim","api-management","elasticsearch","typesense","cache","performance"],"author":{"name":"Ajay Singh"},"license":"MIT","_id":"@ajay.inpis/multitenant-search@1.0.6","maintainers":[{"name":"ajay.inpis","email":"ajay@inichepro.com"}],"homepage":"https://github.com/ajaysingh452/multitenant-search#readme","bugs":{"url":"https://github.com/ajaysingh452/multitenant-search/issues"},"dist":{"shasum":"31270960ff5c1bb362c6f6c8e6488f8ef6e830fa","tarball":"https://registry.npmjs.org/@ajay.inpis/multitenant-search/-/multitenant-search-1.0.6.tgz","fileCount":30,"integrity":"sha512-OAWcg9WNleKJitMVB/9Za1DogyBheKI4z8tEh3MG2QK68RfrzvzOA1G49YOnI15cyLYfkMcnmo6LpntGQn/dHA==","signatures":[{"sig":"MEYCIQCXW+SrBjPljY5sK8rZCCcb5QHKXcrFapGdhJx0+MOOSwIhAJ8jsMEQ5eeUSvM25hF4oqyt9LiZiYsjb1AiuYwg+vsJ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":98594},"main":"lib/package-index.js","types":"lib/package-index.d.ts","engines":{"npm":">=8.0.0","node":">=16.0.0"},"gitHead":"51ac8c7b2ef009ff7f9a89ea8efe2d30a0d1511f","scripts":{"dev":"tsc -p tsconfig.package.json --watch","demo":"node demo.js","test":"jest","build":"tsc -p tsconfig.package.json","start":"node lib/search-platform.js","build:full":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"ajay.inpis","email":"ajay@inichepro.com"},"repository":{"url":"git+https://github.com/ajaysingh452/multitenant-search.git","type":"git"},"_npmVersion":"10.5.0","description":"Production-grade multi-tenant search platform.","directories":{},"_nodeVersion":"20.12.2","dependencies":{"joi":"^17.9.2","cors":"^2.8.5","pino":"^8.14.1","uuid":"^9.0.0","helmet":"^7.0.0","morgan":"^1.10.0","express":"^4.18.2","node-cache":"^5.1.2","compression":"^1.7.4","pino-pretty":"^10.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","ts-jest":"^29.1.0","typescript":"^5.1.3","@types/cors":"^2.8.13","@types/jest":"^29.5.2","@types/node":"^20.0.0","@types/uuid":"^9.0.2","@types/morgan":"^1.9.4","@types/express":"^4.17.17","@types/compression":"^1.7.2"},"peerDependencies":{"redis":"^4.0.0","typesense":"^1.7.0","@opensearch-project/opensearch":"^2.0.0"},"peerDependenciesMeta":{"redis":{"optional":true},"typesense":{"optional":true},"@opensearch-project/opensearch":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/multitenant-search_1.0.6_1759999044877_0.9315547461752156","host":"s3://npm-registry-packages-npm-production"}},"1.0.7":{"name":"@ajay.inpis/multitenant-search","version":"1.0.7","keywords":["search","multi-tenant","apim","api-management","elasticsearch","typesense","cache","performance"],"author":{"name":"Ajay Singh"},"license":"MIT","_id":"@ajay.inpis/multitenant-search@1.0.7","maintainers":[{"name":"ajay.inpis","email":"ajay@inichepro.com"}],"homepage":"https://github.com/ajaysingh452/multitenant-search#readme","bugs":{"url":"https://github.com/ajaysingh452/multitenant-search/issues"},"dist":{"shasum":"21b5a6d948c636b48789eb347d8a0851cf909a58","tarball":"https://registry.npmjs.org/@ajay.inpis/multitenant-search/-/multitenant-search-1.0.7.tgz","fileCount":30,"integrity":"sha512-f2yhaiSdrCCeh1ADdZ18LJZk0AgVLKw/0mBrOce4TuZpzT2/GUHcAsGD8AQkSFiLnxZnKvYG0YgQb/UdcGrLMg==","signatures":[{"sig":"MEQCIFlCqa4Lhgol7PnHPPvxYqd+Y5xF2uGvjjyg/PxhYgSWAiAinuF+reiiVUYvC0/YN2T6wUjCS0eisfAg9kP6ISVl8g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":105502},"main":"lib/package-index.js","types":"lib/package-index.d.ts","engines":{"npm":">=8.0.0","node":">=16.0.0"},"gitHead":"51ac8c7b2ef009ff7f9a89ea8efe2d30a0d1511f","scripts":{"dev":"tsc -p tsconfig.package.json --watch","demo":"node demo.js","test":"jest","build":"tsc -p tsconfig.package.json","start":"node lib/search-platform.js","build:full":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"ajay.inpis","email":"ajay@inichepro.com"},"repository":{"url":"git+https://github.com/ajaysingh452/multitenant-search.git","type":"git"},"_npmVersion":"10.5.0","description":"Production-grade multi-tenant search platform.","directories":{},"_nodeVersion":"20.12.2","dependencies":{"joi":"^17.9.2","cors":"^2.8.5","pino":"^8.14.1","uuid":"^9.0.0","helmet":"^7.0.0","morgan":"^1.10.0","express":"^4.18.2","node-cache":"^5.1.2","compression":"^1.7.4","pino-pretty":"^10.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.5.0","ts-jest":"^29.1.0","typescript":"^5.1.3","@types/cors":"^2.8.13","@types/jest":"^29.5.2","@types/node":"^20.0.0","@types/uuid":"^9.0.2","@types/morgan":"^1.9.4","@types/express":"^4.17.17","@types/compression":"^1.7.2"},"peerDependencies":{"redis":"^4.0.0","typesense":"^1.7.0","@opensearch-project/opensearch":"^2.0.0"},"peerDependenciesMeta":{"redis":{"optional":true},"typesense":{"optional":true},"@opensearch-project/opensearch":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/multitenant-search_1.0.7_1759999270794_0.6804460139352277","host":"s3://npm-registry-packages-npm-production"}},"1.0.8":{"name":"@ajay.inpis/multitenant-search","version":"1.0.8","description":"Production-grade multi-tenant search platform.","main":"lib/package-index.js","types":"lib/package-index.d.ts","scripts":{"build":"tsc -p tsconfig.package.json","build:full":"tsc","dev":"tsc -p tsconfig.package.json --watch","test":"jest","prepublishOnly":"npm run build","start":"node lib/search-platform.js","demo":"node demo.js"},"keywords":["search","multi-tenant","apim","api-management","elasticsearch","typesense","cache","performance"],"author":{"name":"Ajay Singh"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/ajaysingh452/multitenant-search.git"},"bugs":{"url":"https://github.com/ajaysingh452/multitenant-search/issues"},"homepage":"https://github.com/ajaysingh452/multitenant-search#readme","dependencies":{"express":"^4.18.2","cors":"^2.8.5","helmet":"^7.0.0","compression":"^1.7.4","morgan":"^1.10.0","node-cache":"^5.1.2","uuid":"^9.0.0","joi":"^17.9.2","pino":"^8.14.1","pino-pretty":"^10.0.0"},"devDependencies":{"@types/node":"^20.0.0","@types/express":"^4.17.17","@types/cors":"^2.8.13","@types/compression":"^1.7.2","@types/morgan":"^1.9.4","@types/uuid":"^9.0.2","typescript":"^5.1.3","jest":"^29.5.0","@types/jest":"^29.5.2","ts-jest":"^29.1.0"},"peerDependencies":{"redis":"^4.0.0","@opensearch-project/opensearch":"^2.0.0","typesense":"^1.7.0"},"peerDependenciesMeta":{"redis":{"optional":true},"@opensearch-project/opensearch":{"optional":true},"typesense":{"optional":true}},"engines":{"node":">=16.0.0","npm":">=8.0.0"},"_id":"@ajay.inpis/multitenant-search@1.0.8","gitHead":"8f0beeac7e5db56953dd2a79d75e72a4ba304f65","_nodeVersion":"20.12.2","_npmVersion":"10.5.0","dist":{"integrity":"sha512-AtlDTGOijT8iRWLWbkqmdyUUq2OYyWJ+t1CY1vM9eGulLWOL6jNRP2hlvvHzcC93csxeoQBNpaudcEw+CFI46w==","shasum":"5c0cdbd9069ead1de7ab89c322aa9b24bcd7f3a1","tarball":"https://registry.npmjs.org/@ajay.inpis/multitenant-search/-/multitenant-search-1.0.8.tgz","fileCount":30,"unpackedSize":105502,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCPM9bR6hUjFmrLbWleq1NejRGO/LIkw0LByTW3xpB7lgIhAOMWIvc+1/cAjQS3Jjm+NkY+F9K9rLNnLMtupmB6WKjP"}]},"_npmUser":{"name":"ajay.inpis","email":"ajay@inichepro.com"},"directories":{},"maintainers":[{"name":"ajay.inpis","email":"ajay@inichepro.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/multitenant-search_1.0.8_1759999565736_0.9669288977937553"},"_hasShrinkwrap":false}},"time":{"created":"2025-10-06T14:06:56.389Z","modified":"2025-10-09T08:46:06.099Z","1.0.0":"2025-10-06T14:06:56.663Z","1.0.1":"2025-10-06T16:10:03.879Z","1.0.2":"2025-10-06T16:16:46.139Z","1.0.3":"2025-10-06T16:22:01.058Z","1.0.4":"2025-10-09T08:32:51.267Z","1.0.5":"2025-10-09T08:35:41.249Z","1.0.6":"2025-10-09T08:37:25.045Z","1.0.7":"2025-10-09T08:41:10.996Z","1.0.8":"2025-10-09T08:46:05.934Z"},"bugs":{"url":"https://github.com/ajaysingh452/multitenant-search/issues"},"author":{"name":"Ajay Singh"},"license":"MIT","homepage":"https://github.com/ajaysingh452/multitenant-search#readme","keywords":["search","multi-tenant","apim","api-management","elasticsearch","typesense","cache","performance"],"repository":{"type":"git","url":"git+https://github.com/ajaysingh452/multitenant-search.git"},"description":"Production-grade multi-tenant search platform.","maintainers":[{"name":"ajay.inpis","email":"ajay@inichepro.com"}],"readme":"# @ajay.inpis/multitenant-search\r\n\r\nProduction-grade multi-tenant search platform. Add lightning-fast search to your Express.js applications with minimal configuration.\r\n\r\n[![npm version](https://badge.fury.io/js/@ajay.inpis%2Fmultitenant-search.svg)](https://www.npmjs.com/package/@ajay.inpis/multitenant-search)\r\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\r\n[![Node.js Version](https://img.shields.io/badge/node-%3E%3D16.0.0-brightgreen.svg)](https://nodejs.org/)\r\n\r\n## Features\r\n\r\n🚀 **Multi-Tenant Architecture** - Complete tenant isolation with intelligent query routing  \r\n⚡ **Lightning Fast** - Built-in L1/L2 caching with sub-50ms response times  \r\n🔧 **Easy Integration** - Express middleware for automatic search synchronization  \r\n🛠️ **Production Ready** - Built with TypeScript, comprehensive error handling  \r\n🔍 **Flexible Search** - Support for simple queries (Typesense) and complex queries (OpenSearch)  \r\n📊 **Analytics Ready** - Built-in metrics, performance monitoring, and debugging tools  \r\n\r\n## Quick Start\r\n\r\n### Installation\r\n\r\n```bash\r\nnpm install @ajay.inpis/multitenant-search\r\n```\r\n\r\n### Basic Usage\r\n\r\n```javascript\r\nconst { SearchPlatform, SearchClient, SearchMiddleware } = require('@ajay.inpis/multitenant-search');\r\n\r\n// 1. Start the search platform\r\nconst platform = new SearchPlatform({ port: 3000 });\r\nawait platform.start();\r\n\r\n// 2. Add to your Express app\r\nconst app = require('express')();\r\nconst search = new SearchMiddleware({\r\n  searchServiceUrl: 'http://localhost:3000'\r\n});\r\n\r\n// 3. Add search capabilities\r\napp.get('/api/search', search.search());\r\napp.post('/api/users', search.syncOnCreate(), createUser);\r\n```\r\n\r\n### Express Middleware Integration\r\n\r\n```javascript\r\nimport express from 'express';\r\nimport { SearchMiddleware } from '@ajay.inpis/multitenant-search';\r\n\r\nconst app = express();\r\nconst searchMiddleware = new SearchMiddleware({\r\n  searchServiceUrl: 'http://localhost:3000'\r\n});\r\n\r\n// Auto-sync on CRUD operations\r\napp.post('/api/users', searchMiddleware.syncOnCreate(), (req, res) => {\r\n  // Your existing logic - search sync happens automatically\r\n  res.json({ success: true });\r\n});\r\n\r\n// Add search endpoints\r\napp.get('/api/search', searchMiddleware.search());\r\napp.get('/api/autocomplete', searchMiddleware.autocomplete());\r\n```\r\n\r\n## API Reference\r\n\r\n### SearchPlatform\r\n\r\n```javascript\r\nconst { SearchPlatform, createProductionConfig } = require('@ajay.inpis/multitenant-search');\r\n\r\nconst platform = new SearchPlatform(createProductionConfig());\r\nawait platform.start();\r\n```\r\n\r\n### SearchClient\r\n\r\n```javascript\r\nconst { SearchClient } = require('@ajay.inpis/multitenant-search');\r\n\r\nconst client = new SearchClient({\r\n  baseUrl: 'http://localhost:3000',\r\n  timeout: 5000\r\n});\r\n\r\nconst results = await client.search({\r\n  query: 'nodejs typescript',\r\n  tenant_id: 'my-tenant',\r\n  limit: 20\r\n});\r\n```\r\n\r\n### SearchMiddleware\r\n\r\n```javascript\r\nconst { SearchMiddleware } = require('@ajay.inpis/multitenant-search');\r\n\r\nconst middleware = new SearchMiddleware({\r\n  searchServiceUrl: 'http://localhost:3000'\r\n});\r\n\r\n// Sync middleware\r\napp.post('/users', middleware.syncOnCreate());\r\napp.put('/users/:id', middleware.syncOnUpdate());\r\napp.delete('/users/:id', middleware.syncOnDelete());\r\n\r\n// Search endpoints\r\napp.get('/search', middleware.search());\r\napp.get('/autocomplete', middleware.autocomplete());\r\n```\r\n\r\n## Configuration\r\n\r\n### Environment Variables\r\n\r\n```bash\r\n# Server Configuration\r\nPORT=3000\r\nHOST=0.0.0.0\r\n\r\n# Search Engines\r\nOPENSEARCH_URL=https://search.example.com:9200\r\nTYPESENSE_HOST=typesense.example.com\r\nREDIS_HOST=redis.example.com\r\n\r\n# Cache Settings\r\nCACHE_L1_MAX_SIZE=10000\r\nCACHE_L1_TTL_MS=300000\r\n```\r\n\r\n### Programmatic Configuration\r\n\r\n```javascript\r\nconst config = {\r\n  port: 3000,\r\n  enableMetrics: true,\r\n  engines: {\r\n    mock: true, // For development\r\n    opensearch: { node: 'https://search.company.com' },\r\n    typesense: { nodes: [{ host: 'ts.company.com' }] }\r\n  },\r\n  cache: {\r\n    l1MaxSize: 50000,\r\n    l1TtlMs: 300000\r\n  }\r\n};\r\n```\r\n\r\n## Search Query Format\r\n\r\n```javascript\r\nconst searchQuery = {\r\n  query: 'search text',\r\n  tenant_id: 'my-tenant',\r\n  limit: 10,\r\n  filters: { category: 'docs', status: 'active' },\r\n  sort: [{ field: 'created_at', direction: 'desc' }]\r\n};\r\n\r\nconst results = await client.search(searchQuery);\r\n```\r\n\r\n## Performance\r\n\r\n- **Response Time**: < 50ms (cached), < 200ms (fresh)\r\n- **Throughput**: 1000+ searches/second per instance\r\n- **Memory Usage**: ~50MB base + configurable cache\r\n- **Cache Hit Rate**: 70-85% in typical usage\r\n\r\n## Integration Examples\r\n\r\n### Next.js API Route\r\n\r\n```javascript\r\n// pages/api/search.js\r\nimport { SearchClient } from '@ajay.inpis/multitenant-search';\r\n\r\nconst client = new SearchClient({\r\n  baseUrl: process.env.SEARCH_SERVICE_URL\r\n});\r\n\r\nexport default async function handler(req, res) {\r\n  const results = await client.search({\r\n    query: req.query.q,\r\n    tenant_id: req.user.tenantId,\r\n    limit: 20\r\n  });\r\n  res.json(results);\r\n}\r\n```\r\n\r\n### Docker Deployment\r\n\r\n```yaml\r\nversion: '3.8'\r\nservices:\r\n  search-platform:\r\n    image: node:18-alpine\r\n    command: npm start\r\n    ports: [\"3000:3000\"]\r\n    environment:\r\n      - NODE_ENV=production\r\n      - OPENSEARCH_URL=http://opensearch:9200\r\n```\r\n\r\n## Monitoring\r\n\r\n```javascript\r\n// Health check\r\nconst health = await client.health();\r\nconsole.log(health.status); // 'healthy'\r\n\r\n// Performance metrics\r\nconst metrics = await client.metrics();\r\nconsole.log(metrics.queries_per_minute); // 23.5\r\n\r\n// Query explanation (debugging)\r\nconst explanation = await client.explain({\r\n  query: 'complex search',\r\n  tenant_id: 'my-tenant'\r\n});\r\n```\r\n\r\n## TypeScript Support\r\n\r\nFull TypeScript definitions included:\r\n\r\n```typescript\r\nimport { \r\n  SearchPlatform, \r\n  SearchClient, \r\n  SearchMiddleware,\r\n  SearchQuery,\r\n  SearchResponse \r\n} from '@ajay.inpis/multitenant-search';\r\n\r\nconst client: SearchClient = new SearchClient({\r\n  baseUrl: 'http://localhost:3000'\r\n});\r\n\r\nconst results: SearchResponse = await client.search({\r\n  query: 'typescript',\r\n  tenant_id: 'my-tenant'\r\n});\r\n```\r\n\r\n## 📈 Monitoring & Analytics\r\n\r\n### Built-in Metrics\r\n```javascript\r\nconst health = await client.health();\r\n// { status: 'healthy', uptime: 3600, engines: {...} }\r\n\r\nconst metrics = await client.metrics();\r\n// { queries_total: 1543, avg_response_time: 45ms, cache_hit_rate: 0.78 }\r\n\r\nconst explanation = await client.explain({ query: 'complex search', tenant_id: 'acme' });\r\n// { classification: 'complex', engine: 'opensearch', estimated_time: 150 }\r\n```\r\n\r\n### Custom Monitoring\r\n```javascript\r\nconst platform = new SearchPlatform({\r\n  onQuery: (query, tenant, responseTime) => {\r\n    console.log(`Query by ${tenant}: ${responseTime}ms`);\r\n    // Send to monitoring service\r\n  },\r\n  onCacheHit: (key, level) => {\r\n    console.log(`Cache hit: ${key} (${level})`);\r\n  },\r\n  onError: (error, context) => {\r\n    console.error('Search error:', error, context);\r\n    // Send to error tracking\r\n  }\r\n});\r\n```\r\n\r\n## 🔄 L2 Cache Without Redis\r\n\r\n### Cache Architecture Overview\r\nThe solution uses a **two-level caching strategy**:\r\n- **L1 Cache**: In-memory LRU cache (Node.js process)\r\n- **L2 Cache**: Distributed cache (Redis by default, but optional)\r\n\r\n### When You Don't Want Redis\r\n\r\nIf you prefer not to use Redis, here are your L2 cache alternatives:\r\n\r\n#### Option 1: L1 Cache Only (Simplest Solution)\r\n```javascript\r\nconst config = {\r\n  cache: {\r\n    l1MaxSize: 50000,           // Increase L1 cache size\r\n    l1TtlMs: 15 * 60 * 1000,   // 15 minutes TTL\r\n    l2Enabled: false           // Disable L2 cache completely\r\n  }\r\n  // No redis configuration needed\r\n};\r\n\r\nconst platform = new SearchPlatform(config);\r\n```\r\n\r\n**Performance Impact:**\r\n- ✅ **Very fast**: Sub-5ms cache hits\r\n- ⚠️ **Limited capacity**: Constrained by Node.js memory\r\n- ❌ **No persistence**: Cache lost on restart\r\n- ❌ **No sharing**: Each instance has separate cache\r\n\r\n#### Option 2: In-Memory L2 Cache Extension\r\n```javascript\r\n// Custom implementation for single-instance deployments\r\nclass MemoryL2Cache {\r\n  constructor(maxSize = 100000, cleanupIntervalMs = 5 * 60 * 1000) {\r\n    this.cache = new Map();\r\n    this.maxSize = maxSize;\r\n    \r\n    // Automatic cleanup of expired entries\r\n    setInterval(() => this.cleanup(), cleanupIntervalMs);\r\n  }\r\n  \r\n  async get(key) {\r\n    const entry = this.cache.get(key);\r\n    if (entry && entry.expires > Date.now()) {\r\n      return entry.value;\r\n    }\r\n    this.cache.delete(key);\r\n    return null;\r\n  }\r\n  \r\n  async set(key, value, ttlSeconds) {\r\n    // Implement LRU eviction if needed\r\n    if (this.cache.size >= this.maxSize) {\r\n      const firstKey = this.cache.keys().next().value;\r\n      this.cache.delete(firstKey);\r\n    }\r\n    \r\n    this.cache.set(key, {\r\n      value,\r\n      expires: Date.now() + (ttlSeconds * 1000)\r\n    });\r\n  }\r\n  \r\n  cleanup() {\r\n    const now = Date.now();\r\n    for (const [key, entry] of this.cache.entries()) {\r\n      if (entry.expires <= now) {\r\n        this.cache.delete(key);\r\n      }\r\n    }\r\n  }\r\n}\r\n```\r\n\r\n#### Option 3: File-Based L2 Cache\r\n```javascript\r\nimport fs from 'fs/promises';\r\nimport path from 'path';\r\n\r\nclass FileCacheL2 {\r\n  constructor(cacheDir = './cache') {\r\n    this.cacheDir = cacheDir;\r\n    this.ensureCacheDir();\r\n  }\r\n  \r\n  async get(key) {\r\n    try {\r\n      const filePath = this.getCacheFilePath(key);\r\n      const data = await fs.readFile(filePath, 'utf8');\r\n      const parsed = JSON.parse(data);\r\n      \r\n      if (parsed.expires > Date.now()) {\r\n        return parsed.value;\r\n      }\r\n      \r\n      await fs.unlink(filePath); // Remove expired\r\n      return null;\r\n    } catch {\r\n      return null;\r\n    }\r\n  }\r\n  \r\n  async set(key, value, ttlSeconds) {\r\n    const filePath = this.getCacheFilePath(key);\r\n    const data = {\r\n      value,\r\n      expires: Date.now() + (ttlSeconds * 1000),\r\n      created: Date.now()\r\n    };\r\n    \r\n    await fs.writeFile(filePath, JSON.stringify(data));\r\n  }\r\n  \r\n  private getCacheFilePath(key) {\r\n    const hash = Buffer.from(key).toString('base64url');\r\n    return path.join(this.cacheDir, `${hash.substring(0, 2)}`, `${hash}.json`);\r\n  }\r\n}\r\n```\r\n\r\n### Performance Comparison\r\n\r\n| Cache Strategy | Response Time | Memory Usage | Persistence | Multi-Instance |\r\n|---|---|---|---|---|\r\n| **L1 Only** | 2-5ms | High | ❌ | ❌ |\r\n| **L1 + Memory L2** | 3-8ms | Very High | ❌ | ❌ |\r\n| **L1 + File L2** | 5-15ms | Medium | ✅ | ❌ |\r\n| **L1 + Redis L2** | 5-15ms | Low | ✅ | ✅ |\r\n\r\n### Configuration Without Redis\r\n\r\n#### Environment Variables\r\n```bash\r\n# Cache configuration without Redis\r\nCACHE_L1_MAX_SIZE=50000\r\nCACHE_L1_TTL_MS=900000\r\nCACHE_L2_ENABLED=false\r\n\r\n# No Redis variables needed\r\n# REDIS_HOST=localhost\r\n# REDIS_PORT=6379\r\n```\r\n\r\n#### Programmatic Configuration\r\n```javascript\r\nconst searchConfig = {\r\n  engines: {\r\n    typesense: {\r\n      nodes: [{ host: 'localhost', port: 8108, protocol: 'http' }],\r\n      apiKey: 'your-api-key'\r\n    },\r\n    opensearch: {\r\n      node: 'http://localhost:9200'\r\n    }\r\n    // No redis configuration\r\n  },\r\n  cache: {\r\n    l1MaxSize: 50000,              // Larger L1 cache\r\n    l1TtlMs: 15 * 60 * 1000,      // 15 minutes\r\n    l2Enabled: false               // Disable L2\r\n  }\r\n};\r\n\r\nconst platform = new SearchPlatform(searchConfig);\r\n```\r\n\r\n### Recommendations by Use Case\r\n\r\n#### Development/Testing\r\n```javascript\r\n// Minimal setup - L1 cache only\r\nconst config = {\r\n  cache: { l1MaxSize: 1000, l1TtlMs: 5 * 60 * 1000, l2Enabled: false }\r\n};\r\n```\r\n\r\n#### Single-Instance Production\r\n```javascript\r\n// Enhanced L1 with memory L2\r\nconst config = {\r\n  cache: { \r\n    l1MaxSize: 10000, \r\n    l1TtlMs: 10 * 60 * 1000, \r\n    l2Enabled: false  // Use custom memory L2\r\n  }\r\n};\r\n```\r\n\r\n#### Multi-Instance Production\r\n```javascript\r\n// Consider Redis or external cache service\r\nconst config = {\r\n  cache: { l2Enabled: true },\r\n  redis: { host: 'redis-cluster', port: 6379 }\r\n};\r\n```\r\n\r\nThe solution **gracefully degrades** when Redis is unavailable - your search will still work with L1 caching, just with reduced performance and no cross-instance cache sharing.\r\n\r\n## 🎯 Architecture Benefits\r\n\r\n### For Developers\r\n- **Zero Learning Curve**: Uses familiar Express.js patterns\r\n- **Minimal Code Changes**: Add search with 3 lines of code\r\n- **TypeScript Support**: Full IntelliSense and type safety\r\n- **Flexible Integration**: Multiple patterns for different needs\r\n\r\n### For Operations\r\n- **Production Ready**: Built-in error handling, retry logic, monitoring\r\n- **Scalable**: Horizontal scaling with Redis and clustered search\r\n- **Observable**: Comprehensive metrics and health checks\r\n- **Maintainable**: Clean separation of concerns\r\n\r\n### For Business\r\n- **Fast Time to Market**: Search features in minutes, not weeks\r\n- **Cost Effective**: Efficient caching reduces infrastructure costs\r\n- **Reliable**: Multi-level redundancy and fault tolerance\r\n- **Secure**: Enterprise-grade multi-tenant isolation\r\n\r\n## License\r\n\r\nMIT\r\n\r\n## Support\r\n\r\n- 📖 [Full Documentation](https://github.com/ajaysingh452/multitenant-search)\r\n- 🐛 [Issues](https://github.com/ajaysingh452/multitenant-search/issues)\r\n- 💬 [Discussions](https://github.com/ajaysingh452/multitenant-search/discussions)","readmeFilename":"README.md"}