{"_id":"@gramio/composer","_rev":"10-86f6baaf7de616b5ed016d569c5f2703","name":"@gramio/composer","dist-tags":{"latest":"0.5.0"},"versions":{"0.1.0":{"name":"@gramio/composer","version":"0.1.0","keywords":["gramio","middleware","composer","compose","koa","typescript"],"author":"kravets","license":"MIT","_id":"@gramio/composer@0.1.0","maintainers":[{"name":"skravets","email":"vsevlamor@gmail.com"}],"dist":{"shasum":"0f7a8cdb1ae9e35b70c9c5e08df269fc09332285","tarball":"https://registry.npmjs.org/@gramio/composer/-/composer-0.1.0.tgz","fileCount":7,"integrity":"sha512-OQKDaK136BOT3DctM9JGKIYO7yfmfQB4ouYdf0op5JC5t4fsbnEi5f5xMqf1z4WGnQ7GzYubkqKNA4KddxFU5A==","signatures":[{"sig":"MEUCIQDYcDmskcyTA+wmLOra19G++YAgiT3zB4alZyQs8hA5+QIgUz2LixGa/d9ZCkQdPONw+2X1PLcJfx8N8g8GyWmK7rY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":67184},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","shasum":"0f7a8cdb1ae9e35b70c9c5e08df269fc09332285","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"lint":"bunx @biomejs/biome check src","test":"bun test","lint:fix":"bun lint --write","prepublishOnly":"bunx pkgroll"},"_npmUser":{"name":"skravets","email":"vsevlamor@gmail.com"},"_integrity":"sha512-OQKDaK136BOT3DctM9JGKIYO7yfmfQB4ouYdf0op5JC5t4fsbnEi5f5xMqf1z4WGnQ7GzYubkqKNA4KddxFU5A==","_npmVersion":"10.8.3","description":"General-purpose, type-safe middleware composition library for TypeScript","directories":{},"_nodeVersion":"22.6.0","_hasShrinkwrap":false,"devDependencies":{"pkgroll":"^2.5.1","@types/bun":"^1.3.9","typescript":"^5.7.2","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/composer_0.1.0_1771286275947_0.6228568172743729","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@gramio/composer","version":"0.1.1","keywords":["gramio","middleware","composer","compose","koa","typescript"],"author":"kravets","license":"MIT","_id":"@gramio/composer@0.1.1","maintainers":[{"name":"skravets","email":"vsevlamor@gmail.com"}],"dist":{"shasum":"438bbee807aed825030275383bd208fe66de4bef","tarball":"https://registry.npmjs.org/@gramio/composer/-/composer-0.1.1.tgz","fileCount":7,"integrity":"sha512-o8MvfWKQ2syx8KKe5wi2YMB/6DSkrDZLlo0bkd2R4Z2Ith+MTJXjDTgUra84YwPAhIxE5PE/Vv1CCgnKys3Ykw==","signatures":[{"sig":"MEQCIED0+6wPoG5FPd56X742Kb5+FfYXMIdHSZClOIFUXctEAiBZZEqOmZM11yE9kAbBxh3WES+3FNJi0qSzS1yLqxkXIA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":67780},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","shasum":"438bbee807aed825030275383bd208fe66de4bef","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"lint":"bunx @biomejs/biome check src","test":"bun test","lint:fix":"bun lint --write","prepublishOnly":"bunx pkgroll"},"_npmUser":{"name":"skravets","email":"vsevlamor@gmail.com"},"_integrity":"sha512-o8MvfWKQ2syx8KKe5wi2YMB/6DSkrDZLlo0bkd2R4Z2Ith+MTJXjDTgUra84YwPAhIxE5PE/Vv1CCgnKys3Ykw==","_npmVersion":"10.8.3","description":"General-purpose, type-safe middleware composition library for TypeScript","directories":{},"_nodeVersion":"22.6.0","_hasShrinkwrap":false,"devDependencies":{"pkgroll":"^2.5.1","@types/bun":"^1.3.9","typescript":"^5.7.2","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/composer_0.1.1_1771292087698_0.2760481501842309","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@gramio/composer","version":"0.2.0","keywords":["gramio","middleware","composer","compose","koa","typescript"],"author":"kravets","license":"MIT","_id":"@gramio/composer@0.2.0","maintainers":[{"name":"skravets","email":"vsevlamor@gmail.com"}],"dist":{"shasum":"3fd0a9c9419bb03e256cc572eaa6a45600b5309d","tarball":"https://registry.npmjs.org/@gramio/composer/-/composer-0.2.0.tgz","fileCount":7,"integrity":"sha512-rjXePc47md99qPsxcfA9Uj+h10X2RxDPX/h88PXwVMH+98yh8KXmk4ZlNqcG+Bj7Pxn1/9ysrFL2B+NislxPJQ==","signatures":[{"sig":"MEYCIQDtScpOOVNsyNgpf5cOjt8cCfYJbPzspNDi2+Ojb1mNzwIhAI4Ho5l+y8eG4d4Vb5TfmMBoxotwO4GWMNSAd2r/sUOK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":71404},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","shasum":"3fd0a9c9419bb03e256cc572eaa6a45600b5309d","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"lint":"bunx @biomejs/biome check src","test":"bun test","lint:fix":"bun lint --write","prepublishOnly":"bunx pkgroll"},"_npmUser":{"name":"skravets","email":"vsevlamor@gmail.com"},"_integrity":"sha512-rjXePc47md99qPsxcfA9Uj+h10X2RxDPX/h88PXwVMH+98yh8KXmk4ZlNqcG+Bj7Pxn1/9ysrFL2B+NislxPJQ==","_npmVersion":"10.8.3","description":"General-purpose, type-safe middleware composition library for TypeScript","directories":{},"_nodeVersion":"22.6.0","_hasShrinkwrap":false,"devDependencies":{"pkgroll":"^2.5.1","@types/bun":"^1.3.9","typescript":"^5.7.2","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/composer_0.2.0_1771326192299_0.6855813584734864","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@gramio/composer","version":"0.3.0","keywords":["gramio","middleware","composer","compose","koa","typescript"],"author":"kravets","license":"MIT","_id":"@gramio/composer@0.3.0","maintainers":[{"name":"skravets","email":"vsevlamor@gmail.com"}],"dist":{"shasum":"03fa9a3e6c268436dea217005f7889b271c61208","tarball":"https://registry.npmjs.org/@gramio/composer/-/composer-0.3.0.tgz","fileCount":7,"integrity":"sha512-IqO6FqehXH9xx+o6HRP87E6a6v78IuGrVFeoiH1HQ9FXNtq3xQZ/ZhP5f9MgT09vNMgRoRvxjFQ2aK2w++pTXQ==","signatures":[{"sig":"MEQCIH64WaN0FHZ3OztN2Fm4H1R6EMApsAB7zXJ5UVwbEMjfAiAls/yqcmwH1xgvKQEpqDMljKZImGqD4A3AO3wanPze7Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":105585},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","shasum":"03fa9a3e6c268436dea217005f7889b271c61208","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"lint":"bunx @biomejs/biome check src","test":"bun test","lint:fix":"bun lint --write","prepublishOnly":"bunx pkgroll"},"_npmUser":{"name":"skravets","email":"vsevlamor@gmail.com"},"_integrity":"sha512-IqO6FqehXH9xx+o6HRP87E6a6v78IuGrVFeoiH1HQ9FXNtq3xQZ/ZhP5f9MgT09vNMgRoRvxjFQ2aK2w++pTXQ==","_npmVersion":"10.8.3","description":"General-purpose, type-safe middleware composition library for TypeScript","directories":{},"_nodeVersion":"22.6.0","_hasShrinkwrap":false,"devDependencies":{"pkgroll":"^2.5.1","@types/bun":"^1.3.9","typescript":"^5.7.2","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/composer_0.3.0_1772061436655_0.02678245720725303","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"@gramio/composer","version":"0.3.1","keywords":["gramio","middleware","composer","compose","koa","typescript"],"author":"kravets","license":"MIT","_id":"@gramio/composer@0.3.1","maintainers":[{"name":"skravets","email":"vsevlamor@gmail.com"}],"dist":{"shasum":"8cd7aa7cfbc6eb24a006d86ec0341edb09a70501","tarball":"https://registry.npmjs.org/@gramio/composer/-/composer-0.3.1.tgz","fileCount":7,"integrity":"sha512-m/OJPlwXSR/Fbne1Jgi3cMNrNRa6UBXasCpnySXvVztpGcZ239UutOGRnwGTwaUhxt6+Jp6ET9KlvTg8Hr1/7g==","signatures":[{"sig":"MEUCICOMePjdy1BKseAmCE4ananedav2qzqtnXfsWIkwwsZJAiEAkuzP1wlv8KhYY5/QJ36o5RtA3Aiht8+7+RIVor7iczA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":108092},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","shasum":"8cd7aa7cfbc6eb24a006d86ec0341edb09a70501","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"lint":"bunx @biomejs/biome check src","test":"bun test","lint:fix":"bun lint --write","prepublishOnly":"bunx pkgroll"},"_npmUser":{"name":"skravets","email":"vsevlamor@gmail.com"},"_integrity":"sha512-m/OJPlwXSR/Fbne1Jgi3cMNrNRa6UBXasCpnySXvVztpGcZ239UutOGRnwGTwaUhxt6+Jp6ET9KlvTg8Hr1/7g==","_npmVersion":"10.8.3","description":"General-purpose, type-safe middleware composition library for TypeScript","directories":{},"_nodeVersion":"22.6.0","_hasShrinkwrap":false,"devDependencies":{"pkgroll":"^2.5.1","@types/bun":"^1.3.9","typescript":"^5.7.2","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/composer_0.3.1_1772192796517_0.6536069109967737","host":"s3://npm-registry-packages-npm-production"}},"0.3.3":{"name":"@gramio/composer","version":"0.3.3","keywords":["gramio","middleware","composer","compose","koa","typescript"],"author":"kravets","license":"MIT","_id":"@gramio/composer@0.3.3","maintainers":[{"name":"skravets","email":"vsevlamor@gmail.com"}],"dist":{"shasum":"4c59125d026cf39fac9150b02eac28ec365d7ad6","tarball":"https://registry.npmjs.org/@gramio/composer/-/composer-0.3.3.tgz","fileCount":7,"integrity":"sha512-IB+nnAh8NO8QweO+7XAL/UHaLAk/V5oVY4yUaVYyCPJi5R8zjdYNYbpaTSDtwryx6RQs7BWvj+wU1yvsq9K8vA==","signatures":[{"sig":"MEYCIQCIeYxP6dcG5rWnCmdB7rD2hWy99a8VwP7kCtHmZ/KyUAIhAOZ25DIvUGz/tD5/RJ36HwkWoeXH+KH/ma9hr+hZLjQp","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":113213},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","shasum":"4c59125d026cf39fac9150b02eac28ec365d7ad6","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"lint":"bunx @biomejs/biome check src","test":"bun test","lint:fix":"bun lint --write","prepublishOnly":"bunx pkgroll"},"_npmUser":{"name":"skravets","email":"vsevlamor@gmail.com"},"_integrity":"sha512-IB+nnAh8NO8QweO+7XAL/UHaLAk/V5oVY4yUaVYyCPJi5R8zjdYNYbpaTSDtwryx6RQs7BWvj+wU1yvsq9K8vA==","_npmVersion":"10.8.3","description":"General-purpose, type-safe middleware composition library for TypeScript","directories":{},"_nodeVersion":"22.6.0","_hasShrinkwrap":false,"devDependencies":{"pkgroll":"^2.5.1","@types/bun":"^1.3.9","typescript":"^5.7.2","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/composer_0.3.3_1772278727984_0.789031061476231","host":"s3://npm-registry-packages-npm-production"}},"0.3.4":{"name":"@gramio/composer","version":"0.3.4","keywords":["gramio","middleware","composer","compose","koa","typescript"],"author":"kravets","license":"MIT","_id":"@gramio/composer@0.3.4","maintainers":[{"name":"skravets","email":"vsevlamor@gmail.com"}],"dist":{"shasum":"403b8756f5717bbe0900e1d18a496e75697a7182","tarball":"https://registry.npmjs.org/@gramio/composer/-/composer-0.3.4.tgz","fileCount":7,"integrity":"sha512-1UiXTCq8aZnEiQjnpDbWxw+AlwbZOgAjpu8lhUei2cYam1qrKh2OJqGSQ5HzdTuIDnrsUOtvjJ2+ThvwLt9oBQ==","signatures":[{"sig":"MEUCIQCsXC+CxaFSgcaQv77RIKhxT1hhi/TR5PiKpPrrOQ6TCgIgSckBDBRDqGCskOTgk+ybWMWmqUszJr8fLwTe/6eP0yM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":116189},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","shasum":"403b8756f5717bbe0900e1d18a496e75697a7182","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"lint":"bunx @biomejs/biome check src","test":"bun test","lint:fix":"bun lint --write","prepublishOnly":"bunx pkgroll"},"_npmUser":{"name":"skravets","email":"vsevlamor@gmail.com"},"_integrity":"sha512-1UiXTCq8aZnEiQjnpDbWxw+AlwbZOgAjpu8lhUei2cYam1qrKh2OJqGSQ5HzdTuIDnrsUOtvjJ2+ThvwLt9oBQ==","_npmVersion":"10.8.3","description":"General-purpose, type-safe middleware composition library for TypeScript","directories":{},"_nodeVersion":"22.6.0","_hasShrinkwrap":false,"devDependencies":{"pkgroll":"^2.5.1","@types/bun":"^1.3.9","typescript":"^5.7.2","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/composer_0.3.4_1772477420563_0.47396646683781496","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@gramio/composer","version":"0.4.0","keywords":["gramio","middleware","composer","compose","koa","typescript"],"author":"kravets","license":"MIT","_id":"@gramio/composer@0.4.0","maintainers":[{"name":"skravets","email":"vsevlamor@gmail.com"}],"dist":{"shasum":"471dfaf0b25012e79809f18ca3c6bbe2c4a0f4b2","tarball":"https://registry.npmjs.org/@gramio/composer/-/composer-0.4.0.tgz","fileCount":7,"integrity":"sha512-WhZDF69f+1N7GDrHYkH/sptt1Z1TvFSwJjsG0Zr3YdGC6ZnE8SLshR5d3MpEHz9J6pzmnXkwsBRDCLtMSA/Z3w==","signatures":[{"sig":"MEUCIQDwGYpeto9zD1h6lZuDiuACTBsu+cXZhxhhTqthQR5LyAIgEp1zUGPQjTtcchgYzoF2Gbl/vXJ7mHH4x73fKdLxZOo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":118803},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","shasum":"471dfaf0b25012e79809f18ca3c6bbe2c4a0f4b2","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"lint":"bunx @biomejs/biome check src","test":"bun test","lint:fix":"bun lint --write","prepublishOnly":"bunx pkgroll"},"_npmUser":{"name":"skravets","email":"vsevlamor@gmail.com"},"_integrity":"sha512-WhZDF69f+1N7GDrHYkH/sptt1Z1TvFSwJjsG0Zr3YdGC6ZnE8SLshR5d3MpEHz9J6pzmnXkwsBRDCLtMSA/Z3w==","_npmVersion":"10.8.3","description":"General-purpose, type-safe middleware composition library for TypeScript","directories":{},"_nodeVersion":"22.6.0","_hasShrinkwrap":false,"devDependencies":{"pkgroll":"^2.5.1","@types/bun":"^1.3.9","typescript":"^5.7.2","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/composer_0.4.0_1773972217891_0.661512774352061","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@gramio/composer","version":"0.4.1","keywords":["gramio","middleware","composer","compose","koa","typescript"],"author":"kravets","license":"MIT","_id":"@gramio/composer@0.4.1","maintainers":[{"name":"skravets","email":"vsevlamor@gmail.com"}],"dist":{"shasum":"ce17ac0ccff94e54d2dcdde413970cd2ba1449cd","tarball":"https://registry.npmjs.org/@gramio/composer/-/composer-0.4.1.tgz","fileCount":7,"integrity":"sha512-oGW1Kj0wiAD1NpORhxDSt9/WId2GANOwYmwlI3bivf4LGEEWB1kokcDW6Ji5/s3FwcK17YjTq1wWtgk0Z/uHnQ==","signatures":[{"sig":"MEYCIQCQW3Jn36X5C0sEVjqWWs5jdLeFqbp8UQUhRCNyzV0hCgIhANuYp9uEa8MiIaQj5yz2qBWJCT85y4yYLVCJzrUDdZRz","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":117183},"main":"dist/index.cjs","type":"module","types":"dist/index.d.ts","module":"dist/index.js","shasum":"ce17ac0ccff94e54d2dcdde413970cd2ba1449cd","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"lint":"bunx @biomejs/biome check src","test":"bun test","lint:fix":"bun lint --write","prepublishOnly":"bunx pkgroll"},"_npmUser":{"name":"skravets","email":"vsevlamor@gmail.com"},"_integrity":"sha512-oGW1Kj0wiAD1NpORhxDSt9/WId2GANOwYmwlI3bivf4LGEEWB1kokcDW6Ji5/s3FwcK17YjTq1wWtgk0Z/uHnQ==","_npmVersion":"10.8.3","description":"General-purpose, type-safe middleware composition library for TypeScript","directories":{},"_nodeVersion":"22.6.0","_hasShrinkwrap":false,"devDependencies":{"pkgroll":"^2.5.1","@types/bun":"^1.3.9","typescript":"^5.7.2","@biomejs/biome":"^1.9.4"},"_npmOperationalInternal":{"tmp":"tmp/composer_0.4.1_1773972600359_0.6638006430131971","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@gramio/composer","version":"0.5.0","description":"General-purpose, type-safe middleware composition library for TypeScript","main":"dist/index.cjs","module":"dist/index.js","types":"dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"type":"module","author":"kravets","license":"MIT","keywords":["gramio","middleware","composer","compose","koa","typescript"],"scripts":{"prepublishOnly":"bunx pkgroll","test":"bun test","lint":"bunx @biomejs/biome check src","lint:fix":"bun lint --write"},"devDependencies":{"@biomejs/biome":"^1.9.4","@types/bun":"^1.3.9","pkgroll":"^2.5.1","typescript":"^5.7.2"},"_id":"@gramio/composer@0.5.0","_integrity":"sha512-CP8DxNzDmVl2uO/L2VtjYycLi6jrPkZvTJoN/qVtct2Ms0oUKlKFgnNidH/i2R41HUow2fU0tlcGb1LR4NPHtg==","_nodeVersion":"24.3.0","_npmVersion":"10.8.3","shasum":"284d3f10031a2a93ead8ca8f59c60ac63b229554","dist":{"integrity":"sha512-CP8DxNzDmVl2uO/L2VtjYycLi6jrPkZvTJoN/qVtct2Ms0oUKlKFgnNidH/i2R41HUow2fU0tlcGb1LR4NPHtg==","shasum":"284d3f10031a2a93ead8ca8f59c60ac63b229554","tarball":"https://registry.npmjs.org/@gramio/composer/-/composer-0.5.0.tgz","fileCount":7,"unpackedSize":123850,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIGFHZu2dFV31QXCcNTlfqmXEN4XZcIhmv4BvJQbOxJXbAiEA+XOXC8Ajr6AD8L4JaOHjl062gRnGT2zc+YkybPyzsvw="}]},"_npmUser":{"name":"skravets","email":"vsevlamor@gmail.com"},"directories":{},"maintainers":[{"name":"skravets","email":"vsevlamor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/composer_0.5.0_1780504869036_0.9967412630254684"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-16T23:57:55.847Z","modified":"2026-06-03T16:41:09.325Z","0.1.0":"2026-02-16T23:57:56.089Z","0.1.1":"2026-02-17T01:34:47.845Z","0.2.0":"2026-02-17T11:03:12.452Z","0.3.0":"2026-02-25T23:17:16.808Z","0.3.1":"2026-02-27T11:46:36.662Z","0.3.3":"2026-02-28T11:38:48.137Z","0.3.4":"2026-03-02T18:50:20.701Z","0.4.0":"2026-03-20T02:03:38.067Z","0.4.1":"2026-03-20T02:10:00.526Z","0.5.0":"2026-06-03T16:41:09.193Z"},"author":"kravets","license":"MIT","keywords":["gramio","middleware","composer","compose","koa","typescript"],"description":"General-purpose, type-safe middleware composition library for TypeScript","maintainers":[{"name":"skravets","email":"vsevlamor@gmail.com"}],"readme":"# @gramio/composer\n\n[![npm](https://img.shields.io/npm/v/@gramio/composer?logo=npm&style=flat&labelColor=000&color=3b82f6)](https://www.npmjs.org/package/@gramio/composer)\n[![npm downloads](https://img.shields.io/npm/dw/@gramio/composer?logo=npm&style=flat&labelColor=000&color=3b82f6)](https://www.npmjs.org/package/@gramio/composer)\n[![JSR](https://jsr.io/badges/@gramio/composer)](https://jsr.io/@gramio/composer)\n[![JSR Score](https://jsr.io/badges/@gramio/composer/score)](https://jsr.io/@gramio/composer)\n\nGeneral-purpose, type-safe middleware composition library for TypeScript.\nZero dependencies. Cross-runtime (Bun / Node.js / Deno).\n\n## Features\n\n- Koa-style onion middleware composition\n- Type-safe context accumulation via `derive()`\n- Scope isolation (local / scoped / global) like Elysia\n- Plugin deduplication by name + seed\n- Abstract event system via factory pattern (`.on()`)\n- Concurrent event queue with graceful shutdown\n- Branching, routing, forking, lazy middleware\n\n## Installation\n\n```bash\n# npm\nnpm install @gramio/composer\n\n# bun\nbun add @gramio/composer\n\n# deno\ndeno add jsr:@gramio/composer\n```\n\n## Quick Start\n\n```ts\nimport { Composer } from \"@gramio/composer\";\n\nconst app = new Composer<{ request: Request }>()\n  .use(async (ctx, next) => {\n    console.log(\"before\");\n    await next();\n    console.log(\"after\");\n  })\n  .derive((ctx) => ({\n    url: new URL(ctx.request.url),\n  }))\n  .use((ctx, next) => {\n    console.log(ctx.url.pathname); // typed!\n    return next();\n  });\n\nawait app.run({ request: new Request(\"https://example.com/hello\") });\n```\n\n## API\n\n### `compose(middlewares)`\n\nStandalone Koa-style onion composition. Takes an array of middleware, returns a single composed middleware.\n\n```ts\nimport { compose } from \"@gramio/composer\";\n\nconst handler = compose([\n  async (ctx, next) => { console.log(1); await next(); console.log(4); },\n  async (ctx, next) => { console.log(2); await next(); console.log(3); },\n]);\n\nawait handler({});\n// 1 → 2 → 3 → 4\n```\n\n### `Composer`\n\nThe core class. Registers middleware with type-safe context accumulation.\n\n#### `use(...middleware)`\n\nRegister raw middleware functions.\n\n```ts\napp.use((ctx, next) => {\n  // do something\n  return next();\n});\n```\n\n#### `derive(handler, options?)`\n\nCompute and assign additional context properties. Subsequent middleware sees the new types.\n\n```ts\napp\n  .derive((ctx) => ({ user: getUser(ctx) }))\n  .use((ctx, next) => {\n    ctx.user; // typed!\n    return next();\n  });\n```\n\nWith scope propagation:\n\n```ts\nconst plugin = new Composer({ name: \"auth\" })\n  .derive((ctx) => ({ user: getUser(ctx) }), { as: \"scoped\" });\n```\n\n#### `guard(predicate, ...middleware)`\n\nTwo modes depending on whether handlers are provided:\n\n**With handlers** — run middleware as side-effects when true, always continue the chain:\n\n```ts\napp.guard(\n  (ctx): ctx is WithText => \"text\" in ctx,\n  (ctx, next) => { /* ctx.text is typed */ return next(); }\n);\n```\n\n**Without handlers (gate mode)** — if false, stop this composer's remaining middleware. When a type predicate is used, downstream context is narrowed:\n\n```ts\n// Only admin can reach subsequent middleware\napp\n  .guard((ctx) => ctx.role === \"admin\")\n  .use(adminOnlyHandler);  // skipped if not admin\n\n// Type predicate narrows context for all downstream handlers\napp\n  .guard((ctx): ctx is Ctx & { text: string } => \"text\" in ctx)\n  .on(\"message\", (ctx, next) => {\n    ctx.text; // string (narrowed by guard)\n    return next();\n  });\n```\n\nWhen used inside an `extend()`-ed plugin, the guard stops the plugin's chain but the parent continues:\n\n```ts\nconst adminPlugin = new Composer()\n  .guard((ctx) => ctx.isAdmin)\n  .use(adminDashboard);          // skipped if not admin\n\napp\n  .extend(adminPlugin)  // guard inside, isolated\n  .use(alwaysRuns);     // parent continues regardless\n```\n\n#### `branch(predicate, onTrue, onFalse?)`\n\nIf/else branching. Static boolean optimization at registration time.\n\n```ts\napp.branch(\n  (ctx) => ctx.isAdmin,\n  adminHandler,\n  userHandler\n);\n```\n\n#### `route(router, cases, fallback?)`\n\nMulti-way dispatch (like a switch).\n\n```ts\napp.route(\n  (ctx) => ctx.type,\n  {\n    message: handleMessage,\n    callback: handleCallback,\n  },\n  handleFallback\n);\n```\n\n#### `fork(...middleware)`\n\nFire-and-forget parallel execution. Doesn't block the main chain.\n\n```ts\napp.fork(analyticsMiddleware);\n```\n\n#### `tap(...middleware)`\n\nRun middleware but always continue the chain (cannot stop it).\n\n```ts\napp.tap(loggingMiddleware);\n```\n\n#### `lazy(factory)`\n\nDynamic middleware selection. Factory is called on every invocation (not cached).\n\n```ts\napp.lazy((ctx) => ctx.premium ? premiumHandler : freeHandler);\n```\n\n#### `onError(handler)`\n\nError boundary for all subsequent middleware.\n\n```ts\napp.onError((ctx, error) => {\n  console.error(error);\n});\n```\n\n#### `group(fn)`\n\nIsolated sub-chain. Derives inside the group don't leak to the parent.\n\n```ts\napp.group((g) => {\n  g.derive(() => ({ internal: true }))\n   .use((ctx, next) => {\n     ctx.internal; // available here\n     return next();\n   });\n});\n// ctx.internal is NOT available here\n```\n\n#### `extend(other)`\n\nMerge another composer. Scope-aware and dedup-aware.\n\n```ts\nconst auth = new Composer({ name: \"auth\" })\n  .derive(() => ({ user: \"alice\" }))\n  .as(\"scoped\");\n\napp.extend(auth);\n// app now sees ctx.user\n```\n\n#### `as(scope)`\n\nPromote all middleware to `\"scoped\"` (one level) or `\"global\"` (all levels).\n\n#### `compose()` / `run(context)`\n\nCompile to a single middleware or run directly.\n\n```ts\nconst handler = app.compose();\nawait handler(ctx);\n\n// or\nawait app.run(ctx);\n```\n\n### Scope System\n\nWhen `parent.extend(child)`:\n\n| Child scope | Effect in parent |\n|---|---|\n| `local` (default) | Isolated via `Object.create()` — derives don't leak |\n| `scoped` | Merged into parent, stops there (one level) |\n| `global` | Merged into parent and propagates to all ancestors |\n\n### Plugin Deduplication\n\nComposers with a `name` are deduplicated. Same name + seed = skipped on second extend.\n\n```ts\nconst auth = new Composer({ name: \"auth\" });\napp.extend(auth); // applied\napp.extend(auth); // skipped\n```\n\nDifferent seed = different plugin:\n\n```ts\nconst limit100 = new Composer({ name: \"rate-limit\", seed: { max: 100 } });\nconst limit200 = new Composer({ name: \"rate-limit\", seed: { max: 200 } });\napp.extend(limit100); // applied\napp.extend(limit200); // applied (different seed)\n```\n\n> [!WARNING]\n> **Dedup removes middleware at registration time — not at runtime per-request.**\n>\n> If a shared plugin (e.g. `withUser`) is extended only inside sub-composers, its\n> `derive` runs inside each sub-composer's isolation group. When dedup removes the\n> derive from the second sub-composer, `ctx.user` set in the first group is **not\n> visible** in the second — TypeScript types are correct, runtime value is `undefined`.\n>\n> **Fix:** extend the shared composer at the level where its data must be available,\n> and let sub-composers extend it only for type safety (dedup prevents double execution).\n>\n> ```ts\n> // ✅ correct — withUser runs once on the real ctx, both routers see ctx.user\n> app\n>   .extend(withUser)    // derive on real ctx\n>   .extend(adminRouter) // withUser inside → deduped (skipped)\n>   .extend(chatRouter); // withUser inside → deduped (skipped)\n>\n> // ⚠️  risky — works only if routers are mutually exclusive (one handles per update)\n> app\n>   .extend(adminRouter) // withUser runs in isolation group\n>   .extend(chatRouter); // withUser deduped → chatHandlers can't see ctx.user\n> ```\n>\n> See [`docs/layered-composers.md`](./docs/layered-composers.md) for the full breakdown.\n\n### `createComposer(config)` — Event System\n\nFactory that creates a Composer class with `.on()` event discrimination.\n\n```ts\nimport { createComposer } from \"@gramio/composer\";\n\ninterface BaseCtx { updateType: string }\ninterface MessageCtx extends BaseCtx { text?: string }\ninterface CallbackCtx extends BaseCtx { data?: string }\n\nconst { Composer, EventQueue } = createComposer<BaseCtx, {\n  message: MessageCtx;\n  callback_query: CallbackCtx;\n}>({\n  discriminator: (ctx) => ctx.updateType,\n});\n\nconst app = new Composer()\n  .derive(() => ({ timestamp: Date.now() }))\n  .on(\"message\", (ctx, next) => {\n    ctx.text;      // string | undefined\n    ctx.timestamp;  // number\n    return next();\n  })\n  .on(\"callback_query\", (ctx, next) => {\n    ctx.data;       // string | undefined\n    return next();\n  });\n```\n\n#### `.on()` with filters\n\n**Filter-only (no event name)** — the 2-arg `on(filter, handler)` applies the filter to **all** events without discriminating by event type:\n\n```ts\n// Type-narrowing filter — handler sees narrowed context across all compatible events\napp.on(\n  (ctx): ctx is { text: string } => typeof (ctx as any).text === \"string\",\n  (ctx, next) => {\n    ctx.text; // string (narrowed)\n    return next();\n  },\n);\n\n// Boolean filter — no narrowing, handler gets base TOut\napp.on(\n  (ctx) => ctx.updateType === \"message\",\n  (ctx, next) => {\n    // no type narrowing, full context\n    return next();\n  },\n);\n```\n\n**Event + filter** — the 3-arg `on(event, filter, handler)` supports both type-narrowing predicates and boolean filters:\n\n```ts\n// Type-narrowing filter — handler sees narrowed context\napp.on(\n  \"message\",\n  (ctx): ctx is MessageCtx & { text: string } => ctx.text !== undefined,\n  (ctx, next) => {\n    ctx.text; // string (narrowed, not string | undefined)\n    return next();\n  },\n);\n\n// Boolean filter — no narrowing, handler sees full context\napp.on(\n  \"message\",\n  (ctx) => ctx.text !== undefined,\n  (ctx, next) => {\n    ctx.text; // string | undefined (not narrowed)\n    return next();\n  },\n);\n```\n\nThe 2-arg `on()` also accepts an optional `Patch` generic for context extensions (useful in custom methods):\n\n```ts\napp.on<\"message\", { args: string }>(\"message\", (ctx, next) => {\n  ctx.args; // string — type-safe without casting\n  return next();\n});\n```\n\n`.use()` supports the same `Patch` generic — handy when a custom method enriches context before delegating to a user-provided handler:\n\n```ts\napp.use<{ args: string }>((ctx, next) => {\n  ctx.args; // string — type-safe without casting\n  return next();\n});\n```\n\n`Patch` does not change `TOut` — it is a local escape hatch for one handler, not a permanent context extension. Use `derive()` when you want the addition to propagate to all downstream middleware.\n\n#### `types` + `eventTypes()` — phantom type inference\n\nTypeScript cannot partially infer type arguments, so when you need both `TEventMap` and `TMethods` inferred together, use the `types` phantom field with the `eventTypes()` helper instead of explicit type parameters:\n\n```ts\nimport { createComposer, eventTypes } from \"@gramio/composer\";\n\n// eventTypes<T>() returns undefined at runtime — purely for inference\nconst { Composer } = createComposer({\n  discriminator: (ctx: BaseCtx) => ctx.updateType,\n  types: eventTypes<{ message: MessageCtx; callback_query: CallbackCtx }>(),\n});\n// TBase inferred from discriminator, TEventMap inferred from types\n```\n\n#### `methods` — custom prototype methods\n\nInject framework-specific DX sugar directly onto the Composer prototype. Custom methods are preserved through **all** method chains (`on`, `use`, `derive`, `extend`, etc.). A runtime conflict check throws if a method name collides with a built-in.\n\n**Simple methods** (no access to accumulated derives) work directly in `methods`:\n\n```ts\nconst { Composer } = createComposer({\n  discriminator: (ctx: BaseCtx) => ctx.updateType,\n  types: eventTypes<{ message: MessageCtx }>(),\n  methods: {\n    hears(trigger: RegExp | string, handler: (ctx: MessageCtx) => unknown) {\n      return this.on(\"message\", (ctx, next) => {\n        const text = ctx.text;\n        if (\n          (typeof trigger === \"string\" && text === trigger) ||\n          (trigger instanceof RegExp && text && trigger.test(text))\n        ) {\n          return handler(ctx);\n        }\n        return next();\n      });\n    },\n  },\n});\n```\n\n**Methods that receive accumulated derives** require two steps. TypeScript cannot infer generic method signatures when `TMethods` is nested inside the return type of `createComposer`, so use `defineComposerMethods` first — its return type is directly `TMethods`, which preserves generic signatures. Then pass `typeof methods` as the 3rd type argument.\n\nUse `ComposerLike<TThis>` as an F-bounded constraint so that `this.on(...)` is fully typed and returns `TThis` — no casts needed.\n\n**Pattern: `this: TThis` + `ContextOf<TThis>` — zero annotation at the call site:**\n\n```ts\nimport { createComposer, defineComposerMethods, eventTypes } from \"@gramio/composer\";\nimport type { ComposerLike, ContextOf, Middleware } from \"@gramio/composer\";\n\nconst methods = defineComposerMethods({\n  command<TThis extends ComposerLike<TThis>>(\n    this: TThis,\n    name: string,\n    handler: Middleware<MessageCtx & ContextOf<TThis>>,\n  ): TThis {\n    const inner: Middleware<MessageCtx & ContextOf<TThis>> = (ctx, next) => {\n      if (ctx.text === `/${name}`) return handler(ctx, next);\n      return next();\n    };\n    return this.on(\"message\", inner);\n  },\n});\n\nconst { Composer } = createComposer<BaseCtx, { message: MessageCtx }, typeof methods>({\n  discriminator: (ctx) => ctx.updateType,\n  methods,\n});\n\n// Derives flow into the handler automatically — no annotation needed:\nnew Composer()\n  .derive(() => ({ user: { id: 1, name: \"Alice\" } }))\n  .command(\"start\", (ctx, next) => {\n    ctx.user.id;   // ✅ typed — inferred from ContextOf<TThis>\n    ctx.text;      // ✅ string | undefined — from MessageCtx\n    return next();\n  });\n```\n\n#### `ContextOf<T>` — extract the current context type\n\nExtracts `TOut` (the fully accumulated context type after all `.derive()` and `.decorate()` calls) from a Composer or EventComposer instance type.\n\n**Naming a plugin's context type for reuse:**\n\n```ts\nimport type { ContextOf } from \"@gramio/composer\";\n\nconst withUser = new Composer()\n  .derive(async (ctx) => ({\n    user: await db.getUser(ctx.userId),\n  }));\n\n// Extract the enriched context — no manual conditional type needed\nexport type WithUser = ContextOf<typeof withUser>;\n// WithUser = { userId: string } & { user: User }\n\n// Use it in standalone functions, other plugins, or type assertions:\nfunction requireAdmin(ctx: WithUser) {\n  if (!ctx.user.isAdmin) throw new Error(\"Forbidden\");\n}\n```\n\n**In a custom method signature** — `ContextOf<TThis>` captures all derives accumulated at the call site:\n\n```ts\ncommand<TThis extends ComposerLike<TThis>>(\n  this: TThis,\n  handler: Middleware<ContextOf<TThis>>,\n): TThis\n```\n\n#### `EventContextOf<T, E>` — extract context for a specific event (global + per-event derives)\n\nLike `ContextOf<T>`, but also includes per-event derives registered via `derive(event, handler)`.\n\n| | Includes |\n|---|---|\n| `ContextOf<TThis>` | `TOut` — global derives only |\n| `EventContextOf<TThis, \"message\">` | `TOut & TDerives[\"message\"]` — global **and** per-event derives |\n\n**Why it matters:** when a custom method always routes to a specific event (e.g. `command` → `\"message\"`), its handler should see per-event derives too. With `ContextOf` alone, a `derive(\"message\", ...)` plugin's types are invisible inside the handler even though the value is there at runtime.\n\n```ts\nimport { createComposer, defineComposerMethods, eventTypes } from \"@gramio/composer\";\nimport type { ComposerLike, EventContextOf, Middleware } from \"@gramio/composer\";\n\nconst methods = defineComposerMethods({\n  command<TThis extends ComposerLike<TThis>>(\n    this: TThis,\n    name: string,\n    //                  ↓ EventContextOf instead of ContextOf\n    handler: Middleware<MessageCtx & EventContextOf<TThis, \"message\">>,\n  ): TThis {\n    return this.on(\"message\", (ctx: any, next: Next) => {\n      if (ctx.text === `/${name}`) return handler(ctx, next);\n      return next();\n    });\n  },\n});\n\nconst { Composer } = createComposer<BaseCtx, { message: MessageCtx }, typeof methods>({\n  discriminator: (ctx) => ctx.updateType,\n  methods,\n});\n\n// Per-event plugin that adds `t` only for message events:\nconst i18nPlugin = new Composer({ name: \"i18n\" })\n  .derive(\"message\", (ctx) => ({\n    t: i18n.buildT(ctx.from?.languageCode ?? \"en\"),\n  }))\n  .as(\"scoped\");\n\nnew Composer()\n  .extend(i18nPlugin)\n  .command(\"start\", (ctx, next) => {\n    ctx.t(\"Hello\");   // ✅ typed — EventContextOf sees TDerives[\"message\"]\n    ctx.text;         // ✅ string | undefined — from MessageCtx\n    return next();\n  })\n  .on(\"message\", (ctx, next) => {\n    ctx.t(\"Hi\");      // ✅ also works here via ResolveEventCtx\n    return next();\n  });\n```\n\n> [!NOTE]\n> If the derive is registered globally (`.derive(() => ...)` without an event name), both `ContextOf` and `EventContextOf` will see it. Per-event derives (`derive(\"message\", ...)`) are only visible through `EventContextOf` in custom method signatures, or directly inside `.on(\"message\", ...)` handlers.\n\n#### `ComposerLike<T>` — minimal structural type for `this` constraints\n\nA minimal interface `{ on(event: any, handler: any): T }` used as an F-bounded constraint on `TThis`. Makes `this.on(...)` fully typed and return `TThis` without casts.\n\n```ts\nimport type { ComposerLike } from \"@gramio/composer\";\n\n// Constraint in a custom method:\ncommand<TThis extends ComposerLike<TThis>>(this: TThis, ...): TThis {\n  return this.on(\"message\", inner); // returns TThis — no `as TThis` needed\n}\n```\n\n### `EventQueue`\n\nConcurrent event queue with graceful shutdown.\n\n```ts\nimport { EventQueue } from \"@gramio/composer\";\n\nconst queue = new EventQueue<RawEvent>(async (event) => {\n  const ctx = createContext(event);\n  return app.run(ctx);\n});\n\nqueue.add(event);\nqueue.addBatch(events);\n\n// Graceful shutdown (waits up to 5s for pending handlers)\nawait queue.stop(5000);\n```\n\n### Macro System\n\nDeclarative handler options inspired by [Elysia macros](https://elysiajs.com/patterns/macro.md). Register reusable behaviors (guards, rate-limits, auth) as macros, then activate them via an options object on handler methods.\n\n#### `macro(name, definition)` / `macro(definitions)`\n\nRegister macros on a Composer or EventComposer instance.\n\n```ts\nimport { Composer, type MacroDef, type ContextCallback } from \"@gramio/composer\";\n\n// Boolean shorthand macro — plain hooks object\nconst onlyAdmin: MacroDef<void, {}> = {\n  preHandler: (ctx, next) => {\n    if (ctx.role !== \"admin\") return; // stops chain\n    return next();\n  },\n};\n\n// Parameterized macro — function receiving options\ninterface ThrottleOptions {\n  limit: number;\n  window?: number;\n  onLimit?: ContextCallback; // ← replaced with actual ctx type at call site\n}\n\nconst throttle: MacroDef<ThrottleOptions, {}> = (opts) => ({\n  preHandler: createThrottleMiddleware(opts),\n});\n\n// Macro with derive — enriches handler context\ninterface AuthDerived { user: { id: number; name: string } }\n\nconst auth: MacroDef<void, AuthDerived> = {\n  derive: async (ctx) => {\n    const user = await getUser(ctx.token);\n    if (!user) return; // void = stop chain (guard behavior)\n    return { user };\n  },\n};\n\nconst app = new Composer()\n  .macro(\"onlyAdmin\", onlyAdmin)\n  .macro({ throttle, auth }); // batch registration\n```\n\n#### `buildFromOptions(macros, options, handler)`\n\nRuntime helper that composes a handler with macro hooks. Used internally by frameworks to wire macros into handler methods.\n\n```ts\nimport { buildFromOptions } from \"@gramio/composer\";\n\n// Execution order:\n// 1. options.preHandler[] (explicit guards — user controls order)\n// 2. Per-macro in options property order:\n//    a. macro.preHandler (guard middleware)\n//    b. macro.derive (context enrichment; void = stop chain)\n// 3. Main handler\nconst composed = buildFromOptions(\n  app[\"~\"].macros,\n  { auth: true, throttle: { limit: 5 } },\n  mainHandler,\n);\n```\n\n#### Macro Types\n\n```ts\nimport type {\n  MacroDef,          // Macro definition (function or hooks object)\n  MacroHooks,        // { preHandler?, derive? }\n  MacroDefinitions,  // Record<string, MacroDef<any, any>>\n  ContextCallback,   // Marker type for context-aware callbacks\n  WithCtx,           // Recursively replaces ContextCallback with real ctx type\n  HandlerOptions,    // Builds the options parameter type for handler methods\n  DeriveFromOptions, // Collects derive types from activated macros\n  MacroOptionType,   // Extracts option type from MacroDef\n  MacroDeriveType,   // Extracts derive return type from MacroDef\n} from \"@gramio/composer\";\n```\n\n### Utilities\n\n```ts\nimport { noopNext, skip, stop } from \"@gramio/composer\";\n\nnoopNext;  // () => Promise.resolve()\nskip;      // middleware that calls next()\nstop;      // middleware that does NOT call next()\n```\n","readmeFilename":"README.md"}