-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
npm_lockfile.go
107 lines (90 loc) · 3.36 KB
/
npm_lockfile.go
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
package lockfile
import (
"encoding/json"
"io"
mapset "github.com/deckarep/golang-set"
"github.com/vercel/turbo/cli/internal/ffi"
"github.com/vercel/turbo/cli/internal/turbopath"
)
// NpmLockfile representation of package-lock.json
type NpmLockfile struct {
// We just story the entire lockfile in memory and pass it for every call
contents []byte
}
// ResolvePackage Given a workspace, a package it imports and version returns the key, resolved version, and if it was found
func (l *NpmLockfile) ResolvePackage(workspacePath turbopath.AnchoredUnixPath, name string, version string) (Package, error) {
// This is only used when doing calculating the transitive deps, but Rust
// implementations do this calculation on the Rust side.
panic("Unreachable")
}
// AllDependencies Given a lockfile key return all (dev/optional/peer) dependencies of that package
func (l *NpmLockfile) AllDependencies(key string) (map[string]string, bool) {
// This is only used when doing calculating the transitive deps, but Rust
// implementations do this calculation on the Rust side.
panic("Unreachable")
}
// Subgraph Given a list of lockfile keys returns a Lockfile based off the original one that only contains the packages given
func (l *NpmLockfile) Subgraph(workspacePackages []turbopath.AnchoredSystemPath, packages []string) (Lockfile, error) {
workspaces := make([]string, len(workspacePackages))
for i, workspace := range workspacePackages {
workspaces[i] = workspace.ToUnixPath().ToString()
}
contents, err := ffi.NpmSubgraph(l.contents, workspaces, packages)
if err != nil {
return nil, err
}
return &NpmLockfile{contents: contents}, nil
}
// Encode the lockfile representation and write it to the given writer
func (l *NpmLockfile) Encode(w io.Writer) error {
_, err := w.Write(l.contents)
return err
}
// Patches return a list of patches used in the lockfile
func (l *NpmLockfile) Patches() []turbopath.AnchoredUnixPath {
return nil
}
// GlobalChange checks if there are any differences between lockfiles that would completely invalidate
// the cache.
func (l *NpmLockfile) GlobalChange(other Lockfile) bool {
o, ok := other.(*NpmLockfile)
if !ok {
return true
}
// We just grab the few global fields and check if they've changed
type minimalJSON struct {
LockfileVersion string `json:"version"`
Requires bool `json:"requires"`
}
var self minimalJSON
var otherJSON minimalJSON
if err := json.Unmarshal(o.contents, &otherJSON); err != nil {
return true
}
if err := json.Unmarshal(l.contents, &self); err != nil {
return true
}
return self.LockfileVersion != otherJSON.LockfileVersion ||
self.Requires != otherJSON.Requires
}
var _ (Lockfile) = (*NpmLockfile)(nil)
// DecodeNpmLockfile Parse contents of package-lock.json into NpmLockfile
func DecodeNpmLockfile(contents []byte) (Lockfile, error) {
return &NpmLockfile{contents: contents}, nil
}
func npmTransitiveDeps(lockfile *NpmLockfile, workspacePath turbopath.AnchoredUnixPath, unresolvedDeps map[string]string) (mapset.Set, error) {
pkgDir := workspacePath.ToString()
packages, err := ffi.NpmTransitiveDeps(lockfile.contents, pkgDir, unresolvedDeps)
if err != nil {
return nil, err
}
deps := make([]interface{}, len(packages))
for i, pkg := range packages {
deps[i] = Package{
Found: pkg.Found,
Key: pkg.Key,
Version: pkg.Version,
}
}
return mapset.NewSetFromSlice(deps), nil
}