• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

cameri / nostream / 24610041211

18 Apr 2026 05:30PM UTC coverage: 63.346% (+0.5%) from 62.807%
24610041211

Pull #498

github

web-flow
Merge 90e995e5b into 26bcdd51d
Pull Request #498: Implement caching for user admission check

827 of 1385 branches covered (59.71%)

Branch coverage included in aggregate %.

374 of 647 new or added lines in 82 files covered. (57.81%)

19 existing lines in 10 files now uncovered.

2123 of 3272 relevant lines covered (64.88%)

10.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/scripts/export-events.ts
1
import 'pg-query-stream'
×
2
import dotenv from 'dotenv'
×
3
dotenv.config()
×
4

5
import fs from 'fs'
×
6
import path from 'path'
×
7
import { pipeline } from 'stream/promises'
×
8
import { Transform } from 'stream'
×
9

10
import { getMasterDbClient } from '../database/client'
×
11

12
type EventRow = {
13
  event_id: Buffer
14
  event_pubkey: Buffer
15
  event_kind: number
16
  event_created_at: number
17
  event_content: string
18
  event_tags: unknown[] | null
19
  event_signature: Buffer
20
}
21

22
async function exportEvents(): Promise<void> {
23
  const filename = process.argv[2] || 'events.jsonl'
×
24
  const outputPath = path.resolve(filename)
×
25
  const db = getMasterDbClient()
×
26
  const abortController = new AbortController()
×
27
  let interruptedBySignal: NodeJS.Signals | undefined
28

29
  const onSignal = (signal: NodeJS.Signals) => {
×
30
    if (abortController.signal.aborted) {
×
31
      return
×
32
    }
33

34
    interruptedBySignal = signal
×
35
    process.exitCode = 130
×
36
    console.log(`${signal} received. Stopping export...`)
×
37
    abortController.abort()
×
38
  }
39

NEW
40
  process.on('SIGINT', onSignal).on('SIGTERM', onSignal)
×
41

42
  try {
×
NEW
43
    const firstEvent = await db('events').select('event_id').whereNull('deleted_at').first()
×
44

45
    if (abortController.signal.aborted) {
×
46
      return
×
47
    }
48

49
    if (!firstEvent) {
×
50
      console.log('No events to export.')
×
51
      return
×
52
    }
53

54
    console.log(`Exporting events to ${outputPath}`)
×
55

56
    const output = fs.createWriteStream(outputPath)
×
57
    let exported = 0
×
58

59
    const dbStream = db('events')
×
60
      .select(
61
        'event_id',
62
        'event_pubkey',
63
        'event_kind',
64
        'event_created_at',
65
        'event_content',
66
        'event_tags',
67
        'event_signature',
68
      )
69
      .whereNull('deleted_at')
70
      .orderBy('event_created_at', 'asc')
71
      .orderBy('event_id', 'asc')
72
      .stream()
73

74
    const toJsonLine = new Transform({
×
75
      objectMode: true,
76
      transform(row: EventRow, _encoding, callback) {
77
        const event = {
×
78
          id: row.event_id.toString('hex'),
79
          pubkey: row.event_pubkey.toString('hex'),
80
          created_at: row.event_created_at,
81
          kind: row.event_kind,
82
          tags: Array.isArray(row.event_tags) ? row.event_tags : [],
×
83
          content: row.event_content,
84
          sig: row.event_signature.toString('hex'),
85
        }
86

87
        exported++
×
88
        if (exported % 10000 === 0) {
×
89
          console.log(`Exported ${exported} events...`)
×
90
        }
91

92
        callback(null, JSON.stringify(event) + '\n')
×
93
      },
94
    })
95

96
    await pipeline(dbStream, toJsonLine, output, {
×
97
      signal: abortController.signal,
98
    })
99

100
    console.log(`Export complete: ${exported} events written to ${outputPath}`)
×
101
  } catch (error) {
102
    if (abortController.signal.aborted) {
×
103
      console.log(`Export interrupted by ${interruptedBySignal ?? 'signal'}.`)
×
104
      process.exitCode = 130
×
105
      return
×
106
    }
107

108
    throw error
×
109
  } finally {
NEW
110
    process.off('SIGINT', onSignal).off('SIGTERM', onSignal)
×
111

112
    await db.destroy()
×
113
  }
114
}
115

116
exportEvents().catch((error) => {
×
117
  console.error('Export failed:', error.message)
×
118
  process.exit(1)
×
119
})
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc