-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathhandle-patch-info.mts
More file actions
115 lines (98 loc) · 3.07 KB
/
handle-patch-info.mts
File metadata and controls
115 lines (98 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { promises as fs } from 'node:fs'
import path from 'node:path'
import { UTF8 } from '@socketsecurity/lib/constants/encoding'
import { getDefaultLogger } from '@socketsecurity/lib/logger'
import { DOT_SOCKET_DIR } from '@socketsecurity/lib/paths/dirnames'
import { MANIFEST_JSON } from '@socketsecurity/lib/paths/filenames'
import { normalizePath } from '@socketsecurity/lib/paths/normalize'
import { PatchManifestSchema } from './manifest-schema.mts'
import { outputPatchInfoResult } from './output-patch-info-result.mts'
import { getErrorCause, InputError } from '../../utils/error/errors.mjs'
import { normalizePurl } from '../../utils/purl/parse.mjs'
import type { PatchRecord } from './manifest-schema.mts'
import type { OutputKind } from '../../types.mts'
import type { Spinner } from '@socketsecurity/lib/spinner'
export interface PatchInfoData {
description: string | undefined
exportedAt: string
files: Record<string, { afterHash: string; beforeHash: string }>
license: string | undefined
purl: string
tier: string | undefined
uuid: string | undefined
vulnerabilities: PatchRecord['vulnerabilities']
}
export interface HandlePatchInfoConfig {
cwd: string
outputKind: OutputKind
purl: string
spinner: Spinner | null
}
export async function handlePatchInfo({
cwd,
outputKind,
purl,
spinner,
}: HandlePatchInfoConfig): Promise<void> {
try {
spinner?.start('Reading patch manifest')
const dotSocketDirPath = normalizePath(path.join(cwd, DOT_SOCKET_DIR))
const manifestPath = normalizePath(
path.join(dotSocketDirPath, MANIFEST_JSON),
)
const manifestContent = await fs.readFile(manifestPath, UTF8)
const manifestData = JSON.parse(manifestContent)
const validated = PatchManifestSchema.parse(manifestData)
const normalizedPurl = normalizePurl(purl)
const patch = validated.patches[normalizedPurl]
if (!patch) {
spinner?.stop()
throw new InputError(`Patch not found for PURL: ${purl}`)
}
spinner?.stop()
if (outputKind === 'text') {
const logger = getDefaultLogger()
logger.log(`Patch information for: ${normalizedPurl}`)
}
const patchInfo: PatchInfoData = {
description: patch.description,
exportedAt: patch.exportedAt,
files: patch.files,
license: patch.license,
purl: normalizedPurl,
tier: patch.tier,
uuid: patch.uuid,
vulnerabilities: patch.vulnerabilities,
}
await outputPatchInfoResult(
{
ok: true,
data: patchInfo,
},
outputKind,
)
} catch (e) {
spinner?.stop()
if (e instanceof InputError) {
throw e
}
let message = 'Failed to get patch info'
let cause = getErrorCause(e)
if (e instanceof SyntaxError) {
message = `Invalid JSON in ${MANIFEST_JSON}`
cause = e.message
} else if (e instanceof Error && 'issues' in e) {
message = 'Schema validation failed'
cause = String(e)
}
await outputPatchInfoResult(
{
ok: false,
code: 1,
message,
cause,
},
outputKind,
)
}
}