github.com/google/osv-scalibr@v0.4.1/internal/dependencyfile/packagelockjson/packagelockjson.go (about)

     1  // Copyright 2025 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package packagelockjson provides the structures for npm's package-lock.json lockfile format.
    16  package packagelockjson
    17  
    18  // LockFile is the npm package-lock.json lockfile.
    19  type LockFile struct {
    20  	Version int `json:"lockfileVersion"`
    21  	// npm v1- lockfiles use "dependencies"
    22  	Dependencies map[string]Dependency `json:"dependencies,omitempty"`
    23  	// npm v2+ lockfiles use "packages"
    24  	Packages map[string]Package `json:"packages,omitempty"`
    25  }
    26  
    27  // Dependency is the representation of an installed dependency in lockfileVersion 1
    28  type Dependency struct {
    29  	// For an aliased package, Version is like "npm:[name]@[version]"
    30  	Version  string `json:"version"`
    31  	Resolved string `json:"resolved"`
    32  
    33  	Dev      bool `json:"dev,omitempty"`
    34  	Optional bool `json:"optional,omitempty"`
    35  
    36  	Requires     map[string]string     `json:"requires,omitempty"`
    37  	Dependencies map[string]Dependency `json:"dependencies,omitempty"`
    38  }
    39  
    40  // DepGroups returns the list of groups this dependency belongs to.
    41  // May be empty, or one or both of "dev", "optional".
    42  func (dep Dependency) DepGroups() []string {
    43  	if dep.Dev && dep.Optional {
    44  		return []string{"dev", "optional"}
    45  	}
    46  	if dep.Dev {
    47  		return []string{"dev"}
    48  	}
    49  	if dep.Optional {
    50  		return []string{"optional"}
    51  	}
    52  
    53  	return nil
    54  }
    55  
    56  // Package is the representation of an installed dependency in lockfileVersion 2+
    57  type Package struct {
    58  	// For an aliased package, Name is the real package name
    59  	Name     string `json:"name,omitempty"`
    60  	Version  string `json:"version"`
    61  	Resolved string `json:"resolved"`
    62  	Link     bool   `json:"link,omitempty"`
    63  
    64  	Dev         bool `json:"dev,omitempty"`
    65  	DevOptional bool `json:"devOptional,omitempty"`
    66  	Optional    bool `json:"optional,omitempty"`
    67  	InBundle    bool `json:"inBundle,omitempty"`
    68  
    69  	Dependencies         map[string]string `json:"dependencies,omitempty"`
    70  	DevDependencies      map[string]string `json:"devDependencies,omitempty"`
    71  	OptionalDependencies map[string]string `json:"optionalDependencies,omitempty"`
    72  	PeerDependencies     map[string]string `json:"peerDependencies,omitempty"`
    73  	PeerDependenciesMeta map[string]struct {
    74  		Optional bool `json:"optional,omitempty"`
    75  	} `json:"peerDependenciesMeta,omitempty"`
    76  }
    77  
    78  // DepGroups returns the list of groups this package belongs to.
    79  // Supported groups are "bundled", "dev", and "optional", with an
    80  // empty group implying a production dependency.
    81  func (pkg Package) DepGroups() []string {
    82  	var groups []string
    83  
    84  	if pkg.InBundle {
    85  		groups = []string{"bundled"}
    86  	}
    87  
    88  	if pkg.DevOptional {
    89  		groups = append(groups, "dev", "optional")
    90  
    91  		return groups
    92  	}
    93  
    94  	if pkg.Dev {
    95  		groups = append(groups, "dev")
    96  	}
    97  	if pkg.Optional {
    98  		groups = append(groups, "optional")
    99  	}
   100  
   101  	return groups
   102  }