@@ -5,29 +5,35 @@ import { globby } from 'globby'
55import ignore from 'ignore'
66// @ts -ignore This package provides no types
77import { directories } from 'ignore-by-default'
8+ import micromatch from 'micromatch'
89import { ErrorWithCause } from 'pony-cause'
910
1011import { InputError } from './errors.js'
12+ import { setupSdk } from './sdk.js'
1113import { isErrnoException } from './type-helpers.js'
1214
13- /** @type {readonly string[] } */
14- const SUPPORTED_LOCKFILES = [
15- 'package-lock.json' ,
16- 'yarn.lock' ,
17- ]
18-
1915/**
2016 * There are a lot of possible folders that we should not be looking in and "ignore-by-default" helps us with defining those
2117 *
2218 * @type {readonly string[] }
2319 */
2420const ignoreByDefault = directories ( )
2521
26- /** @type {readonly string[] } */
22+ /** @type { string[] } */
2723const GLOB_IGNORE = [
2824 ...ignoreByDefault . map ( item => '**/' + item )
2925]
3026
27+ /** @type {import('globby').Options } */
28+ const BASE_GLOBBY_OPTS = {
29+ absolute : true ,
30+ expandDirectories : false ,
31+ gitignore : true ,
32+ ignore : GLOB_IGNORE ,
33+ markDirectories : true ,
34+ unique : true ,
35+ }
36+
3137/**
3238 * Resolves package.json and lockfiles from (globbed) input paths, applying relevant ignores
3339 *
@@ -43,14 +49,9 @@ export async function getPackageFiles (cwd, inputPaths, config, debugLog) {
4349
4450 // TODO: Does not support `~/` paths
4551 const entries = await globby ( inputPaths , {
46- absolute : true ,
52+ ... BASE_GLOBBY_OPTS ,
4753 cwd,
48- expandDirectories : false ,
49- gitignore : true ,
50- ignore : [ ...GLOB_IGNORE ] ,
51- markDirectories : true ,
52- onlyFiles : false ,
53- unique : true ,
54+ onlyFiles : false
5455 } )
5556
5657 debugLog ( `Globbed resolved ${ inputPaths . length } paths to ${ entries . length } paths:` , entries )
@@ -77,7 +78,12 @@ export async function getPackageFiles (cwd, inputPaths, config, debugLog) {
7778 * @throws {InputError }
7879 */
7980export async function mapGlobResultToFiles ( entries ) {
80- const packageFiles = await Promise . all ( entries . map ( mapGlobEntryToFiles ) )
81+ // TODO: setupSdk(getDefaultKey() || FREE_API_KEY) after #46 merged
82+ const sdk = await setupSdk ( )
83+ const supportedFiles = await sdk . getReportSupportedFiles ( )
84+ const packageFiles = await Promise . all (
85+ entries . map ( entry => mapGlobEntryToFiles ( entry , supportedFiles ) )
86+ )
8187
8288 const uniquePackageFiles = [ ...new Set ( packageFiles . flat ( ) ) ]
8389
@@ -88,46 +94,54 @@ export async function mapGlobResultToFiles (entries) {
8894 * Takes a single path to a folder, package.json or a recognized lock file and resolves to a package.json + lockfile pair (where possible)
8995 *
9096 * @param {string } entry
97+ * @param {import('@socketsecurity/sdk').SocketSdkReturnType<'getReportSupportedFiles'>['data'] } supportedFiles
9198 * @returns {Promise<string[]> }
9299 * @throws {InputError }
93100 */
94- export async function mapGlobEntryToFiles ( entry ) {
101+ export async function mapGlobEntryToFiles ( entry , supportedFiles ) {
95102 /** @type {string|undefined } */
96- let pkgFile
97- /** @type {string|undefined } */
98- let lockFile
99-
103+ let pkgJSFile
104+ /** @type {string[] } */
105+ let jsLockFiles = [ ]
106+ /** @type {string[] } */
107+ let pyFiles = [ ]
108+
109+ const jsSupported = supportedFiles [ 'npm' ] || { }
110+ const jsLockFilePatterns = Object . keys ( jsSupported )
111+ . filter ( key => key !== 'packagejson' )
112+ . map ( key => /** @type {{ pattern: string } } */ ( jsSupported [ key ] ) . pattern )
113+
114+ const pyFilePatterns = Object . values ( supportedFiles [ 'pypi' ] || { } ) . map ( p => p . pattern )
100115 if ( entry . endsWith ( '/' ) ) {
101116 // If the match is a folder and that folder contains a package.json file, then include it
102117 const filePath = path . resolve ( entry , 'package.json' )
103- pkgFile = await fileExists ( filePath ) ? filePath : undefined
118+ if ( await fileExists ( filePath ) ) pkgJSFile = filePath
119+ pyFiles = await globby ( pyFilePatterns , {
120+ ...BASE_GLOBBY_OPTS ,
121+ cwd : entry
122+ } )
104123 } else if ( path . basename ( entry ) === 'package.json' ) {
105124 // If the match is a package.json file, then include it
106- pkgFile = entry
107- } else if ( SUPPORTED_LOCKFILES . includes ( path . basename ( entry ) ) ) {
108- // If the match is a lock file, include both it and the corresponding package.json file
109- lockFile = entry
110- pkgFile = path . resolve ( path . dirname ( entry ) , 'package.json' )
125+ pkgJSFile = entry
126+ } else if ( micromatch . isMatch ( entry , jsLockFilePatterns ) ) {
127+ jsLockFiles = [ entry ]
128+ pkgJSFile = path . resolve ( path . dirname ( entry ) , 'package.json' )
129+ if ( ! ( await fileExists ( pkgJSFile ) ) ) return [ ]
130+ } else if ( micromatch . isMatch ( entry , pyFilePatterns ) ) {
131+ pyFiles = [ entry ]
111132 }
112133
113134 // If we will include a package.json file but don't already have a corresponding lockfile, then look for one
114- if ( ! lockFile && pkgFile ) {
115- const pkgDir = path . dirname ( pkgFile )
116-
117- for ( const name of SUPPORTED_LOCKFILES ) {
118- const lockFileAlternative = path . resolve ( pkgDir , name )
119- if ( await fileExists ( lockFileAlternative ) ) {
120- lockFile = lockFileAlternative
121- break
122- }
123- }
124- }
135+ if ( ! jsLockFiles . length && pkgJSFile ) {
136+ const pkgDir = path . dirname ( pkgJSFile )
125137
126- if ( pkgFile && lockFile ) {
127- return [ pkgFile , lockFile ]
138+ jsLockFiles = await globby ( jsLockFilePatterns , {
139+ ...BASE_GLOBBY_OPTS ,
140+ cwd : pkgDir
141+ } )
128142 }
129143
130- return pkgFile ? [ pkgFile ] : [ ]
144+ return [ ... jsLockFiles , ... pyFiles ] . concat ( pkgJSFile ? [ pkgJSFile ] : [ ] )
131145}
132146
133147/**
0 commit comments