@@ -197,28 +197,27 @@ <h2>getLine</h2>
197
197
198
198
function getLine ( opt ) {
199
199
let { error, stackLine = 2 } = opt || { } ;
200
-
200
+
201
201
if ( ! Number . isInteger ( stackLine ) ) {
202
202
throw new Error ( `getLine: stackLine must be an integer` ) ;
203
203
}
204
-
204
+
205
205
// Create an Error object to capture the stack trace
206
206
if ( ! error ) {
207
207
error = new Error ( ) ;
208
208
}
209
-
209
+
210
210
// Parse the stack trace to extract the line number
211
211
const stackLines = error . stack . split ( "\n" ) ;
212
-
212
+
213
213
// Get the caller's stack frame (index 2 skips this function and its immediate caller)
214
214
const callerFrame = stackLines [ stackLine ] ;
215
-
215
+
216
216
// Extract the line number using regex
217
217
const lineMatch = callerFrame . match ( / : ( \d + ) : \d + \) ? $ / ) ;
218
-
218
+
219
219
return lineMatch ? parseInt ( lineMatch [ 1 ] , 10 ) : - 1 ;
220
220
}
221
-
222
221
</ script >
223
222
< h2 > useful</ h2 >
224
223
< script type ="editor " data-lang ="sh ">
@@ -1401,64 +1400,234 @@ <h2>nodemon & chokidar</h2>
1401
1400
< br />
1402
1401
< a href ="https://stackoverflow.com/a/13807906 "> about fswatch</ a >
1403
1402
< h2 > streams</ h2 >
1404
- < script type ="editor " data-lang ="js ">
1405
1403
1406
- // https://github.com/substack/stream-handbook
1407
- // from: https://github.com/nkzawa/socket.io-stream
1404
+ < div data-vanilla-tabs >
1405
+ < div data-buttons >
1406
+ < span class ="active "> stream</ span >
1407
+ < span > pipeline</ span >
1408
+ < span > Transform</ span >
1409
+ < span > response to file</ span >
1410
+ < span > Transform Streams</ span >
1411
+ < span > stream to response</ span >
1412
+ </ div >
1413
+ < div data-tabs >
1414
+ < div >
1415
+ < script type ="editor " data-lang ="js ">
1416
+
1417
+ // https://github.com/substack/stream-handbook
1418
+ // from: https://github.com/nkzawa/socket.io-stream
1408
1419
1409
- // https://nodesource.com/blog/understanding-streams-in-nodejs/
1420
+ // https://nodesource.com/blog/understanding-streams-in-nodejs/
1410
1421
1411
1422
1412
- // https://www.freecodecamp.org/news/node-js-streams-everything-you-need-to-know-c9141306be93/
1413
- // Create big file using stream
1414
- const fs = require ( 'fs' ) ;
1415
- const file = fs . createWriteStream ( './big.file' ) ;
1423
+ // https://www.freecodecamp.org/news/node-js-streams-everything-you-need-to-know-c9141306be93/
1424
+ // Create big file using stream
1425
+ const fs = require ( 'fs' ) ;
1426
+ const file = fs . createWriteStream ( './big.file' ) ;
1416
1427
1417
- for ( let i = 0 ; i <= 1e6 ; i ++ ) {
1418
- file . write ( 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n' ) ;
1419
- }
1428
+ for ( let i = 0 ; i <= 1e6 ; i ++ ) {
1429
+ file . write ( 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n' ) ;
1430
+ }
1420
1431
1421
- file . end ( ) ;
1432
+ file . end ( ) ;
1422
1433
1423
1434
1424
1435
1425
- # https://www.freecodecamp.org/news/node-js-streams-everything-you-need-to-know-c9141306be93/
1426
- # more: https://jscomplete.com/learn/node-beyond-basics/node-streams g(node beyond basics)
1436
+ # https://www.freecodecamp.org/news/node-js-streams-everything-you-need-to-know-c9141306be93/
1437
+ # more: https://jscomplete.com/learn/node-beyond-basics/node-streams g(node beyond basics)
1427
1438
1428
- # https://www.sitepoint.com/basics-node-js-streams/
1429
- # http://2ality.com/2018/04/async-iter-nodejs.html
1430
- # http://2ality.com/2018/05/child-process-streams.html
1439
+ # https://www.sitepoint.com/basics-node-js-streams/
1440
+ # http://2ality.com/2018/04/async-iter-nodejs.html
1441
+ # http://2ality.com/2018/05/child-process-streams.html
1431
1442
1432
- # read file to http response:
1433
- const stream = fs . createReadStream ( file ) ;
1434
- stream . pipe ( res ) ;
1443
+ # read file to http response:
1444
+ const stream = fs . createReadStream ( file ) ;
1445
+ stream . pipe ( res ) ;
1435
1446
1436
- # write http response to file:
1437
- const stream = fs . createWriteStream ( file ) ;
1438
- res . pipe ( stream ) ;
1447
+ # write http response to file:
1448
+ const stream = fs . createWriteStream ( file ) ;
1449
+ res . pipe ( stream ) ;
1439
1450
1440
- readableStream . pipe ( writableStream ) ;
1451
+ readableStream . pipe ( writableStream ) ;
1441
1452
1442
- # pipe stream error handling
1443
- await new Promise ( ( resolve , reject ) => {
1453
+ # pipe stream error handling
1454
+ await new Promise ( ( resolve , reject ) => {
1444
1455
1445
- var stream = res . pipe ( fs . createWriteStream ( file ) ) ;
1456
+ var stream = res . pipe ( fs . createWriteStream ( file ) ) ;
1446
1457
1447
- stream . on ( 'finish' , ( ) => resolve ( ) ) ;
1458
+ stream . on ( 'finish' , ( ) => resolve ( ) ) ;
1448
1459
1449
- stream . on ( 'error' , e => reject ( {
1450
- writable_stream_error : e
1451
- } ) ) ;
1452
- } ) ;
1460
+ stream . on ( 'error' , e => reject ( {
1461
+ writable_stream_error : e
1462
+ } ) ) ;
1463
+ } ) ;
1453
1464
1454
- # unzip
1455
- var fs = require ( 'fs' ) ;
1456
- var zlib = require ( 'zlib' ) ;
1465
+ # unzip
1466
+ var fs = require ( 'fs' ) ;
1467
+ var zlib = require ( 'zlib' ) ;
1468
+
1469
+ fs . createReadStream ( 'input.txt.gz' )
1470
+ . pipe ( zlib . createGunzip ( ) )
1471
+ . pipe ( fs . createWriteStream ( 'output.txt' ) ) ;
1472
+ </ script >
1473
+ </ div >
1474
+ < div >
1475
+ < script type ="editor " data-lang ="ts ">
1476
+
1477
+ // from: https://www.sitepoint.com/node-js-streams-with-typescript/#h-example-4-compressing-files-with-a-duplex-stream
1478
+
1479
+ import { createReadStream , createWriteStream } from 'fs' ;
1480
+ import { createGzip } from 'zlib' ;
1481
+ import { pipeline } from 'stream' ;
1482
+
1483
+ const source = createReadStream ( 'data.txt' ) ;
1484
+ const destination = createWriteStream ( 'data.txt.gz' ) ;
1485
+ const gzip = createGzip ( ) ;
1486
+
1487
+ pipeline ( source , gzip , destination , ( err : Error | null ) => {
1488
+ if ( err ) {
1489
+ console . error ( 'Compression failed:' , err . message ) ;
1490
+ return ;
1491
+ }
1492
+ console . log ( 'File compressed successfully! Check data.txt.gz' ) ;
1493
+ } ) ;
1494
+ </ script >
1495
+ </ div >
1496
+ < div >
1497
+ < script type ="editor " data-lang ="ts ">
1498
+
1499
+ // from: https://www.sitepoint.com/node-js-streams-with-typescript/#h-example-3-piping-with-a-transform-stream
1500
+
1501
+ import { createReadStream , createWriteStream } from 'fs' ;
1502
+ import { Transform , TransformCallback } from 'stream' ;
1503
+
1504
+ // Custom Transform stream to uppercase text
1505
+ class UppercaseTransform extends Transform {
1506
+ _transform ( chunk : Buffer , encoding : string , callback : TransformCallback ) : void {
1507
+ const upperChunk = chunk . toString ( ) . toUpperCase ( ) ;
1508
+ this . push ( upperChunk ) ;
1509
+ callback ( ) ;
1510
+ }
1511
+ }
1512
+
1513
+ const readStream = createReadStream ( 'data.txt' , { encoding : 'utf8' } ) ;
1514
+ const writeStream = createWriteStream ( 'output_upper.txt' ) ;
1515
+ const transformStream = new UppercaseTransform ( ) ;
1516
+
1517
+ readStream
1518
+ . pipe ( transformStream )
1519
+ . pipe ( writeStream )
1520
+ . on ( 'finish' , ( ) => {
1521
+ console . log ( 'Transform complete! Check output_upper.txt' ) ;
1522
+ } )
1523
+ . on ( 'error' , ( err : Error ) => {
1524
+ console . error ( 'Error:' , err . message ) ;
1525
+ } ) ;
1526
+ </ script >
1527
+ </ div >
1528
+
1529
+ < div >
1530
+ < script type ="editor " data-lang ="ts ">
1531
+
1532
+ // from: https://www.sitepoint.com/node-js-streams-with-typescript/#h-example-5-streaming-http-responses
1533
+
1534
+ import axios from 'axios' ;
1535
+ import { createWriteStream } from 'fs' ;
1536
+ import { Writable } from 'stream' ;
1537
+
1538
+ async function streamHttpResponse ( url : string , outputFile : string ) : Promise < void > {
1539
+ const response = await axios ( {
1540
+ method : 'get' ,
1541
+ url,
1542
+ responseType : 'stream' ,
1543
+ } ) ;
1544
+
1545
+ const writeStream : Writable = createWriteStream ( outputFile ) ;
1546
+ response . data . pipe ( writeStream ) ;
1547
+
1548
+ return new Promise ( ( resolve , reject ) => {
1549
+ writeStream . on ( 'finish' , ( ) => {
1550
+ console . log ( `Downloaded to ${ outputFile } ` ) ;
1551
+ resolve ( ) ;
1552
+ } ) ;
1553
+ writeStream . on ( 'error' , ( err : Error ) => {
1554
+ console . error ( 'Download failed:' , err . message ) ;
1555
+ reject ( err ) ;
1556
+ } ) ;
1557
+ } ) ;
1558
+ }
1559
+
1560
+ streamHttpResponse ( 'https://example.com' , 'example.html' ) . catch ( console . error ) ;
1561
+ </ script >
1562
+ </ div >
1563
+
1564
+ < div >
1565
+ < script type ="editor " data-lang ="ts ">
1566
+
1567
+ // from: https://www.sitepoint.com/node-js-streams-with-typescript/#h-example-6-real-time-data-processing-with-a-custom-readable-stream
1568
+
1569
+ import { createReadStream , createWriteStream } from 'fs' ;
1570
+ import { Transform , TransformCallback } from 'stream' ;
1571
+
1572
+ class UppercaseTransform extends Transform {
1573
+ _transform ( chunk : Buffer , encoding : string , callback : TransformCallback ) : void {
1574
+ this . push ( chunk . toString ( ) . toUpperCase ( ) ) ;
1575
+ callback ( ) ;
1576
+ }
1577
+ }
1578
+
1579
+ class TimestampTransform extends Transform {
1580
+ _transform ( chunk : Buffer , encoding : string , callback : TransformCallback ) : void {
1581
+ const timestamp = new Date ( ) . toISOString ( ) ;
1582
+ this . push ( `[${ timestamp } ] ${ chunk . toString ( ) } ` ) ;
1583
+ callback ( ) ;
1584
+ }
1585
+ }
1586
+
1587
+ const readStream = createReadStream ( 'data.txt' , { encoding : 'utf8' } ) ;
1588
+ const writeStream = createWriteStream ( 'output_chain.txt' ) ;
1589
+ const upper = new UppercaseTransform ( ) ;
1590
+ const timestamp = new TimestampTransform ( ) ;
1591
+
1592
+ readStream
1593
+ . pipe ( upper )
1594
+ . pipe ( timestamp )
1595
+ . pipe ( writeStream )
1596
+ . on ( 'finish' , ( ) => {
1597
+ console . log ( 'Chained transform complete! Check output_chain.txt' ) ;
1598
+ } )
1599
+ . on ( 'error' , ( err : Error ) => {
1600
+ console . error ( 'Error:' , err . message ) ;
1601
+ } ) ;
1602
+ </ script >
1603
+ </ div >
1604
+
1605
+ < div >
1606
+ < script type ="editor " data-lang ="ts ">
1607
+
1608
+ // from: https://www.sitepoint.com/node-js-streams-with-typescript/#h-real-world-use-case-streaming-api-responses
1609
+
1610
+ import express from 'express' ;
1611
+ import { Readable } from 'stream' ;
1612
+
1613
+ const app = express ( ) ;
1614
+
1615
+ app . get ( '/stream-data' , ( req , res ) => {
1616
+ const data = [ 'Item 1\n' , 'Item 2\n' , 'Item 3\n' ] ;
1617
+ const stream = Readable . from ( data ) ;
1618
+
1619
+ res . setHeader ( 'Content-Type' , 'text/plain' ) ;
1620
+ stream . pipe ( res ) ;
1621
+ } ) ;
1622
+
1623
+ app . listen ( 3000 , ( ) => {
1624
+ console . log ( 'Server running on port 3000' ) ;
1625
+ } ) ;
1626
+ </ script >
1627
+ </ div >
1628
+ </ div >
1629
+ </ div >
1457
1630
1458
- fs . createReadStream ( 'input.txt.gz' )
1459
- . pipe ( zlib . createGunzip ( ) )
1460
- . pipe ( fs . createWriteStream ( 'output.txt' ) ) ;
1461
- </ script >
1462
1631
< h2 > Signleton (kinda) module template</ h2 >
1463
1632
< script type ="editor " data-lang ="js ">
1464
1633
0 commit comments