ニジカ投稿局 https://tv.nizika.tv
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

59 lines
1.6 KiB

  1. import { Transform, TransformCallback } from 'stream'
  2. // Thanks: https://stackoverflow.com/a/45126242
  3. class StreamReplacer extends Transform {
  4. private pendingChunk: Buffer
  5. constructor (private readonly replacer: (line: string) => string) {
  6. super()
  7. }
  8. _transform (chunk: Buffer, _encoding: BufferEncoding, done: TransformCallback) {
  9. try {
  10. this.pendingChunk = this.pendingChunk?.length
  11. ? Buffer.concat([ this.pendingChunk, chunk ])
  12. : chunk
  13. let index: number
  14. // As long as we keep finding newlines, keep making slices of the buffer and push them to the
  15. // readable side of the transform stream
  16. while ((index = this.pendingChunk.indexOf('\n')) !== -1) {
  17. // The `end` parameter is non-inclusive, so increase it to include the newline we found
  18. const line = this.pendingChunk.slice(0, ++index)
  19. // `start` is inclusive, but we are already one char ahead of the newline -> all good
  20. this.pendingChunk = this.pendingChunk.slice(index)
  21. // We have a single line here! Prepend the string we want
  22. this.push(this.doReplace(line))
  23. }
  24. return done()
  25. } catch (err) {
  26. return done(err)
  27. }
  28. }
  29. _flush (done: TransformCallback) {
  30. // If we have any remaining data in the cache, send it out
  31. if (!this.pendingChunk?.length) return done()
  32. try {
  33. return done(null, this.doReplace(this.pendingChunk))
  34. } catch (err) {
  35. return done(err)
  36. }
  37. }
  38. private doReplace (buffer: Buffer) {
  39. const line = this.replacer(buffer.toString('utf8'))
  40. return Buffer.from(line, 'utf8')
  41. }
  42. }
  43. export {
  44. StreamReplacer
  45. }