{"_id":"@bestoneconsulting/sap-b1-bridge","_rev":"26-ca69ae60c3829c1becdcbbbcbc5268bd","name":"@bestoneconsulting/sap-b1-bridge","dist-tags":{"latest":"1.5.4"},"versions":{"1.0.0":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.0.0","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.0.0","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"93ce81076e12103862e6e30759841efa4241a1ce","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.0.0.tgz","fileCount":11,"integrity":"sha512-3NLhit9+F3Tfh7p4z/R+0QzJEUdnna9C8D2dDxvaREotR/0VCDrxs94fcYemT7kwpyFI4JpEH+7/ArSfPiwybA==","signatures":[{"sig":"MEUCID398VYNnMM/TWJBoI08GD6iJ/1OeilnlJ9NB85aBmbAAiEA2+QzZM2oVm7gmeNcYHPwsyrDBMy1UzfhVxQdpnuBrjA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":42465},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"71c59786e9f6d9542225161d56354c599e5d36ec","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"11.10.0","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.0.0_1771226172766_0.7593568620673514","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.0.1","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.0.1","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"120f04a3519b83921593b6fff970d6251b10375b","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.0.1.tgz","fileCount":12,"integrity":"sha512-vE3vwySp6z/dlb4+/Vljss40/fbF/lVDr3M9Jx6a6b3ECPdyMO2YvSwbtk8R0vUGJimtK3O6TofyPiyQ4I4zrw==","signatures":[{"sig":"MEUCIQDpOy+SDakJmXT5bqXowdjC0Pc89cyeXU4ZLL5OIyU52QIgNc3XL7RNVB335+g209hmYMbf3BqY2sgH+mgCi5pJ/OQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":54978},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"71c59786e9f6d9542225161d56354c599e5d36ec","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"11.10.0","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.0.1_1771226469642_0.3991579873645579","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.1.0","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.1.0","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"f6f87604179b6546d18c0ee760b73c6c8bf567d5","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.1.0.tgz","fileCount":14,"integrity":"sha512-+/bfr70ys7iZpb6HU4gndCrnK6pe+bYSphXf9Y6rQ08jk85LD8qQKwYUQVjJ9Zj6MlBv64oQiEQzx3M8D0D24Q==","signatures":[{"sig":"MEQCIHc8ZkgwyeNakViwN7filw730QKuOK2nCpFfiTLAa97IAiAsKm5bGb69r5E4sCzDxHQ4aAMcLy8xTivENsLVTTJoIg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":82041},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"d6823b4c213905465260f85b274d57278c94fefd","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"11.10.0","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0"},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.1.0_1771227005729_0.9143741646817976","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.2.0","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.2.0","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"8e6422d93a4d0d4fd0a66fa7f8b44f361a6205f2","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.2.0.tgz","fileCount":18,"integrity":"sha512-dNrIpulWhUgCqRH5xH7MYnDLWtLujfo3Z/BFr/T9pQlrDrCTRA4Oy0ckvw6UBvhhrf0cjTGcyCXkYwgK6Dub3w==","signatures":[{"sig":"MEUCIDipwxEkt58OBDAB6Men1r/rjoNj+oeu9ZPbcF9SHYgLAiEAgatkk1yaI0fwpRK5cHTxMOop83lG7XTx2oGe8WAlyT4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":108518},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"4618daa94523893fdb41facaa4c14d0a06932f6e","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.2.0_1771228172870_0.18806182156808982","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.2.1","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.2.1","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"213b7c6c9928e3ca58cf8e837c790012f01d36bf","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.2.1.tgz","fileCount":18,"integrity":"sha512-0/r/ri6T5hGnFvE6QURLn+C2/oMJH+KZRYCOuQFn4Z6oSxVF7hlbrh8N9k303Q6/5b+/Qh90gzD8Qu+RbkzC3Q==","signatures":[{"sig":"MEUCIEzkcbqAq5iMyecGKh2LbV6Tkk5IO6huXCf2L5YlV8aHAiEApiJl1E3V74bPJBwDSPEE3TTcBz+BCeMSwLCb5JQWouY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":110670},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"02fd81dd41ce3f35fc0065f1135dd94d3c2e3e99","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.2.1_1771229251881_0.7877562679890948","host":"s3://npm-registry-packages-npm-production"}},"1.2.2":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.2.2","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.2.2","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"1860b6106a5fbff702b94435465aed385eff92f5","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.2.2.tgz","fileCount":18,"integrity":"sha512-gyKril7MAKjWgbtZVR2wQgEiY8hgPyLvXdVPUW+QFfnXl9C0+BCgTw36n9XBFYiIifQzpwBRHwM2nM6WTlHdLQ==","signatures":[{"sig":"MEQCIFBz9GQI9UAdsSIRc1MX3BligmdGP1TTnG3ENEpLG7X6AiB2F0AxeTN7AaOEXuuw4zK9mhPtet07s2qmVXhDXiiQOA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":110713},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"22b221cbb4989234ef32b271749544983665c2be","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.2.2_1771230135108_0.4202969506784944","host":"s3://npm-registry-packages-npm-production"}},"1.2.3":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.2.3","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.2.3","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"5be54c55c8200ec69a547cfca465113ecfa33cd1","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.2.3.tgz","fileCount":18,"integrity":"sha512-WvH0DsFMVCVfAPER/HeuZcknouvfKakiGQjLn3IsSlnNlf8C1GaGY5R4DxAahIdVWGPHDEBfjF8x0L8L7gcHDw==","signatures":[{"sig":"MEUCIQDLHQUZJX47ZbIBuWKqVnsWpo7KCwIqPgQeBGG+xg9F4gIgLAY6FxHiHxcFPS0q5F/hvz8JXaXI5EieOw+3lv41x/0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":111838},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"f28cf8aa9cd1f2215c8b3f511fe9d6afab391959","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.2.3_1771230375457_0.5110083833228247","host":"s3://npm-registry-packages-npm-production"}},"1.2.4":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.2.4","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.2.4","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"b2086fbd67e39f9eec2ef8c03afad00619a9ca1d","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.2.4.tgz","fileCount":18,"integrity":"sha512-jxUYEkqI/vRpg0ELF45fCy10k15qN8Tv7Wd84txuojvfwE9YY/vGSLOyxv2Ebmhz9l00J4beHhhE+2gYt8mX0A==","signatures":[{"sig":"MEUCIBc5fQcYPvkle/xfq4/DN6ks9VyKq16SSCtmz0RoJAw2AiEArvSW50OkRhStu+3g2+tRcVKKWvSJVmJkHH//ZbY8StM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":112919},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"e1bafff1485ebf1cbae2121ad57b448376b1042e","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.2.4_1771231166029_0.15434241573192686","host":"s3://npm-registry-packages-npm-production"}},"1.2.5":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.2.5","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":"Best One Consulting <https://www.bestoneconsulting.com/>","license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.2.5","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","dist":{"shasum":"7f27bf7d2e184fbde1ffe73be308569d707e8da2","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.2.5.tgz","fileCount":18,"integrity":"sha512-dO08wuTAKuKxX0ZGZqDUYEEmStXpgv5M0yRy83zYiON66L0opx6hJlUoMJVlD2lPnEfdG/C9pGtkXpgiyPSIOg==","signatures":[{"sig":"MEUCIGJ04eIElMqkyVAzna5OqEKzXnwXJW3nhNGopm5u15gjAiEA2tPxyhY1dd/pwJ+rWnGD3lmb/lSaGop5dzKuKhzRU/A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":120119},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge","type":"git"},"description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.2.5_1771260210199_0.035500879618003855","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.3.0","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.3.0","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"a6ab1548a54640b3432ffbb07539274d76b762fc","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.3.0.tgz","fileCount":18,"integrity":"sha512-X7KT91KafyCDecpTEM2oHShEPCUd4ODtUd0r3CVL8VFdfH1ktFNXe7uZObt5uq8rbBmToXFfKfYpIXjB/RjgHw==","signatures":[{"sig":"MEQCIEMXjAMMGM1ZLfEvrXvNMhBC4i15YdkVTiNLVMIP9hwFAiA+KqL2bwCavcGf3KFFUJ5RLMHvqUwCChbMnGimHzFPBQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":117376},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"a0ae883cdebc8bf290c34ae7cf61f3520111bdc2","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.3.0_1771265659502_0.2502363161559895","host":"s3://npm-registry-packages-npm-production"}},"1.3.1":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.3.1","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.3.1","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"7219fa6848c482cf7c0504d930dbd5736a68906e","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.3.1.tgz","fileCount":18,"integrity":"sha512-UZ9R1HzDlwFJW8JZHHAVkB0myJHYxFxGkaNe/lo/eziYS37Z09VO5yV15dkQxB7WpwD2c3lLe/BxFkclKpPBWA==","signatures":[{"sig":"MEQCIAb93Eq7b+WNdbyuKlYMtlsPKhYlURXyclVqMwhNDnpQAiAIew7wg/mgXj6imHiweYbpMu302Dxcio1tr+Num1/e3Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":122566},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"fd1fdbc179bc3fe9b66e16c8c2da1d19a299c7be","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.3.1_1771367059245_0.7327455357515553","host":"s3://npm-registry-packages-npm-production"}},"1.3.2":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.3.2","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.3.2","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"93896a5507e297fcdc74c6cbd12c44448c9e4110","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.3.2.tgz","fileCount":18,"integrity":"sha512-V0MDQwoHlnwU4xqIKuDIL62X2+674eJomRopi2h3W6pJOSijuZwaxBm0r57WHyC7rwH4U+FlYyu0s66KMuTiug==","signatures":[{"sig":"MEUCIFVCW2lDV0w3A/FTdnGRMY02AnQgcVV2BJjsKpG65oCDAiEAs2kb1A1RnwRPcxlMQw9WBdVRIz2KH97TdMb2jyt1jCA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":122566},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"1edccce9985a33b83a7417e239fd33278f4e7105","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.3.2_1771367172182_0.8262092423300538","host":"s3://npm-registry-packages-npm-production"}},"1.4.0":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.4.0","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.4.0","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"fbf05af3e7288e677a0a85d807885fe49e4b04ee","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.4.0.tgz","fileCount":18,"integrity":"sha512-Gw362/9eIaFMOHnCHTyRTR5J8TvNTwwCYMw24/Y5KpV23uNkxeudU/PLlBhadGJxSOxPMsGaHpiqQdUqx2RzLg==","signatures":[{"sig":"MEUCIGgwobAP24oKmvP947A8kGAC/i/2+TSCUf8WIx7/zVb8AiEAwcJy4Mnf+yaNDAK7pXUJCnbBCeS8tZuypgrb+Uvof68=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":124781},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"13983032437707d6671373d478013e7a041ec043","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.4.0_1772150300894_0.4433632196064279","host":"s3://npm-registry-packages-npm-production"}},"1.4.1":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.4.1","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.4.1","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"a05c69f4e33075f398c399760fea1afdc5171331","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.4.1.tgz","fileCount":18,"integrity":"sha512-fHuOQ7yLfBoJc5tu5LVvu5Pn9O1ZFoKklnfC5fhOGLhhrjaGX7oxIxSX958Fx1UkK8ZYw50sN9d1kfWlUi2naw==","signatures":[{"sig":"MEUCIQC46dE1valA0Moq0UPWxsiLmoN3jPbPanT8emobJ2IsPAIgStqBuERrWAdH32ohSR0XMmhqk6oOjL23DBsPtxsYAhw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":149486},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"51af9bc5f1beb38c18c276e011be2aedc48b4aa5","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.4.1_1778890879500_0.5039421024804676","host":"s3://npm-registry-packages-npm-production"}},"1.4.2":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.4.2","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.4.2","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"905dfe1d859a57c63338f991ad22e1b3cabd777e","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.4.2.tgz","fileCount":18,"integrity":"sha512-0Wgwi4c7OAAx0T2iAzO5l01jMKAQz5Z1ZOKCQC4amKPZHb1ebqv4XjuicEH/Eu9XwCbrNIH1BVud3WYPzDwABQ==","signatures":[{"sig":"MEQCIES4uY4agKFKQ7RMsTTV2hfJTQKezgvp7siUrwOAlliwAiAiT5N3XU717FydEG4t5aglDc9fz04I5cYgLTQsU6Wo/Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":149903},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"01a34a198c55288c6f82c3418818d1453042cec6","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.4.2_1779121074117_0.4479454069425082","host":"s3://npm-registry-packages-npm-production"}},"1.4.3":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.4.3","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.4.3","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"351bf79c44b012b24d69cdcbcd93954f2a80b8af","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.4.3.tgz","fileCount":18,"integrity":"sha512-DtMDcp/6PKhmHbskMWhNbfHjqPgk2YRYB70ZL2up46JayeyNBeMW3JseZG8ql4rGbbOxKTlGa8ZJbVtyWRQdJA==","signatures":[{"sig":"MEUCIQDD+R1kccK8Bmr5CCKVQ6W9tJ0YHy95Yj9u4sIZl8BssAIgLC6Qjl43WjUB6EcWRSoKGZufM00AJOBT9ZSdt6EOOms=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":151703},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"ef1b5614e2bb8dbf65b80d797e0afc029c2b73b1","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.4.3_1779123521212_0.020440517296585137","host":"s3://npm-registry-packages-npm-production"}},"1.4.4":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.4.4","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.4.4","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"cd080b9cc4f38d2ea74f690fc268f81397b15a8b","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.4.4.tgz","fileCount":18,"integrity":"sha512-kGA2LQcg9uJvAZBp1qKrw3gPdDGHts7tCiL1zdEdGKX1bUOWIs6dst40YTsgPlEXYkF03+zdhnZKU4TTQsmz8w==","signatures":[{"sig":"MEYCIQDkKVwUXa7PAUQ6945FlXO4Vy5IVArayFqZvZJdXnI+WwIhANX98WALpdCto7qOQz/dbgGHrBhcIBbUY04TMxWnTREj","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":151737},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"18c7098c08ff3be8405236e86477c0752798746d","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.4.4_1779125018576_0.7551516474613627","host":"s3://npm-registry-packages-npm-production"}},"1.4.5":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.4.5","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.4.5","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"b6361b8a238d42190a6ebaa2aa9857549a15a864","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.4.5.tgz","fileCount":18,"integrity":"sha512-aSDRyChB1lZoR1jQuR5R0uo6nrNLbEuwtnfmqZLSUtlw+e0TR2hXtjsan7YjuGAT3vzmM577NlgCQ6KpNkp5mg==","signatures":[{"sig":"MEQCIFXWABha1MJjynEdTt1QiMdlWDfINNt4HbGQgVE3y8+pAiAf/Xvgcrec8Is/XMfY0NlCya2tTquj0sUG5i626U6nAQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":152078},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"d974054e111733b07e4dda56e89f2dac5fd9107e","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.4.5_1779128260553_0.6908639426663155","host":"s3://npm-registry-packages-npm-production"}},"1.4.6":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.4.6","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.4.6","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"58e2993064af9276d201df1eb15aec1bd10e89be","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.4.6.tgz","fileCount":18,"integrity":"sha512-74fgwiXgWa9kcHJPI0U2cOLbSWfufhUy892rNyklXjY3W0phvZgGaIBLCDu33bTZmhbj+KMN5ZwWtIJX3Y2YGw==","signatures":[{"sig":"MEUCIH/VxQLOVelFF8cFnU4b11ccMq5C0CZstR38ZohXhhx8AiEAzXSw3HP8WKL/TXHE11ZTv2ut475/yQlAqqSER5mVmhU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":155621},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"077e380be87041194d464a58ac48101870d76767","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.4.6_1781898953975_0.4376035552408908","host":"s3://npm-registry-packages-npm-production"}},"1.4.7":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.4.7","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.4.7","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"d53143d4f356c6632381282cf02257917408aa5b","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.4.7.tgz","fileCount":18,"integrity":"sha512-hUXSnxlWWDVahAH1LRGFNkV0T49BapRRfSTEtRF35D7ns4xDOd4QypMiZW/A3L1OaH1OZqumcxSkomrRGzEcPg==","signatures":[{"sig":"MEUCIQCv49N1wrXgan5Qb4Xb+O3JZ7gKLIM2ZqYtBG6mNZxJ6wIgKm/MjKpw24da4upLZE29MYE6mSP99bgVRm1T/f61wj4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":155665},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"3ea5e4da6a47bd8d94a91e4a37381868c5cb013c","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.4.7_1785260114240_0.16655921796554862","host":"s3://npm-registry-packages-npm-production"}},"1.4.8":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.4.8","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.4.8","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"687814915e80661abc80fdb76df96879e5f58af3","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.4.8.tgz","fileCount":18,"integrity":"sha512-ozizcUhROsdtVJDP5B8IfegMguNPD3mj8B0qz2a6un0mlovUI9XhaOZOh/Wo/oxeIjuGd4wIAAIyK3HeERuyOg==","signatures":[{"sig":"MEUCICVz1L8dopuYC6rZ+15vJgMuxYKvCQL5Wr49WLdnNWXKAiEAvWDc0bQd/PQpDZzUJnd9L0sqH54xfEo8AyjnwJu61A8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":170821},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"6bb7bad6b3c4b7398c2cfb4d2cc60d574339dfe2","scripts":{"build":"tsc -p ../tsconfig.bridge.json","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.4.8_1786552970757_0.3773532355351257","host":"s3://npm-registry-packages-npm-production"}},"1.5.0":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.5.0","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.5.0","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"0e6a934afe2efd1d632c703eb7562d42fc0b7e27","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.5.0.tgz","fileCount":13,"integrity":"sha512-G5zCJJB3gtCYEOWT7qzzt+663dKslTmJFtEsPtYD+3gBWpInPPUiAC783ykB0f6w/QK35Ax44qjatXwbYfU4Gw==","signatures":[{"sig":"MEUCIQD8FD2UFdmqbF+H3Di+kR/p5QKzzphmmHrt+Bg3lqS+kwIgLYnIspEpvb9qyG+RsNkshNLMgT4y/JLbhGPmTF5BXo4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCICWjCuRu8VRNyU6WzNcOZHbGdWzimOrBsKsugihaKDQPAiEAyduJ77cLWCZZDy5aI4HsWodiusPSMs2nReZhkci3RF0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":281404},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"bbd7b0e370e7dc15729b15a8c4f30101d9a2fa4c","scripts":{"build":"node ../scripts/build-bridge.mjs","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.5.0_1789680708848_0.8121865309002447","host":"s3://npm-registry-packages-npm-production"}},"1.5.1":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.5.1","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.5.1","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"8bd5dde99747247dcd562d43bbd1d9bbac393619","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.5.1.tgz","fileCount":13,"integrity":"sha512-y3HDkeuMUTEO615+fQLmdg42z0piJH8su6XFcy+NEziyl2dwcKApccY6joqpIf2C2cpUBdeX4foiVwcOJ1IcgA==","signatures":[{"sig":"MEYCIQCJvxyhXuY2PEz1l2WAd2A8woRxLry9wrU7kvN7AA3wfAIhAL5ekjXcBOw4+Fj8zeXzjTL3AjsBKRlRTn38vagN76EC","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCID3oEYaWPsBw791u36JH/jjqrHOgX3yCz8AU1TAEYQniAiAgQCM1Aui/ScOXdEIvvJdpwkJ72KwQPsSDByJO9Grm5Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":293118},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"dd3a5d16ddd83c26ef3ae76ba2ed58b9e6bb3804","scripts":{"test":"node --import ../node_modules/tsx/dist/loader.mjs --test ../tests/shared-files.test.ts ../tests/shutdown.test.ts","build":"node ../scripts/build-bridge.mjs","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.5.1_1789794260878_0.5437029449547781","host":"s3://npm-registry-packages-npm-production"}},"1.5.2":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.5.2","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.5.2","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"3d6515defdd4f2d9f82a6c0ed92d9c52403f7995","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.5.2.tgz","fileCount":14,"integrity":"sha512-qkm9TrQdsVP14KZwwOHetJPOffoXSDrcRziEFDLd15lwNYD5/K7X5t2AXUP0fxV8QSuH4uy+WKoaD0Ye1jh1dQ==","signatures":[{"sig":"MEUCIGbML7sF4FAjTR+Ybezwlg3x8vNrwJA+ZEFR9MpTp95zAiEAuY8VloDVk13iH6NIe7phcEsk0dYHDKnvfxDwYodfbhU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCICDHJrQurLRZJd6kyzPbc4m+tCeu5XkERk63U5/QYmnaAiEAmmOFrS318opTLKjgCk7iXlWEOZw73VrDeLyAWDFMyDY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":296194},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"08c33ed9783baedf2d982eae65f11b184dcf3724","scripts":{"test":"node --import ../node_modules/tsx/dist/loader.mjs --test ../tests/shared-files.test.ts ../tests/shutdown.test.ts ../tests/app-url.test.ts","build":"node ../scripts/build-bridge.mjs","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.5.2_1789851050157_0.43436212461228396","host":"s3://npm-registry-packages-npm-production"}},"1.5.3":{"name":"@bestoneconsulting/sap-b1-bridge","version":"1.5.3","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","_id":"@bestoneconsulting/sap-b1-bridge@1.5.3","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"homepage":"https://www.bestoneconsulting.com/","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"7047adc3a5b8ad67b91f580b386f3bbf08a0615b","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.5.3.tgz","fileCount":14,"integrity":"sha512-pzsjXZmWBsIR19OoaBJdi2iwGwDwJZ3qN6W52QWMkN/XmZ4AMdFfOms15T/QouasbCfDKFoBkCqpnSniOv5fzQ==","signatures":[{"sig":"MEQCIAEVTdB6JLWf5k6AbHY7z7e8pgg8vetvv1PgJDbLycBTAiAC4ko6hA2BuaJ3J/Y9y70PFdkU8UdLCiH1oJjwsg7n8A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQC5Pnq25D2tD/9ckbhXAQpb2hYdG/UMgFqm1tzaaUjoGQIhALXUQvDv+p0DeBY8gR1YlbRjWf5L9o9EntV9XwSucAfu","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":296194},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"f2da984b0a011ebec9a4fe3f68d2edf89f2f345f","scripts":{"test":"node --import ../node_modules/tsx/dist/loader.mjs --test ../tests/shared-files.test.ts ../tests/shutdown.test.ts ../tests/app-url.test.ts","build":"node ../scripts/build-bridge.mjs","prepublishOnly":"npm run build"},"_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sap-b1-bridge_1.5.3_1790362909493_0.23725246104547493","host":"s3://npm-registry-packages-npm-production"}},"1.5.4":{"_id":"@bestoneconsulting/sap-b1-bridge@1.5.4","bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"dist":{"shasum":"36aeb9bc90723fe9106d6e13f3b489edaa108fc7","tarball":"https://registry.npmjs.org/@bestoneconsulting/sap-b1-bridge/-/sap-b1-bridge-1.5.4.tgz","fileCount":14,"integrity":"sha512-VfvUvD7+Guucr1zrTi1tHifV45/tESuZQpnZMnl65p4L1PQI0c3m2wEG/GFyBl4jW7l5UaI18LDN6+5STc4jJw==","signatures":[{"sig":"MEYCIQC7b51a+41GakX4toDosTh+BSlv1XyBnDWzTVgQ5kC0VQIhANZFkWhd/JvPHBZ+VFydwWlJ9JSd87dK8ObHE18Jf77L","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCkRPOXE05WUNCOOnmX99GtglBVcNjkwsLqylYZqqvDUAIhAIg3VyD6PANI1ICbup8i5IB63DonyzizZb7wP5mnKP8v"}],"unpackedSize":301116},"main":"./dist/index.js","name":"@bestoneconsulting/sap-b1-bridge","type":"module","types":"./dist/index.d.ts","author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"3acc6af218d45f68e52bbb9384748fe66decbbac","license":"MIT","scripts":{"test":"node --import ../node_modules/tsx/dist/loader.mjs --test ../tests/shared-files.test.ts ../tests/shutdown.test.ts ../tests/app-url.test.ts ../tests/reconnect.test.ts ../tests/console-helper.test.ts","build":"node ../scripts/build-bridge.mjs","prepublishOnly":"npm run build"},"version":"1.5.4","_npmUser":{"name":"keshavabest","email":"npm@bestb1.com"},"homepage":"https://www.bestoneconsulting.com/","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"_npmVersion":"10.8.2","description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","directories":{},"maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"_nodeVersion":"20.20.0","_hasShrinkwrap":false,"peerDependencies":{"ws":">=8.0.0","zod":">=3.0.0","express":">=4.0.0","drizzle-orm":">=0.30.0"},"peerDependenciesMeta":{"drizzle-orm":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sap-b1-bridge_1.5.4_1790401298625_0.2969045858535395"}}},"time":{"created":"2026-02-16T07:16:12.601Z","modified":"2026-09-26T05:41:38.913Z","1.0.0":"2026-02-16T07:16:12.896Z","1.0.1":"2026-02-16T07:21:09.796Z","1.1.0":"2026-02-16T07:30:05.886Z","1.2.0":"2026-02-16T07:49:33.009Z","1.2.1":"2026-02-16T08:07:32.032Z","1.2.2":"2026-02-16T08:22:15.254Z","1.2.3":"2026-02-16T08:26:15.608Z","1.2.4":"2026-02-16T08:39:26.254Z","1.2.5":"2026-02-16T16:43:30.350Z","1.3.0":"2026-02-16T18:14:19.677Z","1.3.1":"2026-02-17T22:24:19.387Z","1.3.2":"2026-02-17T22:26:12.333Z","1.4.0":"2026-02-26T23:58:21.024Z","1.4.1":"2026-05-16T00:21:19.680Z","1.4.2":"2026-05-18T16:17:54.246Z","1.4.3":"2026-05-18T16:58:41.354Z","1.4.4":"2026-05-18T17:23:38.734Z","1.4.5":"2026-05-18T18:17:40.707Z","1.4.6":"2026-06-19T19:55:54.110Z","1.4.7":"2026-07-28T17:35:14.440Z","1.4.8":"2026-08-12T16:42:50.912Z","1.5.0":"2026-09-17T21:31:48.954Z","1.5.1":"2026-09-19T05:04:20.955Z","1.5.2":"2026-09-19T20:50:50.249Z","1.5.3":"2026-09-25T19:01:49.667Z","1.5.4":"2026-09-26T05:41:38.715Z"},"bugs":{"url":"https://github.com/bestoneconsulting/sap-b1-bridge/issues"},"author":{"name":"Best One Consulting","email":"https://www.bestoneconsulting.com/"},"license":"MIT","homepage":"https://www.bestoneconsulting.com/","keywords":["sap","business-one","b1","sql-server","bridge","websocket","agent","erp","di-api","service-layer"],"repository":{"url":"git+https://github.com/bestoneconsulting/sap-b1-bridge.git","type":"git"},"description":"SAP Business One & SQL Server bridge for secure database and ERP access behind firewalls via WebSocket agents","maintainers":[{"name":"keshavabest","email":"npm@bestb1.com"}],"readme":"# SAP B1 Bridge\n\nSecurely query and manage SAP Business One and SQL Server databases behind firewalls. No ports to open, no VPN required.\n\nSAP B1 Bridge connects your cloud application to on-premise SAP Business One systems and SQL Server databases through lightweight Windows agents that communicate outbound via WebSocket. Your internal systems stay protected behind the firewall while your app gets full access to data and SAP operations.\n\n```\nYour App (Cloud)           Firewall           Your Network\n+------------------+          ||          +-------------------+\n| Express + Bridge | <========||========= | Bridge Agent      |\n|  - WebSocket     |   outbound only      |  - SQL Server     |\n|  - REST API      |          ||          |  - SAP B1 SL      |\n|  - Programmatic  |          ||          |  - SAP B1 DI API  |\n+------------------+          ||          +-------------------+\n```\n\n## How It Works\n\nSAP B1 Bridge uses a **synchronous direct-push** communication model:\n\n1. **Agent connects outbound** — The Windows agent initiates a WebSocket connection from inside your network to your cloud server. No inbound firewall ports needed.\n2. **Server pushes commands directly** — When you execute a query or SAP request (via the programmatic API, REST endpoint, or test console), the server sends the command directly to the connected agent over the open WebSocket.\n3. **Agent executes and responds** — The agent runs the SQL query or SAP operation locally and sends the result back over the same WebSocket connection.\n4. **Server resolves the result** — The server matches the response to the original request and returns it to your code as a resolved Promise, or broadcasts it to connected UI clients in real time.\n\nThere is **no polling**. The server does not queue commands for agents to fetch later. Commands are dispatched immediately to the target agent, and the programmatic API methods (`executeQuery`, `callServiceLayer`, `callDiApi`) return a Promise that resolves when the agent responds or times out.\n\n## Installation\n\n```bash\nnpm install @bestoneconsulting/sap-b1-bridge\n```\n\n**Peer dependencies** (install if not already in your project):\n\n```bash\nnpm install express ws zod\n```\n\n## Quick Start\n\n```typescript\nimport express from \"express\";\nimport { createServer } from \"http\";\nimport { createSAPB1Bridge } from \"@bestoneconsulting/sap-b1-bridge\";\n\nconst app = express();\n// Apply your host's authentication/authorization BEFORE the bridge API/UI.\n// See \"Host middleware and transfer limits\" below for production integration.\napp.post(\"/api/queries\", express.json({ limit: \"36mb\" }));\napp.use(express.json()); // ordinary endpoints retain the smaller default\nconst server = createServer(app);\n\nconst bridge = await createSAPB1Bridge({\n  app,\n  server,\n  appName: \"My Company App\",\n  wsPath: \"/ws\",\n  apiPrefix: \"/api\",\n});\n\nbridge.mountUI(\"/bridge\");\n\nserver.listen(3000, () => {\n  console.log(\"Bridge running on http://localhost:3000\");\n  console.log(\"Test console at http://localhost:3000/bridge\");\n});\n```\n\nThat's it. Your app now has:\n\n- A WebSocket endpoint at `/ws` for agents to connect to\n- REST API endpoints under `/api` for managing agents and submitting queries\n- A programmatic API for executing queries and SAP requests directly from your code\n- A test console at `/bridge` for managing agents and running queries from your browser\n\n## Public application URL (1.5.2)\n\nSet optional `appUrl` on `SAPB1BridgeOptions` / `createSAPB1Bridge` to send\nthe application's canonical published URL in the agent's `auth_success` message.\nThe supplied value is returned unchanged (no trimming, slash removal, or rewriting).\nFor Lucky Feather, use:\n\n```typescript\nconst bridge = await createSAPB1Bridge({\n  app,\n  server,\n  appName: \"Lucky Feather\",\n  appUrl: \"https://hub.luckyfeather.com\",\n});\n```\n\nPlanetJill must supply its **actual primary published URL**; do not use a guessed\ndomain or a Replit development URL. This package has no downstream URL default.\n\nWhen `appUrl` is omitted, both bridge entry points resolve metadata from the\noriginal WebSocket upgrade request in this order:\n\n1. First comma-separated `x-forwarded-host` value, trimmed.\n2. `Host`, trimmed.\n3. `REPLIT_DEV_DOMAIN`, only when `NODE_ENV !== \"production\"` and request host\n   information is absent.\n\nRequest-derived URLs use the first trimmed `x-forwarded-proto` value, defaulting\nto `https` (also for the development-domain fallback). Empty header values are\ntreated as absent. Without a usable host or permitted development fallback,\n`appUrl` is undefined and omitted from serialized JSON. Explicit values use\nnullish precedence, so even an explicit empty string is preserved.\nExisting callers need no changes. The v2 `createBridge` options are unchanged.\nForwarded headers are metadata supplied by the host/proxy, not an authentication\nor authorization signal; configure trusted proxy/header handling in the host.\n\nAfter confirming public registry availability:\n\n```bash\nnpm view @bestoneconsulting/sap-b1-bridge@1.5.2 version --registry=https://registry.npmjs.org/\nnpm install @bestoneconsulting/sap-b1-bridge@1.5.2 --registry=https://registry.npmjs.org/\n```\n\nConfigure the canonical URL, reconnect an agent, and confirm its `auth_success`\nmetadata before removing a downstream temporary URL patch. No Lucky Feather or\nPlanetJill deployment or patch is modified by this release.\n\n## Registering an Agent\n\nBefore the bridge can talk to your on-premise systems, you need to register an agent and install the agent software on your Windows server.\n\n```typescript\nconst agent = await bridge.registerAgent({\n  name: \"Main Office\",\n  serverName: \"Production ERP\",  // A friendly label — not a hostname or connection string\n  capabilities: [\"sql_server\", \"sap_service_layer\", \"sap_di_api\"],\n});\n\nconsole.log(\"Agent API Key:\", agent.apiKey);\n// Give this API key to the agent software running on your Windows server\n```\n\nThe `serverName` field is a descriptive label to help you identify which server or environment this agent represents (e.g. \"Production ERP\", \"US Warehouse\", \"Dev Server\"). It is not used as a connection string.\n\nContact [Best One Consulting](https://www.bestoneconsulting.com/) to obtain the Windows agent installer.\n\n## Built-in Test Console\n\nThe package includes a built-in web-based test console for managing agents, running queries, and viewing history. No separate build step or static files required.\n\n```typescript\nbridge.mountUI(\"/bridge\");\n// Now accessible at http://localhost:3000/bridge\n```\n\nThe test console includes:\n\n- **Query Console** — Execute SQL queries, SAP Service Layer requests, DI API operations, and Crystal Reports renders with a form-based interface. Select your target type and agent, enter your query or request details, and see results pushed back in real time over WebSocket.\n- **Crystal Reports rendering** — Choose the **Crystal Reports** target type to render a `.rpt` file that lives on the agent's machine. Enter the full report path (e.g. `C:\\Program Files (x86)\\SAP\\SAP Business One Server\\B1_SHR\\CR\\Documents.rpt`), optional string parameters as JSON (e.g. `{\"DocKey@\":\"1\",\"ObjectId@\":\"13\"}`), the output format (PDF, Excel, or Word), and an output file name. When the render completes, the console shows the file name, type, and size with a one-click **Download** button. Renders are given up to ~4 minutes before the console reports a timeout (the History tab still records the final status).\n- **Shared Files** — Choose the **Shared Files** target and an online agent, refresh its folders, and select an operator-shared folder. List immediate contents, navigate permitted subfolders, read/download original file bytes, or explicitly upload a selected file. Choose whether to replace an existing file and confirm the write. File diagnostics only list a valid shared root; they never upload or modify files.\n- **Agents** — Register new agents, view live connection status, copy API keys, and delete agents. Displays the **WebSocket URL** that agents need to connect to, with a one-click copy button.\n- **History** — View recent query history with status, execution time, and row counts.\n- **Live WebSocket** — Real-time connection status indicator and instant result updates. When a query completes, the result is pushed to all connected UI clients immediately.\n\nThe test console adapts to your bridge configuration (app name, API prefix, WebSocket path) automatically.\n\nIf you have a custom full-featured UI (such as the React-based interface from the source repository), you can serve it instead by providing a `staticDir`:\n\n```typescript\nbridge.mountUI(\"/bridge\", \"./path/to/custom-ui-dist\");\n```\n\n## Programmatic API\n\n### Shared files (introduced in 1.5.0)\n\nBoth `createBridge(app, options)` and the legacy `createSAPB1Bridge(options)`\nexpose these methods with the **same** typed `BridgeResult` return envelopes:\n\n```typescript\nlistFiles(agentId: string, options: FileListCall): Promise<BridgeResult<FileListResult>>\nreadFile(agentId: string, options: FileReadCall): Promise<BridgeResult<FileReadResult>>\nwriteFile(agentId: string, options: FileWriteCall): Promise<BridgeResult<FileWriteResult>>\nrefreshAgentCapabilities(agentId: string): Promise<boolean>\n```\n\nThe package exports `SharedFileFolder`, `SharedFileEntry`, `FileCapabilityStatus`,\n`FileCall`, `FileListCall`, `FileReadCall`, `FileWriteCall`, and all three result\ntypes. Calls resolve with `completed`, `failed`, `timeout`, or `agent_offline`;\ncheck the status before using `result`. Agent errors are preserved.\n\n#### Discover folders and refresh changes\n\nThe operator configures folder IDs on the **Windows agent**, not in the cloud.\nThere is no separate folder lookup operation. Refresh after the operator changes\nsharing settings; no server restart is needed:\n\n```typescript\nimport { createBridge } from \"@bestoneconsulting/sap-b1-bridge\";\n\nconst bridge = createBridge(app, { server, agents: registeredAgents });\nconst refreshed = await bridge.refreshAgentCapabilities(agentId);\nif (!refreshed) throw new Error(\"Agent offline or capability refresh failed\");\nconst agent = bridge.getAgent(agentId);\nif (!agent?.online || !agent.capabilities.files) {\n  throw new Error(\"File sharing is unavailable\");\n}\nconst folder = agent.capabilities.fileFolders[0];\nif (!folder) throw new Error(\"The operator has not shared any folders\");\n\nconst listing = await bridge.listFiles(agentId, { folderId: folder.id });\nif (listing.status !== \"completed\") throw new Error(listing.error);\nfor (const entry of listing.result!.entries) {\n  console.log(entry.name, entry.relativePath, entry.isDirectory,\n    entry.sizeBytes, entry.lastModifiedUtc);\n}\n\nconst read = await bridge.readFile(agentId, {\n  folderId: folder.id,\n  relativePath: \"invoice.pdf\",\n});\nif (read.status !== \"completed\") throw new Error(read.error);\nconst originalBytes = Buffer.from(read.result!.dataBase64, \"base64\");\n// originalBytes may legitimately be an empty Buffer.\n\n// This is an explicit write. In a user-facing app, request confirmation first.\nconst written = await bridge.writeFile(agentId, {\n  folderId: folder.id,\n  relativePath: \"result.txt\",\n  dataBase64: Buffer.from(\"Export complete\\n\", \"utf8\").toString(\"base64\"),\n  overwrite: false, // safer opt-in; omitting this field defaults to true\n});\nif (written.status !== \"completed\") throw new Error(written.error);\nconsole.log(written.result!.fileName, written.result!.sizeBytes);\n```\n\n#### File Sharing capability and status\n\nThe wire capability key is exactly **`files`** (case-sensitive), not\n`fileSharing`. **File Sharing** is the portal's display label; the built-in\ntester's target is **Files**. An agent can advertise:\n\n```json\n{\n  \"type\": \"capabilities\",\n  \"capabilities\": {\n    \"sql\": { \"enabled\": true, \"available\": true, \"reason\": null },\n    \"serviceLayer\": { \"enabled\": false, \"available\": false, \"reason\": null },\n    \"diApi\": { \"enabled\": false, \"available\": false, \"reason\": null },\n    \"files\": {\n      \"enabled\": true,\n      \"available\": true,\n      \"reason\": null,\n      \"folders\": [\n        {\n          \"id\": \"exports\",\n          \"path\": \"C:\\\\SAP\\\\Exports\",\n          \"includeSubfolders\": true\n        }\n      ]\n    }\n  }\n}\n```\n\nFile operations require both `enabled` and `available` to be true. Folder IDs\nidentify operator-approved roots; `includeSubfolders` controls access beneath\neach root. Use `reason` to explain disabled or unavailable sharing.\n\n**Capability mapping:** the wire uses a detailed `files` object, while the v2\nSDK exposes a normalized boolean and a separate folder list:\n\n```typescript\n// createBridge().getAgent(id).capabilities\n{\n  sql: true, serviceLayer: true, diApi: true, crystalReports: false,\n  files: true,\n  fileFolders: [\n    { id: \"operator-folder-id\", path: \"C:\\\\SAP\\\\Exports\", includeSubfolders: true }\n  ]\n}\n```\n\nThe detailed/legacy representation retains the wire metadata:\n\n```typescript\n// legacyBridge.getAgentCapabilities(id), or GET /api/agents/capabilities\n{\n  // sql / serviceLayer / diApi / crystalReports omitted here\n  files: {\n    enabled: true, available: true, reason: null,\n    folders: [\n      { id: \"operator-folder-id\", path: \"C:\\\\SAP\\\\Exports\", includeSubfolders: true }\n    ]\n  }\n}\n```\n\nFor the legacy API, call `await legacyBridge.refreshAgentCapabilities(agentId)`,\nthen read `legacyBridge.getAgentCapabilities(agentId)?.files?.folders`.\nOld agents without Files support remain compatible and are treated as unavailable\nwith no shared folders. Refresh supports modern and legacy capability envelopes.\nAn empty folder list is valid even when sharing is enabled. Never reuse an ID\nafter it disappears from refreshed capabilities.\n\nCapabilities are updated when the agent sends a `capabilities` message and when\nan on-demand `agent_capabilities` request completes. Refresh responses may use\n`result` or `results`, including a nested `capabilities` object. The server\nbroadcasts the refreshed status to connected UI clients; capabilities are not\ncaptured only at authentication. `auth_success` is the server's authentication\nacknowledgment, not the agent's capability report.\n\n#### Restrictions and transport\n\n- A file is limited to **25 MiB (26,214,400 bytes)** in either direction.\n  Base64 overhead does not count toward the decoded file cap. Empty files work.\n- `listFiles` lists one directory, nonrecursively. `relativePath` defaults to `\"\"`\n  (the shared root). Read and write require a nonempty relative file path.\n- Use forward slashes. Absolute paths, drive paths, backslashes and `..` traversal\n  are rejected. `includeSubfolders: false` permits only root listing and direct\n  child files; it does not allow listing a subdirectory.\n- `path` is display metadata on the **agent's own machine**, never a path to\n  access through the cloud server's filesystem.\n- `overwrite` defaults to **true** at the SDK/protocol level. Pass `false` to\n  reject an existing file. Testers require an explicit overwrite choice.\n- Malformed base64 and oversized writes fail before dispatch. Filesystem access,\n  actual read sizes, permissions, and final path/subfolder enforcement remain\n  authoritative on the agent.\n- Disabled sharing, unknown folders, forbidden paths, missing files, overwrite\n  conflicts, timeouts and offline agents return errors. There are no automatic\n  retries, chunking, delete operations, synchronization or recursive bulk transfers.\n- Each file call accepts an optional `timeoutMs`; otherwise the SDK's normal\n  query timeout applies. A timeout is not a cancellation of work on the agent;\n  do not automatically repeat a write.\n\nThe existing JSON transport is used without a new binary protocol:\n`execute_request`, `targetType: \"sap\"`, and `requestPayload.operation` equal to\n`file_list`, `file_read` or `file_write`. The tester API target is **`files`**:\n\n```json\n{\n  \"agentId\": \"registered-agent-id\",\n  \"targetType\": \"files\",\n  \"requestPayload\": {\n    \"operation\": \"file_list\",\n    \"folderId\": \"operator-folder-id\",\n    \"relativePath\": \"\"\n  }\n}\n```\n\nSend this to `POST /api/queries`. Completion uses the existing query lifecycle.\nFor a browser download, first connect the tester WebSocket with\n`{ \"type\": \"ui_connect\" }`, take the server-issued `clientId` from `ui_connected`,\nand include it as `uiClientId` in the HTTP POST body. Full file results are sent\nonly to that requesting socket. Other UI subscribers receive metadata without\nbytes; SDK calls do not broadcast their file contents to testers. The included\ntesters handle this automatically. History and active-query summaries are not\ndownload endpoints.\nObject payloads in `query_result.results` (plural), including messages without\na `status`, are retained as the result. Read results contain `dataBase64`,\n`fileName`, `relativePath`, `sizeBytes` and `success`; write results contain the\nsame metadata without bytes. History summaries omit file bytes. Download bytes\nare for the initiating result view, not for rendering as JSON or logging.\n\n#### Host middleware and transfer limits\n\nExpress's default JSON limit is too small for file uploads. A parser that runs\nfirst cannot be overridden later by the SDK. Scope a **36 MiB** JSON limit to\nthe authenticated query endpoint, **before** any smaller global JSON parser:\n\n```typescript\n// Supply these from your application's existing security/session layer.\napp.use(\"/api\", authenticateUser, authorizeBridgeAccess);\napp.use(\"/bridge\", authenticateUser, authorizeBridgeAccess);\napp.post(\"/api/queries\", express.json({ limit: \"36mb\" }));\napp.use(express.json()); // other endpoints retain their default limit\n// Only now construct the bridge and mount its tester.\n```\n\nIf your authentication routes require a global parser first, skip\n`POST /api/queries` in that parser, then mount its larger parser **after**\nauthentication/authorization. Do not raise the global unauthenticated body\nlimit. The SDK does not provide your application's user authentication; secure\nthe tester, REST endpoints, and UI WebSocket upgrades in your host.\n\nThe 36 MiB HTTP allowance fits a 25 MiB file encoded as ~33⅓ MiB of base64 plus\nJSON metadata. The bridge explicitly caps incoming WebSocket messages at\n100 MiB, retaining the previous transport allowance for Crystal Reports.\nConfigure reverse proxies with sufficient finite request/frame limits too.\nReturn HTTP 413 with a clear size error instead of retrying an oversized body.\nDo not log request/response bodies containing file bytes.\n\n#### Verification from the source repository\n\n```bash\nnpm run check\nnpm run test:bridge\nnpm run test:files-ui\nnpm run build\nnpm run smoke:bridge-package\n```\n\nThe bridge suite uses mock WebSocket agents, including exact-cap HTTP/WS byte\nround-trips and legacy SQL/SAP/Crystal regression checks. Browser tests use\nisolated fixtures for both testers; they do not access live Windows folders.\nThe package smoke test builds and packs the release, installs that tarball in a\nclean temporary npm consumer, checks exported TypeScript APIs, and executes both\nSDK surfaces against mock agents. The UI suite requires Chromium (set\n`PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH` when it is not at the Replit default).\nLive Windows permissions, configured folder paths, and agent runtime behavior\nmust be verified separately in an operator-approved test folder.\n\nAll programmatic methods are **synchronous** — they return a Promise that resolves when the agent responds with the result or the request times out (default: 5 minutes). The server sends the command directly to the agent over WebSocket and waits for the response.\n\n### Execute SQL Queries\n\nRun queries against SQL Server databases on your internal network:\n\n```typescript\nconst result = await bridge.executeQuery(agentId, \"SELECT TOP 10 * FROM OITM\");\n\nif (result.status === \"completed\") {\n  console.log(\"Rows:\", result.rowCount);\n  console.log(\"Data:\", result.result);\n  console.log(\"Duration:\", result.executionTime, \"ms\");\n} else {\n  console.log(\"Error:\", result.error);\n}\n```\n\n### Call SAP Service Layer\n\nSend REST API requests to SAP Business One Service Layer:\n\n```typescript\n// GET request\nconst partners = await bridge.callServiceLayer(agentId, {\n  method: \"GET\",\n  endpoint: \"/BusinessPartners\",\n  queryParams: {\n    $top: \"5\",\n    $select: \"CardCode,CardName,CardType\",\n    $filter: \"CardType eq 'C'\",\n  },\n});\n\n// POST request\nconst newOrder = await bridge.callServiceLayer(agentId, {\n  method: \"POST\",\n  endpoint: \"/Orders\",\n  body: {\n    CardCode: \"C20000\",\n    DocumentLines: [\n      { ItemCode: \"A00001\", Quantity: 10 },\n    ],\n  },\n});\n\n// PATCH request\nawait bridge.callServiceLayer(agentId, {\n  method: \"PATCH\",\n  endpoint: \"/BusinessPartners('C20000')\",\n  body: { Phone1: \"555-0100\" },\n});\n```\n\n### Call SAP DI API\n\nInvoke SAP Business One DI API methods using the XML-first contract:\n\n```typescript\n// Get an item\nconst item = await bridge.callDiApi(agentId, {\n  operation: \"di_get\",\n  object: \"Items\",\n  key: { ItemCode: \"A00001\" },\n});\n\n// Add a business partner with XML\nconst result = await bridge.callDiApi(agentId, {\n  operation: \"di_add\",\n  object: \"BusinessPartners\",\n  sapXml: `<BOM>\n    <BO>\n      <AdmInfo><Object>2</Object></AdmInfo>\n      <BusinessPartners>\n        <row>\n          <CardCode>C99999</CardCode>\n          <CardName>New Customer</CardName>\n          <CardType>cCustomer</CardType>\n        </row>\n      </BusinessPartners>\n    </BO>\n  </BOM>`,\n  options: { dryRun: false },\n});\n\n// Run a DI query\nconst queryResult = await bridge.callDiApi(agentId, {\n  operation: \"di_query\",\n  object: \"Items\",\n  sapXml: `<env:Envelope xmlns:env=\"http://www.w3.org/2003/05/soap-envelope\">\n    <env:Body>\n      <dis:DoQuery xmlns:dis=\"http://www.sap.com/SBO/DIS\">\n        <QueryParams>SELECT ItemCode, ItemName FROM OITM WHERE ItemCode LIKE 'A%'</QueryParams>\n      </dis:DoQuery>\n    </env:Body>\n  </env:Envelope>`,\n});\n```\n\n**DI API Operations:**\n\n| Operation | Description | Required Fields |\n|-----------|-------------|-----------------|\n| `di_get` | Retrieve an object | `object`, `key` |\n| `di_add` | Create a new object | `object`, `sapXml` |\n| `di_update` | Update an existing object | `object`, `key`, `sapXml` |\n| `di_action` | Perform an action (cancel, close, remove) | `object`, `key`, `action` |\n| `di_query` | Execute a DI query | `object`, `sapXml` |\n\n**DI API Options:**\n\n| Option | Type | Description |\n|--------|------|-------------|\n| `dryRun` | `boolean` | Validate without committing |\n| `transaction` | `boolean` | Wrap in a transaction |\n| `returnXml` | `boolean` | Return raw XML response |\n| `allowDiQuery` | `boolean` | Allow DI query execution |\n\n### Render Crystal Reports\n\nRender a Crystal Reports `.rpt` file that lives on the agent's machine to PDF, Excel, or Word. The rendered document comes back base64-encoded inside the result — no separate download channel needed.\n\n```typescript\nconst r = await bridge.renderCrystalReport(agentId, {\n  reportPath: \"C:\\\\SAP\\\\CR_ASSOC\\\\AR Invoice.rpt\", // must end in .rpt\n  overrideDataSources: true,                        // default true — use the agent's configured SQL connection\n  parameters: { \"DocKey@\": \"1\", \"ObjectId@\": \"13\" },\n  outputFormat: \"pdf\",                              // \"pdf\" | \"excel\" | \"word\"\n  outputFileName: \"AR Invoice 1\",                   // base name, no extension\n});\n\nif (r.status === \"completed\" && r.result) {\n  const bytes = Buffer.from(r.result.dataBase64, \"base64\");\n  // r.result: { success, fileName, contentType, dataBase64, sizeBytes }\n  // e.g. stream `bytes` back to the browser as r.result.contentType, named r.result.fileName\n} else {\n  // Surface r.error in full — the agent appends diagnostic notes to\n  // Crystal's often-misleading \"Database logon failed\" errors. Don't truncate it.\n  console.error(r.error);\n}\n```\n\nThe request is dispatched as an `execute_request` with payload `{ operation: \"crystal_render\", reportPath, overrideDataSources, parameters, outputFormat, outputFileName }` and the result is read from `query_result.result` as a single object (not a row array).\n\n**Fields:**\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `reportPath` | `string` | Full path to a `.rpt` file on the agent's machine (required, must end in `.rpt`) |\n| `overrideDataSources` | `boolean` | Default `true`. Overrides report datasources with the agent's configured SQL connection |\n| `parameters` | `Record<string, string>` | Report parameter values; unrecognized names are skipped and listed in `warning` |\n| `outputFormat` | `\"pdf\" \\| \"excel\" \\| \"word\"` | Export format (required). Determines returned `fileName` extension and `contentType` |\n| `outputFileName` | `string` | Base file name without extension (required) |\n| `timeoutMs` | `number` | Client-side timeout override. Default **240000 (4 minutes)** |\n\n**Timeout guidance:** rendering runs in a separate helper process on the agent with its own 3-minute limit — longer than the 2-minute limit for SQL/Service Layer. The SDK therefore uses a **4-minute** client-side timeout for `renderCrystalReport` by default so it never races the agent's own limit. Note that `dataBase64` can be several MB for multi-page reports.\n\nAgents report a `crystalReports` capability. If the Crystal Reports runtime isn't installed (or the feature is disabled in the agent profile), `crystalReports` is `false` on the agent record and `crystal_render` requests fail immediately with a clear error. Offline agents return `{ status: \"agent_offline\" }` without a round-trip.\n\n### Agent Management\n\n```typescript\n// List all agents\nconst agents = await bridge.getAgents();\n\n// Get a specific agent\nconst agent = await bridge.getAgent(agentId);\n\n// Check if an agent is currently connected\nconst online = bridge.isAgentConnected(agentId);\n\n// Get live capability status (from in-memory cache, reported by agent)\nconst caps = bridge.getAgentCapabilities(agentId);\n// Returns: { sql: { enabled, available, reason }, serviceLayer: {...}, diApi: {...} }\n\n// Request an agent to refresh its capabilities\nawait bridge.refreshAgentCapabilities(agentId);\n\n// Get all currently connected agent IDs\nconst connectedIds = bridge.getConnectedAgentIds();\n\n// Dispatch a previously created query to an agent for execution\nawait bridge.dispatchQueryToAgent(agentId, queryId);\n\n// Delete an agent\nawait bridge.deleteAgent(agentId);\n```\n\n### Company Management\n\nOrganize agents by company for multi-tenant setups:\n\n```typescript\nconst company = await bridge.createCompany(\"Acme Corp\", \"Production environment\");\nconst companies = await bridge.getCompanies();\nawait bridge.deleteCompany(company.id);\n```\n\n## REST API Endpoints\n\nThe bridge automatically registers these REST endpoints on your Express app:\n\n| Endpoint | Method | Description |\n|----------|--------|-------------|\n| `{prefix}/agents` | `GET` | List all registered agents |\n| `{prefix}/agents` | `POST` | Register a new agent |\n| `{prefix}/agents/:id` | `PATCH` | Update agent details |\n| `{prefix}/agents/:id` | `DELETE` | Remove an agent |\n| `{prefix}/agents/capabilities` | `GET` | Get live capability status for all agents |\n| `{prefix}/agents/:id/refresh-capabilities` | `POST` | Request capability refresh from agent |\n| `{prefix}/agents/:id/test` | `POST` | Test agent connection (sends ping, waits for pong) |\n| `{prefix}/queries` | `POST` | Submit a query for execution |\n| `{prefix}/queries/active` | `GET` | Get most recent query |\n| `{prefix}/queries/recent` | `GET` | Get recent query history |\n| `{prefix}/queries` | `GET` | Get all queries |\n| `{prefix}/companies` | `GET` | List companies |\n| `{prefix}/companies` | `POST` | Create a company |\n| `{prefix}/companies/:id` | `PATCH` | Update a company |\n| `{prefix}/companies/:id` | `DELETE` | Delete a company |\n| `{prefix}/config` | `GET` | Get bridge configuration |\n\n### Query Submission (POST `{prefix}/queries`)\n\nWhen you submit a query via the REST endpoint, the server:\n\n1. Creates the query record in storage with status `pending`\n2. If the target agent is connected, immediately sends the command (`execute_query` for SQL or `execute_request` for SAP targets) directly to the agent and updates status to `executing`\n3. If the agent is not connected, marks the query as `error` with the message \"Agent is not connected\"\n4. Returns the query record (with its current status) in the response\n\nResults arrive asynchronously over WebSocket and are broadcast to connected UI clients as `query_completed` events. If you need to await the result in server code, use the programmatic API (`executeQuery`, `callServiceLayer`, `callDiApi`) instead.\n\n## WebSocket Protocol\n\nAgents connect to `{wsPath}` and the bridge handles all communication over a single persistent WebSocket connection per agent.\n\n### Agent Authentication Flow\n\n1. Agent opens WebSocket to `{wsPath}`\n2. Agent sends `{ type: \"auth\", apiKey: \"agent_xxx\" }`\n3. Bridge validates the API key and responds with `{ type: \"auth_success\", agentId, connectionName, appName, appUrl }` or `{ type: \"auth_failed\" }` (and closes the connection)\n4. Agent is now connected and ready to receive commands\n\n### Server-to-Agent Messages (Direct Push)\n\nThe server pushes commands directly to the agent — the agent never polls for work:\n\n| Message Type | Direction | Description |\n|---|---|---|\n| `execute_query` | Server → Agent | Execute a SQL query. Fields: `queryId`, `sqlQuery` |\n| `execute_request` | Server → Agent | Execute a SAP request. Fields: `queryId`, `targetType`, `requestPayload` |\n| `ping` | Server → Agent | Connection health check. Fields: `pingId` |\n| `heartbeat_ack` | Server → Agent | Acknowledgment of agent heartbeat |\n\n### Agent-to-Server Messages\n\n| Message Type | Direction | Description |\n|---|---|---|\n| `auth` | Agent → Server | Authenticate with API key |\n| `heartbeat` | Agent → Server | Periodic keepalive (every 30s) |\n| `capabilities` | Agent → Server | Report available capabilities |\n| `query_result` | Agent → Server | Return query/request results. Fields: `queryId`, `result`, `rowCount`, `executionTime`, `error` |\n| `pong` | Agent → Server | Response to ping. Fields: `pingId` |\n\n### UI Client Messages\n\nBrowser clients connect to the same WebSocket endpoint with `{ type: \"ui_connect\" }` to receive real-time updates:\n\n| Message Type | Direction | Description |\n|---|---|---|\n| `ui_connect` | Client → Server | Register as a UI client |\n| `ui_connected` | Server → Client | Confirmation of UI registration |\n| `agent_status_update` | Server → Client | Agent went online/offline. Fields: `agentId`, `status` |\n| `agent_capabilities_update` | Server → Client | Agent capabilities changed. Fields: `agentId`, `capabilities` |\n| `query_submitted` | Server → Client | New query created. Fields: `queryId`, `agentId` |\n| `query_executing` | Server → Client | Query sent to agent for execution. Fields: `queryId` |\n| `query_completed` | Server → Client | Query finished. Fields: `queryId`, `status`, `result`, `rowCount`, `executionTime`, `error` |\n\n```typescript\nconst ws = new WebSocket(\"ws://localhost:3000/ws\");\n\nws.onopen = () => {\n  ws.send(JSON.stringify({ type: \"ui_connect\" }));\n};\n\nws.onmessage = (event) => {\n  const message = JSON.parse(event.data);\n  switch (message.type) {\n    case \"ui_connected\":\n      console.log(\"Connected to bridge\");\n      break;\n    case \"agent_status_update\":\n      console.log(`Agent ${message.agentId} is now ${message.status}`);\n      break;\n    case \"query_completed\":\n      console.log(`Query ${message.queryId}: ${message.status}`, message.result);\n      break;\n  }\n};\n```\n\n## Custom Storage\n\nBy default, the bridge uses **in-memory storage** (data is lost on restart). For persistence, provide your own storage implementation:\n\n```typescript\nimport { createSAPB1Bridge } from \"@bestoneconsulting/sap-b1-bridge\";\nimport type { IBridgeStorage } from \"@bestoneconsulting/sap-b1-bridge\";\n\nclass MyDatabaseStorage implements IBridgeStorage {\n  async getAgents() { /* query your database */ }\n  async getAgent(id) { /* ... */ }\n  async getAgentByApiKey(apiKey) { /* ... */ }\n  async createAgent(data) { /* ... */ }\n  async updateAgent(id, updates) { /* ... */ }\n  async updateAgentStatus(id, status, lastHeartbeat) { /* ... */ }\n  async deleteAgent(id) { /* ... */ }\n\n  async getQueries() { /* ... */ }\n  async getQuery(id) { /* ... */ }\n  async getRecentQueries(limit) { /* ... */ }\n  async getActiveQuery() { /* ... */ }\n  async createQuery(data) { /* ... */ }\n  async updateQueryStatus(id, status, updates?) { /* ... */ }\n\n  async getCompanies() { /* ... */ }\n  async getCompany(id) { /* ... */ }\n  async createCompany(name, description?) { /* ... */ }\n  async updateCompany(id, updates) { /* ... */ }\n  async deleteCompany(id) { /* ... */ }\n}\n\nconst bridge = await createSAPB1Bridge(options, new MyDatabaseStorage());\n```\n\nSee the full [`IBridgeStorage` interface](https://github.com/bestoneconsulting/sap-b1-bridge/blob/main/bridge/storage.ts) for method signatures and return types.\n\n### Built-in PostgreSQL Storage (Drizzle ORM)\n\nThe package includes a ready-to-use PostgreSQL storage adapter built on [Drizzle ORM](https://orm.drizzle.team/). This gives you persistent storage without writing any database code.\n\n**1. Install Drizzle dependencies:**\n\n```bash\nnpm install drizzle-orm pg drizzle-kit\nnpm install -D @types/pg\n```\n\nOr if you use Neon serverless PostgreSQL:\n\n```bash\nnpm install drizzle-orm @neondatabase/serverless drizzle-kit\n```\n\n**2. Set up the database connection and push the schema:**\n\nCreate a `drizzle.config.ts` in your project root:\n\n```typescript\nimport { defineConfig } from \"drizzle-kit\";\n\nexport default defineConfig({\n  out: \"./drizzle\",\n  schema: \"./src/db/schema.ts\",\n  dialect: \"postgresql\",\n  dbCredentials: {\n    url: process.env.DATABASE_URL!,\n  },\n});\n```\n\nCreate `src/db/schema.ts` that re-exports the bridge schema (and any of your own tables):\n\n```typescript\nexport { bridgeCompanies, bridgeAgents, bridgeQueries } from \"@bestoneconsulting/sap-b1-bridge\";\n\n// Add your own application tables here if needed\n```\n\nPush the schema to your database:\n\n```bash\nnpx drizzle-kit push\n```\n\nThis creates three tables: `bridge_companies`, `bridge_agents`, and `bridge_queries`. The `bridge_` prefix avoids conflicts with your own application tables.\n\n**3. Create the Drizzle client and pass it to the bridge:**\n\nFor standard PostgreSQL (using `pg`):\n\n```typescript\nimport express from \"express\";\nimport { createServer } from \"http\";\nimport { Pool } from \"pg\";\nimport { drizzle } from \"drizzle-orm/node-postgres\";\nimport { createSAPB1Bridge, createDrizzleBridgeStorage } from \"@bestoneconsulting/sap-b1-bridge\";\n\nconst pool = new Pool({ connectionString: process.env.DATABASE_URL });\nconst db = drizzle(pool);\n\nconst app = express();\napp.use(express.json());\nconst server = createServer(app);\n\nconst storage = createDrizzleBridgeStorage(db);\n\nconst bridge = await createSAPB1Bridge(\n  { app, server, appName: \"My SAP App\" },\n  storage\n);\n\nbridge.mountUI(\"/bridge\");\nserver.listen(3000);\n```\n\nFor Neon serverless PostgreSQL:\n\n```typescript\nimport express from \"express\";\nimport { createServer } from \"http\";\nimport { neon } from \"@neondatabase/serverless\";\nimport { drizzle } from \"drizzle-orm/neon-http\";\nimport { createSAPB1Bridge, createDrizzleBridgeStorage } from \"@bestoneconsulting/sap-b1-bridge\";\n\nconst sql = neon(process.env.DATABASE_URL!);\nconst db = drizzle(sql);\n\nconst app = express();\napp.use(express.json());\nconst server = createServer(app);\n\nconst storage = createDrizzleBridgeStorage(db);\n\nconst bridge = await createSAPB1Bridge(\n  { app, server, appName: \"My SAP App\" },\n  storage\n);\n\nbridge.mountUI(\"/bridge\");\nserver.listen(3000);\n```\n\n**Schema details:**\n\n| Table | Purpose |\n|-------|---------|\n| `bridge_companies` | Organization grouping for agents |\n| `bridge_agents` | Registered agents with API keys and connection status |\n| `bridge_queries` | Query history with status, results, and execution metrics |\n\nThe Drizzle schema objects are exported for advanced use cases (custom queries, migrations, extending):\n\n```typescript\nimport { bridgeCompanies, bridgeAgents, bridgeQueries } from \"@bestoneconsulting/sap-b1-bridge\";\n```\n\n## Configuration Options\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `app` | `Express` | *required* | Your Express application instance |\n| `server` | `Server` | *required* | Node.js HTTP server instance |\n| `appName` | `string` | `\"SAP B1 Bridge\"` | Application name sent to agents on connection |\n| `wsPath` | `string` | `\"/ws\"` | WebSocket endpoint path |\n| `apiPrefix` | `string` | `\"/api\"` | Prefix for all REST API routes |\n\n## Graceful shutdown (introduced in 1.5.1)\n\nBoth `createBridge()` and `createSAPB1Bridge()` expose the public method:\n\n```typescript\nshutdown(options?: { timeoutMs?: number }): Promise<void>\n```\n\nCall `await bridge.shutdown({ timeoutMs: 5000 })` before the host exits.\nThe bridge sends WebSocket close code **1012**, reason **Service Restart**, to\nagent and UI connections and allows a bounded time for close handshakes.\nUnresponsive connections are terminated after the timeout (default 5 seconds).\nRepeated calls are safe; shutdown is permanent for that bridge instance.\nCreate a new instance when starting the application again.\n\nShutdown rejects new bridge work, settles pending calls, and clears bridge\ntimers. It waits for cleanup writes within the same timeout; a slow external\nstorage adapter may finish its writes after the deadline. It removes its\nWebSocket upgrade listener at completion without closing other host services.\n\nThe package does **not** register signal handlers, call `process.exit()`, or\nclose the host's HTTP server. The host owns those resources and must also stop\nits schedulers and other work. For example, after creating `bridge` and `server`:\n\n```typescript\nlet shuttingDown = false;\n\nasync function stop() {\n  if (shuttingDown) return;\n  shuttingDown = true;\n  // Stop your schedulers and reject new application work here.\n  const deadline = setTimeout(() => process.exit(1), 8000);\n  try {\n    const httpClosed = new Promise<void>((resolve, reject) => {\n      server.close(error => error ? reject(error) : resolve());\n    });\n    await Promise.all([bridge.shutdown({ timeoutMs: 5000 }), httpClosed]);\n    // Close your database pools and other host-owned resources here.\n    clearTimeout(deadline);\n    process.exit(0);\n  } catch (error) {\n    console.error(\"Shutdown failed\", error);\n    process.exit(1);\n  }\n}\n\nprocess.on(\"SIGTERM\", () => { void stop(); });\nprocess.on(\"SIGINT\", () => { void stop(); });\n```\n\nChoose deadlines shorter than your host's termination grace period. Clients\nmust still reconnect after abnormal disconnects: a forced kill or machine crash\ncannot perform a clean WebSocket handshake.\n\n## Timeouts\n\n- **Query timeout**: 300 seconds (5 minutes). If an agent doesn't respond within this window, the Promise rejects and the query is marked as `error` with message \"Query timed out\".\n- **Crystal Reports render timeout**: 240 seconds (4 minutes) by default for `renderCrystalReport` — longer than the agent's own 3-minute render limit so the client never races it. Override per call with `timeoutMs`.\n- **Agent test timeout**: 5 seconds. The `POST {prefix}/agents/:id/test` endpoint sends a ping and waits up to 5 seconds for a pong response.\n- **Heartbeat interval**: Agents send heartbeats every 30 seconds. An agent is marked offline if no heartbeat is received within 90 seconds.\n\n## TypeScript Support\n\nFull TypeScript support with exported types:\n\n```typescript\nimport type {\n  SAPB1BridgeOptions,\n  SAPB1BridgeAPI,\n  AgentInfo,\n  QueryResult,\n  ServiceLayerRequest,\n  DiApiRequest,\n  AgentCapabilities,\n  CapabilityStatus,\n  CrystalReportRenderCall,\n  CrystalReportRenderResult,\n  CompanyInfo,\n  RegisterAgentOptions,\n  IBridgeStorage,\n  BridgeQuery,\n} from \"@bestoneconsulting/sap-b1-bridge\";\n```\n\n## Target Types\n\n| Target | Capability Key | Description |\n|--------|---------------|-------------|\n| SQL Server | `sql_server` | Execute T-SQL queries against Microsoft SQL Server |\n| SAP Service Layer | `sap_service_layer` | REST API calls to SAP Business One Service Layer |\n| SAP DI API | `sap_di_api` | XML-based SAP Business One DI API operations |\n| Crystal Reports | `sap_crystal_reports` | Render Crystal Reports `.rpt` files to PDF/Excel/Word on the agent's machine |\n\n## Example: Express App with SAP Integration\n\n```typescript\nimport express from \"express\";\nimport { createServer } from \"http\";\nimport { createSAPB1Bridge } from \"@bestoneconsulting/sap-b1-bridge\";\n\nconst app = express();\napp.use(express.json());\nconst server = createServer(app);\n\nconst bridge = await createSAPB1Bridge({\n  app,\n  server,\n  appName: \"Inventory Dashboard\",\n  apiPrefix: \"/api/bridge\",\n});\n\n// Your own route that uses the bridge programmatic API\napp.get(\"/api/inventory\", async (req, res) => {\n  const agents = await bridge.getAgents();\n  const onlineAgent = agents.find((a) => bridge.isAgentConnected(a.id));\n\n  if (!onlineAgent) {\n    return res.status(503).json({ error: \"No agents online\" });\n  }\n\n  try {\n    // This awaits the result — the server sends the command to the agent\n    // and waits for the response over WebSocket\n    const result = await bridge.executeQuery(\n      onlineAgent.id,\n      \"SELECT ItemCode, ItemName, OnHand FROM OITM WHERE OnHand > 0\"\n    );\n\n    if (result.status === \"completed\") {\n      res.json({ items: result.result, count: result.rowCount });\n    } else {\n      res.status(500).json({ error: result.error });\n    }\n  } catch (err) {\n    res.status(500).json({ error: \"Query failed\" });\n  }\n});\n\nserver.listen(3000);\n```\n\n## License\n\nMIT License - Copyright (c) 2025 [Best One Consulting](https://www.bestoneconsulting.com/)\n\n## Support\n\nFor questions, agent software, or implementation help:\n\n**Best One Consulting**\n[https://www.bestoneconsulting.com/](https://www.bestoneconsulting.com/)\n","readmeFilename":"README.md"}