├── README.md ├── preclass ├── annotations.txt ├── app │ ├── index.html │ ├── index.js │ ├── package-lock.json │ └── package.json └── server │ ├── animeflv.csv │ ├── package-lock.json │ ├── package.json │ └── server.js └── recorded ├── .vscode └── settings.json ├── app ├── index.html ├── index.js ├── package-lock.json └── package.json └── server ├── animeflv.csv ├── index-bug-resolvido.js ├── index.js ├── package-lock.json └── package.json /README.md: -------------------------------------------------------------------------------- 1 | # Webstreams nodejs and browser tutorial (ptbr) 2 | 3 | ## About 4 | Welcome, this repo is part of my [**youtube video**](https://youtu.be/-IpRYbL4yMk) about **How to read 10GB of JSON in the frontend without crashing the screen - Webstreams 101 (pt-br)** 5 | First of all, leave your star 🌟 on this repo. 6 | 7 | Access our [**exclusive telegram channel**](https://bit.ly/canalerickwendel) so I'll let you know about all the content I've been producing 8 | 9 | ## Complete source code 10 | - Access it in [app](./recorded/) 11 | 12 | ![10GB-Json](https://user-images.githubusercontent.com/8060102/212579868-0d5875f9-6c0e-42c1-b2a3-ca6d7d8b0327.jpg) 13 | 14 | 15 | ## Have fun! 16 | 17 | -------------------------------------------------------------------------------- /preclass/annotations.txt: -------------------------------------------------------------------------------- 1 | https://developer.chrome.com/articles/fetch-streaming-requests/ 2 | https://www.kaggle.com/datasets/danielalbarracinm/list-of-anime-from-1990-to-2022?resource=download 3 | https://www.tpeczek.com/2019/04/fetch-api-streams-api-ndjson-and-aspnet.html 4 | https://developer.mozilla.org/en-US/docs/Web/API/Streams_API/Using_writable_streams -------------------------------------------------------------------------------- /preclass/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Webstreams 9 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 |
36 |
37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /preclass/app/index.js: -------------------------------------------------------------------------------- 1 | const API_URL = 'http://localhost:3000' 2 | 3 | async function consumeAPI(signal) { 4 | const response = await fetch(API_URL, { 5 | signal 6 | }) 7 | 8 | const reader = response.body 9 | .pipeThrough(new TextDecoderStream()) 10 | .pipeThrough(parseNDJSON()) 11 | 12 | return reader 13 | } 14 | 15 | function parseNDJSON() { 16 | let ndjsonBuffer = '' 17 | 18 | return new TransformStream({ 19 | transform(ndjsonChunk, controller) { 20 | ndjsonBuffer += ndjsonChunk 21 | const jsonValues = ndjsonBuffer.split('\n') 22 | jsonValues.slice(0, -1) 23 | .forEach((jsonValue) => controller.enqueue(JSON.parse(jsonValue))) 24 | 25 | ndjsonBuffer = jsonValues[jsonValues.length - 1] 26 | }, 27 | flush(controller) { 28 | if (!ndjsonBuffer) return 29 | controller.enqueue(JSON.parse(ndjsonBuffer)) 30 | } 31 | }) 32 | } 33 | 34 | function appendToHTML(el) { 35 | return new WritableStream({ 36 | async write({ title, description, url_anime }) { 37 | const card = ` 38 |
39 |
40 |

[${++counter}] ${title}

41 |

${description.slice(0, 100)}

42 | Here's why 43 |
44 |
45 | ` 46 | el.innerHTML += card 47 | }, 48 | abort(reason) { 49 | console.log('aborted**', reason) 50 | } 51 | }) 52 | } 53 | 54 | const [ 55 | start, 56 | stop, 57 | cards 58 | ] = ['Start', 'Stop', 'cards'] 59 | .map( 60 | id => document.getElementById(id) 61 | ) 62 | 63 | let abortController = new AbortController() 64 | let counter = 0 65 | 66 | start.addEventListener('click', async () => { 67 | const reader = await consumeAPI(abortController.signal) 68 | reader.pipeTo(appendToHTML(cards)) 69 | }) 70 | 71 | stop.addEventListener('click', () => { 72 | abortController.abort() 73 | console.log('aborting...') 74 | abortController = new AbortController() 75 | }) -------------------------------------------------------------------------------- /preclass/app/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "devDependencies": { 8 | "http-server": "^14.1.1" 9 | } 10 | }, 11 | "node_modules/ansi-styles": { 12 | "version": "4.3.0", 13 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 14 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 15 | "dev": true, 16 | "dependencies": { 17 | "color-convert": "^2.0.1" 18 | }, 19 | "engines": { 20 | "node": ">=8" 21 | }, 22 | "funding": { 23 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 24 | } 25 | }, 26 | "node_modules/async": { 27 | "version": "2.6.4", 28 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", 29 | "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", 30 | "dev": true, 31 | "dependencies": { 32 | "lodash": "^4.17.14" 33 | } 34 | }, 35 | "node_modules/basic-auth": { 36 | "version": "2.0.1", 37 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", 38 | "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", 39 | "dev": true, 40 | "dependencies": { 41 | "safe-buffer": "5.1.2" 42 | }, 43 | "engines": { 44 | "node": ">= 0.8" 45 | } 46 | }, 47 | "node_modules/call-bind": { 48 | "version": "1.0.2", 49 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 50 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 51 | "dev": true, 52 | "dependencies": { 53 | "function-bind": "^1.1.1", 54 | "get-intrinsic": "^1.0.2" 55 | }, 56 | "funding": { 57 | "url": "https://github.com/sponsors/ljharb" 58 | } 59 | }, 60 | "node_modules/chalk": { 61 | "version": "4.1.2", 62 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 63 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 64 | "dev": true, 65 | "dependencies": { 66 | "ansi-styles": "^4.1.0", 67 | "supports-color": "^7.1.0" 68 | }, 69 | "engines": { 70 | "node": ">=10" 71 | }, 72 | "funding": { 73 | "url": "https://github.com/chalk/chalk?sponsor=1" 74 | } 75 | }, 76 | "node_modules/color-convert": { 77 | "version": "2.0.1", 78 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 79 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 80 | "dev": true, 81 | "dependencies": { 82 | "color-name": "~1.1.4" 83 | }, 84 | "engines": { 85 | "node": ">=7.0.0" 86 | } 87 | }, 88 | "node_modules/color-name": { 89 | "version": "1.1.4", 90 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 91 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 92 | "dev": true 93 | }, 94 | "node_modules/corser": { 95 | "version": "2.0.1", 96 | "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", 97 | "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", 98 | "dev": true, 99 | "engines": { 100 | "node": ">= 0.4.0" 101 | } 102 | }, 103 | "node_modules/debug": { 104 | "version": "3.2.7", 105 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 106 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 107 | "dev": true, 108 | "dependencies": { 109 | "ms": "^2.1.1" 110 | } 111 | }, 112 | "node_modules/eventemitter3": { 113 | "version": "4.0.7", 114 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", 115 | "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", 116 | "dev": true 117 | }, 118 | "node_modules/follow-redirects": { 119 | "version": "1.15.2", 120 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", 121 | "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", 122 | "dev": true, 123 | "funding": [ 124 | { 125 | "type": "individual", 126 | "url": "https://github.com/sponsors/RubenVerborgh" 127 | } 128 | ], 129 | "engines": { 130 | "node": ">=4.0" 131 | }, 132 | "peerDependenciesMeta": { 133 | "debug": { 134 | "optional": true 135 | } 136 | } 137 | }, 138 | "node_modules/function-bind": { 139 | "version": "1.1.1", 140 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 141 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 142 | "dev": true 143 | }, 144 | "node_modules/get-intrinsic": { 145 | "version": "1.1.3", 146 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", 147 | "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", 148 | "dev": true, 149 | "dependencies": { 150 | "function-bind": "^1.1.1", 151 | "has": "^1.0.3", 152 | "has-symbols": "^1.0.3" 153 | }, 154 | "funding": { 155 | "url": "https://github.com/sponsors/ljharb" 156 | } 157 | }, 158 | "node_modules/has": { 159 | "version": "1.0.3", 160 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 161 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 162 | "dev": true, 163 | "dependencies": { 164 | "function-bind": "^1.1.1" 165 | }, 166 | "engines": { 167 | "node": ">= 0.4.0" 168 | } 169 | }, 170 | "node_modules/has-flag": { 171 | "version": "4.0.0", 172 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 173 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 174 | "dev": true, 175 | "engines": { 176 | "node": ">=8" 177 | } 178 | }, 179 | "node_modules/has-symbols": { 180 | "version": "1.0.3", 181 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 182 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 183 | "dev": true, 184 | "engines": { 185 | "node": ">= 0.4" 186 | }, 187 | "funding": { 188 | "url": "https://github.com/sponsors/ljharb" 189 | } 190 | }, 191 | "node_modules/he": { 192 | "version": "1.2.0", 193 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 194 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 195 | "dev": true, 196 | "bin": { 197 | "he": "bin/he" 198 | } 199 | }, 200 | "node_modules/html-encoding-sniffer": { 201 | "version": "3.0.0", 202 | "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", 203 | "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", 204 | "dev": true, 205 | "dependencies": { 206 | "whatwg-encoding": "^2.0.0" 207 | }, 208 | "engines": { 209 | "node": ">=12" 210 | } 211 | }, 212 | "node_modules/http-proxy": { 213 | "version": "1.18.1", 214 | "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", 215 | "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", 216 | "dev": true, 217 | "dependencies": { 218 | "eventemitter3": "^4.0.0", 219 | "follow-redirects": "^1.0.0", 220 | "requires-port": "^1.0.0" 221 | }, 222 | "engines": { 223 | "node": ">=8.0.0" 224 | } 225 | }, 226 | "node_modules/http-server": { 227 | "version": "14.1.1", 228 | "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", 229 | "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", 230 | "dev": true, 231 | "dependencies": { 232 | "basic-auth": "^2.0.1", 233 | "chalk": "^4.1.2", 234 | "corser": "^2.0.1", 235 | "he": "^1.2.0", 236 | "html-encoding-sniffer": "^3.0.0", 237 | "http-proxy": "^1.18.1", 238 | "mime": "^1.6.0", 239 | "minimist": "^1.2.6", 240 | "opener": "^1.5.1", 241 | "portfinder": "^1.0.28", 242 | "secure-compare": "3.0.1", 243 | "union": "~0.5.0", 244 | "url-join": "^4.0.1" 245 | }, 246 | "bin": { 247 | "http-server": "bin/http-server" 248 | }, 249 | "engines": { 250 | "node": ">=12" 251 | } 252 | }, 253 | "node_modules/iconv-lite": { 254 | "version": "0.6.3", 255 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 256 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 257 | "dev": true, 258 | "dependencies": { 259 | "safer-buffer": ">= 2.1.2 < 3.0.0" 260 | }, 261 | "engines": { 262 | "node": ">=0.10.0" 263 | } 264 | }, 265 | "node_modules/lodash": { 266 | "version": "4.17.21", 267 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 268 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 269 | "dev": true 270 | }, 271 | "node_modules/mime": { 272 | "version": "1.6.0", 273 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 274 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 275 | "dev": true, 276 | "bin": { 277 | "mime": "cli.js" 278 | }, 279 | "engines": { 280 | "node": ">=4" 281 | } 282 | }, 283 | "node_modules/minimist": { 284 | "version": "1.2.7", 285 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", 286 | "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", 287 | "dev": true, 288 | "funding": { 289 | "url": "https://github.com/sponsors/ljharb" 290 | } 291 | }, 292 | "node_modules/mkdirp": { 293 | "version": "0.5.6", 294 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 295 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 296 | "dev": true, 297 | "dependencies": { 298 | "minimist": "^1.2.6" 299 | }, 300 | "bin": { 301 | "mkdirp": "bin/cmd.js" 302 | } 303 | }, 304 | "node_modules/ms": { 305 | "version": "2.1.3", 306 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 307 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 308 | "dev": true 309 | }, 310 | "node_modules/object-inspect": { 311 | "version": "1.12.2", 312 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", 313 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", 314 | "dev": true, 315 | "funding": { 316 | "url": "https://github.com/sponsors/ljharb" 317 | } 318 | }, 319 | "node_modules/opener": { 320 | "version": "1.5.2", 321 | "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", 322 | "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", 323 | "dev": true, 324 | "bin": { 325 | "opener": "bin/opener-bin.js" 326 | } 327 | }, 328 | "node_modules/portfinder": { 329 | "version": "1.0.32", 330 | "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", 331 | "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", 332 | "dev": true, 333 | "dependencies": { 334 | "async": "^2.6.4", 335 | "debug": "^3.2.7", 336 | "mkdirp": "^0.5.6" 337 | }, 338 | "engines": { 339 | "node": ">= 0.12.0" 340 | } 341 | }, 342 | "node_modules/qs": { 343 | "version": "6.11.0", 344 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 345 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 346 | "dev": true, 347 | "dependencies": { 348 | "side-channel": "^1.0.4" 349 | }, 350 | "engines": { 351 | "node": ">=0.6" 352 | }, 353 | "funding": { 354 | "url": "https://github.com/sponsors/ljharb" 355 | } 356 | }, 357 | "node_modules/requires-port": { 358 | "version": "1.0.0", 359 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 360 | "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", 361 | "dev": true 362 | }, 363 | "node_modules/safe-buffer": { 364 | "version": "5.1.2", 365 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 366 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 367 | "dev": true 368 | }, 369 | "node_modules/safer-buffer": { 370 | "version": "2.1.2", 371 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 372 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 373 | "dev": true 374 | }, 375 | "node_modules/secure-compare": { 376 | "version": "3.0.1", 377 | "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", 378 | "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", 379 | "dev": true 380 | }, 381 | "node_modules/side-channel": { 382 | "version": "1.0.4", 383 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 384 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 385 | "dev": true, 386 | "dependencies": { 387 | "call-bind": "^1.0.0", 388 | "get-intrinsic": "^1.0.2", 389 | "object-inspect": "^1.9.0" 390 | }, 391 | "funding": { 392 | "url": "https://github.com/sponsors/ljharb" 393 | } 394 | }, 395 | "node_modules/supports-color": { 396 | "version": "7.2.0", 397 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 398 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 399 | "dev": true, 400 | "dependencies": { 401 | "has-flag": "^4.0.0" 402 | }, 403 | "engines": { 404 | "node": ">=8" 405 | } 406 | }, 407 | "node_modules/union": { 408 | "version": "0.5.0", 409 | "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", 410 | "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", 411 | "dev": true, 412 | "dependencies": { 413 | "qs": "^6.4.0" 414 | }, 415 | "engines": { 416 | "node": ">= 0.8.0" 417 | } 418 | }, 419 | "node_modules/url-join": { 420 | "version": "4.0.1", 421 | "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", 422 | "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", 423 | "dev": true 424 | }, 425 | "node_modules/whatwg-encoding": { 426 | "version": "2.0.0", 427 | "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", 428 | "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", 429 | "dev": true, 430 | "dependencies": { 431 | "iconv-lite": "0.6.3" 432 | }, 433 | "engines": { 434 | "node": ">=12" 435 | } 436 | } 437 | } 438 | } 439 | -------------------------------------------------------------------------------- /preclass/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "devDependencies": { 3 | "http-server": "^14.1.1" 4 | }, 5 | "name": "app", 6 | "version": "0.0.1", 7 | "main": "index.js", 8 | "dependencies": { 9 | "async": "^2.6.4", 10 | "ansi-styles": "^4.3.0", 11 | "call-bind": "^1.0.2", 12 | "basic-auth": "^2.0.1", 13 | "chalk": "^4.1.2", 14 | "color-convert": "^2.0.1", 15 | "color-name": "^1.1.4", 16 | "corser": "^2.0.1", 17 | "debug": "^3.2.7", 18 | "eventemitter3": "^4.0.7", 19 | "follow-redirects": "^1.15.2", 20 | "function-bind": "^1.1.1", 21 | "get-intrinsic": "^1.1.3", 22 | "has": "^1.0.3", 23 | "has-flag": "^4.0.0", 24 | "he": "^1.2.0", 25 | "has-symbols": "^1.0.3", 26 | "http-proxy": "^1.18.1", 27 | "html-encoding-sniffer": "^3.0.0", 28 | "iconv-lite": "^0.6.3", 29 | "lodash": "^4.17.21", 30 | "mime": "^1.6.0", 31 | "minimist": "^1.2.7", 32 | "mkdirp": "^0.5.6", 33 | "ms": "^2.1.3", 34 | "object-inspect": "^1.12.2", 35 | "opener": "^1.5.2", 36 | "portfinder": "^1.0.32", 37 | "qs": "^6.11.0", 38 | "requires-port": "^1.0.0", 39 | "safe-buffer": "^5.1.2", 40 | "safer-buffer": "^2.1.2", 41 | "secure-compare": "^3.0.1", 42 | "side-channel": "^1.0.4", 43 | "supports-color": "^7.2.0", 44 | "url-join": "^4.0.1", 45 | "union": "^0.5.0", 46 | "whatwg-encoding": "^2.0.0" 47 | }, 48 | "scripts": { 49 | "start": "http-server .", 50 | "test": "echo \"Error: no test specified\" && exit 1" 51 | }, 52 | "keywords": [], 53 | "author": "", 54 | "license": "ISC", 55 | "description": "" 56 | } 57 | -------------------------------------------------------------------------------- /preclass/server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webstreams", 3 | "version": "0.0.1", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "webstreams", 9 | "version": "0.0.1", 10 | "license": "ISC", 11 | "dependencies": { 12 | "csvtojson": "^2.0.10" 13 | } 14 | }, 15 | "node_modules/bluebird": { 16 | "version": "3.7.2", 17 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 18 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" 19 | }, 20 | "node_modules/csvtojson": { 21 | "version": "2.0.10", 22 | "resolved": "https://registry.npmjs.org/csvtojson/-/csvtojson-2.0.10.tgz", 23 | "integrity": "sha512-lUWFxGKyhraKCW8Qghz6Z0f2l/PqB1W3AO0HKJzGIQ5JRSlR651ekJDiGJbBT4sRNNv5ddnSGVEnsxP9XRCVpQ==", 24 | "dependencies": { 25 | "bluebird": "^3.5.1", 26 | "lodash": "^4.17.3", 27 | "strip-bom": "^2.0.0" 28 | }, 29 | "bin": { 30 | "csvtojson": "bin/csvtojson" 31 | }, 32 | "engines": { 33 | "node": ">=4.0.0" 34 | } 35 | }, 36 | "node_modules/is-utf8": { 37 | "version": "0.2.1", 38 | "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", 39 | "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" 40 | }, 41 | "node_modules/lodash": { 42 | "version": "4.17.21", 43 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 44 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 45 | }, 46 | "node_modules/strip-bom": { 47 | "version": "2.0.0", 48 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", 49 | "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", 50 | "dependencies": { 51 | "is-utf8": "^0.2.0" 52 | }, 53 | "engines": { 54 | "node": ">=0.10.0" 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /preclass/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webstreams", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "server.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1", 9 | "start": "node server.js" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "csvtojson": "^2.0.10" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /preclass/server/server.js: -------------------------------------------------------------------------------- 1 | import { createServer } from 'node:http' 2 | import { createReadStream } from 'node:fs' 3 | import { setTimeout } from 'node:timers/promises' 4 | import { Transform, Readable } from 'node:stream' 5 | import { TransformStream, WritableStream } from 'node:stream/web' 6 | import csvtojson from 'csvtojson' 7 | 8 | const PORT = 3000 9 | // curl -N localhost:3000 10 | createServer(async (request, response) => { 11 | const headers = { 12 | 'Access-Control-Allow-Origin': '*', 13 | 'Access-Control-Allow-Methods': '*', 14 | } 15 | if (request.method === 'OPTIONS') { 16 | response.writeHead(204, headers) 17 | response.end() 18 | return 19 | } 20 | 21 | let items = 0 22 | request.once('close', () => console.log('connection was closed!', items)) 23 | 24 | // const d = (await r.getReader().read()).value 25 | // console.log('d', Buffer.from(d).toString('utf8')) 26 | Readable.toWeb(createReadStream('./animeflv.csv')) 27 | .pipeThrough(Transform.toWeb(csvtojson())) 28 | .pipeThrough( 29 | new TransformStream({ 30 | transform(chunk, controller) { 31 | const d = JSON.parse(Buffer.from(chunk)) 32 | controller.enqueue( 33 | JSON.stringify({ 34 | title: d.title, 35 | description: d.description, 36 | url_anime: d.url_anime, 37 | image: d.image 38 | }).concat('\n') 39 | ) 40 | }, 41 | }) 42 | ) 43 | .pipeTo( 44 | new WritableStream({ 45 | async write(chunk) { 46 | await setTimeout(200) 47 | items++ 48 | response.write(chunk) 49 | }, 50 | close() { 51 | response.end() 52 | } 53 | }) 54 | ) 55 | 56 | response.writeHead(200, headers) 57 | }) 58 | .listen(PORT) 59 | .on('listening', _ => console.log('server running at ', PORT)) -------------------------------------------------------------------------------- /recorded/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "window.zoomLevel": 3 3 | } -------------------------------------------------------------------------------- /recorded/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Webstream é o terroooorr 8 | 23 | 24 | 25 | 26 | 27 |
28 |
29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /recorded/app/index.js: -------------------------------------------------------------------------------- 1 | const API_URL = 'http://localhost:3000' 2 | let counter = 0 3 | 4 | async function consumeAPI(signal) { 5 | const response = await fetch(API_URL, { 6 | signal 7 | }) 8 | const reader = response.body 9 | .pipeThrough(new TextDecoderStream()) 10 | .pipeThrough(parseNDJSON()) 11 | // .pipeTo(new WritableStream({ 12 | // write(chunk) { 13 | // console.log(++counter, 'chunk', chunk) 14 | // } 15 | // })) 16 | 17 | return reader 18 | } 19 | 20 | function appendToHTML(element) { 21 | return new WritableStream({ 22 | write({ title, description, url_anime}) { 23 | const card = ` 24 |
25 |
26 |

[${++counter}] ${title}

27 |

${description.slice(0, 100)}

28 | Here's why 29 |
30 |
31 | ` 32 | element.innerHTML += card 33 | }, 34 | abort(reason) { 35 | console.log('aborted**', reason) 36 | } 37 | }) 38 | } 39 | // essa função vai se certificar que caso dois chunks cheguem em uma unica transmissao 40 | // converta corretamente para JSON 41 | // dado:{}\n{} 42 | // deve 43 | // {} 44 | // {} 45 | function parseNDJSON() { 46 | let ndjsonBuffer = '' 47 | return new TransformStream({ 48 | transform(chunk, controller) { 49 | ndjsonBuffer += chunk 50 | const items = ndjsonBuffer.split('\n') 51 | items.slice(0, -1) 52 | .forEach(item => controller.enqueue(JSON.parse(item))) 53 | 54 | ndjsonBuffer = items[items.length -1] 55 | }, 56 | flush(controller) { 57 | if(!ndjsonBuffer) return; 58 | controller.enqueue(JSON.parse(ndjsonBuffer)) 59 | } 60 | }) 61 | } 62 | const [ 63 | start, 64 | stop, 65 | cards 66 | ] = ['start', 'stop', 'cards'].map(item => document.getElementById(item)) 67 | 68 | let abortController = new AbortController() 69 | start.addEventListener('click', async () => { 70 | try { 71 | const readable = await consumeAPI(abortController.signal) 72 | // add signal and await to handle the abortError exception after abortion 73 | await readable.pipeTo(appendToHTML(cards), { signal: abortController.signal }) 74 | } catch (error) { 75 | if (!error.message.includes('abort')) throw error 76 | } 77 | }) 78 | 79 | stop.addEventListener('click', () => { 80 | abortController.abort() 81 | console.log('aborting...') 82 | abortController = new AbortController() 83 | }) 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /recorded/app/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "version": "0.0.1", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "app", 9 | "version": "0.0.1", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "http-server": "^14.1.1" 13 | } 14 | }, 15 | "node_modules/ansi-styles": { 16 | "version": "4.3.0", 17 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 18 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 19 | "dev": true, 20 | "dependencies": { 21 | "color-convert": "^2.0.1" 22 | }, 23 | "engines": { 24 | "node": ">=8" 25 | }, 26 | "funding": { 27 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 28 | } 29 | }, 30 | "node_modules/async": { 31 | "version": "2.6.4", 32 | "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", 33 | "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", 34 | "dev": true, 35 | "dependencies": { 36 | "lodash": "^4.17.14" 37 | } 38 | }, 39 | "node_modules/basic-auth": { 40 | "version": "2.0.1", 41 | "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", 42 | "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", 43 | "dev": true, 44 | "dependencies": { 45 | "safe-buffer": "5.1.2" 46 | }, 47 | "engines": { 48 | "node": ">= 0.8" 49 | } 50 | }, 51 | "node_modules/call-bind": { 52 | "version": "1.0.2", 53 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 54 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 55 | "dev": true, 56 | "dependencies": { 57 | "function-bind": "^1.1.1", 58 | "get-intrinsic": "^1.0.2" 59 | }, 60 | "funding": { 61 | "url": "https://github.com/sponsors/ljharb" 62 | } 63 | }, 64 | "node_modules/chalk": { 65 | "version": "4.1.2", 66 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 67 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 68 | "dev": true, 69 | "dependencies": { 70 | "ansi-styles": "^4.1.0", 71 | "supports-color": "^7.1.0" 72 | }, 73 | "engines": { 74 | "node": ">=10" 75 | }, 76 | "funding": { 77 | "url": "https://github.com/chalk/chalk?sponsor=1" 78 | } 79 | }, 80 | "node_modules/color-convert": { 81 | "version": "2.0.1", 82 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 83 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 84 | "dev": true, 85 | "dependencies": { 86 | "color-name": "~1.1.4" 87 | }, 88 | "engines": { 89 | "node": ">=7.0.0" 90 | } 91 | }, 92 | "node_modules/color-name": { 93 | "version": "1.1.4", 94 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 95 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 96 | "dev": true 97 | }, 98 | "node_modules/corser": { 99 | "version": "2.0.1", 100 | "resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz", 101 | "integrity": "sha512-utCYNzRSQIZNPIcGZdQc92UVJYAhtGAteCFg0yRaFm8f0P+CPtyGyHXJcGXnffjCybUCEx3FQ2G7U3/o9eIkVQ==", 102 | "dev": true, 103 | "engines": { 104 | "node": ">= 0.4.0" 105 | } 106 | }, 107 | "node_modules/debug": { 108 | "version": "3.2.7", 109 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", 110 | "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", 111 | "dev": true, 112 | "dependencies": { 113 | "ms": "^2.1.1" 114 | } 115 | }, 116 | "node_modules/eventemitter3": { 117 | "version": "4.0.7", 118 | "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", 119 | "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", 120 | "dev": true 121 | }, 122 | "node_modules/follow-redirects": { 123 | "version": "1.15.2", 124 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", 125 | "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", 126 | "dev": true, 127 | "funding": [ 128 | { 129 | "type": "individual", 130 | "url": "https://github.com/sponsors/RubenVerborgh" 131 | } 132 | ], 133 | "engines": { 134 | "node": ">=4.0" 135 | }, 136 | "peerDependenciesMeta": { 137 | "debug": { 138 | "optional": true 139 | } 140 | } 141 | }, 142 | "node_modules/function-bind": { 143 | "version": "1.1.1", 144 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 145 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 146 | "dev": true 147 | }, 148 | "node_modules/get-intrinsic": { 149 | "version": "1.1.3", 150 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", 151 | "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", 152 | "dev": true, 153 | "dependencies": { 154 | "function-bind": "^1.1.1", 155 | "has": "^1.0.3", 156 | "has-symbols": "^1.0.3" 157 | }, 158 | "funding": { 159 | "url": "https://github.com/sponsors/ljharb" 160 | } 161 | }, 162 | "node_modules/has": { 163 | "version": "1.0.3", 164 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 165 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 166 | "dev": true, 167 | "dependencies": { 168 | "function-bind": "^1.1.1" 169 | }, 170 | "engines": { 171 | "node": ">= 0.4.0" 172 | } 173 | }, 174 | "node_modules/has-flag": { 175 | "version": "4.0.0", 176 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 177 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 178 | "dev": true, 179 | "engines": { 180 | "node": ">=8" 181 | } 182 | }, 183 | "node_modules/has-symbols": { 184 | "version": "1.0.3", 185 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 186 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 187 | "dev": true, 188 | "engines": { 189 | "node": ">= 0.4" 190 | }, 191 | "funding": { 192 | "url": "https://github.com/sponsors/ljharb" 193 | } 194 | }, 195 | "node_modules/he": { 196 | "version": "1.2.0", 197 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", 198 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", 199 | "dev": true, 200 | "bin": { 201 | "he": "bin/he" 202 | } 203 | }, 204 | "node_modules/html-encoding-sniffer": { 205 | "version": "3.0.0", 206 | "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", 207 | "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", 208 | "dev": true, 209 | "dependencies": { 210 | "whatwg-encoding": "^2.0.0" 211 | }, 212 | "engines": { 213 | "node": ">=12" 214 | } 215 | }, 216 | "node_modules/http-proxy": { 217 | "version": "1.18.1", 218 | "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", 219 | "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", 220 | "dev": true, 221 | "dependencies": { 222 | "eventemitter3": "^4.0.0", 223 | "follow-redirects": "^1.0.0", 224 | "requires-port": "^1.0.0" 225 | }, 226 | "engines": { 227 | "node": ">=8.0.0" 228 | } 229 | }, 230 | "node_modules/http-server": { 231 | "version": "14.1.1", 232 | "resolved": "https://registry.npmjs.org/http-server/-/http-server-14.1.1.tgz", 233 | "integrity": "sha512-+cbxadF40UXd9T01zUHgA+rlo2Bg1Srer4+B4NwIHdaGxAGGv59nYRnGGDJ9LBk7alpS0US+J+bLLdQOOkJq4A==", 234 | "dev": true, 235 | "dependencies": { 236 | "basic-auth": "^2.0.1", 237 | "chalk": "^4.1.2", 238 | "corser": "^2.0.1", 239 | "he": "^1.2.0", 240 | "html-encoding-sniffer": "^3.0.0", 241 | "http-proxy": "^1.18.1", 242 | "mime": "^1.6.0", 243 | "minimist": "^1.2.6", 244 | "opener": "^1.5.1", 245 | "portfinder": "^1.0.28", 246 | "secure-compare": "3.0.1", 247 | "union": "~0.5.0", 248 | "url-join": "^4.0.1" 249 | }, 250 | "bin": { 251 | "http-server": "bin/http-server" 252 | }, 253 | "engines": { 254 | "node": ">=12" 255 | } 256 | }, 257 | "node_modules/iconv-lite": { 258 | "version": "0.6.3", 259 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", 260 | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", 261 | "dev": true, 262 | "dependencies": { 263 | "safer-buffer": ">= 2.1.2 < 3.0.0" 264 | }, 265 | "engines": { 266 | "node": ">=0.10.0" 267 | } 268 | }, 269 | "node_modules/lodash": { 270 | "version": "4.17.21", 271 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 272 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", 273 | "dev": true 274 | }, 275 | "node_modules/mime": { 276 | "version": "1.6.0", 277 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 278 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 279 | "dev": true, 280 | "bin": { 281 | "mime": "cli.js" 282 | }, 283 | "engines": { 284 | "node": ">=4" 285 | } 286 | }, 287 | "node_modules/minimist": { 288 | "version": "1.2.7", 289 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", 290 | "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", 291 | "dev": true, 292 | "funding": { 293 | "url": "https://github.com/sponsors/ljharb" 294 | } 295 | }, 296 | "node_modules/mkdirp": { 297 | "version": "0.5.6", 298 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 299 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 300 | "dev": true, 301 | "dependencies": { 302 | "minimist": "^1.2.6" 303 | }, 304 | "bin": { 305 | "mkdirp": "bin/cmd.js" 306 | } 307 | }, 308 | "node_modules/ms": { 309 | "version": "2.1.3", 310 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 311 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 312 | "dev": true 313 | }, 314 | "node_modules/object-inspect": { 315 | "version": "1.12.2", 316 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", 317 | "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", 318 | "dev": true, 319 | "funding": { 320 | "url": "https://github.com/sponsors/ljharb" 321 | } 322 | }, 323 | "node_modules/opener": { 324 | "version": "1.5.2", 325 | "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", 326 | "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", 327 | "dev": true, 328 | "bin": { 329 | "opener": "bin/opener-bin.js" 330 | } 331 | }, 332 | "node_modules/portfinder": { 333 | "version": "1.0.32", 334 | "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", 335 | "integrity": "sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg==", 336 | "dev": true, 337 | "dependencies": { 338 | "async": "^2.6.4", 339 | "debug": "^3.2.7", 340 | "mkdirp": "^0.5.6" 341 | }, 342 | "engines": { 343 | "node": ">= 0.12.0" 344 | } 345 | }, 346 | "node_modules/qs": { 347 | "version": "6.11.0", 348 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 349 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 350 | "dev": true, 351 | "dependencies": { 352 | "side-channel": "^1.0.4" 353 | }, 354 | "engines": { 355 | "node": ">=0.6" 356 | }, 357 | "funding": { 358 | "url": "https://github.com/sponsors/ljharb" 359 | } 360 | }, 361 | "node_modules/requires-port": { 362 | "version": "1.0.0", 363 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 364 | "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", 365 | "dev": true 366 | }, 367 | "node_modules/safe-buffer": { 368 | "version": "5.1.2", 369 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 370 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 371 | "dev": true 372 | }, 373 | "node_modules/safer-buffer": { 374 | "version": "2.1.2", 375 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 376 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 377 | "dev": true 378 | }, 379 | "node_modules/secure-compare": { 380 | "version": "3.0.1", 381 | "resolved": "https://registry.npmjs.org/secure-compare/-/secure-compare-3.0.1.tgz", 382 | "integrity": "sha512-AckIIV90rPDcBcglUwXPF3kg0P0qmPsPXAj6BBEENQE1p5yA1xfmDJzfi1Tappj37Pv2mVbKpL3Z1T+Nn7k1Qw==", 383 | "dev": true 384 | }, 385 | "node_modules/side-channel": { 386 | "version": "1.0.4", 387 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 388 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 389 | "dev": true, 390 | "dependencies": { 391 | "call-bind": "^1.0.0", 392 | "get-intrinsic": "^1.0.2", 393 | "object-inspect": "^1.9.0" 394 | }, 395 | "funding": { 396 | "url": "https://github.com/sponsors/ljharb" 397 | } 398 | }, 399 | "node_modules/supports-color": { 400 | "version": "7.2.0", 401 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 402 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 403 | "dev": true, 404 | "dependencies": { 405 | "has-flag": "^4.0.0" 406 | }, 407 | "engines": { 408 | "node": ">=8" 409 | } 410 | }, 411 | "node_modules/union": { 412 | "version": "0.5.0", 413 | "resolved": "https://registry.npmjs.org/union/-/union-0.5.0.tgz", 414 | "integrity": "sha512-N6uOhuW6zO95P3Mel2I2zMsbsanvvtgn6jVqJv4vbVcz/JN0OkL9suomjQGmWtxJQXOCqUJvquc1sMeNz/IwlA==", 415 | "dev": true, 416 | "dependencies": { 417 | "qs": "^6.4.0" 418 | }, 419 | "engines": { 420 | "node": ">= 0.8.0" 421 | } 422 | }, 423 | "node_modules/url-join": { 424 | "version": "4.0.1", 425 | "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz", 426 | "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", 427 | "dev": true 428 | }, 429 | "node_modules/whatwg-encoding": { 430 | "version": "2.0.0", 431 | "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", 432 | "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", 433 | "dev": true, 434 | "dependencies": { 435 | "iconv-lite": "0.6.3" 436 | }, 437 | "engines": { 438 | "node": ">=12" 439 | } 440 | } 441 | } 442 | } 443 | -------------------------------------------------------------------------------- /recorded/app/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "npx http-server .", 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "http-server": "^14.1.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /recorded/server/index-bug-resolvido.js: -------------------------------------------------------------------------------- 1 | import { createServer } from 'node:http' 2 | import { createReadStream } from 'node:fs' 3 | import { Readable, Transform } from 'node:stream' 4 | import { WritableStream, TransformStream } from 'node:stream/web' 5 | import { setTimeout } from 'node:timers/promises' 6 | 7 | import csvtojson from 'csvtojson' 8 | const PORT = 3000 9 | // curl -i -X OPTIONS -N localhost:3000 10 | // curl -N localhost:3000 11 | createServer(async (request, response) => { 12 | const headers = { 13 | 'Access-Control-Allow-Origin': '*', 14 | 'Access-Control-Allow-Methods': '*', 15 | } 16 | 17 | if (request.method === 'OPTIONS') { 18 | response.writeHead(204, headers) 19 | response.end() 20 | return 21 | } 22 | let items = 0 23 | const abortController = new AbortController() 24 | request.once('close', _ => { 25 | console.log(`connection was closed!`, items) 26 | abortController.abort() 27 | }) 28 | try { 29 | response.writeHead(200, headers) 30 | 31 | await Readable.toWeb(createReadStream('./animeflv.csv')) 32 | // o passo a passo que cada item individual vai trafegar 33 | .pipeThrough(Transform.toWeb(csvtojson())) 34 | .pipeThrough(new TransformStream({ 35 | transform(chunk, controller) { 36 | const data = JSON.parse(Buffer.from(chunk)) 37 | const mappedData = { 38 | title: data.title, 39 | description: data.description, 40 | url_anime: data.url_anime 41 | } 42 | // quebra de linha pois é um NDJSON 43 | controller.enqueue(JSON.stringify(mappedData).concat('\n')) 44 | } 45 | })) 46 | // pipeTo é a ultima etapa 47 | .pipeTo(new WritableStream({ 48 | async write(chunk) { 49 | await setTimeout(200) 50 | items++ 51 | response.write(chunk) 52 | }, 53 | close() { 54 | response.end() 55 | } 56 | 57 | }), { 58 | signal: abortController.signal 59 | }) 60 | 61 | } catch (error) { 62 | if (!error.message.includes('abort')) throw error 63 | } 64 | 65 | }) 66 | .listen(PORT) 67 | .on('listening', _ => console.log(`server is running at ${PORT}`)) -------------------------------------------------------------------------------- /recorded/server/index.js: -------------------------------------------------------------------------------- 1 | import { createServer } from 'node:http' 2 | import { createReadStream } from 'node:fs' 3 | import { Readable, Transform } from 'node:stream' 4 | import { WritableStream, TransformStream } from 'node:stream/web' 5 | import { setTimeout } from 'node:timers/promises' 6 | 7 | import csvtojson from 'csvtojson' 8 | const PORT = 3000 9 | // curl -i -X OPTIONS -N localhost:3000 10 | // curl -N localhost:3000 11 | createServer(async (request, response) => { 12 | const headers = { 13 | 'Access-Control-Allow-Origin': '*', 14 | 'Access-Control-Allow-Methods': '*', 15 | } 16 | 17 | if (request.method === 'OPTIONS') { 18 | response.writeHead(204, headers) 19 | response.end() 20 | return 21 | } 22 | let items = 0 23 | request.once('close', _ => console.log(`connection was closed!`, items)) 24 | Readable.toWeb(createReadStream('./animeflv.csv')) 25 | // o passo a passo que cada item individual vai trafegar 26 | .pipeThrough(Transform.toWeb(csvtojson())) 27 | .pipeThrough(new TransformStream({ 28 | transform(chunk, controller) { 29 | const data = JSON.parse(Buffer.from(chunk)) 30 | const mappedData = { 31 | title: data.title, 32 | description: data.description, 33 | url_anime: data.url_anime 34 | } 35 | // quebra de linha pois é um NDJSON 36 | controller.enqueue(JSON.stringify(mappedData).concat('\n')) 37 | } 38 | })) 39 | // pipeTo é a ultima etapa 40 | .pipeTo(new WritableStream({ 41 | async write(chunk) { 42 | // await setTimeout(200) 43 | items++ 44 | response.write(chunk) 45 | }, 46 | close() { 47 | response.end() 48 | } 49 | 50 | })) 51 | 52 | response.writeHead(200, headers) 53 | }) 54 | .listen(PORT) 55 | .on('listening', _ => console.log(`server is running at ${PORT}`)) -------------------------------------------------------------------------------- /recorded/server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "0.0.1", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "server", 9 | "version": "0.0.1", 10 | "license": "ISC", 11 | "dependencies": { 12 | "csvtojson": "^2.0.10" 13 | } 14 | }, 15 | "node_modules/bluebird": { 16 | "version": "3.7.2", 17 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", 18 | "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" 19 | }, 20 | "node_modules/csvtojson": { 21 | "version": "2.0.10", 22 | "resolved": "https://registry.npmjs.org/csvtojson/-/csvtojson-2.0.10.tgz", 23 | "integrity": "sha512-lUWFxGKyhraKCW8Qghz6Z0f2l/PqB1W3AO0HKJzGIQ5JRSlR651ekJDiGJbBT4sRNNv5ddnSGVEnsxP9XRCVpQ==", 24 | "dependencies": { 25 | "bluebird": "^3.5.1", 26 | "lodash": "^4.17.3", 27 | "strip-bom": "^2.0.0" 28 | }, 29 | "bin": { 30 | "csvtojson": "bin/csvtojson" 31 | }, 32 | "engines": { 33 | "node": ">=4.0.0" 34 | } 35 | }, 36 | "node_modules/is-utf8": { 37 | "version": "0.2.1", 38 | "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", 39 | "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==" 40 | }, 41 | "node_modules/lodash": { 42 | "version": "4.17.21", 43 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 44 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 45 | }, 46 | "node_modules/strip-bom": { 47 | "version": "2.0.0", 48 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", 49 | "integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==", 50 | "dependencies": { 51 | "is-utf8": "^0.2.0" 52 | }, 53 | "engines": { 54 | "node": ">=0.10.0" 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /recorded/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "0.0.1", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "dev": "node --watch index-bug-resolvido.js", 9 | "test": "echo \"Error: no test specified\" && exit 1" 10 | }, 11 | "keywords": [], 12 | "author": "", 13 | "license": "ISC", 14 | "dependencies": { 15 | "csvtojson": "^2.0.10" 16 | } 17 | } 18 | --------------------------------------------------------------------------------