@ecosyste-ms/critical 1.0.20260328 → 1.1.20260514
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin.js +2 -2
- package/critical-packages.db.gz +0 -0
- package/lib/index.js +52 -27
- package/package.json +2 -5
package/bin.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { build, databasePath } from './lib/index.js'
|
|
3
|
-
import
|
|
3
|
+
import { DatabaseSync } from 'node:sqlite'
|
|
4
4
|
import { existsSync } from 'fs'
|
|
5
5
|
|
|
6
6
|
const args = process.argv.slice(2)
|
|
@@ -40,7 +40,7 @@ if (args.includes('--stats')) {
|
|
|
40
40
|
console.error(`Database not found: ${path}`)
|
|
41
41
|
process.exit(1)
|
|
42
42
|
}
|
|
43
|
-
const db = new
|
|
43
|
+
const db = new DatabaseSync(path, { readOnly: true })
|
|
44
44
|
const info = db.prepare('SELECT * FROM build_info WHERE id = 1').get()
|
|
45
45
|
const packageCount = db.prepare('SELECT COUNT(*) as count FROM packages').get().count
|
|
46
46
|
const versionCount = db.prepare('SELECT COUNT(*) as count FROM versions').get().count
|
package/critical-packages.db.gz
CHANGED
|
Binary file
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { DatabaseSync } from 'node:sqlite'
|
|
2
2
|
import { createReadStream, createWriteStream, existsSync } from 'fs'
|
|
3
3
|
import { mkdir, unlink, readFile } from 'fs/promises'
|
|
4
4
|
import { dirname, join } from 'path'
|
|
@@ -21,22 +21,39 @@ if (!existsSync(databasePath) && existsSync(gzPath)) {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
const API_BASE = 'https://packages.ecosyste.ms/api/v1'
|
|
24
|
-
const PER_PAGE =
|
|
24
|
+
const PER_PAGE = 100
|
|
25
25
|
const RATE_LIMIT_MS = 50
|
|
26
26
|
const CONCURRENCY = 10
|
|
27
|
+
const MAX_RETRIES = 5
|
|
28
|
+
const RETRY_BASE_MS = 1000
|
|
27
29
|
|
|
28
30
|
function sleep(ms) {
|
|
29
31
|
return new Promise(resolve => setTimeout(resolve, ms))
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
async function fetchJson(url) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
let lastErr
|
|
36
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
37
|
+
try {
|
|
38
|
+
const response = await fetch(url, {
|
|
39
|
+
headers: { 'User-Agent': USER_AGENT }
|
|
40
|
+
})
|
|
41
|
+
if (response.ok) return response.json()
|
|
42
|
+
// 4xx is a client error — don't retry. 5xx is server-side; retry.
|
|
43
|
+
if (response.status < 500) {
|
|
44
|
+
throw new Error(`HTTP ${response.status}: ${url}`)
|
|
45
|
+
}
|
|
46
|
+
lastErr = new Error(`HTTP ${response.status}: ${url}`)
|
|
47
|
+
} catch (err) {
|
|
48
|
+
// Network errors (fetch throws TypeError) are retryable.
|
|
49
|
+
if (err.message?.startsWith('HTTP ') && !err.message.match(/HTTP 5\d\d/)) throw err
|
|
50
|
+
lastErr = err
|
|
51
|
+
}
|
|
52
|
+
if (attempt < MAX_RETRIES) {
|
|
53
|
+
await sleep(RETRY_BASE_MS * Math.pow(2, attempt))
|
|
54
|
+
}
|
|
38
55
|
}
|
|
39
|
-
|
|
56
|
+
throw lastErr
|
|
40
57
|
}
|
|
41
58
|
|
|
42
59
|
async function fetchAllCriticalPackages(onProgress) {
|
|
@@ -96,8 +113,8 @@ function ecosystemToRegistry(ecosystem) {
|
|
|
96
113
|
}
|
|
97
114
|
|
|
98
115
|
function createDatabase(dbPath) {
|
|
99
|
-
const db = new
|
|
100
|
-
db.
|
|
116
|
+
const db = new DatabaseSync(dbPath)
|
|
117
|
+
db.exec('PRAGMA journal_mode = WAL')
|
|
101
118
|
|
|
102
119
|
db.exec(`
|
|
103
120
|
CREATE TABLE packages (
|
|
@@ -263,14 +280,14 @@ function insertRepoMetadata(db, packageId, repoMetadata, host) {
|
|
|
263
280
|
|
|
264
281
|
stmt.run(
|
|
265
282
|
packageId,
|
|
266
|
-
repoMetadata.owner,
|
|
267
|
-
repoMetadata.name,
|
|
268
|
-
repoMetadata.full_name,
|
|
269
|
-
host?.name,
|
|
270
|
-
repoMetadata.language,
|
|
271
|
-
repoMetadata.stargazers_count,
|
|
272
|
-
repoMetadata.forks_count,
|
|
273
|
-
repoMetadata.open_issues_count,
|
|
283
|
+
repoMetadata.owner ?? null,
|
|
284
|
+
repoMetadata.name ?? null,
|
|
285
|
+
repoMetadata.full_name ?? null,
|
|
286
|
+
host?.name ?? null,
|
|
287
|
+
repoMetadata.language ?? null,
|
|
288
|
+
repoMetadata.stargazers_count ?? null,
|
|
289
|
+
repoMetadata.forks_count ?? null,
|
|
290
|
+
repoMetadata.open_issues_count ?? null,
|
|
274
291
|
repoMetadata.archived ? 1 : 0,
|
|
275
292
|
repoMetadata.fork ? 1 : 0
|
|
276
293
|
)
|
|
@@ -342,16 +359,19 @@ async function build(options = {}) {
|
|
|
342
359
|
const packages = await fetchAllCriticalPackages(onProgress)
|
|
343
360
|
onProgress(`Found ${packages.length} critical packages`)
|
|
344
361
|
|
|
345
|
-
|
|
346
|
-
|
|
362
|
+
onProgress('Inserting packages...')
|
|
363
|
+
db.exec('BEGIN')
|
|
364
|
+
try {
|
|
365
|
+
for (const pkg of packages) {
|
|
347
366
|
insertPackage(db, pkg)
|
|
348
367
|
insertRepoMetadata(db, pkg.id, pkg.repo_metadata, pkg.host)
|
|
349
368
|
insertAdvisories(db, pkg.id, pkg.advisories)
|
|
350
369
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
370
|
+
db.exec('COMMIT')
|
|
371
|
+
} catch (err) {
|
|
372
|
+
db.exec('ROLLBACK')
|
|
373
|
+
throw err
|
|
374
|
+
}
|
|
355
375
|
|
|
356
376
|
if (fetchVersionsData) {
|
|
357
377
|
onProgress('Fetching versions...')
|
|
@@ -369,13 +389,18 @@ async function build(options = {}) {
|
|
|
369
389
|
const batch = packages.slice(i, i + CONCURRENCY)
|
|
370
390
|
const results = await Promise.all(batch.map(processPackage))
|
|
371
391
|
|
|
372
|
-
db.
|
|
392
|
+
db.exec('BEGIN')
|
|
393
|
+
try {
|
|
373
394
|
for (const { pkg, versions } of results) {
|
|
374
395
|
if (versions.length > 0) {
|
|
375
396
|
insertVersions(db, pkg.id, versions)
|
|
376
397
|
}
|
|
377
398
|
}
|
|
378
|
-
|
|
399
|
+
db.exec('COMMIT')
|
|
400
|
+
} catch (err) {
|
|
401
|
+
db.exec('ROLLBACK')
|
|
402
|
+
throw err
|
|
403
|
+
}
|
|
379
404
|
|
|
380
405
|
completed += batch.length
|
|
381
406
|
onProgress(`Fetched versions for ${completed}/${total} packages`)
|
|
@@ -391,4 +416,4 @@ async function build(options = {}) {
|
|
|
391
416
|
return info
|
|
392
417
|
}
|
|
393
418
|
|
|
394
|
-
export { build, createDatabase, fetchAllCriticalPackages, fetchVersionNumbers, databasePath }
|
|
419
|
+
export { build, createDatabase, fetchAllCriticalPackages, fetchVersionNumbers, databasePath, insertRepoMetadata }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ecosyste-ms/critical",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.20260514",
|
|
4
4
|
"description": "SQLite database of critical packages from ecosyste.ms",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -35,9 +35,6 @@
|
|
|
35
35
|
"access": "public"
|
|
36
36
|
},
|
|
37
37
|
"engines": {
|
|
38
|
-
"node": ">=
|
|
39
|
-
},
|
|
40
|
-
"dependencies": {
|
|
41
|
-
"better-sqlite3": "^12.5.0"
|
|
38
|
+
"node": ">=22.5.0"
|
|
42
39
|
}
|
|
43
40
|
}
|