@socketsecurity/cli 0.10.1 → 0.11.1
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/README.md +22 -22
- package/bin/npm +2 -0
- package/bin/npx +2 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +3419 -0
- package/dist/errors.d.ts +7 -0
- package/dist/link.d.ts +2 -0
- package/dist/link.js +45 -0
- package/dist/npm-cli.d.ts +2 -0
- package/dist/npm-cli.js +84 -0
- package/dist/npm-injection.d.ts +1 -0
- package/dist/npm-injection.js +913 -0
- package/dist/npm-injection2.d.ts +25 -0
- package/dist/npm-injection2.js +899 -0
- package/dist/npx-cli.d.ts +2 -0
- package/dist/npx-cli.js +60 -0
- package/dist/path-resolve.d.ts +12 -0
- package/dist/path-resolve.js +139 -0
- package/dist/sdk.d.ts +27 -0
- package/dist/sdk.js +224 -0
- package/dist/settings.d.ts +9 -0
- package/dist/type-helpers.d.ts +3 -0
- package/dist/vendor.js +25421 -0
- package/package.json +105 -52
- package/{lib/shadow/translations.json → translations.json} +20 -20
- package/cli.js +0 -72
- package/lib/commands/audit-log/index.js +0 -162
- package/lib/commands/cdxgen/index.js +0 -211
- package/lib/commands/dependencies/index.js +0 -150
- package/lib/commands/index.js +0 -14
- package/lib/commands/info/index.js +0 -287
- package/lib/commands/login/index.js +0 -170
- package/lib/commands/logout/index.js +0 -35
- package/lib/commands/npm/index.js +0 -27
- package/lib/commands/npx/index.js +0 -22
- package/lib/commands/raw-npm/index.js +0 -59
- package/lib/commands/raw-npx/index.js +0 -59
- package/lib/commands/report/create.js +0 -251
- package/lib/commands/report/index.js +0 -24
- package/lib/commands/report/view.js +0 -176
- package/lib/commands/repos/create.js +0 -166
- package/lib/commands/repos/delete.js +0 -93
- package/lib/commands/repos/index.js +0 -30
- package/lib/commands/repos/list.js +0 -170
- package/lib/commands/repos/update.js +0 -166
- package/lib/commands/repos/view.js +0 -128
- package/lib/commands/scan/create.js +0 -245
- package/lib/commands/scan/delete.js +0 -112
- package/lib/commands/scan/index.js +0 -30
- package/lib/commands/scan/list.js +0 -192
- package/lib/commands/scan/metadata.js +0 -113
- package/lib/commands/scan/stream.js +0 -115
- package/lib/commands/wrapper/index.js +0 -199
- package/lib/flags/command.js +0 -14
- package/lib/flags/index.js +0 -3
- package/lib/flags/output.js +0 -16
- package/lib/flags/validation.js +0 -14
- package/lib/shadow/bin/npm +0 -2
- package/lib/shadow/bin/npx +0 -2
- package/lib/shadow/link.cjs +0 -50
- package/lib/shadow/npm-cli.cjs +0 -27
- package/lib/shadow/npm-injection.cjs +0 -649
- package/lib/shadow/npx-cli.cjs +0 -27
- package/lib/shadow/package.json +0 -3
- package/lib/shadow/tty-server.cjs +0 -222
- package/lib/shadow/update-notifier.mjs +0 -3
- package/lib/utils/api-helpers.js +0 -42
- package/lib/utils/chalk-markdown.js +0 -125
- package/lib/utils/errors.js +0 -14
- package/lib/utils/flags.js +0 -27
- package/lib/utils/format-issues.js +0 -99
- package/lib/utils/formatting.js +0 -47
- package/lib/utils/issue-rules.cjs +0 -180
- package/lib/utils/meow-with-subcommands.js +0 -87
- package/lib/utils/misc.js +0 -61
- package/lib/utils/path-resolve.js +0 -204
- package/lib/utils/sdk.js +0 -99
- package/lib/utils/settings.js +0 -69
- package/lib/utils/type-helpers.cjs +0 -13
- package/lib/utils/update-notifier.js +0 -18
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
|
|
3
|
-
import chalk from 'chalk'
|
|
4
|
-
// @ts-ignore
|
|
5
|
-
import chalkTable from 'chalk-table'
|
|
6
|
-
import meow from 'meow'
|
|
7
|
-
import ora from 'ora'
|
|
8
|
-
|
|
9
|
-
import { outputFlags } from '../../flags/index.js'
|
|
10
|
-
import { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api-helpers.js'
|
|
11
|
-
import { prepareFlags } from '../../utils/flags.js'
|
|
12
|
-
import { printFlagList } from '../../utils/formatting.js'
|
|
13
|
-
import { getDefaultKey, setupSdk } from '../../utils/sdk.js'
|
|
14
|
-
|
|
15
|
-
/** @type {import('../../utils/meow-with-subcommands.js').CliSubcommand} */
|
|
16
|
-
export const list = {
|
|
17
|
-
description: 'List scans for an organization',
|
|
18
|
-
async run (argv, importMeta, { parentName }) {
|
|
19
|
-
const name = parentName + ' list'
|
|
20
|
-
|
|
21
|
-
const input = setupCommand(name, list.description, argv, importMeta)
|
|
22
|
-
if (input) {
|
|
23
|
-
const spinnerText = 'Listing scans... \n'
|
|
24
|
-
const spinner = ora(spinnerText).start()
|
|
25
|
-
await listOrgFullScan(input.orgSlug, input, spinner)
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const listFullScanFlags = prepareFlags({
|
|
31
|
-
sort: {
|
|
32
|
-
type: 'string',
|
|
33
|
-
shortFlag: 's',
|
|
34
|
-
default: 'created_at',
|
|
35
|
-
description: 'Sorting option (`name` or `created_at`) - default is `created_at`',
|
|
36
|
-
},
|
|
37
|
-
direction: {
|
|
38
|
-
type: 'string',
|
|
39
|
-
shortFlag: 'd',
|
|
40
|
-
default: 'desc',
|
|
41
|
-
description: 'Direction option (`desc` or `asc`) - Default is `desc`',
|
|
42
|
-
},
|
|
43
|
-
perPage: {
|
|
44
|
-
type: 'number',
|
|
45
|
-
shortFlag: 'pp',
|
|
46
|
-
default: 30,
|
|
47
|
-
description: 'Results per page - Default is 30',
|
|
48
|
-
},
|
|
49
|
-
page: {
|
|
50
|
-
type: 'number',
|
|
51
|
-
shortFlag: 'p',
|
|
52
|
-
default: 1,
|
|
53
|
-
description: 'Page number - Default is 1',
|
|
54
|
-
},
|
|
55
|
-
fromTime: {
|
|
56
|
-
type: 'string',
|
|
57
|
-
shortFlag: 'f',
|
|
58
|
-
default: '',
|
|
59
|
-
description: 'From time - as a unix timestamp',
|
|
60
|
-
},
|
|
61
|
-
untilTime: {
|
|
62
|
-
type: 'string',
|
|
63
|
-
shortFlag: 'u',
|
|
64
|
-
default: '',
|
|
65
|
-
description: 'Until time - as a unix timestamp',
|
|
66
|
-
}
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
// Internal functions
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* @typedef CommandContext
|
|
73
|
-
* @property {boolean} outputJson
|
|
74
|
-
* @property {boolean} outputMarkdown
|
|
75
|
-
* @property {string} orgSlug
|
|
76
|
-
* @property {string} sort
|
|
77
|
-
* @property {string} direction
|
|
78
|
-
* @property {number} per_page
|
|
79
|
-
* @property {number} page
|
|
80
|
-
* @property {string} from_time
|
|
81
|
-
* @property {string} until_time
|
|
82
|
-
*/
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* @param {string} name
|
|
86
|
-
* @param {string} description
|
|
87
|
-
* @param {readonly string[]} argv
|
|
88
|
-
* @param {ImportMeta} importMeta
|
|
89
|
-
* @returns {void|CommandContext}
|
|
90
|
-
*/
|
|
91
|
-
function setupCommand (name, description, argv, importMeta) {
|
|
92
|
-
const flags = {
|
|
93
|
-
...outputFlags,
|
|
94
|
-
...listFullScanFlags
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const cli = meow(`
|
|
98
|
-
Usage
|
|
99
|
-
$ ${name} <org slug>
|
|
100
|
-
|
|
101
|
-
Options
|
|
102
|
-
${printFlagList(flags, 6)}
|
|
103
|
-
|
|
104
|
-
Examples
|
|
105
|
-
$ ${name} FakeOrg
|
|
106
|
-
`, {
|
|
107
|
-
argv,
|
|
108
|
-
description,
|
|
109
|
-
importMeta,
|
|
110
|
-
flags
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
const {
|
|
114
|
-
json: outputJson,
|
|
115
|
-
markdown: outputMarkdown,
|
|
116
|
-
sort,
|
|
117
|
-
direction,
|
|
118
|
-
perPage,
|
|
119
|
-
page,
|
|
120
|
-
fromTime,
|
|
121
|
-
untilTime
|
|
122
|
-
} = cli.flags
|
|
123
|
-
|
|
124
|
-
if (!cli.input[0]) {
|
|
125
|
-
console.error(`${chalk.bgRed('Input error')}: Please specify an organization slug.\n`)
|
|
126
|
-
cli.showHelp()
|
|
127
|
-
return
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const [orgSlug = ''] = cli.input
|
|
131
|
-
|
|
132
|
-
return {
|
|
133
|
-
outputJson,
|
|
134
|
-
outputMarkdown,
|
|
135
|
-
orgSlug,
|
|
136
|
-
sort,
|
|
137
|
-
direction,
|
|
138
|
-
per_page: perPage,
|
|
139
|
-
page,
|
|
140
|
-
from_time: fromTime,
|
|
141
|
-
until_time: untilTime
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* @typedef FullScansData
|
|
147
|
-
* @property {import('@socketsecurity/sdk').SocketSdkReturnType<'getOrgFullScanList'>["data"]} data
|
|
148
|
-
*/
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* @param {string} orgSlug
|
|
152
|
-
* @param {CommandContext} input
|
|
153
|
-
* @param {import('ora').Ora} spinner
|
|
154
|
-
* @returns {Promise<void|FullScansData>}
|
|
155
|
-
*/
|
|
156
|
-
async function listOrgFullScan (orgSlug, input, spinner) {
|
|
157
|
-
const socketSdk = await setupSdk(getDefaultKey())
|
|
158
|
-
const result = await handleApiCall(socketSdk.getOrgFullScanList(orgSlug, input), 'Listing scans')
|
|
159
|
-
|
|
160
|
-
if (!result.success) {
|
|
161
|
-
return handleUnsuccessfulApiResponse('getOrgFullScanList', result, spinner)
|
|
162
|
-
}
|
|
163
|
-
spinner.stop()
|
|
164
|
-
|
|
165
|
-
console.log(`\n Listing scans for: ${orgSlug} \n`)
|
|
166
|
-
|
|
167
|
-
const options = {
|
|
168
|
-
columns: [
|
|
169
|
-
{ field: 'id', name: chalk.magenta('ID') },
|
|
170
|
-
{ field: 'report_url', name: chalk.magenta('Scan URL') },
|
|
171
|
-
{ field: 'branch', name: chalk.magenta('Branch') },
|
|
172
|
-
{ field: 'created_at', name: chalk.magenta('Created at') }
|
|
173
|
-
]
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const formattedResults = result.data.results.map(d => {
|
|
177
|
-
return {
|
|
178
|
-
id: d.id,
|
|
179
|
-
report_url: chalk.underline(`${d.html_report_url}`),
|
|
180
|
-
created_at: d.created_at ? new Date(d.created_at).toLocaleDateString('en-us', { year: 'numeric', month: 'numeric', day: 'numeric' }) : '',
|
|
181
|
-
branch: d.branch
|
|
182
|
-
}
|
|
183
|
-
})
|
|
184
|
-
|
|
185
|
-
const table = chalkTable(options, formattedResults)
|
|
186
|
-
|
|
187
|
-
console.log(table, '\n')
|
|
188
|
-
|
|
189
|
-
return {
|
|
190
|
-
data: result.data
|
|
191
|
-
}
|
|
192
|
-
}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
|
|
3
|
-
import chalk from 'chalk'
|
|
4
|
-
import meow from 'meow'
|
|
5
|
-
import ora from 'ora'
|
|
6
|
-
|
|
7
|
-
import { outputFlags } from '../../flags/index.js'
|
|
8
|
-
import { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api-helpers.js'
|
|
9
|
-
import { printFlagList } from '../../utils/formatting.js'
|
|
10
|
-
import { getDefaultKey, setupSdk } from '../../utils/sdk.js'
|
|
11
|
-
|
|
12
|
-
/** @type {import('../../utils/meow-with-subcommands.js').CliSubcommand} */
|
|
13
|
-
export const metadata = {
|
|
14
|
-
description: 'Get a scan\'s metadata',
|
|
15
|
-
async run (argv, importMeta, { parentName }) {
|
|
16
|
-
const name = parentName + ' metadata'
|
|
17
|
-
|
|
18
|
-
const input = setupCommand(name, metadata.description, argv, importMeta)
|
|
19
|
-
if (input) {
|
|
20
|
-
const spinnerText = 'Getting scan\'s metadata... \n'
|
|
21
|
-
const spinner = ora(spinnerText).start()
|
|
22
|
-
await getOrgScanMetadata(input.orgSlug, input.scanID, spinner)
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Internal functions
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @typedef CommandContext
|
|
31
|
-
* @property {boolean} outputJson
|
|
32
|
-
* @property {boolean} outputMarkdown
|
|
33
|
-
* @property {string} orgSlug
|
|
34
|
-
* @property {string} scanID
|
|
35
|
-
*/
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* @param {string} name
|
|
39
|
-
* @param {string} description
|
|
40
|
-
* @param {readonly string[]} argv
|
|
41
|
-
* @param {ImportMeta} importMeta
|
|
42
|
-
* @returns {void|CommandContext}
|
|
43
|
-
*/
|
|
44
|
-
function setupCommand (name, description, argv, importMeta) {
|
|
45
|
-
const flags = {
|
|
46
|
-
...outputFlags,
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const cli = meow(`
|
|
50
|
-
Usage
|
|
51
|
-
$ ${name} <org slug> <scan id>
|
|
52
|
-
|
|
53
|
-
Options
|
|
54
|
-
${printFlagList(flags, 6)}
|
|
55
|
-
|
|
56
|
-
Examples
|
|
57
|
-
$ ${name} FakeOrg 000aaaa1-0000-0a0a-00a0-00a0000000a0
|
|
58
|
-
`, {
|
|
59
|
-
argv,
|
|
60
|
-
description,
|
|
61
|
-
importMeta,
|
|
62
|
-
flags
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
const {
|
|
66
|
-
json: outputJson,
|
|
67
|
-
markdown: outputMarkdown,
|
|
68
|
-
} = cli.flags
|
|
69
|
-
|
|
70
|
-
if (cli.input.length < 2) {
|
|
71
|
-
console.error(`${chalk.bgRed('Input error')}: Please specify an organization slug and a scan ID.\n`)
|
|
72
|
-
cli.showHelp()
|
|
73
|
-
return
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const [orgSlug = '', scanID = ''] = cli.input
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
outputJson,
|
|
80
|
-
outputMarkdown,
|
|
81
|
-
orgSlug,
|
|
82
|
-
scanID
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* @typedef FullScansData
|
|
88
|
-
* @property {import('@socketsecurity/sdk').SocketSdkReturnType<'getOrgFullScanMetadata'>["data"]} data
|
|
89
|
-
*/
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* @param {string} orgSlug
|
|
93
|
-
* @param {string} scanId
|
|
94
|
-
* @param {import('ora').Ora} spinner
|
|
95
|
-
* @returns {Promise<void|FullScansData>}
|
|
96
|
-
*/
|
|
97
|
-
async function getOrgScanMetadata (orgSlug, scanId, spinner) {
|
|
98
|
-
const socketSdk = await setupSdk(getDefaultKey())
|
|
99
|
-
const result = await handleApiCall(socketSdk.getOrgFullScanMetadata(orgSlug, scanId), 'Listing scans')
|
|
100
|
-
|
|
101
|
-
if (!result.success) {
|
|
102
|
-
return handleUnsuccessfulApiResponse('getOrgFullScanMetadata', result, spinner)
|
|
103
|
-
}
|
|
104
|
-
spinner.stop()
|
|
105
|
-
|
|
106
|
-
console.log('\nScan metadata: \n')
|
|
107
|
-
|
|
108
|
-
console.log(result.data)
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
data: result.data
|
|
112
|
-
}
|
|
113
|
-
}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
|
|
3
|
-
import chalk from 'chalk'
|
|
4
|
-
import meow from 'meow'
|
|
5
|
-
import ora from 'ora'
|
|
6
|
-
|
|
7
|
-
import { outputFlags } from '../../flags/index.js'
|
|
8
|
-
import { handleApiCall, handleUnsuccessfulApiResponse } from '../../utils/api-helpers.js'
|
|
9
|
-
import { printFlagList } from '../../utils/formatting.js'
|
|
10
|
-
import { getDefaultKey, setupSdk } from '../../utils/sdk.js'
|
|
11
|
-
|
|
12
|
-
/** @type {import('../../utils/meow-with-subcommands.js').CliSubcommand} */
|
|
13
|
-
export const stream = {
|
|
14
|
-
description: 'Stream the output of a scan',
|
|
15
|
-
async run (argv, importMeta, { parentName }) {
|
|
16
|
-
const name = parentName + ' stream'
|
|
17
|
-
|
|
18
|
-
const input = setupCommand(name, stream.description, argv, importMeta)
|
|
19
|
-
if (input) {
|
|
20
|
-
const spinnerText = 'Streaming scan... \n'
|
|
21
|
-
const spinner = ora(spinnerText).start()
|
|
22
|
-
await getOrgFullScan(input.orgSlug, input.fullScanId, input.file, spinner)
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Internal functions
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* @typedef CommandContext
|
|
31
|
-
* @property {boolean} outputJson
|
|
32
|
-
* @property {boolean} outputMarkdown
|
|
33
|
-
* @property {string} orgSlug
|
|
34
|
-
* @property {string} fullScanId
|
|
35
|
-
* @property {string | undefined} file
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* @param {string} name
|
|
40
|
-
* @param {string} description
|
|
41
|
-
* @param {readonly string[]} argv
|
|
42
|
-
* @param {ImportMeta} importMeta
|
|
43
|
-
* @returns {void|CommandContext}
|
|
44
|
-
*/
|
|
45
|
-
function setupCommand (name, description, argv, importMeta) {
|
|
46
|
-
const flags = {
|
|
47
|
-
...outputFlags
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const cli = meow(`
|
|
51
|
-
Usage
|
|
52
|
-
$ ${name} <org slug> <scan ID> <path to output file>
|
|
53
|
-
|
|
54
|
-
Options
|
|
55
|
-
${printFlagList(flags, 6)}
|
|
56
|
-
|
|
57
|
-
Examples
|
|
58
|
-
$ ${name} FakeOrg 000aaaa1-0000-0a0a-00a0-00a0000000a0 ./stream.txt
|
|
59
|
-
`, {
|
|
60
|
-
argv,
|
|
61
|
-
description,
|
|
62
|
-
importMeta,
|
|
63
|
-
flags
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
const {
|
|
67
|
-
json: outputJson,
|
|
68
|
-
markdown: outputMarkdown,
|
|
69
|
-
} = cli.flags
|
|
70
|
-
|
|
71
|
-
if (cli.input.length < 2) {
|
|
72
|
-
console.error(`${chalk.bgRed('Input error')}: Please specify an organization slug and a scan ID.\n`)
|
|
73
|
-
cli.showHelp()
|
|
74
|
-
return
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const [orgSlug = '', fullScanId = '', file] = cli.input
|
|
78
|
-
|
|
79
|
-
return {
|
|
80
|
-
outputJson,
|
|
81
|
-
outputMarkdown,
|
|
82
|
-
orgSlug,
|
|
83
|
-
fullScanId,
|
|
84
|
-
file
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* @typedef FullScanData
|
|
90
|
-
* @property {import('@socketsecurity/sdk').SocketSdkReturnType<'getOrgFullScan'>["data"]} data
|
|
91
|
-
*/
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* @param {string} orgSlug
|
|
95
|
-
* @param {string} fullScanId
|
|
96
|
-
* @param {string | undefined} file
|
|
97
|
-
* @param {import('ora').Ora} spinner
|
|
98
|
-
* @returns {Promise<void|FullScanData>}
|
|
99
|
-
*/
|
|
100
|
-
async function getOrgFullScan (orgSlug, fullScanId, file, spinner) {
|
|
101
|
-
const socketSdk = await setupSdk(getDefaultKey())
|
|
102
|
-
const result = await handleApiCall(socketSdk.getOrgFullScan(orgSlug, fullScanId, file), 'Streaming a scan')
|
|
103
|
-
|
|
104
|
-
if (!result?.success) {
|
|
105
|
-
return handleUnsuccessfulApiResponse('getOrgFullScan', result, spinner)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
spinner.stop()
|
|
109
|
-
|
|
110
|
-
console.log(file ? `\nFull scan details written to ${file} \n` : '\nFull scan details: \n')
|
|
111
|
-
|
|
112
|
-
return {
|
|
113
|
-
data: result.data
|
|
114
|
-
}
|
|
115
|
-
}
|
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
/* eslint-disable no-console */
|
|
2
|
-
import fs from 'fs'
|
|
3
|
-
import homedir from 'os'
|
|
4
|
-
import readline from 'readline'
|
|
5
|
-
|
|
6
|
-
import meow from 'meow'
|
|
7
|
-
|
|
8
|
-
import { commandFlags } from '../../flags/index.js'
|
|
9
|
-
import { printFlagList } from '../../utils/formatting.js'
|
|
10
|
-
|
|
11
|
-
const BASH_FILE = `${homedir.homedir()}/.bashrc`
|
|
12
|
-
const ZSH_BASH_FILE = `${homedir.homedir()}/.zshrc`
|
|
13
|
-
|
|
14
|
-
/** @type {import('../../utils/meow-with-subcommands.js').CliSubcommand} */
|
|
15
|
-
export const wrapper = {
|
|
16
|
-
description: 'Enable or disable the Socket npm/npx wrapper',
|
|
17
|
-
async run (argv, importMeta, { parentName }) {
|
|
18
|
-
const name = parentName + ' wrapper'
|
|
19
|
-
|
|
20
|
-
setupCommand(name, wrapper.description, argv, importMeta)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* @param {string} name
|
|
26
|
-
* @param {string} description
|
|
27
|
-
* @param {readonly string[]} argv
|
|
28
|
-
* @param {ImportMeta} importMeta
|
|
29
|
-
* @returns {void}
|
|
30
|
-
*/
|
|
31
|
-
function setupCommand (name, description, argv, importMeta) {
|
|
32
|
-
const flags = commandFlags
|
|
33
|
-
|
|
34
|
-
const cli = meow(`
|
|
35
|
-
Usage
|
|
36
|
-
$ ${name} <flag>
|
|
37
|
-
|
|
38
|
-
Options
|
|
39
|
-
${printFlagList(flags, 6)}
|
|
40
|
-
|
|
41
|
-
Examples
|
|
42
|
-
$ ${name} --enable
|
|
43
|
-
$ ${name} --disable
|
|
44
|
-
`, {
|
|
45
|
-
argv,
|
|
46
|
-
description,
|
|
47
|
-
importMeta,
|
|
48
|
-
flags
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
const { enable, disable } = cli.flags
|
|
52
|
-
|
|
53
|
-
if (argv[0] === '--postinstall') {
|
|
54
|
-
// Check if the wrapper is already enabled before showing the postinstall prompt
|
|
55
|
-
const socketWrapperEnabled = (fs.existsSync(BASH_FILE) && checkSocketWrapperAlreadySetup(BASH_FILE)) || (fs.existsSync(ZSH_BASH_FILE) && checkSocketWrapperAlreadySetup(ZSH_BASH_FILE))
|
|
56
|
-
|
|
57
|
-
if (!socketWrapperEnabled) {
|
|
58
|
-
installSafeNpm(`The Socket CLI is now successfully installed! 🎉
|
|
59
|
-
|
|
60
|
-
To better protect yourself against supply-chain attacks, our "safe npm" wrapper can warn you about malicious packages whenever you run 'npm install'.
|
|
61
|
-
|
|
62
|
-
Do you want to install "safe npm" (this will create an alias to the socket-npm command)? (y/n)`)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (!enable && !disable) {
|
|
69
|
-
cli.showHelp()
|
|
70
|
-
return
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (enable) {
|
|
74
|
-
if (fs.existsSync(BASH_FILE)) {
|
|
75
|
-
const socketWrapperEnabled = checkSocketWrapperAlreadySetup(BASH_FILE)
|
|
76
|
-
!socketWrapperEnabled && addAlias(BASH_FILE)
|
|
77
|
-
}
|
|
78
|
-
if (fs.existsSync(ZSH_BASH_FILE)) {
|
|
79
|
-
const socketWrapperEnabled = checkSocketWrapperAlreadySetup(ZSH_BASH_FILE)
|
|
80
|
-
!socketWrapperEnabled && addAlias(ZSH_BASH_FILE)
|
|
81
|
-
}
|
|
82
|
-
} else if (disable) {
|
|
83
|
-
if (fs.existsSync(BASH_FILE)) {
|
|
84
|
-
removeAlias(BASH_FILE)
|
|
85
|
-
}
|
|
86
|
-
if (fs.existsSync(ZSH_BASH_FILE)) {
|
|
87
|
-
removeAlias(ZSH_BASH_FILE)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
if (!fs.existsSync(BASH_FILE) && !fs.existsSync(ZSH_BASH_FILE)) {
|
|
91
|
-
console.error('There was an issue setting up the alias in your bash profile')
|
|
92
|
-
}
|
|
93
|
-
return
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* @param {string} query
|
|
98
|
-
* @returns {void}
|
|
99
|
-
*/
|
|
100
|
-
const installSafeNpm = (query) => {
|
|
101
|
-
console.log(`
|
|
102
|
-
_____ _ _
|
|
103
|
-
| __|___ ___| |_ ___| |_
|
|
104
|
-
|__ | . | _| '_| -_| _|
|
|
105
|
-
|_____|___|___|_,_|___|_|
|
|
106
|
-
|
|
107
|
-
`)
|
|
108
|
-
|
|
109
|
-
const rl = readline.createInterface({
|
|
110
|
-
input: process.stdin,
|
|
111
|
-
output: process.stdout,
|
|
112
|
-
})
|
|
113
|
-
return askQuestion(rl, query)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* @param {any} rl
|
|
118
|
-
* @param {string} query
|
|
119
|
-
* @returns {void}
|
|
120
|
-
*/
|
|
121
|
-
const askQuestion = (rl, query) => {
|
|
122
|
-
rl.question(query, (/** @type {string} */ ans) => {
|
|
123
|
-
if (ans.toLowerCase() === 'y') {
|
|
124
|
-
try {
|
|
125
|
-
if (fs.existsSync(BASH_FILE)) {
|
|
126
|
-
addAlias(BASH_FILE)
|
|
127
|
-
}
|
|
128
|
-
if (fs.existsSync(ZSH_BASH_FILE)) {
|
|
129
|
-
addAlias(ZSH_BASH_FILE)
|
|
130
|
-
}
|
|
131
|
-
} catch (e) {
|
|
132
|
-
throw new Error(`There was an issue setting up the alias: ${e}`)
|
|
133
|
-
}
|
|
134
|
-
rl.close()
|
|
135
|
-
} else if (ans.toLowerCase() !== 'n') {
|
|
136
|
-
askQuestion(rl, 'Incorrect input: please enter either y (yes) or n (no): ')
|
|
137
|
-
} else {
|
|
138
|
-
rl.close()
|
|
139
|
-
}
|
|
140
|
-
})
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* @param {string} file
|
|
145
|
-
* @returns {void}
|
|
146
|
-
*/
|
|
147
|
-
const addAlias = (file) => {
|
|
148
|
-
return fs.appendFile(file, 'alias npm="socket npm"\nalias npx="socket npx"\n', (err) => {
|
|
149
|
-
if (err) {
|
|
150
|
-
return new Error(`There was an error setting up the alias: ${err}`)
|
|
151
|
-
}
|
|
152
|
-
console.log(`
|
|
153
|
-
The alias was added to ${file}. Running 'npm install' will now be wrapped in Socket's "safe npm" 🎉
|
|
154
|
-
If you want to disable it at any time, run \`socket wrapper --disable\`
|
|
155
|
-
`)
|
|
156
|
-
})
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* @param {string} file
|
|
161
|
-
* @returns {void}
|
|
162
|
-
*/
|
|
163
|
-
const removeAlias = (file) => {
|
|
164
|
-
return fs.readFile(file, 'utf8', function (err, data) {
|
|
165
|
-
if (err) {
|
|
166
|
-
console.error(`There was an error removing the alias: ${err}`)
|
|
167
|
-
return
|
|
168
|
-
}
|
|
169
|
-
const linesWithoutSocketAlias = data.split('\n').filter(l => l !== 'alias npm="socket npm"' && l !== 'alias npx="socket npx"')
|
|
170
|
-
|
|
171
|
-
const updatedFileContent = linesWithoutSocketAlias.join('\n')
|
|
172
|
-
|
|
173
|
-
fs.writeFile(file, updatedFileContent, function (err) {
|
|
174
|
-
if (err) {
|
|
175
|
-
console.log(err)
|
|
176
|
-
return
|
|
177
|
-
} else {
|
|
178
|
-
console.log(`
|
|
179
|
-
The alias was removed from ${file}. Running 'npm install' will now run the standard npm command.
|
|
180
|
-
`)
|
|
181
|
-
}
|
|
182
|
-
})
|
|
183
|
-
})
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* @param {string} file
|
|
188
|
-
* @returns {boolean}
|
|
189
|
-
*/
|
|
190
|
-
const checkSocketWrapperAlreadySetup = (file) => {
|
|
191
|
-
const fileContent = fs.readFileSync(file, 'utf-8')
|
|
192
|
-
const linesWithSocketAlias = fileContent.split('\n').filter(l => l === 'alias npm="socket npm"' || l === 'alias npx="socket npx"')
|
|
193
|
-
|
|
194
|
-
if (linesWithSocketAlias.length) {
|
|
195
|
-
console.log(`The Socket npm/npx wrapper is set up in your bash profile (${file}).`)
|
|
196
|
-
return true
|
|
197
|
-
}
|
|
198
|
-
return false
|
|
199
|
-
}
|
package/lib/flags/command.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { prepareFlags } from '../utils/flags.js'
|
|
2
|
-
|
|
3
|
-
export const commandFlags = prepareFlags({
|
|
4
|
-
enable: {
|
|
5
|
-
type: 'boolean',
|
|
6
|
-
default: false,
|
|
7
|
-
description: 'Enables the Socket npm/npx wrapper',
|
|
8
|
-
},
|
|
9
|
-
disable: {
|
|
10
|
-
type: 'boolean',
|
|
11
|
-
default: false,
|
|
12
|
-
description: 'Disables the Socket npm/npx wrapper',
|
|
13
|
-
}
|
|
14
|
-
})
|
package/lib/flags/index.js
DELETED
package/lib/flags/output.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { prepareFlags } from '../utils/flags.js'
|
|
2
|
-
|
|
3
|
-
export const outputFlags = prepareFlags({
|
|
4
|
-
json: {
|
|
5
|
-
type: 'boolean',
|
|
6
|
-
shortFlag: 'j',
|
|
7
|
-
default: false,
|
|
8
|
-
description: 'Output result as json',
|
|
9
|
-
},
|
|
10
|
-
markdown: {
|
|
11
|
-
type: 'boolean',
|
|
12
|
-
shortFlag: 'm',
|
|
13
|
-
default: false,
|
|
14
|
-
description: 'Output result as markdown',
|
|
15
|
-
},
|
|
16
|
-
})
|
package/lib/flags/validation.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { prepareFlags } from '../utils/flags.js'
|
|
2
|
-
|
|
3
|
-
export const validationFlags = prepareFlags({
|
|
4
|
-
all: {
|
|
5
|
-
type: 'boolean',
|
|
6
|
-
default: false,
|
|
7
|
-
description: 'Include all issues',
|
|
8
|
-
},
|
|
9
|
-
strict: {
|
|
10
|
-
type: 'boolean',
|
|
11
|
-
default: false,
|
|
12
|
-
description: 'Exits with an error code if any matching issues are found',
|
|
13
|
-
},
|
|
14
|
-
})
|
package/lib/shadow/bin/npm
DELETED
package/lib/shadow/bin/npx
DELETED