{"_id":"graphql-workers-subscriptions","_rev":"18-5e45e93a9d33e6a7e064bcc424d1eae3","name":"graphql-workers-subscriptions","dist-tags":{"latest":"0.1.6","beta":"0.1.0-beta.0","alpha":"0.1.5-alpha.1"},"versions":{"0.0.1":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.0.1","type":"module","license":"MIT","main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"start":"wrangler dev","build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","build-app":"esbuild src/app/app.ts --bundle --format=esm --outfile=dist-app/app.js --resolve-extensions=.mts,.mjs,.ts,.js,.json","prepublishOnly":"npm run build"},"dependencies":{"@graphql-tools/schema":"^9.0.13","graphiql":"^2.2.0","graphql":"^16.6.0","graphql-ws":"^5.11.2","graphql-yoga":"^3.3.0","lodash":"^4.17.21"},"resolutions":{"graphql":"^16.6.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20221111.1","@databases/split-sql-query":"^1.0.3","@databases/sql":"^3.3.0","@types/lodash":"^4.14.191","better-sqlite3":"^8.0.1","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4","wrangler":"^2.7.1"},"packageManager":"yarn@3.3.1","types":"./dist/index.d.ts","gitHead":"db04c6323c3c2d87a66a0b320840c88ca09f359d","_id":"graphql-workers-subscriptions@0.0.1","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-QEl3eLFU8YnKNtnUbUTn9fm49tN+RAUz+ovGrV16aUC7gH2e5nv0/QFkGIJ4zz0nbaR1DVuXEXxYt71z5DC0AQ==","shasum":"09a83b9954d90db145f54c83d432912a161a0e4d","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.0.1.tgz","fileCount":9,"unpackedSize":44498,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGcW70ap9FufoD5KATu/UVhtrSNdMld3Jt2d+WJ5qcdLAiBftGoTNOllML6Lo2GG9AQkJnMvR4s1r+9sl1uNbDB2AQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjx3mXACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmoFIw//VI8upoCyy+K1Xm2k4CP7p9NTiX9+dbVkUWOEgngQJ7NrDg8u\r\n+ZvW6s8LIXWCuZJDY7usvBYjlfbXrOr/kE2Tp028VnszbUC2ufnpa2dXGx8S\r\nl+qyYb6gp7tSPTd33hGJ/K7jAY6ynffxF2rsQcWU0RFyVedraxeK4e00aUEm\r\nrjZb4n7HoEddNUTu8NkHJ6zUruY+cKT8Q3M9P0UiVud50JJCDlw0XlcVfgt0\r\nu2HiAHuaK+LSD2IU9Ko66O16d3UedI7xLYlL3FVXraVV088VgfFbpbdlVatQ\r\nmEQtbc8c1Y+qau37OygafBzcMCQM3NSG7ntqkvTDYb9F4Ar3MgtEhZNw6nfb\r\nCrLWCgMONPqVP4gr9vJb4DhDi9tRRGaIKi8xOrZBH5y7LaUsDNX4rYr3wiDM\r\nmf4OXn8nP19VK9wCXhaLZun18HSIC/Il7F37COOj8/zQ858ALF6Dup/UZzGb\r\nMKf4WzW7IHFq979yIDaXTKRqTcKNJyVjJnwQCnxsBLY6JVdcyTxPyCq9vvQl\r\nUNGdNVX80ImyYzLW3wHCyB4lMY2bbhDVDYYbg5VrEA2+yfP00aDEbggHFRJQ\r\nXxtRcQuXhSm9RJCpc+tprrX7x7pnMZlsOpER6AV2XvnI5nu2LFpdmIXGHYqB\r\nHmIhNuAAyToY7jETm6o6FvhptBtMc6Cs6x8=\r\n=/IUi\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.0.1_1674017175555_0.5704122283708561"},"_hasShrinkwrap":false},"0.0.2":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.0.2","type":"module","license":"MIT","main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"start":"wrangler dev","build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","build-app":"esbuild src/app/app.ts --bundle --format=esm --outfile=dist-app/app.js --resolve-extensions=.mts,.mjs,.ts,.js,.json","prepublishOnly":"npm run build"},"dependencies":{"@graphql-tools/schema":"^9.0.13","graphiql":"^2.2.0","graphql":"^16.6.0","graphql-ws":"^5.11.2","graphql-yoga":"^3.3.0","lodash":"^4.17.21"},"resolutions":{"graphql":"^16.6.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20221111.1","@databases/split-sql-query":"^1.0.3","@databases/sql":"^3.3.0","@types/lodash":"^4.14.191","better-sqlite3":"^8.0.1","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4","wrangler":"^2.7.1"},"packageManager":"yarn@3.3.1","types":"./dist/index.d.ts","gitHead":"c19c853a8871db7bf383500977ea014526cf1752","_id":"graphql-workers-subscriptions@0.0.2","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-FJ3J0Pwe0d+JCuTxQjG1iDh+cANHMwNeg/Bc2GxrJ2KzMDjz3jeinwNw1ROGVtr2PWQrglTXxiK2KKvdaPHihQ==","shasum":"4a7170cf0d9e233cdfcfdc617235879804386a97","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.0.2.tgz","fileCount":9,"unpackedSize":46308,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIApVJxPxfYtmQXlMEYy6iPteQ5hTeH8fgQEjfXzEU0qlAiAJ2YDqlVtiddTKCpXdSxbbR6orbDY0W5+SO0NLX7RKGQ=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjx6DVACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmqTHQ//bMRmQ64/na+1ugALZ+90f+WZzFig9Ezhhr0/boGbdZLvy7wY\r\nMu4QlUdyPk7mxwjqAWP0tM2QWZefFkb2UwdWRWNhqD00CclIcrb3ICXdp/H2\r\nL2BGfT2qQq/h10suBqmQV9jpGK4tG1AgcQjdN2StxnC+36X/jfQc97HUweCo\r\nT3/VZdQmgFfc1e0LwtHzNjC39CBMfT9KAsq+SNJUJ/T9wuGhuph6Nv00qcvO\r\ncX+xF5fzKrStDv9TLHyVkxWiNZQ7nOz0CKf8g3mG1JqxMU+6Uc9KaMdn6X/7\r\nK9iv77INsRHwuT/5y2O1ermgAdHPuQLveNZDSEx2TJRFIXTEAQKeuecOUdMM\r\ntCkAWbhj6gsnwDlJX2REe4cvlGtkBb02iHCFpZKW6kmBj87o5eihVb5W5j1c\r\nBR4gbt8NlVgrOzw4Xtw6k+xQkKWelk0YW2B2kGKtDRKJ83iKysd7kk7IIIHg\r\nZQvTEpfyhU9l/3eBOcz6B6l0ZnbfS3oPc/8ivJ7SwruBOYjK3TExvd83Oy6I\r\nEPUao39VPWSzIQOIKyMDPrMSj7FGfw3dutjvA1NIIfNVQrcFwlpf6to5xMF4\r\nEULmJfxyr6q9P3e4jPA+iLSWia/keT1nma2T2AVkw30zlEL+j5S46XgCjsIa\r\nwHTEQ7ONV6mWb/yrrZPPTouC8bEWNnlBCm0=\r\n=sBVo\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.0.2_1674027221109_0.7336868941051309"},"_hasShrinkwrap":false},"0.0.3":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.0.3","type":"module","license":"MIT","keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"npm run build"},"dependencies":{"graphql":"^16.6.0","graphql-ws":"^5.11.2","lodash":"^4.17.21"},"resolutions":{"graphql":"^16.6.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20221111.1","@databases/split-sql-query":"^1.0.3","@databases/sql":"^3.3.0","@types/lodash":"^4.14.191","better-sqlite3":"^8.0.1","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","types":"./dist/index.d.ts","gitHead":"b6e80cf13f65115c0727bd33349f321725029595","_id":"graphql-workers-subscriptions@0.0.3","_nodeVersion":"16.14.2","_npmVersion":"8.5.0","dist":{"integrity":"sha512-36jAr/l/K2TYl4oWSnKlH275RyJEeXpWRaFV/5NH4oYf5DnA6uuarcKkh9c/UwyuJI1r1jZvcpf6i/1bdabKEg==","shasum":"6e33c588ae43399572a8cf87cbf5e7d0e42106bd","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.0.3.tgz","fileCount":9,"unpackedSize":46639,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFJ+q8eJZ4tHnuqHr1zX0aVN0NLkGl1m7yl2kXFhXMoDAiAwDiPE2jMCQ/n1++S22Oj/SCZ7Kk1lXfQ8/wAcv760yw=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJjyUCTACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqb1Q//TxDjmanb4aCnIqcSfdH76VvRnBzttyw9Qmojq3Q0pdd2cngq\r\n4IaVa4gq5uyH0x4yrOQEArbYNsI2AxsPTon1Op7N/AFsKsHlDOk9HomwL0qM\r\n+DQO7+WVLLaBbB71/MLg68XOcQtMjz6S7J/hcrm5OQKLgYE+u52I0E7I9AKQ\r\nFGDu9JQtIQ9bBLFVKx6mrrNgj/19TrVvpQP0gLUykkvOt53fAe2GdhGHz0bF\r\nMk0rkzXLsgWPxZdoNkU1LCIBwWXfjNrBF1HCUUAc8E25xWXsD9xf+IrJnj+J\r\n7em+682q7t62IQvIDqsUxv7kFtQP+yYfl2TVs8ZohgpVOlQQ8d6lKJG4zBUw\r\nXR/sgkG6WAQ0BfCUBcUCws7mACf01WORSNGbT/5v5iiMfL9ofh26a3J9kcTS\r\nmjLoBaLFa9RlUtW9fBpv3U6itQw75Wqyc2sPw0UGxoJMblJUWOC+kFkSdHsj\r\nDhCota3NK5fKp5qXdnRtFtbeYzU63QPhYQi/j55j/LMzF/VaLKL6KyKTFg4G\r\noBs+dVBbnYSdGMun4rAcF0gePeubyQv4oTuhgOMPpDl8zfc/Z8w9RXppRBH9\r\nIVrhn2pbieJJa8jVvocEpBa4DvoBEjAMYktu5LuXk3JjDMB3tYE5W971/+ax\r\niDktQjuSRTdKIzkE/xYIirXTuf0UjHj1pmI=\r\n=dGbC\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"izidormaklary","email":"maklaryizidor@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.0.3_1674133651063_0.9736218940147101"},"_hasShrinkwrap":false},"0.0.4":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.0.4","type":"module","license":"MIT","keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"npm run build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","lodash":"^4.17.21","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20221111.1","@databases/split-sql-query":"^1.0.3","@databases/sql":"^3.3.0","@types/lodash":"^4.14.191","@types/uuid":"^9.0.0","better-sqlite3":"^8.0.1","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"types":"./dist/index.d.ts","gitHead":"01b905f0a21b83f5a1d706cfe8f1679851e8e747","_id":"graphql-workers-subscriptions@0.0.4","_nodeVersion":"16.14.2","_npmVersion":"8.5.0","dist":{"integrity":"sha512-qg4pcA8n4oYA9FxhO/na09Wgj0n1jyPrwtP2if9E8LJp5gr+DzzPjz4pxNL4v8R4H6onHmVNcoAPjevxKqxBow==","shasum":"6cd3137c4817ac5a4d9260dfcdafd47563734539","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.0.4.tgz","fileCount":9,"unpackedSize":46873,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBiCb3G3fgQ8XNOZ3GDd/AT2Tgb+92eyiYzZiJuYsFnNAiBuWihY7ZkbZ6TGhkuL6eIY3fa54JF6Zxz02hAu2RpQYg=="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj1BYxACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmpgbg/9FCI+youA+txWDJlnBfUjnd/VqewMpU9/Hive8L+VyxY39uex\r\n1WnS4sxVjEQU/JGqRz+hB9zVfrZGbYi47zayxLprK36iBmkFSUMk/+qqiIvi\r\nwgaipvNHv5SRR2evcMe1v3g01XF8tp2EFf78kkKd9Kc14mjV547f4Vo9hHfy\r\nicZOPVxYWqEPyYJS0HgKQC5nVqvFChzOEwqHaYR0Q23JgZpO4vmE3EEpaGp2\r\nrf8zPDfRhDefs6e4Fj0Jrk8ZJlgijo2SXc+j66q9pLVI+o5lji8oAH9pUmNj\r\nKqyctsE+tcbCH8W/0btlDkMvU0TkwS4JaQ25QsRfCFBkgeimwCHzsbXrMD8f\r\nkA2eZc6954VEPY+UExLqNX6wqjwo7G+uIvacYs8NepLhMoFiyw+Kf+GG19Ox\r\nxxkuaogHv5jM/n5KkCvQlH76M8dmR0qCfvnH+ZLpNdmWIAw1mjtiBa8I7xrb\r\nhugeOmJ/De2X68bAPUDVv8xZm6V5Vn6gvFCwk/ZJJm+50gECL8D/lgz8ai4B\r\n9UKyF22+xyfpz7hL1Z56wS/XRbps+842J5B/DkEN6sespsIaC7ovWWj6PVAX\r\nDte0S69TDlhCRVV+ATGrBGaK6H8n1EQNIxxcSlqfqdqjYIEE90Cj43k4T+qx\r\n4IskLLWXKXdX5dsDk+EJQ3X4/AUhxyMfhm4=\r\n=tLKp\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"izidormaklary","email":"maklaryizidor@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.0.4_1674843697611_0.6292415088691656"},"_hasShrinkwrap":false},"0.0.5":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.0.5","type":"module","license":"MIT","keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"npm run build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","lodash":"^4.17.21","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20221111.1","@databases/split-sql-query":"^1.0.3","@databases/sql":"^3.3.0","@types/lodash":"^4.14.191","@types/uuid":"^9.0.0","better-sqlite3":"^8.0.1","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"types":"./dist/index.d.ts","gitHead":"d383d506a1d6919111446daad201ce4b5a2c53ef","_id":"graphql-workers-subscriptions@0.0.5","_nodeVersion":"16.14.2","_npmVersion":"8.5.0","dist":{"integrity":"sha512-f5QS7wk66Utg/fs1UVgm2IHhOfoxJcSF06+fV1jUd5TrbUSWV9hglphBEYhBXBBvKX4xMEVKQMT36UZ8vxDTIg==","shasum":"26e0e2e633a5b8adf1dada4d81cc5d9915dad612","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.0.5.tgz","fileCount":9,"unpackedSize":47185,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQColu9z9wMylMOewYivHQlD0QEb9ydyHnR9n5XIbGYLUAIgaa2lJytkgfkWHjiGU5F6bE9iSgDEUDFH6FpK5mJ8CLo="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj2E7NACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2VmrfTA//WcDwC8uL/c/uRd1BYws0qSM4T6UHhjJJ031O+aBzNgpRTzt3\r\nxUlQ3kZLMkQXgsG5v9Doyer3arUauoV+YWQec+UsVSw+V3MZB3V0I6r9844g\r\nH8B/iN1JSwpugSdXXp6Jp+F0pmVzkHu9HKFyYy1CH6cMPrio7xnyojBmf27d\r\nI5hxQTEniwf8FvlNImULx2qOgSUKuV6gj6D1OKfmCJb28dfxSaatXW7M78qe\r\nmlzuMcK//OMB736+Ekt8M/HhnSUC9umfnr8ookvCzv/KjrE4cVkStVJMLr3b\r\nGLdx6JOH5PeWPFWO0Bn3eHkJcyBI41kqVrsi7b1KeVPDlqvqp6m3BctBp1ER\r\nFScgOuQtqTsHGFg3xl9gSRINWKel5EcYCHpquGMMQiYC+inDZ5wwybeio64H\r\n6RfEFBJ9xBbA3eJbc+SeM45lqvbzLsCozzfouW5V9XE8ZxEV0B1HWeL/yEq0\r\nmPwvIPt+kHjcmVNAMu+Jw4qfmULD2kx+f3GcafQIkZ7iKlAY/C67tD+zhoxi\r\nMbV284b32AdfTVH6yh+2EIBvvvWl9m4Je40qRxglQhOJfXZ/s8qpFaK5JjY5\r\nwGXm3uYANKexvhPksFKI/fAumJTdZlAK/eLmuTx69J2wlRMljJ4UMWK/vOae\r\n3hMq58JbqCw351NAoYEQokJg9SB8y0T0qOM=\r\n=NS5Y\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"izidormaklary","email":"maklaryizidor@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.0.5_1675120332941_0.9510140616646359"},"_hasShrinkwrap":false},"0.0.6":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.0.6","type":"module","license":"MIT","keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"npm run build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","lodash":"^4.17.21","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20221111.1","@databases/split-sql-query":"^1.0.3","@databases/sql":"^3.3.0","@types/lodash":"^4.14.191","@types/uuid":"^9.0.0","better-sqlite3":"^8.0.1","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"types":"./dist/index.d.ts","gitHead":"7f5c54632c166889dbee72445d1f7295488896ce","_id":"graphql-workers-subscriptions@0.0.6","_nodeVersion":"16.14.2","_npmVersion":"8.5.0","dist":{"integrity":"sha512-A53eWtI+mB1bYhyLRi9QY/kp1pZeJDJGVU++Yzap5mP3BeeRpKFzRmyjTbBu0juPHYelpSM4ddbo4+Ie7JFPFg==","shasum":"6b013a9a3a42a35dad4e76da1d6137ad0831f2f8","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.0.6.tgz","fileCount":9,"unpackedSize":47335,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDfmip5D08W7gRF5Sn9/2+2Ea8fbSV6sA96g2s5TxVJkgIgQ3p1ah7z3iN7YmNurd4JDEUl4xioeWwGioKfIabrOTw="}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj2aLGACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmp6Hw/9HPf23ngGVJ8M9tf1rBnqalg5nPETj8KIdU2rq0exD8rNX+0u\r\nsPi9a8A5AA7qCOmKOA2xECJ/Gyiw/jbVWunUCncLK2dwxhkmV20sdDcuZ5Qm\r\nTB9tLFyb/MvH6E+OqP3AgZYOO9GWfMI//vCJ99CYwAxh9VmSCU+1gzzq9uDZ\r\nIkeABwFlFcu2TvAN3Vr4+F7hlvUPGvIrpSt+gL4hZOJM5lQr7dX/LLA4rgc/\r\nNu0WHyB8jRIFJNCbd9BTTkBl5sNTOwE69kIKodwMrn4Z4Ge0UePfu/94V6FY\r\nSuuLDLo7VBV9S2T6to5TrCEJlCIhKm5mAFE/rMvcys/QZH+ZF6eTZou9iSt8\r\n0oBaNxyRAkV0S5wwo8LyHTj20GScDJS8N3jZH2rDTOWZN5rY+MpvqljtKYbj\r\nIMQMtjdgEjTxqeI2aMvA01VkD2EMTqpu8vdGyQL8f7LlwXdHlbNQhJYqiPYm\r\nf/CcB1oi8OZBlrFeveBI6QA4DtL2WS/lC8uJwf21QLVTfx33EBMpyFWRnpGI\r\n2ZH7ELAIpg9EmJvnq5c9O9ACW1jw0zjAEgcrmT4b64Pbd8PVFRY8aVucDLYJ\r\nCcaywJu8AliXncnAYnphNiGW9/IzSbBPYbJkon58vB51jD6mLSe3GGWS/yVB\r\nz1t58ocJBNJisUnYuuADWdzwkeODlUAS5pA=\r\n=nmtM\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"izidormaklary","email":"maklaryizidor@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.0.6_1675207366059_0.2814475440031341"},"_hasShrinkwrap":false},"0.0.7":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.0.7","type":"module","license":"MIT","keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"npm run build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","lodash":"^4.17.21","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20221111.1","@databases/split-sql-query":"^1.0.3","@databases/sql":"^3.3.0","@types/lodash":"^4.14.191","@types/uuid":"^9.0.0","better-sqlite3":"^8.0.1","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"types":"./dist/index.d.ts","gitHead":"c3ea754ab2aa144304b33a60f4201fef6bd643ab","_id":"graphql-workers-subscriptions@0.0.7","_nodeVersion":"16.14.2","_npmVersion":"8.5.0","dist":{"integrity":"sha512-PwtqSSX3MXpYtZNo9f/60Vj8ufRnKQqiBpJu9BC7mVOtzjxEg3s4v7zGd5NPGH1tDfrFmjKNpRYq56NfUds65Q==","shasum":"127fb1d21136bd877a62b6d697f49e83f4bfce02","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.0.7.tgz","fileCount":9,"unpackedSize":48293,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC8Mdltm5kuqwPjmshEcPv+mw5J8Xk1xAJbdPPWvwmECQIhAI1wURaESuXACLZ4MEYIVwRCe0DGC82GCGllrV8CHV1j"}],"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v4.10.10\r\nComment: https://openpgpjs.org\r\n\r\nwsFzBAEBCAAGBQJj2jZ5ACEJED1NWxICdlZqFiEECWMYAoorWMhJKdjhPU1b\r\nEgJ2Vmqi9g/+K7ClMIxPdNOAiczE/LWg60N5AwYrl2KoLmRPxaQY4oSRDv8H\r\nT9pxQb11+Nu//uud5TsDlME6HvMPZa9VZ2w2YjSgE8f2OsACz2isENWVmEoB\r\n7BPfF4TGjgFqELC+PxlMlBDGbnhaITzo7hog5Vx6hYzcMt9Pw/mg2Zd+yuZA\r\nxPD2fSjTR/K1XWVUdikZcPjujKxTdGCRIody+ITAozzkXatNY+A+GFK0JfL6\r\nob7G0hK8AjpSh2FGd5fMxjdPcDUc80w8IW0aihFYf1zt64e87tVPM4m71Z2f\r\nRPl18VjBBSY0LsW2Y6I3eipiLB31aFvJoLwJskJF/dD8waFzj0SbOwPSU0gY\r\ncHCC9uvAnct37gJM/7+WgBwzQlGrq0echMS/fmiyVXyhGYEUtYbrtMQpt5tl\r\nd6xQKze5Uc7GQKS8i/rj/mR4DFreEpYsO0cGQOmRj63UAD/GmoGHf4sp7mmp\r\n8/aIW0owdGMQvltKOXZIy911amF1m+uxC8XdmoDYAN+Ic5TXjNO/tyZvSw7Y\r\nog9Lqow1VR3VzI4xNluBkzwDQ4hgnm1aCL59JdVM1w6o7V4aMAjiS4RcqZ99\r\n5PbJaq3F6ZiMIvpF01gwOraUeMoYWpfHwMLMY7eyxJ9ZB1elXdm9XR4fhh3E\r\nRUipe3bJG57ztaLhQoc71sKXP5qGYOYN23M=\r\n=s17Z\r\n-----END PGP SIGNATURE-----\r\n"},"_npmUser":{"name":"izidormaklary","email":"maklaryizidor@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.0.7_1675245177268_0.10347958830662907"},"_hasShrinkwrap":false},"0.0.8":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.0.8","type":"module","license":"MIT","keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"npm run build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","lodash":"^4.17.21","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20221111.1","@databases/split-sql-query":"^1.0.3","@databases/sql":"^3.3.0","@types/lodash":"^4.14.191","@types/uuid":"^9.0.0","better-sqlite3":"^8.0.1","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"types":"./dist/index.d.ts","gitHead":"b26aaf69062e9b1ead04f0a2953afa6bd4c592eb","_id":"graphql-workers-subscriptions@0.0.8","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-x/Kpo/y/ac1AbL+yG8m9c6QLsdG7hr6LJaWgzXkxA7ofvqUILLdY3O32MvpdCqUsCbHU8q0rceQYVAyMgcQVuA==","shasum":"c12f0669da8953c22d4f4673494fb653dbdf0c3c","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.0.8.tgz","fileCount":9,"unpackedSize":37665,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBlPtHYj5pSMLGGeZEUWBJRw1S7EKxWlZtvoKE6Y7r6mAiBMVjBUBsT9nOhm+bcQWHMhXvyAbzzqAsYPaZ18sZgBdw=="}]},"_npmUser":{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.0.8_1684771263246_0.20500163366770896"},"_hasShrinkwrap":false},"0.1.0-beta.0":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.1.0-beta.0","type":"module","license":"MIT","keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"npm run build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","lodash":"^4.17.21","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20221111.1","@databases/split-sql-query":"^1.0.3","@databases/sql":"^3.3.0","@types/lodash":"^4.14.191","@types/uuid":"^9.0.0","better-sqlite3":"^8.0.1","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"types":"./dist/index.d.ts","readme":"# Cloudflare Workers Topic-based GraphQL Subscriptions\n\nThis library uses Cloudflare Workers, Durable Objects and D1 to provide powerful topic-based GraphQL subscriptions.\n\nFeatures:\n\n- 👀 Easy to integrate with your existing GraphQL stack\n- 🙌 Almost no setup\n- 🔍 In-database JSON filtering\n- 🗺 Publish from anywhere\n- 🎹 Great typings\n- 🔐 Authentication\n\n```ts\n// app.ts\nimport { makeExecutableSchema } from \"@graphql-tools/schema\";\nimport { createYoga } from \"graphql-yoga\";\nimport {\n  handleSubscriptions,\n  createWsConnectionPoolClass,\n  subscribe,\n  DefaultPublishableContext,\n  createDefaultPublishableContext,\n} from \"graphql-worker-subscriptions\";\n\nexport interface ENV {\n  WS_CONNECTION_POOL: DurableObjectNamespace;\n  SUBSCRIPTIONS: D1Database;\n}\n\nexport const schema = makeExecutableSchema<DefaultPublishableContext<ENV>>({\n  typeDefs: /* GraphQL */ `\n    type Greeting {\n      greeting: String\n    }\n    type Query {\n      ping: String\n    }\n    type Subscription {\n      greetings(greeting: String): Greeting\n    }\n    type Mutation {\n      greet(greeting: String!): String\n    }\n  `,\n  resolvers: {\n    Query: {\n      ping: () => \"pong\",\n    },\n    Mutation: {\n      greet: async (root, args, context, info) => {\n        context.publish(\"GREETINGS\", {\n          greetings: { greeting: args.greeting },\n        });\n        return \"ok\";\n      },\n    },\n    Subscription: {\n      greetings: {\n        subscribe: subscribe(\"GREETINGS\", {\n          filter: (root, args, context, info) => {\n            return args.greeting\n              ? { greetings: { greeting: args.greeting } }\n              : {};\n          },\n        }),\n      },\n    },\n  },\n});\n\nconst settings = {\n  schema,\n  wsConnectionPool: (env: ENV) => env.WS_CONNECTION_POOL,\n  subscriptionsDb: (env: ENV) => env.SUBSCRIPTIONS,\n};\n\nconst yoga = createYoga<DefaultPublishableContext<ENV>>({\n  schema,\n  graphiql: {\n    // Use WebSockets in GraphiQL\n    subscriptionsProtocol: \"WS\",\n  },\n});\n\nconst baseFetch: ExportedHandlerFetchHandler<ENV> = (\n  request,\n  env,\n  executionCtx\n) =>\n  yoga.handleRequest(\n    request,\n    createDefaultPublishableContext({\n      env,\n      executionCtx,\n      ...settings,\n    })\n  );\n\nconst fetch = handleSubscriptions({\n  fetch: baseFetch,\n  ...settings,\n});\n\nexport default { fetch };\n\nexport const WsConnectionPool = createWsConnectionPoolClass(settings);\n```\n\n```toml\n# wrangler.toml\n[[migrations]]\nnew_classes = [\"WsConnectionPool\"]\ntag = \"v1\"\n\n[build]\n# your build script\ncommand = 'npm run build'\n\n[[d1_databases]]\nbinding = \"SUBSCRIPTIONS\"\ndatabase_id = \"877f1123-088e-43ed-8d4d-37e71c77157c\"\ndatabase_name = \"SUBSCRIPTIONS\"\nmigrations_dir = \"node_modules/graphql-worker-subscriptions/migrations\"\npreview_database_id = \"877f1123-088e-43ed-8d4d-37e71c77157c\"\n\n[durable_objects]\nbindings = [{name = \"WS_CONNECTION_POOL\", class_name = \"WsConnectionPool\"}]\n```\n\n### Deployment\n\n```shell\n# create db\nwrangler d1 create SUBSCRIPTIONS\n# apply migrations\nwrangler d1 migrations apply SUBSCRIPTIONS\n# publish\nwrangler publish\n```\n\n### Local development\n\n```shell\n# create db\nwrangler d1 create SUBSCRIPTIONS --local\n# apply migrations\nwrangler d1 migrations apply SUBSCRIPTIONS --local\n# publish\nwrangler dev\n```\n\n### Publishing from outside Cloudflare\n\nYou can use `POST /publish` on your Worker to publish events.\n\n```shell\ncurl -X POST https://graphql-worker-subscriptions.bubblydoo.workers.dev/publish -H 'Content-Type: application/json' -d '{\"topic\": \"GREETINGS\", \"payload\":{\"greetings\": {\"greeting\": \"hi!\"}}}'\n```\n\nTo disable this, pass `isAuthorized: () => false` to `handleSubscriptions`, or add custom authorization logic there.\n\n### Pooling\n\nTo minimize Durable Objects costs, one Pool can manage many WebSocket connections.\n\nThere are 3 pooling options:\n- `global`: There is 1 global Pool that manages all WebSocket connections.\n- `colo`: There's 1 Pool per datacenter, based on [`request.cf.colo`](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties)\n- `continent`: There's 1 Pool per continent, based on [`request.cf.continent`](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties) (default)\n- `none`: Every connection uses its own Pool (its own Durable Object)\n\nYou can also pass a custom pooling function to `handleSubscriptions`.\n\n### Expected costs\n\nConsidering you used up all your included credits in the Paid Plan:\n\nOne Pool (one Durable Object) is always charged at 128MB and will not sleep unless all its WebSockets are closed. Having one Pool run for 1 month (2600000 seconds) will be about 325000GBs, which would (at the time of writing) cost $4.0625. With a global pool, that would also be your maximum cost.\n\n1 new connection causes:\n- 1 D1 query\n- 1 Durable Object request (fetch)\n\n1 GraphQL subscription causes:\n- 1 Durable Object fetch (incoming WebSocket message)\n\n1 publish causes:\n- 1 D1 query\n- 1 Durable Object request (fetch) per Pool that has a connection that the publish will send to\n\nIf you would publish a message every second for 1 month to 100 WebSockets in 1 Pool, this would cause only 1 D1 query and 1 Durable Object request per second, and would cost you about $0.648/month. D1 is still free for now.\n\nAccording to the pricing docs, there is no charge for outgoing WebSocket messages.\n\n### Internal details\n\nSubscriptions are stored inside D1.\n\nThe D1 database has 5 columns:\n\n- id (websocket message id that will be matched with the client-side subscription, a string)\n- connectionId (a Durable Object id, a string)\n- subscription (the query the subscriber has requested, a JSON string)\n- topic (a string)\n- filter (the filter against which payloads are checked, a JSON string or null)\n\nThe Durable Object has a reference to the WebSocket, which can then be used to publish data to.\n\nFilters are compared in-database using:\n\n```sql\nSELECT * FROM Subscriptions WHERE topic = ?1 AND (filter is null OR json_patch(?2, filter) = ?2);\n```\n\nwith `?1: topic and ?2: payload`.\n\n### Contributing\n\nCheck out this repo, then run:\n\n```shell\nyarn\n\nyarn build\n```\n\nThen link the package to your project (you can take the example as start).\n\n### Bundling issue\n\nDue to the dual package hazard in GraphQL (see [this issue](https://github.com/graphql/graphql-js/pull/3617)) you might get `duplicate \"graphql\" modules cannot be used at the same time` errors.\n\nThis is because both the CJS and ESM version of `graphql` are loaded.\n\nIn that case, you might have to bundle yourself. When using `esbuild`, the option `--resolve-extensions=.mts,.mjs,.ts,.js,.json` works. See the build-app script in package.json for an example.\n\n### Credits 🙏\n\nThis project was inspired by [cloudflare-worker-graphql-ws-template](https://github.com/enisdenjo/cloudflare-worker-graphql-ws-template) and [subscriptionless](https://github.com/andyrichardson/subscriptionless).\n","readmeFilename":"README.md","gitHead":"8eeb636e321d3580fa6a7cc5f59c5c612367e467","_id":"graphql-workers-subscriptions@0.1.0-beta.0","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-wsf8wqyiCFJWu532U8itGTLw+X6jSZOlI9aT+WwWG8UZ1L2u7hgFMXrR0Hg8cj+uwr7qh03K2Zytsvfo91KMDQ==","shasum":"318e293a0baa4ca70056a7270ed0c06606c7857b","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.1.0-beta.0.tgz","fileCount":10,"unpackedSize":45972,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDQH7Fo73aXCt9XkoDYiEqs8zIz6S1n3h/kMztgVzXpkQIgAIbfQwE9BlK2jFyIK/bQZmq3dxIpc4gPMxThDwfE6tc="}]},"_npmUser":{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.1.0-beta.0_1684776370493_0.6078957942330661"},"_hasShrinkwrap":false},"0.1.0":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.1.0","type":"module","license":"MIT","keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"npm run build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","lodash":"^4.17.21","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20221111.1","@databases/split-sql-query":"^1.0.3","@databases/sql":"^3.3.0","@types/lodash":"^4.14.191","@types/uuid":"^9.0.0","better-sqlite3":"^8.0.1","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"types":"./dist/index.d.ts","gitHead":"7ce663c93f35d9ff5b52f89bd0d9f02aee5899ed","_id":"graphql-workers-subscriptions@0.1.0","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-/Kcf/YvQvnj2U9r1zntABCHciHBaMo9ywMZ4ZVY1ngWEXDj6o/qB5IWNBBDlALlC2TCJAPOOlS79sFrOU4cs9g==","shasum":"e0c1b314d523e7a732860372aa8abd11b9d87ac9","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.1.0.tgz","fileCount":10,"unpackedSize":46881,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDj4TKhIUTAVeSyD3b7lCYNs2/Z+RLYG1eSw7hYggIjmQIgOMtTC6xTR1/ix2XrHBz2Koc71Nffq54nkUSqcG0cu6g="}]},"_npmUser":{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.1.0_1684829986464_0.5040793534727641"},"_hasShrinkwrap":false},"0.1.1":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.1.1","type":"module","license":"MIT","homepage":"https://github.com/bubblydoo/graphql-workers-subscriptions#readme","repository":{"type":"git","url":"git+https://github.com/bubblydoo/graphql-workers-subscriptions.git"},"keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"npm run build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","lodash":"^4.17.21","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20221111.1","@databases/split-sql-query":"^1.0.3","@databases/sql":"^3.3.0","@types/lodash":"^4.14.191","@types/uuid":"^9.0.0","better-sqlite3":"^8.0.1","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"types":"./dist/index.d.ts","gitHead":"929f07ff12a5e07a74573ab3c4ea42fb4c00cf24","bugs":{"url":"https://github.com/bubblydoo/graphql-workers-subscriptions/issues"},"_id":"graphql-workers-subscriptions@0.1.1","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-CtTSBeBt6OuOpia/cpGTjWhsI/KjxugqA/EdTpwbUKLzrMFhXQvMRTknXAkroUnJO+5M+/t41oQkvWQKE3la4w==","shasum":"606f456bb7007875817fdb076d0735cd75c992aa","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.1.1.tgz","fileCount":10,"unpackedSize":47085,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDUZFpiV627wZLUlBY4LORhqCU8yezoMrX5MH0pVOFlwQIgKHlZhrZrhQ+LLX3WNto6vZkA02FlGJhPuCbqFTWjFSY="}]},"_npmUser":{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.1.1_1684830336390_0.250542999149864"},"_hasShrinkwrap":false},"0.1.2":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.1.2","type":"module","license":"MIT","homepage":"https://github.com/bubblydoo/graphql-workers-subscriptions#readme","repository":{"type":"git","url":"git+https://github.com/bubblydoo/graphql-workers-subscriptions.git"},"keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"npm run build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","lodash":"^4.17.21","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20221111.1","@databases/split-sql-query":"^1.0.3","@databases/sql":"^3.3.0","@types/lodash":"^4.14.191","@types/uuid":"^9.0.0","better-sqlite3":"^8.0.1","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"types":"./dist/index.d.ts","gitHead":"929f07ff12a5e07a74573ab3c4ea42fb4c00cf24","bugs":{"url":"https://github.com/bubblydoo/graphql-workers-subscriptions/issues"},"_id":"graphql-workers-subscriptions@0.1.2","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-dpc1gMn5WFz378n70MDN4jDaT5Xx02YXSQTF7iIjL0iAHWF3gAAsLDcPjpasqumC1EvOpKZroOXbwmMv5xugaw==","shasum":"53c89dd4b599e68e6793fd4b0e11d71f412f5dce","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.1.2.tgz","fileCount":10,"unpackedSize":47216,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCnJn3nbp04ArgkLnS1iFodUcZ0a8CW6Of+oE7xCh4WYAIgOzjimVDxw6hIV6Vb+MEL1KMVxZVCb+/LZVzkH8xmsJA="}]},"_npmUser":{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.1.2_1684831149304_0.7987545758515429"},"_hasShrinkwrap":false},"0.1.3":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.1.3","type":"module","license":"MIT","homepage":"https://github.com/bubblydoo/graphql-workers-subscriptions#readme","repository":{"type":"git","url":"https://github.com/bubblydoo/graphql-workers-subscriptions.git"},"keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"npm run build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","lodash":"^4.17.21","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20230518.0","@types/lodash":"^4.14.191","@types/uuid":"^9.0.0","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"_id":"graphql-workers-subscriptions@0.1.3","gitHead":"1a47a82ee7d248e6957ffa9dcf6ac9ce9a537def","dist":{"shasum":"33bdbe39dc939ad9bba80eaebbc54004eabf4a27","integrity":"sha512-uehc16/GMd7qJnMSGmnL5BbwHhhlX0cDe1CT1gh9WA+k0a9qrCPfI+BHZyLY6uy7a/IoYYNZAPoy5MdlGhzY6g==","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.1.3.tgz","fileCount":10,"unpackedSize":48627,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCxebu4Rdv3yoArDQ4Euq6Nyjl3Vg/XzwUbBucigWG6lgIhAOuZRefYr8hm4/ARxshC1CWo+OzMjrV9ueQ4Ze6ZZ78A"}]},"_npmUser":{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.1.3_1684836067173_0.8034492660019268"},"_hasShrinkwrap":false},"0.1.4":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.1.4","type":"module","license":"MIT","homepage":"https://github.com/bubblydoo/graphql-workers-subscriptions#readme","repository":{"type":"git","url":"git+https://github.com/bubblydoo/graphql-workers-subscriptions.git"},"keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"npm run build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","lodash":"^4.17.21","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20230518.0","@types/lodash":"^4.14.191","@types/uuid":"^9.0.0","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"types":"./dist/index.d.ts","gitHead":"f326a8e69fd1936b11a6842ada34c238653822df","bugs":{"url":"https://github.com/bubblydoo/graphql-workers-subscriptions/issues"},"_id":"graphql-workers-subscriptions@0.1.4","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-kfVuyD2f1USNb0jUDEV5XFk9jxH3jAFibpCvhzHnw86/VQn6gn7rsp6mxf4cZAUl02qlj0nSk+Zw/1e6nwFnow==","shasum":"73b2e52b91b072f6fa7f5c0d26e73f4f3edfa9aa","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.1.4.tgz","fileCount":10,"unpackedSize":49245,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFr0fbvISo4G0BKszNMpvD4fAB0nptUi8wO8NWNzZjhaAiB+pVSqIMtKtfDKLnva9cJN+DqpININmeat8eJDp7RMZA=="}]},"_npmUser":{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.1.4_1684836157486_0.1385541025875494"},"_hasShrinkwrap":false},"0.1.5-alpha.0":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.1.5-alpha.0","type":"module","license":"MIT","homepage":"https://github.com/bubblydoo/graphql-workers-subscriptions#readme","repository":{"type":"git","url":"git+https://github.com/bubblydoo/graphql-workers-subscriptions.git"},"keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"yarn build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","lodash":"^4.17.21","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20230518.0","@types/lodash":"^4.14.191","@types/uuid":"^9.0.0","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"types":"./dist/index.d.ts","readme":"# Cloudflare Workers Topic-based GraphQL Subscriptions\n\nThis library uses Cloudflare Workers, Durable Objects and D1 to provide powerful topic-based GraphQL subscriptions.\n\nFeatures:\n\n- 👀 Easy to integrate with your existing GraphQL stack\n- 🙌 Almost no setup\n- 🔍 In-database JSON filtering\n- 🗺 Publish from anywhere\n- 🎹 Great typings\n- 🔐 Authentication\n\n```ts\n// app.ts\nimport { makeExecutableSchema } from \"@graphql-tools/schema\";\nimport { createYoga } from \"graphql-yoga\";\nimport {\n  handleSubscriptions,\n  createWsConnectionPoolClass,\n  subscribe,\n  DefaultPublishableContext,\n  createDefaultPublishableContext,\n} from \"graphql-workers-subscriptions\";\n\nexport interface ENV {\n  WS_CONNECTION_POOL: DurableObjectNamespace;\n  SUBSCRIPTIONS: D1Database;\n}\n\nexport const schema = makeExecutableSchema<DefaultPublishableContext<ENV>>({\n  typeDefs: /* GraphQL */ `\n    type Greeting {\n      greeting: String\n    }\n    type Query {\n      ping: String\n    }\n    type Subscription {\n      greetings(greeting: String): Greeting\n    }\n    type Mutation {\n      greet(greeting: String!): String\n    }\n  `,\n  resolvers: {\n    Query: {\n      ping: () => \"pong\",\n    },\n    Mutation: {\n      greet: async (root, args, context, info) => {\n        context.publish(\"GREETINGS\", {\n          greetings: { greeting: args.greeting },\n        });\n        return \"ok\";\n      },\n    },\n    Subscription: {\n      greetings: {\n        subscribe: subscribe(\"GREETINGS\", {\n          filter: (root, args, context, info) => {\n            return args.greeting\n              ? { greetings: { greeting: args.greeting } }\n              : {};\n          },\n        }),\n      },\n    },\n  },\n});\n\nconst settings = {\n  schema,\n  wsConnectionPool: (env: ENV) => env.WS_CONNECTION_POOL,\n  subscriptionsDb: (env: ENV) => env.SUBSCRIPTIONS,\n};\n\nconst yoga = createYoga<DefaultPublishableContext<ENV>>({\n  schema,\n  graphiql: {\n    // Use WebSockets in GraphiQL\n    subscriptionsProtocol: \"WS\",\n  },\n});\n\nconst baseFetch: ExportedHandlerFetchHandler<ENV> = (\n  request,\n  env,\n  executionCtx\n) =>\n  yoga.handleRequest(\n    request,\n    createDefaultPublishableContext({\n      env,\n      executionCtx,\n      ...settings,\n    })\n  );\n\nconst fetch = handleSubscriptions({\n  fetch: baseFetch,\n  ...settings,\n});\n\nexport default { fetch };\n\nexport const WsConnectionPool = createWsConnectionPoolClass(settings);\n```\n\n```toml\n# wrangler.toml\n[[migrations]]\nnew_classes = [\"WsConnectionPool\"]\ntag = \"v1\"\n\n[build]\n# your build script\ncommand = 'npm run build'\n\n[[d1_databases]]\nbinding = \"SUBSCRIPTIONS\"\ndatabase_id = \"877f1123-088e-43ed-8d4d-37e71c77157c\"\ndatabase_name = \"SUBSCRIPTIONS\"\nmigrations_dir = \"node_modules/graphql-workers-subscriptions/migrations\"\npreview_database_id = \"877f1123-088e-43ed-8d4d-37e71c77157c\"\n\n[durable_objects]\nbindings = [{name = \"WS_CONNECTION_POOL\", class_name = \"WsConnectionPool\"}]\n```\n\n### Deployment\n\n```shell\n# create db\nwrangler d1 create SUBSCRIPTIONS\n# apply migrations\nwrangler d1 migrations apply SUBSCRIPTIONS\n# publish\nwrangler publish\n```\n\n### Local development\n\n```shell\n# create db\nwrangler d1 create SUBSCRIPTIONS --local\n# apply migrations\nwrangler d1 migrations apply SUBSCRIPTIONS --local\n# publish\nwrangler dev\n```\n\n### Authentication\n\nFor WebSocket authentication, you can pass `onConnect` to `createWsConnectionPoolClass` (read more documentation [here](https://the-guild.dev/graphql/ws/recipes#ws-server-and-client-auth-usage-with-token-expiration-validation-and-refresh)):\n\n```ts\nexport const WsConnectionPool = createWsConnectionPoolClass<ENV, { token: string }>({\n  ...settings,\n  onConnect: (ctx) => {\n    const token = ctx.connectionParams.token;\n    return isTokenValid(token, ctx.extra.env.TOKEN);\n  },\n});\n```\n\nThen, on the frontend:\n\n```ts\nimport { GraphQLWsLink } from \"@apollo/client/link/subscriptions\";\nimport { createClient } from 'graphql-ws';\n\nconst wsLink = new GraphQLWsLink(\n  createClient({\n    url: \"wss://subscriptions.workers.dev\",\n    connectionParams: () => {\n      return { token: \"<TOKEN>\" };\n    }\n  })\n);\n```\n\nIf you want to verify individual subscriptions, use `onSubscribe`.\n\nTo verify the incoming HTTP requests, use `isPublishAuthorized` and `isConnectAuthorized`.\n\n### Publishing from outside Cloudflare\n\nYou can use `POST /publish` on your Worker to publish events.\n\n```shell\ncurl -X POST https://graphql-workers-subscriptions.bubblydoo.workers.dev/publish -H 'Content-Type: application/json' -d '{\"topic\": \"GREETINGS\", \"payload\":{\"greetings\": {\"greeting\": \"hi!\"}}}'\n```\n\nTo disable this, pass `isPublishAuthorized: () => false` to `handleSubscriptions`, or add custom authorization logic there.\n\n### Pooling\n\nTo minimize Durable Objects costs, one Pool can manage many WebSocket connections.\n\nThere are 3 pooling options:\n- `global`: There is 1 global Pool that manages all WebSocket connections.\n- `colo`: There's 1 Pool per datacenter, based on [`request.cf.colo`](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties)\n- `continent`: There's 1 Pool per continent, based on [`request.cf.continent`](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties) (default)\n- `none`: Every connection uses its own Pool (its own Durable Object)\n\nYou can also pass a custom pooling function to `handleSubscriptions`.\n\n### Expected costs\n\nConsidering you used up all your included credits in the Paid Plan:\n\nOne Pool (one Durable Object) is always charged at 128MB and will not sleep unless all its WebSockets are closed. Having one Pool run for 1 month (2600000 seconds) will be about 325000GBs, which would (at the time of writing) cost $4.0625. With a global pool, that would also be your maximum cost.\n\n1 new connection causes:\n- 1 D1 query\n- 1 Durable Object request (fetch)\n\n1 GraphQL subscription causes:\n- 1 Durable Object fetch (incoming WebSocket message)\n\n1 publish causes:\n- 1 D1 query\n- 1 Durable Object request (fetch) per Pool that has a connection that the publish will send to\n\nIf you would publish a message every second for 1 month to 100 WebSockets in 1 Pool, this would cause only 1 D1 query and 1 Durable Object request per second, and would cost you about $0.648/month. D1 is still free for now.\n\nAccording to the pricing docs, there is no charge for outgoing WebSocket messages.\n\n### Internal details\n\nSubscriptions are stored inside D1.\n\nThe D1 database has 6 columns:\n\n- id (websocket message id that will be matched with the client-side subscription, a string, generated by the client)\n- connectionId (a uuid, a string, identifying the WebSocket connection, generated by the Worker)\n- connectionPoolId (a Durable Object id identifying the pool, a string, e.g. `global`, or `US`)\n- subscription (the query the subscriber has requested, a JSON string)\n- topic (a string)\n- filter (the filter against which payloads are checked, a JSON string or null)\n\nThe Durable Object has a reference to the WebSocket, which can then be used to publish data to.\n\nFilters are compared in-database using:\n\n```sql\nSELECT * FROM Subscriptions WHERE topic = ?1 AND (filter is null OR json_patch(?2, filter) = ?2);\n```\n\nwith `?1: topic and ?2: payload`.\n\n### Contributing\n\nCheck out this repo, then run:\n\n```shell\nyarn\n\nyarn build\n```\n\nThen link the package to your project (you can take the example as start).\n\n### Bundling issue\n\nDue to the dual package hazard in GraphQL (see [this issue](https://github.com/graphql/graphql-js/pull/3617)) you might get `duplicate \"graphql\" modules cannot be used at the same time` errors.\n\nThis is because both the CJS and ESM version of `graphql` are loaded.\n\nIn that case, you might have to bundle yourself. When using `esbuild`, the option `--resolve-extensions=.mts,.mjs,.ts,.js,.json` works. See the build-app script in package.json for an example.\n\n### Credits 🙏\n\nThis project was inspired by [cloudflare-worker-graphql-ws-template](https://github.com/enisdenjo/cloudflare-worker-graphql-ws-template) and [subscriptionless](https://github.com/andyrichardson/subscriptionless).\n","readmeFilename":"README.md","gitHead":"bddd024486c62d444dc38ffa06c0911f51ef4c7c","bugs":{"url":"https://github.com/bubblydoo/graphql-workers-subscriptions/issues"},"_id":"graphql-workers-subscriptions@0.1.5-alpha.0","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-x95A9VAFdLjKQFaPjKPILWJLym3ozbjAgLYfKFLZJtaaP7dUXN985QO6Fb43B2fGcKxTn3jJNmJJpSriagkxTQ==","shasum":"72c63f04fa5252d98accdbdf92f75d037072d7c1","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.1.5-alpha.0.tgz","fileCount":10,"unpackedSize":49641,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQCqMwLQ/tDX5DenIhBnkyjY/Jp5NmWnCohrAJEduh0edAIhAKjigGC9iTj8f8bENjfp84SvN17dnvSCTDB1Rxi1db5p"}]},"_npmUser":{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.1.5-alpha.0_1686764861198_0.045729182277569835"},"_hasShrinkwrap":false},"0.1.5-alpha.1":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.1.5-alpha.1","type":"module","license":"MIT","homepage":"https://github.com/bubblydoo/graphql-workers-subscriptions#readme","repository":{"type":"git","url":"git+https://github.com/bubblydoo/graphql-workers-subscriptions.git"},"keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"yarn build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","radash":"^10.8.1","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20230518.0","@types/uuid":"^9.0.0","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"types":"./dist/index.d.ts","readme":"# Cloudflare Workers Topic-based GraphQL Subscriptions\n\nThis library uses Cloudflare Workers, Durable Objects and D1 to provide powerful topic-based GraphQL subscriptions.\n\nFeatures:\n\n- 👀 Easy to integrate with your existing GraphQL stack\n- 🙌 Almost no setup\n- 🔍 In-database JSON filtering\n- 🗺 Publish from anywhere\n- 🎹 Great typings\n- 🔐 Authentication\n\n```ts\n// app.ts\nimport { makeExecutableSchema } from \"@graphql-tools/schema\";\nimport { createYoga } from \"graphql-yoga\";\nimport {\n  handleSubscriptions,\n  createWsConnectionPoolClass,\n  subscribe,\n  DefaultPublishableContext,\n  createDefaultPublishableContext,\n} from \"graphql-workers-subscriptions\";\n\nexport interface ENV {\n  WS_CONNECTION_POOL: DurableObjectNamespace;\n  SUBSCRIPTIONS: D1Database;\n}\n\nexport const schema = makeExecutableSchema<DefaultPublishableContext<ENV>>({\n  typeDefs: /* GraphQL */ `\n    type Greeting {\n      greeting: String\n    }\n    type Query {\n      ping: String\n    }\n    type Subscription {\n      greetings(greeting: String): Greeting\n    }\n    type Mutation {\n      greet(greeting: String!): String\n    }\n  `,\n  resolvers: {\n    Query: {\n      ping: () => \"pong\",\n    },\n    Mutation: {\n      greet: async (root, args, context, info) => {\n        context.publish(\"GREETINGS\", {\n          greetings: { greeting: args.greeting },\n        });\n        return \"ok\";\n      },\n    },\n    Subscription: {\n      greetings: {\n        subscribe: subscribe(\"GREETINGS\", {\n          filter: (root, args, context, info) => {\n            return args.greeting\n              ? { greetings: { greeting: args.greeting } }\n              : {};\n          },\n        }),\n      },\n    },\n  },\n});\n\nconst settings = {\n  schema,\n  wsConnectionPool: (env: ENV) => env.WS_CONNECTION_POOL,\n  subscriptionsDb: (env: ENV) => env.SUBSCRIPTIONS,\n};\n\nconst yoga = createYoga<DefaultPublishableContext<ENV>>({\n  schema,\n  graphiql: {\n    // Use WebSockets in GraphiQL\n    subscriptionsProtocol: \"WS\",\n  },\n});\n\nconst baseFetch: ExportedHandlerFetchHandler<ENV> = (\n  request,\n  env,\n  executionCtx\n) =>\n  yoga.handleRequest(\n    request,\n    createDefaultPublishableContext({\n      env,\n      executionCtx,\n      ...settings,\n    })\n  );\n\nconst fetch = handleSubscriptions({\n  fetch: baseFetch,\n  ...settings,\n});\n\nexport default { fetch };\n\nexport const WsConnectionPool = createWsConnectionPoolClass(settings);\n```\n\n```toml\n# wrangler.toml\n[[migrations]]\nnew_classes = [\"WsConnectionPool\"]\ntag = \"v1\"\n\n[build]\n# your build script\ncommand = 'npm run build'\n\n[[d1_databases]]\nbinding = \"SUBSCRIPTIONS\"\ndatabase_id = \"877f1123-088e-43ed-8d4d-37e71c77157c\"\ndatabase_name = \"SUBSCRIPTIONS\"\nmigrations_dir = \"node_modules/graphql-workers-subscriptions/migrations\"\npreview_database_id = \"877f1123-088e-43ed-8d4d-37e71c77157c\"\n\n[durable_objects]\nbindings = [{name = \"WS_CONNECTION_POOL\", class_name = \"WsConnectionPool\"}]\n```\n\n### Deployment\n\n```shell\n# create db\nwrangler d1 create SUBSCRIPTIONS\n# apply migrations\nwrangler d1 migrations apply SUBSCRIPTIONS\n# publish\nwrangler publish\n```\n\n### Local development\n\n```shell\n# create db\nwrangler d1 create SUBSCRIPTIONS --local\n# apply migrations\nwrangler d1 migrations apply SUBSCRIPTIONS --local\n# publish\nwrangler dev\n```\n\n### Authentication\n\nFor WebSocket authentication, you can pass `onConnect` to `createWsConnectionPoolClass` (read more documentation [here](https://the-guild.dev/graphql/ws/recipes#ws-server-and-client-auth-usage-with-token-expiration-validation-and-refresh)):\n\n```ts\nexport const WsConnectionPool = createWsConnectionPoolClass<ENV, { token: string }>({\n  ...settings,\n  onConnect: (ctx) => {\n    const token = ctx.connectionParams.token;\n    return isTokenValid(token, ctx.extra.env.TOKEN);\n  },\n});\n```\n\nThen, on the frontend:\n\n```ts\nimport { GraphQLWsLink } from \"@apollo/client/link/subscriptions\";\nimport { createClient } from 'graphql-ws';\n\nconst wsLink = new GraphQLWsLink(\n  createClient({\n    url: \"wss://subscriptions.workers.dev\",\n    connectionParams: () => {\n      return { token: \"<TOKEN>\" };\n    }\n  })\n);\n```\n\nIf you want to verify individual subscriptions, use `onSubscribe`.\n\nTo verify the incoming HTTP requests, use `isPublishAuthorized` and `isConnectAuthorized`.\n\n### Publishing from outside Cloudflare\n\nYou can use `POST /publish` on your Worker to publish events.\n\n```shell\ncurl -X POST https://graphql-workers-subscriptions.bubblydoo.workers.dev/publish -H 'Content-Type: application/json' -d '{\"topic\": \"GREETINGS\", \"payload\":{\"greetings\": {\"greeting\": \"hi!\"}}}'\n```\n\nTo disable this, pass `isPublishAuthorized: () => false` to `handleSubscriptions`, or add custom authorization logic there.\n\n### Pooling\n\nTo minimize Durable Objects costs, one Pool can manage many WebSocket connections.\n\nThere are 3 pooling options:\n- `global`: There is 1 global Pool that manages all WebSocket connections.\n- `colo`: There's 1 Pool per datacenter, based on [`request.cf.colo`](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties)\n- `continent`: There's 1 Pool per continent, based on [`request.cf.continent`](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties) (default)\n- `none`: Every connection uses its own Pool (its own Durable Object)\n\nYou can also pass a custom pooling function to `handleSubscriptions`.\n\n### Expected costs\n\nConsidering you used up all your included credits in the Paid Plan:\n\nOne Pool (one Durable Object) is always charged at 128MB and will not sleep unless all its WebSockets are closed. Having one Pool run for 1 month (2600000 seconds) will be about 325000GBs, which would (at the time of writing) cost $4.0625. With a global pool, that would also be your maximum cost.\n\n1 new connection causes:\n- 1 D1 query\n- 1 Durable Object request (fetch)\n\n1 GraphQL subscription causes:\n- 1 Durable Object fetch (incoming WebSocket message)\n\n1 publish causes:\n- 1 D1 query\n- 1 Durable Object request (fetch) per Pool that has a connection that the publish will send to\n\nIf you would publish a message every second for 1 month to 100 WebSockets in 1 Pool, this would cause only 1 D1 query and 1 Durable Object request per second, and would cost you about $0.648/month. D1 is still free for now.\n\nAccording to the pricing docs, there is no charge for outgoing WebSocket messages.\n\n### Internal details\n\nSubscriptions are stored inside D1.\n\nThe D1 database has 6 columns:\n\n- id (websocket message id that will be matched with the client-side subscription, a string, generated by the client)\n- connectionId (a uuid, a string, identifying the WebSocket connection, generated by the Worker)\n- connectionPoolId (a Durable Object id identifying the pool, a string, e.g. `global`, or `US`)\n- subscription (the query the subscriber has requested, a JSON string)\n- topic (a string)\n- filter (the filter against which payloads are checked, a JSON string or null)\n\nThe Durable Object has a reference to the WebSocket, which can then be used to publish data to.\n\nFilters are compared in-database using:\n\n```sql\nSELECT * FROM Subscriptions WHERE topic = ?1 AND (filter is null OR json_patch(?2, filter) = ?2);\n```\n\nwith `?1: topic and ?2: payload`.\n\n### Contributing\n\nCheck out this repo, then run:\n\n```shell\nyarn\n\nyarn build\n```\n\nThen link the package to your project (you can take the example as start).\n\n### Bundling issue\n\nDue to the dual package hazard in GraphQL (see [this issue](https://github.com/graphql/graphql-js/pull/3617)) you might get `duplicate \"graphql\" modules cannot be used at the same time` errors.\n\nThis is because both the CJS and ESM version of `graphql` are loaded.\n\nIn that case, you might have to bundle yourself. When using `esbuild`, the option `--resolve-extensions=.mts,.mjs,.ts,.js,.json` works. See the build-app script in package.json for an example.\n\n### Credits 🙏\n\nThis project was inspired by [cloudflare-worker-graphql-ws-template](https://github.com/enisdenjo/cloudflare-worker-graphql-ws-template) and [subscriptionless](https://github.com/andyrichardson/subscriptionless).\n","readmeFilename":"README.md","gitHead":"bddd024486c62d444dc38ffa06c0911f51ef4c7c","bugs":{"url":"https://github.com/bubblydoo/graphql-workers-subscriptions/issues"},"_id":"graphql-workers-subscriptions@0.1.5-alpha.1","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-68Bm2MuHK8WeTbv0eRSouQH96BlLZ1XbNm2VMzo4cKmn4VqX6uVw8slukpBdffVTStHsWpiLijNicmbB3oiaEQ==","shasum":"64e4e00a195c0d838c371d69faa015a1b93e3b26","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.1.5-alpha.1.tgz","fileCount":10,"unpackedSize":49263,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDrvxm0vpsf2cT5b63np+Awa79NHQRgCJWf3TgzbhsqrAIgOlluHmUK5+3WGl5woj2/8u+ltutgejU+DTNFKeLST/Y="}]},"_npmUser":{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.1.5-alpha.1_1686765301053_0.44364126460662767"},"_hasShrinkwrap":false},"0.1.5":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.1.5","type":"module","license":"MIT","homepage":"https://github.com/bubblydoo/graphql-workers-subscriptions#readme","repository":{"type":"git","url":"git+https://github.com/bubblydoo/graphql-workers-subscriptions.git"},"keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"yarn build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","radash":"^10.8.1","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20230518.0","@types/uuid":"^9.0.0","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"types":"./dist/index.d.ts","gitHead":"fd72a884824e46e56c05580933cac44c061d2cab","bugs":{"url":"https://github.com/bubblydoo/graphql-workers-subscriptions/issues"},"_id":"graphql-workers-subscriptions@0.1.5","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-jPDVY1HcZvb4ReQP7zahkDvx+LTphWc53ZEoyNxDmLc54ywDuzGq3HiQ17wXSd5R/jbKpcMZIwQg7e2F5S2DPA==","shasum":"d0a9120244ba2fa88917471471cb2af418ee78b6","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.1.5.tgz","fileCount":10,"unpackedSize":49255,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIFWRBa4ekKsa+ammVPL0Z1jO9V9tyzls2clUyPgHtBQnAiBAfhB/7JfZ3y0ttNdrf9TJGHhMG5sThh18VARgemI1WQ=="}]},"_npmUser":{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.1.5_1686765608469_0.2926461687688491"},"_hasShrinkwrap":false},"0.1.6":{"name":"graphql-workers-subscriptions","description":"Cloudflare Workers Topic-based GraphQL Subscriptions","version":"0.1.6","type":"module","license":"MIT","homepage":"https://github.com/bubblydoo/graphql-workers-subscriptions#readme","repository":{"type":"git","url":"git+https://github.com/bubblydoo/graphql-workers-subscriptions.git"},"keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"main":"./dist/index.js","exports":{"require":"./dist/index.cjs","types":"./dist/index.d.ts","default":"./dist/index.js"},"scripts":{"build":"tsup src/index.ts --format cjs,esm --dts","check":"tsc --pretty --noEmit","prepublishOnly":"yarn build"},"dependencies":{"@graphql-tools/utils":"^9.1.4","graphql":"^16.6.0","graphql-ws":"^5.11.2","radash":"^10.8.1","uuid":"^9.0.0"},"devDependencies":{"@cloudflare/workers-types":"^4.20230518.0","@types/uuid":"^9.0.0","esbuild":"^0.17.2","esbuild-visualizer":"^0.4.0","service-worker-mock":"2.0.5","tsup":"^6.5.0","typescript":"^4.9.4"},"packageManager":"yarn@3.3.1","workspaces":["example"],"types":"./dist/index.d.ts","gitHead":"f59aaf7adc536c7482d5e0f4c5034e88a7d01942","bugs":{"url":"https://github.com/bubblydoo/graphql-workers-subscriptions/issues"},"_id":"graphql-workers-subscriptions@0.1.6","_nodeVersion":"18.12.1","_npmVersion":"8.19.2","dist":{"integrity":"sha512-n0jHXFYdnWfPATmlzlNYD3aISDzLmOzHfOaCDYTdt7pf3No9qy1Vcsa9BpeOnJdIhKU+qpfhDNfJcgpDwGlvmg==","shasum":"3be7685e066d24355c5f3f73a226170ff65faf97","tarball":"https://registry.npmjs.org/graphql-workers-subscriptions/-/graphql-workers-subscriptions-0.1.6.tgz","fileCount":10,"unpackedSize":49703,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC9AKN63D11r2TBczgIleeBu/GxFZ51t4A+vLSwLNRP6gIgNRSnf9ByWdAuQKQ4zWupRd/ik6mnH7NrNQbfM3pl9Ws="}]},"_npmUser":{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},"directories":{},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/graphql-workers-subscriptions_0.1.6_1686934204470_0.3373651103300148"},"_hasShrinkwrap":false}},"time":{"created":"2023-01-18T04:46:15.554Z","0.0.1":"2023-01-18T04:46:15.741Z","modified":"2023-06-16T16:50:04.833Z","0.0.2":"2023-01-18T07:33:41.340Z","0.0.3":"2023-01-19T13:07:31.288Z","0.0.4":"2023-01-27T18:21:37.852Z","0.0.5":"2023-01-30T23:12:13.087Z","0.0.6":"2023-01-31T23:22:46.267Z","0.0.7":"2023-02-01T09:52:57.424Z","0.0.8":"2023-05-22T16:01:03.506Z","0.1.0-beta.0":"2023-05-22T17:26:10.721Z","0.1.0":"2023-05-23T08:19:46.656Z","0.1.1":"2023-05-23T08:25:36.568Z","0.1.2":"2023-05-23T08:39:09.512Z","0.1.3":"2023-05-23T10:01:07.348Z","0.1.4":"2023-05-23T10:02:37.687Z","0.1.5-alpha.0":"2023-06-14T17:47:41.389Z","0.1.5-alpha.1":"2023-06-14T17:55:01.266Z","0.1.5":"2023-06-14T18:00:08.693Z","0.1.6":"2023-06-16T16:50:04.685Z"},"maintainers":[{"name":"hansottowirtz","email":"hansottowirtz@gmail.com"},{"name":"izidormaklary","email":"maklaryizidor@gmail.com"}],"description":"Cloudflare Workers Topic-based GraphQL Subscriptions","license":"MIT","readme":"# Cloudflare Workers Topic-based GraphQL Subscriptions\n\nThis library uses Cloudflare Workers, Durable Objects and D1 to provide powerful topic-based GraphQL subscriptions.\n\nFeatures:\n\n- 👀 Easy to integrate with your existing GraphQL stack\n- 🙌 Almost no setup\n- 🔍 In-database JSON filtering\n- 🗺 Publish from anywhere\n- 🎹 Great typings\n- 🔐 Authentication\n\n```ts\n// app.ts\nimport { makeExecutableSchema } from \"@graphql-tools/schema\";\nimport { createYoga } from \"graphql-yoga\";\nimport {\n  handleSubscriptions,\n  createWsConnectionPoolClass,\n  subscribe,\n  DefaultPublishableContext,\n  createDefaultPublishableContext,\n} from \"graphql-workers-subscriptions\";\n\nexport interface ENV {\n  WS_CONNECTION_POOL: DurableObjectNamespace;\n  SUBSCRIPTIONS: D1Database;\n}\n\nexport const schema = makeExecutableSchema<DefaultPublishableContext<ENV>>({\n  typeDefs: /* GraphQL */ `\n    type Greeting {\n      greeting: String\n    }\n    type Query {\n      ping: String\n    }\n    type Subscription {\n      greetings(greeting: String): Greeting\n    }\n    type Mutation {\n      greet(greeting: String!): String\n    }\n  `,\n  resolvers: {\n    Query: {\n      ping: () => \"pong\",\n    },\n    Mutation: {\n      greet: async (root, args, context, info) => {\n        context.publish(\"GREETINGS\", {\n          greetings: { greeting: args.greeting },\n        });\n        return \"ok\";\n      },\n    },\n    Subscription: {\n      greetings: {\n        subscribe: subscribe(\"GREETINGS\", {\n          filter: (root, args, context, info) => {\n            return args.greeting\n              ? { greetings: { greeting: args.greeting } }\n              : {};\n          },\n        }),\n      },\n    },\n  },\n});\n\nconst settings = {\n  schema,\n  wsConnectionPool: (env: ENV) => env.WS_CONNECTION_POOL,\n  subscriptionsDb: (env: ENV) => env.SUBSCRIPTIONS,\n};\n\nconst yoga = createYoga<DefaultPublishableContext<ENV>>({\n  schema,\n  graphiql: {\n    // Use WebSockets in GraphiQL\n    subscriptionsProtocol: \"WS\",\n  },\n});\n\nconst baseFetch: ExportedHandlerFetchHandler<ENV> = (\n  request,\n  env,\n  executionCtx\n) =>\n  yoga.handleRequest(\n    request,\n    createDefaultPublishableContext({\n      env,\n      executionCtx,\n      ...settings,\n    })\n  );\n\nconst fetch = handleSubscriptions({\n  fetch: baseFetch,\n  ...settings,\n});\n\nexport default { fetch };\n\nexport const WsConnectionPool = createWsConnectionPoolClass(settings);\n```\n\n```toml\n# wrangler.toml\n[[migrations]]\nnew_classes = [\"WsConnectionPool\"]\ntag = \"v1\"\n\n[build]\n# your build script\ncommand = 'npm run build'\n\n[[d1_databases]]\nbinding = \"SUBSCRIPTIONS\"\ndatabase_id = \"877f1123-088e-43ed-8d4d-37e71c77157c\"\ndatabase_name = \"SUBSCRIPTIONS\"\nmigrations_dir = \"node_modules/graphql-workers-subscriptions/migrations\"\npreview_database_id = \"877f1123-088e-43ed-8d4d-37e71c77157c\"\n\n[durable_objects]\nbindings = [{name = \"WS_CONNECTION_POOL\", class_name = \"WsConnectionPool\"}]\n```\n\n### Deployment\n\n```shell\n# create db\nwrangler d1 create SUBSCRIPTIONS\n# apply migrations\nwrangler d1 migrations apply SUBSCRIPTIONS\n# publish\nwrangler publish\n```\n\n### Local development\n\n```shell\n# create db\nwrangler d1 create SUBSCRIPTIONS --local\n# apply migrations\nwrangler d1 migrations apply SUBSCRIPTIONS --local\n# publish\nwrangler dev\n```\n\n### Authentication\n\nFor WebSocket authentication, you can pass `onConnect` to `createWsConnectionPoolClass` (read more documentation [here](https://the-guild.dev/graphql/ws/recipes#ws-server-and-client-auth-usage-with-token-expiration-validation-and-refresh)):\n\n```ts\nexport const WsConnectionPool = createWsConnectionPoolClass<ENV, { token: string }>({\n  ...settings,\n  onConnect: (ctx) => {\n    const token = ctx.connectionParams.token;\n    return isTokenValid(token, ctx.extra.env.TOKEN);\n  },\n});\n```\n\nThen, on the frontend:\n\n```ts\nimport { GraphQLWsLink } from \"@apollo/client/link/subscriptions\";\nimport { createClient } from 'graphql-ws';\n\nconst wsLink = new GraphQLWsLink(\n  createClient({\n    url: \"wss://subscriptions.workers.dev\",\n    connectionParams: () => {\n      return { token: \"<TOKEN>\" };\n    }\n  })\n);\n```\n\nIf you want to verify individual subscriptions, use `onSubscribe`.\n\nTo verify the incoming HTTP requests, use `isPublishAuthorized` and `isConnectAuthorized`.\n\n### Publishing from outside Cloudflare\n\nYou can use `POST /publish` on your Worker to publish events.\n\n```shell\ncurl -X POST https://graphql-workers-subscriptions.bubblydoo.workers.dev/publish -H 'Content-Type: application/json' -d '{\"topic\": \"GREETINGS\", \"payload\":{\"greetings\": {\"greeting\": \"hi!\"}}}'\n```\n\nTo disable this, pass `isPublishAuthorized: () => false` to `handleSubscriptions`, or add custom authorization logic there.\n\n### Pooling\n\nTo minimize Durable Objects costs, one Pool can manage many WebSocket connections.\n\nThere are 3 pooling options:\n- `global`: There is 1 global Pool that manages all WebSocket connections.\n- `colo`: There's 1 Pool per datacenter, based on [`request.cf.colo`](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties)\n- `continent`: There's 1 Pool per continent, based on [`request.cf.continent`](https://developers.cloudflare.com/workers/runtime-apis/request/#incomingrequestcfproperties) (default)\n- `none`: Every connection uses its own Pool (its own Durable Object)\n\nYou can also pass a custom pooling function to `handleSubscriptions`.\n\n### Expected costs\n\nConsidering you used up all your included credits in the Paid Plan:\n\nOne Pool (one Durable Object) is always charged at 128MB and will not sleep unless all its WebSockets are closed. Having one Pool run for 1 month (2600000 seconds) will be about 325000GBs, which would (at the time of writing) cost $4.0625. With a global pool, that would also be your maximum cost.\n\n1 new connection causes:\n- 1 D1 query\n- 1 Durable Object request (fetch)\n\n1 GraphQL subscription causes:\n- 1 Durable Object fetch (incoming WebSocket message)\n\n1 publish causes:\n- 1 D1 query\n- 1 Durable Object request (fetch) per Pool that has a connection that the publish will send to\n\nIf you would publish a message every second for 1 month to 100 WebSockets in 1 Pool, this would cause only 1 D1 query and 1 Durable Object request per second, and would cost you about $0.648/month. D1 is still free for now.\n\nAccording to the pricing docs, there is no charge for outgoing WebSocket messages.\n\n### Internal details\n\nSubscriptions are stored inside D1.\n\nThe D1 database has 6 columns:\n\n- id (websocket message id that will be matched with the client-side subscription, a string, generated by the client)\n- connectionId (a uuid, a string, identifying the WebSocket connection, generated by the Worker)\n- connectionPoolId (a Durable Object id identifying the pool, a string, e.g. `global`, or `US`)\n- subscription (the query the subscriber has requested, a JSON string)\n- topic (a string)\n- filter (the filter against which payloads are checked, a JSON string or null)\n\nThe Durable Object has a reference to the WebSocket, which can then be used to publish data to.\n\nFilters are compared in-database using:\n\n```sql\nSELECT * FROM Subscriptions WHERE topic = ?1 AND (filter is null OR json_patch(?2, filter) = ?2);\n```\n\nwith `?1: topic and ?2: payload`.\n\n### Contributing\n\nCheck out this repo, then run:\n\n```shell\nyarn\n\nyarn build\n```\n\nThen link the package to your project (you can take the example as start).\n\n### Bundling issue\n\nDue to the dual package hazard in GraphQL (see [this issue](https://github.com/graphql/graphql-js/pull/3617)) you might get `duplicate \"graphql\" modules cannot be used at the same time` errors.\n\nThis is because both the CJS and ESM version of `graphql` are loaded.\n\nIn that case, you might have to bundle yourself. When using `esbuild`, the option `--resolve-extensions=.mts,.mjs,.ts,.js,.json` works. See the build-app script in package.json for an example.\n\n### Credits 🙏\n\nThis project was inspired by [cloudflare-worker-graphql-ws-template](https://github.com/enisdenjo/cloudflare-worker-graphql-ws-template) and [subscriptionless](https://github.com/andyrichardson/subscriptionless).\n","readmeFilename":"README.md","keywords":["cloudflare","graphql","graphql-subscriptions","cloudflare-worker","graphql-ws","websocket","subscriptions","durable-objects"],"homepage":"https://github.com/bubblydoo/graphql-workers-subscriptions#readme","repository":{"type":"git","url":"git+https://github.com/bubblydoo/graphql-workers-subscriptions.git"},"bugs":{"url":"https://github.com/bubblydoo/graphql-workers-subscriptions/issues"}}