{"_id":"@demchenko.di/signals","_rev":"11-2e872866773bc6431d87075c19d930d5","name":"@demchenko.di/signals","dist-tags":{"latest":"3.1.0"},"versions":{"1.0.0":{"name":"@demchenko.di/signals","version":"1.0.0","keywords":["signals","reactivity","state","typescript"],"license":"MIT","_id":"@demchenko.di/signals@1.0.0","maintainers":[{"name":"demchenko.di","email":"demchenko.di@gmail.com"}],"dist":{"shasum":"0872759b44f4fa23667371429496e6d905957ecf","tarball":"https://registry.npmjs.org/@demchenko.di/signals/-/signals-1.0.0.tgz","fileCount":19,"integrity":"sha512-vy/O+4jjczq4X7LBbjP+fbO5+YbKmMKO9+kleNzWRsFqNclsnSz2pOeZBmUt/MiYBztu7BgMkRwZgc7zREfRug==","signatures":[{"sig":"MEQCIELEYbvnuGZPTjyR0HXfDac/+cq0jegQkvwnNRQUfhzVAiBziDjzPWZdU/m1lTrGB7AuXBjW5T9ef7EprAMKXxDjDQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":31886},"main":"./dist/index.js","types":"./dist/index.d.ts","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js","require":"./dist/index.js"}},"gitHead":"22cc9da4c34465b6025bb3b060b0cb853966b898","scripts":{"build":"rm -rf dist && ./node_modules/.bin/tsc -p tsconfig.json","check":"tsc --noEmit --pretty false","prepack":"npm run build"},"_npmUser":{"name":"demchenko.di","email":"demchenko.di@gmail.com"},"_npmVersion":"11.12.1","description":"Zero-dependency reactive signals for TypeScript and JavaScript.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/signals_1.0.0_1776761260472_0.582175687639241","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@demchenko.di/signals","version":"1.0.1","keywords":["signals","reactivity","state","typescript"],"license":"MIT","_id":"@demchenko.di/signals@1.0.1","maintainers":[{"name":"demchenko.di","email":"demchenko.di@gmail.com"}],"dist":{"shasum":"f9166d3a87e1f35d8ffbb8121f6a7de4b3578ae2","tarball":"https://registry.npmjs.org/@demchenko.di/signals/-/signals-1.0.1.tgz","fileCount":21,"integrity":"sha512-XnncVGsY2stfjP5NevzVT40zdzx0uLm9IQTg3llN13ZpVZqZf/xwmzO3wTUyFI2XcHSZT1Kyhsxy8JdPvaiCdw==","signatures":[{"sig":"MEQCIDVSTdQUcdZw0VHHlr1hMsGG4fPvFh1ej/UQ51HhSfnpAiAJILe+iyNsR88miV724wnoGBf5psL6rXFKxcYe5OZPyw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":50635},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"af8bc3dd496079dc3c077675333c2df91a4f0abc","scripts":{"build":"rm -rf dist && ./node_modules/.bin/tsc -p tsconfig.json","check":"tsc --noEmit --pretty false","prepack":"npm run build"},"_npmUser":{"name":"demchenko.di","email":"demchenko.di@gmail.com"},"_npmVersion":"11.12.1","description":"Zero-dependency reactive signals for TypeScript and JavaScript.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/signals_1.0.1_1777024064965_0.6970965452255318","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@demchenko.di/signals","version":"1.0.2","keywords":["signals","reactivity","state","typescript"],"license":"MIT","_id":"@demchenko.di/signals@1.0.2","maintainers":[{"name":"demchenko.di","email":"demchenko.di@gmail.com"}],"dist":{"shasum":"b7db786db6b87ff059a20101a8dbaee8b394d296","tarball":"https://registry.npmjs.org/@demchenko.di/signals/-/signals-1.0.2.tgz","fileCount":21,"integrity":"sha512-qLPO20r8Yy4fUR6/PiW0SU6vP9rGNX39CyiQ9dRIgTjkqe7X9ilhG105KBSQg+2aEonRV5Bpo70yEiZIz6RYjg==","signatures":[{"sig":"MEUCIByqNMhJKDJHLuwWGY+2BezblGcrW48WqppFFlQklgG+AiEA4l3J9Reuqe0K8KUASrtJvzE6KRnvbf77aBFlUzvQNoQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":51926},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"97f4afacead788a718b574e0fa8c3f40b78b9298","scripts":{"build":"rm -rf dist && ./node_modules/.bin/tsc -p tsconfig.json","check":"tsc --noEmit --pretty false","prepack":"npm run build"},"_npmUser":{"name":"demchenko.di","email":"demchenko.di@gmail.com"},"_npmVersion":"11.12.1","description":"Zero-dependency reactive signals for TypeScript and JavaScript.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/signals_1.0.2_1777024824177_0.3369375793939835","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@demchenko.di/signals","version":"1.0.3","keywords":["signals","reactivity","state","typescript"],"license":"MIT","_id":"@demchenko.di/signals@1.0.3","maintainers":[{"name":"demchenko.di","email":"demchenko.di@gmail.com"}],"dist":{"shasum":"317ee1a1fa30b964c11ecf96ab77f0bdf1286f82","tarball":"https://registry.npmjs.org/@demchenko.di/signals/-/signals-1.0.3.tgz","fileCount":21,"integrity":"sha512-fxWw5PSWani0yDwkeBoHI2u2D2PjmatmQ3RZscTLPhtHuzZEQO26zUQZfmooaMvU0hGYBgJSsJQA+WvvMLNJFA==","signatures":[{"sig":"MEUCIFbKbr+vqkLxPMqgJEydB+farCIRTpYrPx95bUYPyKl7AiEAmaQf9Iy+YKXnMDnm2FicehVZtErG/DFeHTsUHj095y4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":52592},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"17a9a54c41c5d926c0c2099422766135e29cff6e","scripts":{"build":"rm -rf dist && ./node_modules/.bin/tsc -p tsconfig.json","check":"tsc --noEmit --pretty false","prepack":"npm run build"},"_npmUser":{"name":"demchenko.di","email":"demchenko.di@gmail.com"},"_npmVersion":"11.12.1","description":"Zero-dependency reactive signals for TypeScript and JavaScript.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/signals_1.0.3_1777038986565_0.23970442931654046","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@demchenko.di/signals","version":"2.0.0","keywords":["signals","reactivity","state","typescript"],"license":"MIT","_id":"@demchenko.di/signals@2.0.0","maintainers":[{"name":"demchenko.di","email":"demchenko.di@gmail.com"}],"dist":{"shasum":"3f79cde180cc799b094a3dc1d9e33a4f6f149b8b","tarball":"https://registry.npmjs.org/@demchenko.di/signals/-/signals-2.0.0.tgz","fileCount":26,"integrity":"sha512-h2x/0J394UFh/Ibcmmte9BbmWY5h9dg2UkKaPhtpHtSp72ImTryKG1bRFcNcxm2LSvYDzVOGgccx8F6NYHBLRg==","signatures":[{"sig":"MEUCICgNruUcAc0jJK3EIFRzfUDEAL5KsXAL116vAJiYeIf2AiEAgmPpIKFg34FrYGvA7o9Ezh1oNwVRFRGnJjMPNJam1oE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":74516},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}},"gitHead":"f71d1413c4812877dd842917d15bcafc733ff829","scripts":{"build":"rm -rf dist && ./node_modules/.bin/tsc -p tsconfig.json","check":"tsc --noEmit --pretty false","prepack":"npm run build"},"_npmUser":{"name":"demchenko.di","email":"demchenko.di@gmail.com"},"_npmVersion":"11.12.1","description":"Zero-dependency reactive signals for TypeScript and JavaScript.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.9.3"},"_npmOperationalInternal":{"tmp":"tmp/signals_2.0.0_1777043014459_0.20819756311678983","host":"s3://npm-registry-packages-npm-production"}},"2.0.1":{"name":"@demchenko.di/signals","version":"2.0.1","keywords":["signals","reactivity","state","typescript","nodejs","angular","javascript","RxJS","reactive programming","reactive state management","reactive libraries","reactive programming libraries","reactive programming tools","reactive programming frameworks"],"license":"MIT","_id":"@demchenko.di/signals@2.0.1","maintainers":[{"name":"demchenko.di","email":"demchenko.di@gmail.com"}],"dist":{"shasum":"70e9a4004099a3085ce2fd72fea3432041157ebd","tarball":"https://registry.npmjs.org/@demchenko.di/signals/-/signals-2.0.1.tgz","fileCount":25,"integrity":"sha512-+u8nynmk3/WazWebjb2FauAnknxw95cJmc2W3YKUuWZ0mAs5hfnkxdBMhH5lYqYJgdvkAlComYXRCT99fBXt2g==","signatures":[{"sig":"MEQCIFKNEY7i+Saw9HL1DxkmGXVJXkeKfsYIFdDYTM3uE2Q8AiA+dfhF+zwCfTJdayS6/P7si+J5pkDzuX0Mawf4t9+FhQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":111705},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./min":{"import":"./dist/index.min.js","default":"./dist/index.min.js"}},"gitHead":"070c2654e233c14a1ee8de3210ff396213988d7f","scripts":{"lint":"eslint src/","test":"vitest run","build":"vite build && MINIFY=true vite build && node scripts/minify.js && tsc --emitDeclarationOnly","check":"tsc --noEmit --pretty false","format":"prettier --write \"src/**/*.ts\"","prepack":"npm run build","lint:fix":"eslint src/ --fix","test:watch":"vitest","build:debug":"vite build --minify false && tsc --emitDeclarationOnly","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"demchenko.di","email":"demchenko.di@gmail.com"},"_npmVersion":"11.12.1","description":"Zero-dependency reactive signals for TypeScript and JavaScript.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.2.1","vitest":"^4.1.5","esbuild":"^0.28.0","prettier":"^3.8.3","typescript":"^5.9.3","@types/node":"^25.6.0","vite-plugin-dts":"^4.5.4","typescript-eslint":"^8.59.0","@vitest/coverage-v8":"^4.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@typescript-eslint/parser":"^8.59.0","@typescript-eslint/eslint-plugin":"^8.59.0"},"_npmOperationalInternal":{"tmp":"tmp/signals_2.0.1_1777070368623_0.5188459281385709","host":"s3://npm-registry-packages-npm-production"}},"2.0.2":{"name":"@demchenko.di/signals","version":"2.0.2","keywords":["signals","reactivity","state","typescript","nodejs","node.js","nestjs","nest.js","angular","javascript","RxJS","reactive programming","reactive state management","reactive libraries","reactive programming libraries","reactive programming tools","reactive programming frameworks"],"license":"MIT","_id":"@demchenko.di/signals@2.0.2","maintainers":[{"name":"demchenko.di","email":"demchenko.di@gmail.com"}],"dist":{"shasum":"5a3886ce905f0536c226b37822a3f7711ab8d4cf","tarball":"https://registry.npmjs.org/@demchenko.di/signals/-/signals-2.0.2.tgz","fileCount":25,"integrity":"sha512-XMAfIOnpnYfKI0M/B4qn+D2KB1vFOsCUNgaAxZsOIpe6F6I3Ir84V2BP1WOePeJznT3DlsxzyVHsQ4vSUjs9Ag==","signatures":[{"sig":"MEUCIQD5hSSz+L8QvGQWaZw5mofReA9Ie+uc0G88hJXXBUgYgAIgG+K7IW/V5TnS2B22VMMXUD9pouhy8MbKgP7dbhe1MKY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":116585},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./min":{"import":"./dist/index.min.js","default":"./dist/index.min.js"}},"gitHead":"95a1b1fcbe060659187b141688abe461d3860e35","scripts":{"lint":"eslint src/","test":"vitest run","build":"vite build && MINIFY=true vite build && node scripts/minify.js && tsc --emitDeclarationOnly","check":"tsc --noEmit --pretty false","format":"prettier --write \"src/**/*.ts\"","prepack":"npm run build","lint:fix":"eslint src/ --fix","test:watch":"vitest","build:debug":"vite build --minify false && tsc --emitDeclarationOnly","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"demchenko.di","email":"demchenko.di@gmail.com"},"_npmVersion":"11.12.1","description":"Zero-dependency reactive signals for TypeScript and JavaScript.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.2.1","vitest":"^4.1.5","esbuild":"^0.28.0","prettier":"^3.8.3","typescript":"^5.9.3","@types/node":"^25.6.0","vite-plugin-dts":"^4.5.4","typescript-eslint":"^8.59.0","@vitest/coverage-v8":"^4.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@typescript-eslint/parser":"^8.59.0","@typescript-eslint/eslint-plugin":"^8.59.0"},"_npmOperationalInternal":{"tmp":"tmp/signals_2.0.2_1777113229648_0.9079129726740862","host":"s3://npm-registry-packages-npm-production"}},"2.0.3":{"name":"@demchenko.di/signals","version":"2.0.3","keywords":["signals","reactivity","state","typescript","nodejs","node.js","nestjs","nest.js","angular","javascript","RxJS","reactive programming","reactive state management","reactive libraries","reactive programming libraries","reactive programming tools","reactive programming frameworks"],"license":"MIT","_id":"@demchenko.di/signals@2.0.3","maintainers":[{"name":"demchenko.di","email":"demchenko.di@gmail.com"}],"dist":{"shasum":"054c9577cdc489332293a33cba8981d01e7dfdbc","tarball":"https://registry.npmjs.org/@demchenko.di/signals/-/signals-2.0.3.tgz","fileCount":25,"integrity":"sha512-pxcQioZddN360fj/hivnJTA0iRESwZRYwg5xiLivGQXHnKPPLg+G1Ok9GfSh/OVabXQzYnlSqHzK2Fs63oS6jg==","signatures":[{"sig":"MEUCIQCCeaGQd1KH+dqMrYmvsBll07ah/u1Q7yP8Ce+VRhk5GgIgHEtjuIXkxDJu/Up8oVhTcuVtu8e85xffVNTj7sKv8Uc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":119543},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./min":{"import":"./dist/index.min.js","default":"./dist/index.min.js"}},"gitHead":"329d07baf2c52dff4be654e982ce1487c6bd5dd6","scripts":{"lint":"eslint src/","test":"vitest run","build":"vite build && MINIFY=true vite build && node scripts/minify.js && tsc --emitDeclarationOnly","check":"tsc --noEmit --pretty false","format":"prettier --write \"src/**/*.ts\"","prepack":"npm run build","lint:fix":"eslint src/ --fix","test:watch":"vitest","build:debug":"vite build --minify false && tsc --emitDeclarationOnly","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"demchenko.di","email":"demchenko.di@gmail.com"},"_npmVersion":"11.12.1","description":"Zero-dependency reactive signals for TypeScript and JavaScript.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.2.1","vitest":"^4.1.5","esbuild":"^0.28.0","prettier":"^3.8.3","typescript":"^5.9.3","@types/node":"^25.6.0","vite-plugin-dts":"^4.5.4","typescript-eslint":"^8.59.0","@vitest/coverage-v8":"^4.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@typescript-eslint/parser":"^8.59.0","@typescript-eslint/eslint-plugin":"^8.59.0"},"_npmOperationalInternal":{"tmp":"tmp/signals_2.0.3_1777114445537_0.6264035693689811","host":"s3://npm-registry-packages-npm-production"}},"3.0.0":{"name":"@demchenko.di/signals","version":"3.0.0","keywords":["signals","reactivity","state","typescript","nodejs","node.js","nestjs","nest.js","angular","javascript","RxJS","reactive programming","reactive state management","reactive libraries","reactive programming libraries","reactive programming tools","reactive programming frameworks"],"license":"MIT","_id":"@demchenko.di/signals@3.0.0","maintainers":[{"name":"demchenko.di","email":"demchenko.di@gmail.com"}],"dist":{"shasum":"ead0de6bb52d9bbc78e8bc1e788bc959edf050da","tarball":"https://registry.npmjs.org/@demchenko.di/signals/-/signals-3.0.0.tgz","fileCount":27,"integrity":"sha512-jbgqiUHjAf/yuVtwOc2PGDE1cEo7j5jNyLWM73OSHGEcS09Rj2KGPtTcuyQQKnpeHr4p0UrdEgQ43lhpX1YtCA==","signatures":[{"sig":"MEQCIAEKf9OG9DKR/3tJOVlKB9qkci8SP+ihhA/Vj2+GxR80AiB1g3KMeJaQCz6ilkzwaMrp+AJTNoWftxlb8h7pJVp4iQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":131875},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./min":{"import":"./dist/index.min.js","default":"./dist/index.min.js"}},"gitHead":"02fd18db327e1433d2219bc4bb69db6d9207ce09","scripts":{"lint":"eslint src/","test":"vitest run","build":"vite build && MINIFY=true vite build && node scripts/minify.js && tsc --emitDeclarationOnly","check":"tsc --noEmit --pretty false","format":"prettier --write \"src/**/*.ts\"","prepack":"npm run build","lint:fix":"eslint src/ --fix","test:watch":"vitest","build:debug":"vite build --minify false && tsc --emitDeclarationOnly","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"demchenko.di","email":"demchenko.di@gmail.com"},"_npmVersion":"11.12.1","description":"Zero-dependency reactive signals for TypeScript and JavaScript.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.2.1","vitest":"^4.1.5","esbuild":"^0.28.0","prettier":"^3.8.3","typescript":"^5.9.3","@types/node":"^25.6.0","vite-plugin-dts":"^4.5.4","typescript-eslint":"^8.59.0","@vitest/coverage-v8":"^4.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@typescript-eslint/parser":"^8.59.0","@typescript-eslint/eslint-plugin":"^8.59.0"},"_npmOperationalInternal":{"tmp":"tmp/signals_3.0.0_1777284764774_0.03879697611227595","host":"s3://npm-registry-packages-npm-production"}},"3.0.1":{"name":"@demchenko.di/signals","version":"3.0.1","keywords":["signals","reactivity","state","typescript","nodejs","node.js","nestjs","nest.js","angular","javascript","RxJS","reactive programming","reactive state management","reactive libraries","reactive programming libraries","reactive programming tools","reactive programming frameworks"],"license":"MIT","_id":"@demchenko.di/signals@3.0.1","maintainers":[{"name":"demchenko.di","email":"demchenko.di@gmail.com"}],"dist":{"shasum":"011ea71e66dfbb7796d0e1015de90c503d0ffbc2","tarball":"https://registry.npmjs.org/@demchenko.di/signals/-/signals-3.0.1.tgz","fileCount":27,"integrity":"sha512-X56C+HVJm0zpFxTao2dXxKAczreLFqmnnjkAjfHw/RG+tJrJfBPWeU4kvrUamn4Yk/j62Cal6UDKPFe3KcpgrQ==","signatures":[{"sig":"MEYCIQC2m4VOlFobNwnKgP4ddeiXbNS3egCOBxfkdlZMIqPdvwIhAIo87MJh+jUKUoo8QoEHsfWcuF62jBL83sgZJqYUmkAf","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":132325},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./min":{"import":"./dist/index.min.js","default":"./dist/index.min.js"}},"gitHead":"c6974c8b9871aa9db9381531f924a546f980163d","scripts":{"lint":"eslint src/","test":"vitest run","build":"vite build && MINIFY=true vite build && node scripts/minify.js && tsc --emitDeclarationOnly","check":"tsc --noEmit --pretty false","format":"prettier --write \"src/**/*.ts\"","prepack":"npm run build","lint:fix":"eslint src/ --fix","test:watch":"vitest","build:debug":"vite build --minify false && tsc --emitDeclarationOnly","format:check":"prettier --check \"src/**/*.ts\"","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"demchenko.di","email":"demchenko.di@gmail.com"},"_npmVersion":"11.12.1","description":"Zero-dependency reactive signals for TypeScript and JavaScript.","directories":{},"sideEffects":false,"_nodeVersion":"24.15.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.2.1","vitest":"^4.1.5","esbuild":"^0.28.0","prettier":"^3.8.3","typescript":"^5.9.3","@types/node":"^25.6.0","vite-plugin-dts":"^4.5.4","typescript-eslint":"^8.59.0","@vitest/coverage-v8":"^4.1.5","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","@typescript-eslint/parser":"^8.59.0","@typescript-eslint/eslint-plugin":"^8.59.0"},"_npmOperationalInternal":{"tmp":"tmp/signals_3.0.1_1777285755512_0.43907034324445093","host":"s3://npm-registry-packages-npm-production"}},"3.1.0":{"name":"@demchenko.di/signals","version":"3.1.0","description":"Zero-dependency reactive signals for TypeScript and JavaScript.","license":"MIT","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"},"./min":{"import":"./dist/index.min.js","default":"./dist/index.min.js"}},"publishConfig":{"access":"public"},"sideEffects":false,"scripts":{"build":"vite build && MINIFY=true vite build && node scripts/minify.js && tsc --emitDeclarationOnly","build:debug":"vite build --minify false && tsc --emitDeclarationOnly","check":"tsc --noEmit --pretty false","prepack":"npm run build","lint":"eslint src/","lint:fix":"eslint src/ --fix","format":"prettier --write \"src/**/*.ts\"","format:check":"prettier --check \"src/**/*.ts\"","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage"},"keywords":["signals","reactivity","state","typescript","nodejs","node.js","nestjs","nest.js","angular","javascript","RxJS","reactive programming","reactive state management","reactive libraries","reactive programming libraries","reactive programming tools","reactive programming frameworks"],"devDependencies":{"@types/node":"^25.6.0","@typescript-eslint/eslint-plugin":"^8.59.0","@typescript-eslint/parser":"^8.59.0","@vitest/coverage-v8":"^4.1.5","esbuild":"^0.28.0","eslint":"^10.2.1","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","prettier":"^3.8.3","typescript":"^5.9.3","typescript-eslint":"^8.59.0","vite-plugin-dts":"^4.5.4","vitest":"^4.1.5"},"engines":{"node":">=18"},"gitHead":"85a5a35fe0da581e8fc06d25d463becd5775d850","_id":"@demchenko.di/signals@3.1.0","_nodeVersion":"24.15.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-zpdvDQd77xzuTs/hLSazabBOQRuiWZhCr0amEhjrkCD/kiZQ+YVegxqjEs6p6K2w4bgaoGwMebFovqIrUsijeg==","shasum":"066382b09902ae4d5577dc63b2b5d705ad2ebc19","tarball":"https://registry.npmjs.org/@demchenko.di/signals/-/signals-3.1.0.tgz","fileCount":30,"unpackedSize":146631,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICltQl6velUFIw9SnSAnGEkEcD9y5F9ieZ2g9ftr0qJKAiEAgT4RAg5QpKBW3LItg/L4ogkAQfECQIUVZvSRGlNPLDk="}]},"_npmUser":{"name":"demchenko.di","email":"demchenko.di@gmail.com"},"directories":{},"maintainers":[{"name":"demchenko.di","email":"demchenko.di@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/signals_3.1.0_1777366692644_0.8053385784842546"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-21T08:47:40.390Z","modified":"2026-04-28T08:58:12.873Z","1.0.0":"2026-04-21T08:47:40.619Z","1.0.1":"2026-04-24T09:47:45.103Z","1.0.2":"2026-04-24T10:00:24.365Z","1.0.3":"2026-04-24T13:56:26.705Z","2.0.0":"2026-04-24T15:03:34.618Z","2.0.1":"2026-04-24T22:39:28.768Z","2.0.2":"2026-04-25T10:33:49.803Z","2.0.3":"2026-04-25T10:54:05.665Z","3.0.0":"2026-04-27T10:12:44.950Z","3.0.1":"2026-04-27T10:29:15.640Z","3.1.0":"2026-04-28T08:58:12.774Z"},"license":"MIT","keywords":["signals","reactivity","state","typescript","nodejs","node.js","nestjs","nest.js","angular","javascript","RxJS","reactive programming","reactive state management","reactive libraries","reactive programming libraries","reactive programming tools","reactive programming frameworks"],"description":"Zero-dependency reactive signals for TypeScript and JavaScript.","maintainers":[{"name":"demchenko.di","email":"demchenko.di@gmail.com"}],"readme":"# signals\n\nZero-dependency, glitch-free reactive signals for TypeScript and JavaScript. Built with a highly optimized Push/Pull architecture (inspired by Angular) that guarantees zero wasted computations.\n\nPerfectly suited for **both Browser and Node.js** environments. Use it to drive UI frameworks, build reactive CLI tools, or manage complex server-side state machines.\n\nPackage: https://www.npmjs.com/package/@demchenko.di/signals\n\nDemo: https://dmytrodemchenko.github.io/Signals/demo/\n\n## Install\n\n```bash\nnpm install @demchenko.di/signals\n```\n\n## Features\n\n- **Glitch-free Push/Pull engine:** Guarantees effects only run when values actually change.\n- **Node.js Ready:** Extremely lightweight, fast, and completely decoupled from the DOM.\n- Small core API: `signal`, `computed`, `effect`, `batch`, `untracked`\n- Extra primitives: `linkedSignal`, `resource`, `optimistic`, `debounceSignal`\n- Dual build: Unminified for development, minified for production (`@demchenko.di/signals/min`).\n- No runtime dependencies\n- Typed public API with generated `.d.ts` files\n\n## Benchmarks\n\n**Performance Highlights:**\n- ✅ **1.5x faster than RxJS** on diamond dependency graphs (glitch-free)\n- ✅ **1.4x faster than RxJS** for NestJS WebSocket simulation (1000 concurrent effects)\n- ✅ **Faster than @preact/signals-core** on heavy graph updates\n\n> Measured on Node.js v24.15.0 · Apple Silicon · April 2026\n> \n> Source: [`benchmarks/`](./benchmarks) — run `cd benchmarks && npm start` to reproduce.\n\n### 1. Basic Reads & Writes\n\n| Library | ops/sec |\n|---|---|\n| RxJS `BehaviorSubject` + `getValue()` | 16,662,329 |\n| **@demchenko.di/signals** `signal()` + `set()` | **4,715,875** |\n\n### 2. Diamond Problem (Derived State)\n\n| Library | ops/sec |\n|---|---|\n| RxJS `BehaviorSubject` + `combineLatest` | 871,323 |\n| **@demchenko.di/signals** `signal` + `computed` | **1,228,103** ✅ 1.4× faster |\n\n### 3. Dependency Graph Update (vs Competitors)\n\nThe main benchmark: create a diamond-shaped dependency graph (`a → b, c → d`) and batch 100 updates through it.\n\n| Library | ops/sec | vs us |\n|---|---|---|\n| `@preact/signals-core` | 1,677,734 | 1.26× slower |\n| `alien-signals` | 2,503,989 | 1.19× faster |\n| **@demchenko.di/signals** | **2,105,284** | — |\n\n### 4. NestJS WebSocket Simulation (1000 Subscriptions)\n\nSimulates 1000 concurrent WebSocket connections reacting to a single signal update — a realistic server-side workload.\n\n| Library | ops/sec |\n|---|---|\n| RxJS (1000 Subscriptions) | 39,527 |\n| **@demchenko.di/signals** (1000 Effects) | **47,944** ✅ 1.2× faster |\n\n### Architecture\n\nThe engine uses a **doubly-linked list** of `Link` nodes for dependency tracking instead of `Set`/`Map`. Each `Link` exists in two lists simultaneously (the producer's subscriber list and the consumer's dependency list), enabling O(1) subscribe/unsubscribe with **near-zero GC pressure**. During re-evaluation, existing link nodes are **reused** when the dependency graph is stable — making steady-state updates allocation-free.\n\n## Usage\n\n```ts\nimport { signal, computed, effect, batch } from \"@demchenko.di/signals\";\n\nconst count = signal(0);\nconst doubled = computed(() => count() * 2);\nconst readonlyCount = count.asReadonly();\n\nconst stop = effect(() => {\n  console.log(\"count:\", readonlyCount(), \"doubled:\", doubled());\n});\n\nbatch(() => {\n  count.set(1);\n  count.update((value) => value + 1);\n});\n\nstop();\n```\n\n### Custom equality\n\n```ts\nimport { signal } from \"@demchenko.di/signals\";\n\nconst user = signal({ id: 1, name: \"Ada\" }, {\n  equal: (a, b) => a.id === b.id,\n});\n\nuser.set({ id: 1, name: \"Ada Lovelace\" }); // skipped\nuser.set({ id: 2, name: \"Grace\" }); // notifies\n```\n\n### `linkedSignal`\n\n```ts\nimport { signal, linkedSignal } from \"@demchenko.di/signals\";\n\nconst items = signal([\"a\", \"b\", \"c\"]);\n\nconst selection = linkedSignal<string[], string>({\n  source: () => items(),\n  computation: (nextItems, previous) => {\n    if (previous && nextItems.includes(previous.value)) {\n      return previous.value;\n    }\n    return nextItems[0];\n  },\n});\n```\n\n### `resource`\n\n```ts\nimport { signal, resource } from \"@demchenko.di/signals\";\n\nconst userId = signal(1);\n\nconst user = resource({\n  request: () => userId(),\n  loader: async ({ request, abortSignal }) => {\n    const response = await fetch(`https://example.com/users/${request}`, {\n      signal: abortSignal,\n    });\n    return response.json();\n  },\n});\n\neffect(() => {\n  if (user.isLoading() && !user.hasValue()) {\n    console.log(\"Loading initial user...\");\n    return;\n  }\n\n  if (user.isRefreshing()) {\n    console.log(\"Refreshing user while keeping stale data visible\");\n  }\n});\n```\n\n### `optimistic`\n\n```ts\nimport { optimistic, signal } from \"@demchenko.di/signals\";\n\nconst serverLikes = signal(10);\nconst optimisticLikes = optimistic(serverLikes);\n\nconst tx = optimisticLikes.apply((value) => value + 1);\n\ntry {\n  await api.like();\n  tx.commit((value) => value + 1);\n} catch {\n  tx.rollback();\n}\n```\n\nUse `optimistic()` for async writes that should feel immediate in the UI without mutating committed base state too early. It is especially useful for reactions, toggles, reordering, inline edits, and other mutation-heavy flows where rollback matters.\n\n### `debounceSignal`\n\n```ts\nimport { signal, effect, debounceSignal } from \"@demchenko.di/signals\";\n\nconst query = signal(\"\");\nconst debouncedQuery = debounceSignal(query, 300);\n\neffect(() => {\n  // Only fires once the user stops typing for 300ms\n  console.log(\"Search:\", debouncedQuery());\n});\n\nquery.set(\"h\");\nquery.set(\"he\");\nquery.set(\"hel\");\nquery.set(\"hello\");\n// effect runs once with \"hello\" after 300ms of inactivity\n```\n\n`debounceSignal(source, ms)` returns a read-only signal that mirrors the source with a delay. The output only updates once the source has been stable (no new emissions) for `ms` milliseconds. This is useful for search inputs, resize/scroll handlers, and any scenario where you want to rate-limit reactive computations.\n\n`hasPending()` and `pendingCount()` are regular read signals, so they can be used directly inside `computed()` and `effect()` for UI state:\n\n```ts\nimport { computed, optimistic, signal } from \"@demchenko.di/signals\";\n\nconst serverLikes = signal(10);\nconst optimisticLikes = optimistic(serverLikes);\n\nconst canLike = computed(() => !optimisticLikes.hasPending());\nconst pendingLabel = computed(() =>\n  optimisticLikes.hasPending()\n    ? `Saving (${optimisticLikes.pendingCount()})...`\n    : \"Like\",\n);\n```\n\n### Read-only view\n\n```ts\nimport { signal } from \"@demchenko.di/signals\";\n\nconst count = signal(0);\nconst readonlyCount = count.asReadonly();\n\nreadonlyCount(); // 0\ncount.set(1);\nreadonlyCount(); // 1\n```\n\n## Usage in Node.js & NestJS\n\nWhile signals are typically associated with frontend frameworks, they are incredibly powerful for backend state management, particularly in Node.js and frameworks like NestJS. \n\nIn a backend context, you often need to manage state *at a specific point in time* (e.g., \"What is the current game score?\", \"Is maintenance mode active right now?\"). While RxJS `BehaviorSubject` chains can handle this, they can become complex and prone to memory leaks if not unsubscribed carefully. Signals offer a much simpler, synchronous, and glitch-free alternative.\n\n### Example 1: Real-Time Game Server (WebSockets)\n\nIf you are building a WebSocket gateway in NestJS, you need to manage complex, rapidly changing room or game state. Signals ensure that derived state is calculated efficiently and side-effects (like broadcasting to players) only happen when the underlying data *actually* changes.\n\n```typescript\nimport { Injectable, OnModuleDestroy } from '@nestjs/common';\nimport { signal, computed, effect } from '@demchenko.di/signals';\nimport { WebSocketGateway, WebSocketServer } from '@nestjs/websockets';\nimport { Server } from 'socket.io';\n\n@Injectable()\n@WebSocketGateway()\nexport class GameRoomService implements OnModuleDestroy {\n  @WebSocketServer() server: Server;\n\n  private players = signal<Record<string, { name: string; score: number }>>({});\n  private timeRemaining = signal(60);\n\n  public isGameOver = computed(() => this.timeRemaining() <= 0);\n  \n  public leader = computed(() => {\n    const p = this.players();\n    return Object.values(p).sort((a, b) => b.score - a.score)[0]?.name;\n  });\n\n  private stopEffect: () => void;\n  private timer: NodeJS.Timeout;\n\n  constructor() {\n    this.stopEffect = effect(() => {\n      if (this.isGameOver()) {\n        this.server.emit('game_over', { \n          winner: this.leader(),\n          finalScores: this.players() \n        });\n      }\n    });\n\n    this.timer = setInterval(() => {\n      this.timeRemaining.update(time => Math.max(0, time - 1));\n    }, 1000);\n  }\n\n  onModuleDestroy() {\n    this.stopEffect();\n    clearInterval(this.timer);\n  }\n\n  addScore(playerId: string, points: number) {\n    this.players.update(p => ({\n      ...p,\n      [playerId]: { \n        ...p[playerId], \n        score: (p[playerId]?.score || 0) + points \n      }\n    }));\n  }\n}\n```\n\n### Example 2: Reactive Database Configuration (Mongoose Change Streams)\n\nInstead of writing complex polling loops, you can combine signals with MongoDB Change Streams. When a document updates in the database, the signal updates, dependent computations re-run lazily, and side-effects trigger automatically. Other NestJS services simply read the `computed` signals synchronously and always get the freshest value.\n\n```typescript\nimport { Injectable, Logger, OnModuleDestroy } from '@nestjs/common';\nimport { InjectModel } from '@nestjs/mongoose';\nimport { Model } from 'mongoose';\nimport { signal, computed, effect } from '@demchenko.di/signals';\nimport { Config, ConfigDocument } from './config.schema';\n\n@Injectable()\nexport class ConfigService implements OnModuleDestroy {\n  private readonly logger = new Logger(ConfigService.name);\n\n  private rawConfig = signal({ maintenanceMode: false, rateLimit: 100 });\n\n  public isMaintenanceMode = computed(() => this.rawConfig().maintenanceMode);\n  public currentRateLimit = computed(() => this.rawConfig().rateLimit);\n\n  private stopEffect: () => void;\n\n  constructor(\n    @InjectModel(Config.name) private configModel: Model<ConfigDocument>\n  ) {\n    this.stopEffect = effect(() => {\n      if (this.isMaintenanceMode()) {\n        this.logger.warn('⚠️ SYSTEM ENTERED MAINTENANCE MODE ⚠️');\n      } else {\n        this.logger.log('✅ System operating normally.');\n      }\n    });\n\n    this.watchDatabaseChanges();\n  }\n\n  onModuleDestroy() {\n    this.stopEffect();\n  }\n\n  private async watchDatabaseChanges() {\n    const initialConfig = await this.configModel.findOne().lean();\n    if (initialConfig) {\n      this.rawConfig.set({ \n        maintenanceMode: initialConfig.maintenanceMode, \n        rateLimit: initialConfig.rateLimit \n      });\n    }\n\n    this.configModel.watch().on('change', async (change) => {\n      if (change.operationType === 'update' || change.operationType === 'replace') {\n        const updatedConfig = await this.configModel.findOne().lean();\n        if (updatedConfig) {\n          this.rawConfig.set({ \n            maintenanceMode: updatedConfig.maintenanceMode, \n            rateLimit: updatedConfig.rateLimit \n          });\n        }\n      }\n    });\n  }\n}\n```\n\n### Example 3: Express / Fastify Request Caching\n\nYou can use signals to memoize expensive operations across HTTP requests in standard Node.js applications.\n\n```typescript\nimport express from 'express';\nimport { signal, computed } from '@demchenko.di/signals';\n\nconst app = express();\n\nconst databaseRecords = signal([{ id: 1, value: 100 }, { id: 2, value: 250 }]);\n\nconst expensiveTotal = computed(() => {\n  console.log(\"Running expensive calculation...\");\n  return databaseRecords().reduce((sum, record) => sum + record.value, 0);\n});\n\napp.get('/api/total', (req, res) => {\n  res.json({ total: expensiveTotal() });\n});\n```\n\n## API\n\nThe package exports:\n\n- `signal`\n- `computed`\n- `effect`\n- `EffectOptions`\n- `batch`\n- `untracked`\n- `isSignal`\n- `linkedSignal`\n- `optimistic`\n- `resource`\n- `debounceSignal`\n\n### `batch()` and Async Execution\n\n**Important:** `batch()` is strictly synchronous. It works by temporarily pausing effect execution and flushing them once the provided function completes. \n\nYou should **never** use `await` inside a `batch()` block.\n\n**❌ Incorrect:**\n```typescript\nbatch(async () => {\n  state.set('loading');\n  await fetch('/api/data'); // ⚠️ The batch ends immediately here!\n  state.set('success');     // This executes outside the batch.\n});\n```\n\n**✅ Correct:**\n```typescript\nstate.set('loading');\nawait fetch('/api/data');\n\n// Batch only the synchronous mutations\nbatch(() => {\n  state.set('success');\n  data.set(newData);\n});\n```\n*Note: The library will now throw a `console.warn` if you accidentally return a Promise from inside a `batch()`.*\n\n### `optimistic` helpers\n\n- `optimistic(source)` creates a projected signal layered on top of a writable base signal.\n- `apply(patch)` adds a pending optimistic layer and returns a transaction with `commit()` and `rollback()`.\n- `hasPending()` is `true` while one or more optimistic layers are active.\n- `pendingCount()` is the number of active optimistic layers.\n- `clear()` removes all optimistic layers.\n- `commit(nextBase?)` removes the layer and optionally writes a final value or updater into the base signal.\n- `rollback()` removes the layer without touching the base signal.\n\nBecause `hasPending()` and `pendingCount()` are read signals, they compose naturally with `computed()` for disabled buttons, loading labels, and mutation-aware UI state.\n\nOptimistic layers always rebase on top of the latest base signal value. If the server updates the underlying state while a mutation is pending, the optimistic projection recalculates from the new base value automatically.\n\n### `resource` state helpers\n\n- `hasValue()` is `true` after the resource has produced or been assigned a value, even if that value is `undefined`.\n- `isLoading()` is `true` whenever a request is in flight.\n- `isRefreshing()` is `true` when a request is in flight and the resource is still holding a previous value.\n\n### `effect` options\n\n```ts\nimport { effect } from \"@demchenko.di/signals\";\n\nconst stop = effect(() => {\n  // ...\n}, {\n  allowSignalWrites: true,\n  manualCleanup: true,\n  scheduler: (run) => queueMicrotask(run),\n});\n```\n\n- `allowSignalWrites` defaults to `true`. Set it to `false` to throw on signal writes from the effect or its cleanup.\n- `manualCleanup` is accepted for compatibility with owner-scoped effect APIs. In this library, effects are always disposed manually via the function returned from `effect()`.\n- `scheduler` customizes reruns after invalidation. The first effect run still happens synchronously.\n\n## Development\n\n```bash\nnpm install\nnpm run check\nnpm run build\n```\n","readmeFilename":"README.md"}